Fix build and merged master.

pull/3892/head
Kim Kulling 2021-05-06 21:36:25 +02:00
commit 350f2ea1d3
1098 changed files with 72800 additions and 3960 deletions

3
.github/FUNDING.yml vendored
View File

@ -1,2 +1 @@
patreon: assimp open_collective: assimp
custom: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4

View File

@ -67,7 +67,13 @@ jobs:
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
repository: cpp-pm/polly repository: cpp-pm/polly
path: cmake/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 - name: Cache DX SDK
id: dxcache id: dxcache

6
.gitignore vendored
View File

@ -18,6 +18,9 @@ build
*.VC.db-wal *.VC.db-wal
*.VC.opendb *.VC.opendb
*.ipch *.ipch
.vs/
out/
CMakeSettings.json
# Output # Output
bin/ bin/
@ -113,3 +116,6 @@ tools/assimp_qt_viewer/moc_glview.cpp_parameters
tools/assimp_qt_viewer/moc_mainwindow.cpp tools/assimp_qt_viewer/moc_mainwindow.cpp
tools/assimp_qt_viewer/moc_mainwindow.cpp_parameters tools/assimp_qt_viewer/moc_mainwindow.cpp_parameters
tools/assimp_qt_viewer/ui_mainwindow.h tools/assimp_qt_viewer/ui_mainwindow.h
#Generated directory
generated/*

View File

@ -1,6 +1,6 @@
# Build Instructions # Build / Install Instructions
## Build on all platforms using vcpkg ## Install on all platforms using vcpkg
You can download and install assimp using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager: You can download and install assimp using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager:
```bash ```bash
git clone https://github.com/Microsoft/vcpkg.git git clone https://github.com/Microsoft/vcpkg.git
@ -11,6 +11,18 @@ You can download and install assimp using the [vcpkg](https://github.com/Microso
``` ```
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. 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 install assimp
```
## Install pyassimp
You need to have pip installed:
```
pip install pyassimp
```
## Manual build instructions ## Manual build instructions
### Install CMake ### Install CMake
@ -24,6 +36,12 @@ Make sure you have a working git-installation. Open a command prompt and clone t
```bash ```bash
git clone https://github.com/assimp/assimp.git git clone https://github.com/assimp/assimp.git
``` ```
### Build from source:
```bash
cd assimp
cmake CMakeLists.txt
cmake --build .
```
### Build instructions for Windows with Visual-Studio ### Build instructions for Windows with Visual-Studio

View File

@ -1,6 +1,6 @@
# Open Asset Import Library (assimp) # Open Asset Import Library (assimp)
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# Copyright (c) 2006-2020, assimp team # Copyright (c) 2006-2021, assimp team
# #
# All rights reserved. # All rights reserved.
# #
@ -38,7 +38,7 @@ SET(CMAKE_POLICY_DEFAULT_CMP0012 NEW)
SET(CMAKE_POLICY_DEFAULT_CMP0074 NEW) SET(CMAKE_POLICY_DEFAULT_CMP0074 NEW)
SET(CMAKE_POLICY_DEFAULT_CMP0092 NEW) SET(CMAKE_POLICY_DEFAULT_CMP0092 NEW)
CMAKE_MINIMUM_REQUIRED( VERSION 3.0 ) CMAKE_MINIMUM_REQUIRED( VERSION 3.10 )
# Toggles the use of the hunter package manager # Toggles the use of the hunter package manager
option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF) option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF)
@ -46,8 +46,8 @@ option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF)
IF(ASSIMP_HUNTER_ENABLED) IF(ASSIMP_HUNTER_ENABLED)
include("cmake/HunterGate.cmake") include("cmake/HunterGate.cmake")
HunterGate( HunterGate(
URL "https://github.com/cpp-pm/hunter/archive/v0.23.269.tar.gz" URL "https://github.com/cpp-pm/hunter/archive/v0.23.293.tar.gz"
SHA1 "64024b7b95b4c86d50ae05b926814448c93a70a0" SHA1 "e8e5470652db77149d9b38656db2a6c0b7642693"
) )
add_definitions(-DASSIMP_USE_HUNTER) add_definitions(-DASSIMP_USE_HUNTER)
@ -61,7 +61,6 @@ OPTION( BUILD_SHARED_LIBS
"Build package with shared libraries." "Build package with shared libraries."
ON ON
) )
OPTION( ASSIMP_BUILD_FRAMEWORK OPTION( ASSIMP_BUILD_FRAMEWORK
"Build package as Mac OS X Framework bundle." "Build package as Mac OS X Framework bundle."
OFF OFF
@ -133,9 +132,22 @@ OPTION ( ASSIMP_IGNORE_GIT_HASH
) )
IF ( WIN32 ) IF ( WIN32 )
OPTION ( ASSIMP_BUILD_ASSIMP_VIEW # Use subset of Windows.h
"If the Assimp view tool is built. (requires DirectX)" ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN )
OFF )
OPTION ( ASSIMP_BUILD_ASSIMP_VIEW
"If the Assimp view tool is built. (requires DirectX)"
OFF )
IF(MSVC)
OPTION( ASSIMP_INSTALL_PDB
"Install MSVC debug files."
ON )
IF(NOT (MSVC_VERSION LESS 1900))
# Multibyte character set is deprecated since at least MSVC2015 (possibly earlier)
ADD_DEFINITIONS( -DUNICODE -D_UNICODE )
ENDIF()
ENDIF()
ENDIF() ENDIF()
IF (IOS AND NOT ASSIMP_HUNTER_ENABLED) IF (IOS AND NOT ASSIMP_HUNTER_ENABLED)
@ -145,21 +157,6 @@ IF (IOS AND NOT ASSIMP_HUNTER_ENABLED)
ADD_DEFINITIONS(-DENABLE_BITCODE) ADD_DEFINITIONS(-DENABLE_BITCODE)
ENDIF () ENDIF ()
# Use subset of Windows.h
if (WIN32)
ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN )
endif()
IF(MSVC)
OPTION( ASSIMP_INSTALL_PDB
"Install MSVC debug files."
ON
)
IF(NOT (MSVC_VERSION LESS 1900))
# Multibyte character set is deprecated since at least MSVC2015 (possibly earlier)
ADD_DEFINITIONS( -DUNICODE -D_UNICODE )
ENDIF()
ENDIF()
IF (ASSIMP_BUILD_FRAMEWORK) IF (ASSIMP_BUILD_FRAMEWORK)
SET (BUILD_SHARED_LIBS ON) SET (BUILD_SHARED_LIBS ON)
@ -455,6 +452,12 @@ IF(ASSIMP_HUNTER_ENABLED)
set(ZLIB_LIBRARIES ZLIB::zlib) set(ZLIB_LIBRARIES ZLIB::zlib)
set(ASSIMP_BUILD_MINIZIP TRUE) set(ASSIMP_BUILD_MINIZIP TRUE)
ELSE() ELSE()
# If the zlib is already found outside, add an export in case assimpTargets can't find it.
IF( ZLIB_FOUND )
INSTALL( TARGETS zlib zlibstatic
EXPORT "${TARGETS_EXPORT_NAME}")
ENDIF()
IF ( NOT ASSIMP_BUILD_ZLIB ) IF ( NOT ASSIMP_BUILD_ZLIB )
FIND_PACKAGE(ZLIB) FIND_PACKAGE(ZLIB)
ENDIF() ENDIF()
@ -570,6 +573,94 @@ ELSE ()
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER ) ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER )
ENDIF () 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")
SET ( ASSIMP_BUILD_DRACO OFF CACHE BOOL "Disabled: Draco requires newer cmake" FORCE )
ELSE()
OPTION ( ASSIMP_BUILD_DRACO "If the Draco libraries are to be built. Primarily for glTF" OFF )
IF ( ASSIMP_BUILD_DRACO )
# Primarily for glTF v2
# Enable Draco glTF feature set
set(DRACO_GLTF ON CACHE BOOL "" FORCE)
# Disable unnecessary or omitted components
set(DRACO_JS_GLUE OFF CACHE BOOL "" FORCE)
set(DRACO_WASM OFF CACHE BOOL "" FORCE)
set(DRACO_MAYA_PLUGIN OFF CACHE BOOL "" FORCE)
set(DRACO_UNITY_PLUGIN OFF CACHE BOOL "" FORCE)
set(DRACO_TESTS OFF CACHE BOOL "" FORCE)
IF(ASSIMP_HUNTER_ENABLED)
hunter_add_package(draco)
find_package(draco CONFIG REQUIRED)
set(draco_LIBRARIES draco::draco)
ELSE()
# Draco 1.4.1 has many warnings and will not build with /WX or -Werror
# See https://github.com/google/draco/issues/672
# and https://github.com/google/draco/issues/673
IF(MSVC)
set(DRACO_CXX_FLAGS "/W0")
ELSE()
list(APPEND DRACO_CXX_FLAGS
"-Wno-bool-compare"
"-Wno-comment"
"-Wno-maybe-uninitialized"
"-Wno-sign-compare"
"-Wno-unused-local-typedefs"
)
# Draco 1.4.1 does not explicitly export any symbols under GCC/clang
list(APPEND DRACO_CXX_FLAGS
"-fvisibility=default"
)
ENDIF()
# Don't build or install all of Draco by default
ADD_SUBDIRECTORY( "contrib/draco" EXCLUDE_FROM_ALL )
if(MSVC OR WIN32)
set(draco_LIBRARIES "draco")
else()
if(BUILD_SHARED_LIBS)
set(draco_LIBRARIES "draco_shared")
else()
set(draco_LIBRARIES "draco_static")
endif()
endif()
# Don't build the draco command-line tools by default
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)
TARGET_USE_COMMON_OUTPUT_DIRECTORY(draco_decoder)
set(draco_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/draco/src")
# This is probably wrong
INSTALL( TARGETS ${draco_LIBRARIES}
EXPORT "${TARGETS_EXPORT_NAME}"
LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR}
FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
COMPONENT ${LIBASSIMP_COMPONENT}
INCLUDES DESTINATION include
)
ENDIF()
ENDIF()
ENDIF()
# Main assimp code
ADD_SUBDIRECTORY( code/ ) ADD_SUBDIRECTORY( code/ )
IF ( ASSIMP_BUILD_ASSIMP_TOOLS ) IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
# The viewer for windows only # The viewer for windows only
@ -583,7 +674,7 @@ IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
ADD_SUBDIRECTORY( tools/assimp_cmd/ ) ADD_SUBDIRECTORY( tools/assimp_cmd/ )
ENDIF () ENDIF ()
IF ( ASSIMP_BUILD_SAMPLES) IF ( ASSIMP_BUILD_SAMPLES )
SET( SAMPLES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/samples ) SET( SAMPLES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/samples )
SET( SAMPLES_SHARED_CODE_DIR ${SAMPLES_DIR}/SharedCode ) SET( SAMPLES_SHARED_CODE_DIR ${SAMPLES_DIR}/SharedCode )
IF ( WIN32 ) IF ( WIN32 )

25
Dockerfile 100644
View File

@ -0,0 +1,25 @@
FROM ubuntu:14.04
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 && 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
# Build Assimp
RUN git clone https://github.com/assimp/assimp.git /opt/assimp
WORKDIR /opt/assimp
RUN git checkout master \
&& mkdir build && cd build && \
cmake \
-DCMAKE_BUILD_TYPE=Release \
.. && \
make && make install

37
INSTALL
View File

@ -8,43 +8,10 @@ Getting the documentation
------------------------------ ------------------------------
A regularly-updated copy is available at A regularly-updated copy is available at
http://assimp.sourceforge.net/lib_html/index.html https://assimp-docs.readthedocs.io/en/latest/
A CHM file is included in the SVN repos: ./doc/AssimpDoc_Html/AssimpDoc.chm.
To build the doxygen documentation on your own, follow these steps:
a) download & install latest doxygen
b) make sure doxygen is in the executable search path
c) navigate to ./doc
d) and run 'doxygen'
Open the generated HTML (AssimpDoc_Html/index.html) in the browser of your choice.
Windows only: To generate the CHM doc, install 'Microsoft HTML Workshop'
and configure the path to it in the DOXYFILE first.
------------------------------ ------------------------------
Building Assimp Building Assimp
------------------------------ ------------------------------
More detailed build instructions can be found in the documentation, Just check the build-instaructions which you can find here: https://github.com/assimp/assimp/blob/master/Build.md
this section is just for the inpatient among you.
CMake is the preferred build system for Assimp. The minimum required version
is 2.6. If you don't have it yet, downloads for CMake can be found on
http://www.cmake.org/.
For Unix:
1. mkdir build && cd build
2. cmake .. -G 'Unix Makefiles'
3. make -j4
For Windows:
1. Open a command prompt
2. mkdir build
3. cd build
4. cmake ..
5. cmake --build .
For iOS:
Just check the following project, which deploys a compiler toolchain for different iOS-versions: https://github.com/assimp/assimp/tree/master/port/iOS

View File

@ -1,6 +1,6 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,

View File

@ -8,10 +8,10 @@ A library to import and export various 3d-model-formats including scene-post-pro
<img alt="Coverity Scan Build Status" <img alt="Coverity Scan Build Status"
src="https://scan.coverity.com/projects/5607/badge.svg"/> src="https://scan.coverity.com/projects/5607/badge.svg"/>
</a> </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) [![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) [![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") [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue")
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/5be56faac64f46fc941ac890fb4febef)](https://www.codacy.com/app/kimkulling/assimp?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=assimp/assimp&amp;utm_campaign=Badge_Grade)
[![Total alerts](https://img.shields.io/lgtm/alerts/g/assimp/assimp.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/assimp/assimp/alerts/) [![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> <br>
@ -39,12 +39,13 @@ Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file.
### Ports ### ### Ports ###
* [Android](port/AndroidJNI/README.md) * [Android](port/AndroidJNI/README.md)
* [Python](port/PyAssimp/README.md) * [Python](port/PyAssimp/README.md)
* [.NET](https://github.com/assimp/assimp-net) * [.NET](https://bitbucket.org/Starnick/assimpnet/src/master/)
* [Pascal](port/AssimpPascal/Readme.md) * [Pascal](port/AssimpPascal/Readme.md)
* [Javascript (Alpha)](https://github.com/makc/assimp2json) * [Javascript (Alpha)](https://github.com/makc/assimp2json)
* [Unity 3d Plugin](https://www.assetstore.unity3d.com/en/#!/content/91777) * [Unity 3d Plugin](https://www.assetstore.unity3d.com/en/#!/content/91777)
* [JVM](https://github.com/kotlin-graphics/assimp) Full jvm port (current [status](https://github.com/kotlin-graphics/assimp/wiki/Status)) * [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. * [HAXE-Port](https://github.com/longde123/assimp-haxe) The Assimp-HAXE-port.
* [Rust](https://github.com/jkvargas/russimp)
### Other tools ### ### Other tools ###
[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities. [open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.
@ -75,9 +76,6 @@ For more information, visit [our website](http://assimp.org/). Or check out the
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. 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.
For development discussions, there is also a (very low-volume) mailing list, _assimp-discussions_
[(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions)
Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export. Open Asset Import Library is a library 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> 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>
@ -102,15 +100,6 @@ Become a financial contributor and help us sustain our community. [[Contribute](
<a href="https://opencollective.com/assimp"><img src="https://opencollective.com/assimp/individuals.svg?width=890"></a> <a href="https://opencollective.com/assimp"><img src="https://opencollective.com/assimp/individuals.svg?width=890"></a>
Monthly donations via Patreon:
<br>[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/assimp)
<br>
One-off donations via PayPal:
<br>[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4)
<br>
#### Organizations #### Organizations

View File

@ -1,81 +0,0 @@
# AppVeyor file
# http://www.appveyor.com/docs/appveyor-yml
# clone directory
clone_folder: c:\projects\assimp
clone_depth: 1
# branches to build
branches:
# whitelist
only:
- master
matrix:
fast_finish: true
image:
- Visual Studio 2013
#- Visual Studio 2015
#- Visual Studio 2017
- Visual Studio 2019
#- MinGW
platform:
- Win32
- x64
configuration: Release
install:
- set PATH=C:\Ruby24-x64\bin;%PATH%
- set CMAKE_DEFINES -DASSIMP_WERROR=ON
- if [%COMPILER%]==[MinGW] set PATH=C:\MinGW\bin;%PATH%
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2013" set CMAKE_GENERATOR_NAME=Visual Studio 12 2013
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2019" set CMAKE_GENERATOR_NAME=Visual Studio 16 2019
- cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%" -A %platform% .
# Rename sh.exe as sh.exe in PATH interferes with MinGW - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015
- rename "C:\Program Files\Git\usr\bin\sh.exe" "sh2.exe"
- set PATH=%PATH%;"C:\\Program Files (x86)\\Inno Setup 5"
- ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/5/7/b/57b2947c-7221-4f33-b35e-2fc78cb10df4/vc_redist.x64.exe -OutFile .\packaging\windows-innosetup\vc_redist.x64.exe
- ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/1/d/8/1d8137db-b5bb-4925-8c5d-927424a2e4de/vc_redist.x86.exe -OutFile .\packaging\windows-innosetup\vc_redist.x86.exe
cache:
- code\assimp.dir\%CONFIGURATION%
- contrib\zlib\zlibstatic.dir\%CONFIGURATION%
- contrib\zlib\zlib.dir\%CONFIGURATION%
- tools\assimp_cmd\assimp_cmd.dir\%CONFIGURATION%
- tools\assimp_view\assimp_viewer.dir\%CONFIGURATION%
- test\unit.dir\%CONFIGURATION%
- bin\.mtime_cache
before_build:
- echo NUMBER_OF_PROCESSORS=%NUMBER_OF_PROCESSORS%
- ruby scripts\AppVeyor\mtime_cache -g scripts\AppVeyor\cacheglobs.txt -c bin\.mtime_cache\cache.json
build_script:
cmake --build . --config Release -- /maxcpucount:2
after_build:
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" (
if "%platform%"=="x64" (
iscc packaging\windows-innosetup\script_x64.iss
) else (
iscc packaging\windows-innosetup\script_x86.iss
)
)
- 7z a assimp.7z bin\%CONFIGURATION%\* lib\%CONFIGURATION%\*
test_script:
- cmd: bin\%CONFIGURATION%\unit.exe --gtest_output=xml:testout.xml
on_finish:
- ps: (new-object net.webclient).UploadFile("https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\testout.xml))
artifacts:
- path: assimp.7z
name: assimp_lib

View File

@ -10,5 +10,9 @@ find_package(polyclipping CONFIG REQUIRED)
find_package(zip CONFIG REQUIRED) find_package(zip CONFIG REQUIRED)
find_package(pugixml CONFIG REQUIRED) find_package(pugixml CONFIG REQUIRED)
if(@ASSIMP_BUILD_DRACO@)
find_package(draco CONFIG REQUIRED)
endif()
include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake") include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake")
check_required_components("@PROJECT_NAME@") check_required_components("@PROJECT_NAME@")

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -212,7 +212,7 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat,
mat.AddProperty(&tex, AI_MATKEY_GLOBAL_BACKGROUND_IMAGE); mat.AddProperty(&tex, AI_MATKEY_GLOBAL_BACKGROUND_IMAGE);
// Be sure this is only done for the first material // Be sure this is only done for the first material
mBackgroundImage = std::string(""); mBackgroundImage = std::string();
} }
// At first add the base ambient color of the scene to the material // At first add the base ambient color of the scene to the material

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -102,13 +102,14 @@ private:
// preserves the mesh's given name if it has one. |index| is the index // preserves the mesh's given name if it has one. |index| is the index
// of the mesh in |aiScene::mMeshes|. // of the mesh in |aiScene::mMeshes|.
std::string GetMeshName(const aiMesh &mesh, unsigned int index, const aiNode &node) { std::string GetMeshName(const aiMesh &mesh, unsigned int index, const aiNode &node) {
static const std::string underscore = "_"; static const char underscore = '_';
char postfix[10] = { 0 }; char postfix[10] = { 0 };
ASSIMP_itoa10(postfix, index); ASSIMP_itoa10(postfix, index);
std::string result = node.mName.C_Str(); std::string result = node.mName.C_Str();
if (mesh.mName.length > 0) { if (mesh.mName.length > 0) {
result += underscore + mesh.mName.C_Str(); result += underscore;
result += mesh.mName.C_Str();
} }
return result + underscore + postfix; return result + underscore + postfix;
} }
@ -444,7 +445,7 @@ void Discreet3DSExporter::WriteMeshes() {
const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices); const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
writer.PutU2(count); writer.PutU2(count);
for (unsigned int i = 0; i < mesh.mNumVertices; ++i) { for (unsigned int i = 0; i < mesh.mNumVertices; ++i) {
const aiVector3D &v = trafo * mesh.mVertices[i]; const aiVector3D &v = mesh.mVertices[i];
writer.PutF4(v.x); writer.PutF4(v.x);
writer.PutF4(v.y); writer.PutF4(v.y);
writer.PutF4(v.z); writer.PutF4(v.z);
@ -506,11 +507,16 @@ void Discreet3DSExporter::WriteMeshes() {
// Transformation matrix by which the mesh vertices have been pre-transformed with. // Transformation matrix by which the mesh vertices have been pre-transformed with.
{ {
ChunkWriter curChunk(writer, Discreet3DS::CHUNK_TRMATRIX); ChunkWriter curChunk(writer, Discreet3DS::CHUNK_TRMATRIX);
for (unsigned int r = 0; r < 4; ++r) { // Store rotation 3x3 matrix row wise
for (unsigned int r = 0; r < 3; ++r) {
for (unsigned int c = 0; c < 3; ++c) { for (unsigned int c = 0; c < 3; ++c) {
writer.PutF4(trafo[r][c]); writer.PutF4(trafo[r][c]);
} }
} }
// Store translation sub vector column wise
for (unsigned int r = 0; r < 3; ++r) {
writer.PutF4(trafo[r][3]);
}
} }
} }
} }

View File

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

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -61,20 +61,10 @@ namespace D3DS {
#include <assimp/Compiler/pushpack1.h> #include <assimp/Compiler/pushpack1.h>
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Discreet3DS class: Helper class for loading 3ds files. Defines chunks /** Defines chunks and data structures.
* and data structures.
*/ */
class Discreet3DS { namespace Discreet3DS {
private:
Discreet3DS() AI_NO_EXCEPT {
// empty
}
~Discreet3DS() {
// empty
}
public:
//! data structure for a single chunk in a .3ds file //! data structure for a single chunk in a .3ds file
struct Chunk { struct Chunk {
uint16_t Flag; uint16_t Flag;
@ -314,7 +304,7 @@ public:
// camera sub-chunks // camera sub-chunks
CHUNK_CAM_RANGES = 0x4720 CHUNK_CAM_RANGES = 0x4720
}; };
}; }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure representing a 3ds mesh face */ /** Helper structure representing a 3ds mesh face */

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -164,7 +164,7 @@ void Discreet3DSImporter::InternReadFile(const std::string &pFile,
mRootNode->mHierarchyIndex = -1; mRootNode->mHierarchyIndex = -1;
mRootNode->mParent = nullptr; mRootNode->mParent = nullptr;
mMasterScale = 1.0f; mMasterScale = 1.0f;
mBackgroundImage = ""; mBackgroundImage = std::string();
bHasBG = false; bHasBG = false;
bIsPrj = false; bIsPrj = false;
@ -266,6 +266,7 @@ void Discreet3DSImporter::ParseMainChunk() {
case Discreet3DS::CHUNK_PRJ: case Discreet3DS::CHUNK_PRJ:
bIsPrj = true; bIsPrj = true;
break;
case Discreet3DS::CHUNK_MAIN: case Discreet3DS::CHUNK_MAIN:
ParseEditorChunk(); ParseEditorChunk();
break; break;
@ -323,7 +324,7 @@ void Discreet3DSImporter::ParseObjectChunk() {
case Discreet3DS::CHUNK_MAT_MATERIAL: case Discreet3DS::CHUNK_MAT_MATERIAL:
// Add a new material to the list // Add a new material to the list
mScene->mMaterials.push_back(D3DS::Material(std::string("UNNAMED_" + to_string(mScene->mMaterials.size())))); mScene->mMaterials.push_back(D3DS::Material(std::string("UNNAMED_" + ai_to_string(mScene->mMaterials.size()))));
ParseMaterialChunk(); ParseMaterialChunk();
break; break;

View File

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

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -44,63 +44,66 @@ namespace Assimp {
namespace D3MF { namespace D3MF {
namespace XmlTag { namespace XmlTag {
// Root tag
const char* const RootTag = "3MF";
// Meta-data // Meta-data
static const std::string meta = "metadata"; const char* const meta = "metadata";
static const std::string meta_name = "name"; const char* const meta_name = "name";
// Model-data specific tags // Model-data specific tags
static const std::string model = "model"; const char* const model = "model";
static const std::string model_unit = "unit"; const char* const model_unit = "unit";
static const std::string metadata = "metadata"; const char* const metadata = "metadata";
static const std::string resources = "resources"; const char* const resources = "resources";
static const std::string object = "object"; const char* const object = "object";
static const std::string mesh = "mesh"; const char* const mesh = "mesh";
static const std::string components = "components"; const char* const components = "components";
static const std::string component = "component"; const char* const component = "component";
static const std::string vertices = "vertices"; const char* const vertices = "vertices";
static const std::string vertex = "vertex"; const char* const vertex = "vertex";
static const std::string triangles = "triangles"; const char* const triangles = "triangles";
static const std::string triangle = "triangle"; const char* const triangle = "triangle";
static const std::string x = "x"; const char* const x = "x";
static const std::string y = "y"; const char* const y = "y";
static const std::string z = "z"; const char* const z = "z";
static const std::string v1 = "v1"; const char* const v1 = "v1";
static const std::string v2 = "v2"; const char* const v2 = "v2";
static const std::string v3 = "v3"; const char* const v3 = "v3";
static const std::string id = "id"; const char* const id = "id";
static const std::string pid = "pid"; const char* const pid = "pid";
static const std::string pindex = "pindex"; const char* const pindex = "pindex";
static const std::string p1 = "p1"; const char* const p1 = "p1";
static const std::string name = "name"; const char* const name = "name";
static const std::string type = "type"; const char* const type = "type";
static const std::string build = "build"; const char* const build = "build";
static const std::string item = "item"; const char* const item = "item";
static const std::string objectid = "objectid"; const char* const objectid = "objectid";
static const std::string transform = "transform"; const char* const transform = "transform";
// Material definitions // Material definitions
static const std::string basematerials = "basematerials"; const char* const basematerials = "basematerials";
static const std::string basematerials_id = "id"; const char* const basematerials_id = "id";
static const std::string basematerials_base = "base"; const char* const basematerials_base = "base";
static const std::string basematerials_name = "name"; const char* const basematerials_name = "name";
static const std::string basematerials_displaycolor = "displaycolor"; const char* const basematerials_displaycolor = "displaycolor";
// Meta info tags // Meta info tags
static const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml"; const char* const CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
static const std::string ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels"; const char* const ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels";
static const std::string SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types"; const char* const SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types";
static const std::string SCHEMA_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships"; const char* const SCHEMA_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships";
static const std::string RELS_RELATIONSHIP_CONTAINER = "Relationships"; const char* const RELS_RELATIONSHIP_CONTAINER = "Relationships";
static const std::string RELS_RELATIONSHIP_NODE = "Relationship"; const char* const RELS_RELATIONSHIP_NODE = "Relationship";
static const std::string RELS_ATTRIB_TARGET = "Target"; const char* const RELS_ATTRIB_TARGET = "Target";
static const std::string RELS_ATTRIB_TYPE = "Type"; const char* const RELS_ATTRIB_TYPE = "Type";
static const std::string RELS_ATTRIB_ID = "Id"; const char* const RELS_ATTRIB_ID = "Id";
static const std::string PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel"; const char* const PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel";
static const std::string PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket"; const char* const PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket";
static const std::string PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture"; const char* const PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
static const std::string PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; const char* const PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
static const std::string PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; const char* const PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
} }
} // Namespace D3MF } // Namespace D3MF
} // Namespace Assimp } // Namespace Assimp

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -237,7 +237,7 @@ void D3MFExporter::writeBaseMaterials() {
aiMaterial *mat = mScene->mMaterials[i]; aiMaterial *mat = mScene->mMaterials[i];
aiString name; aiString name;
if (mat->Get(AI_MATKEY_NAME, name) != aiReturn_SUCCESS) { if (mat->Get(AI_MATKEY_NAME, name) != aiReturn_SUCCESS) {
strName = "basemat_" + to_string(i); strName = "basemat_" + ai_to_string(i);
} else { } else {
strName = name.C_Str(); strName = name.C_Str();
} }
@ -248,7 +248,7 @@ void D3MFExporter::writeBaseMaterials() {
// rgbs % // rgbs %
if (color.r <= 1 && color.g <= 1 && color.b <= 1 && color.a <= 1) { if (color.r <= 1 && color.g <= 1 && color.b <= 1 && color.a <= 1) {
hexDiffuseColor = Rgba2Hex( hexDiffuseColor = ai_rgba2hex(
(int)((ai_real)color.r) * 255, (int)((ai_real)color.r) * 255,
(int)((ai_real)color.g) * 255, (int)((ai_real)color.g) * 255,
(int)((ai_real)color.b) * 255, (int)((ai_real)color.b) * 255,
@ -257,13 +257,13 @@ void D3MFExporter::writeBaseMaterials() {
} else { } else {
hexDiffuseColor = "#"; hexDiffuseColor = "#";
tmp = DecimalToHexa((ai_real)color.r); tmp = ai_decimal_to_hexa((ai_real)color.r);
hexDiffuseColor += tmp; hexDiffuseColor += tmp;
tmp = DecimalToHexa((ai_real)color.g); tmp = ai_decimal_to_hexa((ai_real)color.g);
hexDiffuseColor += tmp; hexDiffuseColor += tmp;
tmp = DecimalToHexa((ai_real)color.b); tmp = ai_decimal_to_hexa((ai_real)color.b);
hexDiffuseColor += tmp; hexDiffuseColor += tmp;
tmp = DecimalToHexa((ai_real)color.a); tmp = ai_decimal_to_hexa((ai_real)color.a);
hexDiffuseColor += tmp; hexDiffuseColor += tmp;
} }
} else { } else {
@ -307,18 +307,26 @@ void D3MFExporter::writeMesh(aiMesh *mesh) {
return; return;
} }
mModelOutput << "<" << XmlTag::mesh << ">" << std::endl; mModelOutput << "<"
mModelOutput << "<" << XmlTag::vertices << ">" << std::endl; << XmlTag::mesh
<< ">" << "\n";
mModelOutput << "<"
<< XmlTag::vertices
<< ">" << "\n";
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
writeVertex(mesh->mVertices[i]); writeVertex(mesh->mVertices[i]);
} }
mModelOutput << "</" << XmlTag::vertices << ">" << std::endl; mModelOutput << "</"
<< XmlTag::vertices << ">"
<< "\n";
const unsigned int matIdx(mesh->mMaterialIndex); const unsigned int matIdx(mesh->mMaterialIndex);
writeFaces(mesh, matIdx); writeFaces(mesh, matIdx);
mModelOutput << "</" << XmlTag::mesh << ">" << std::endl; mModelOutput << "</"
<< XmlTag::mesh << ">"
<< "\n";
} }
void D3MFExporter::writeVertex(const aiVector3D &pos) { void D3MFExporter::writeVertex(const aiVector3D &pos) {
@ -334,27 +342,34 @@ void D3MFExporter::writeFaces(aiMesh *mesh, unsigned int matIdx) {
if (!mesh->HasFaces()) { if (!mesh->HasFaces()) {
return; return;
} }
mModelOutput << "<" << XmlTag::triangles << ">" << std::endl; mModelOutput << "<"
<< XmlTag::triangles << ">"
<< "\n";
for (unsigned int i = 0; i < mesh->mNumFaces; ++i) { for (unsigned int i = 0; i < mesh->mNumFaces; ++i) {
aiFace &currentFace = mesh->mFaces[i]; aiFace &currentFace = mesh->mFaces[i];
mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[0] << "\" v2=\"" mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[0] << "\" v2=\""
<< currentFace.mIndices[1] << "\" v3=\"" << currentFace.mIndices[2] << currentFace.mIndices[1] << "\" v3=\"" << currentFace.mIndices[2]
<< "\" pid=\"1\" p1=\"" + to_string(matIdx) + "\" />"; << "\" pid=\"1\" p1=\"" + ai_to_string(matIdx) + "\" />";
mModelOutput << std::endl; mModelOutput << "\n";
} }
mModelOutput << "</" << XmlTag::triangles << ">"; mModelOutput << "</"
mModelOutput << std::endl; << XmlTag::triangles
<< ">";
mModelOutput << "\n";
} }
void D3MFExporter::writeBuild() { void D3MFExporter::writeBuild() {
mModelOutput << "<" << XmlTag::build << ">" << std::endl; mModelOutput << "<"
<< XmlTag::build
<< ">"
<< "\n";
for (size_t i = 0; i < mBuildItems.size(); ++i) { for (size_t i = 0; i < mBuildItems.size(); ++i) {
mModelOutput << "<" << XmlTag::item << " objectid=\"" << i + 2 << "\"/>"; mModelOutput << "<" << XmlTag::item << " objectid=\"" << i + 2 << "\"/>";
mModelOutput << std::endl; mModelOutput << "\n";
} }
mModelOutput << "</" << XmlTag::build << ">"; mModelOutput << "</" << XmlTag::build << ">";
mModelOutput << std::endl; mModelOutput << "\n";
} }
void D3MFExporter::zipContentType(const std::string &filename) { void D3MFExporter::zipContentType(const std::string &filename) {

View File

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

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -42,6 +42,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER #ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
#include "D3MFImporter.h" #include "D3MFImporter.h"
#include "3MFXmlTags.h"
#include "D3MFOpcPackage.h"
#include <assimp/StringComparison.h> #include <assimp/StringComparison.h>
#include <assimp/StringUtils.h> #include <assimp/StringUtils.h>
@ -51,17 +53,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/fast_atof.h>
#include <cassert> #include <cassert>
#include <map> #include <map>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include "3MFXmlTags.h"
#include "D3MFOpcPackage.h"
#include <assimp/fast_atof.h>
#include <iomanip> #include <iomanip>
#include <string.h>
namespace Assimp { namespace Assimp {
namespace D3MF { namespace D3MF {
@ -72,32 +72,39 @@ enum class ResourceType {
RT_Unknown RT_Unknown
}; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...) }; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...)
class Resource class Resource {
{
public: public:
Resource(int id) :
mId(id) {}
virtual ~Resource() {}
int mId; int mId;
virtual ResourceType getType() { Resource(int id) :
mId(id) {
// empty
}
virtual ~Resource() {
// empty
}
virtual ResourceType getType() const {
return ResourceType::RT_Unknown; return ResourceType::RT_Unknown;
} }
}; };
class BaseMaterials : public Resource { class BaseMaterials : public Resource {
public: public:
BaseMaterials(int id) :
Resource(id),
mMaterials(),
mMaterialIndex() {}
std::vector<aiMaterial *> mMaterials; std::vector<aiMaterial *> mMaterials;
std::vector<unsigned int> mMaterialIndex; std::vector<unsigned int> mMaterialIndex;
virtual ResourceType getType() { BaseMaterials(int id) :
Resource(id),
mMaterials(),
mMaterialIndex() {
// empty
}
~BaseMaterials() = default;
ResourceType getType() const override {
return ResourceType::RT_BaseMaterials; return ResourceType::RT_BaseMaterials;
} }
}; };
@ -109,24 +116,26 @@ struct Component {
class Object : public Resource { class Object : public Resource {
public: public:
std::vector<aiMesh*> mMeshes; std::vector<aiMesh *> mMeshes;
std::vector<unsigned int> mMeshIndex; std::vector<unsigned int> mMeshIndex;
std::vector<Component> mComponents; std::vector<Component> mComponents;
std::string mName; std::string mName;
Object(int id) : Object(int id) :
Resource(id), Resource(id),
mName (std::string("Object_") + to_string(id)){} mName(std::string("Object_") + ai_to_string(id)) {
// empty
}
virtual ResourceType getType() { ~Object() = default;
ResourceType getType() const override {
return ResourceType::RT_Object; return ResourceType::RT_Object;
} }
}; };
class XmlSerializer { class XmlSerializer {
public: public:
XmlSerializer(XmlParser *xmlParser) : XmlSerializer(XmlParser *xmlParser) :
mResourcesDictionnary(), mResourcesDictionnary(),
mMaterialCount(0), mMaterialCount(0),
@ -136,7 +145,7 @@ public:
} }
~XmlSerializer() { ~XmlSerializer() {
for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) { for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it ) {
delete it->second; delete it->second;
} }
} }
@ -146,28 +155,28 @@ public:
return; return;
} }
scene->mRootNode = new aiNode("3MF"); scene->mRootNode = new aiNode(XmlTag::RootTag);
XmlNode node = mXmlParser->getRootNode().child("model"); XmlNode node = mXmlParser->getRootNode().child(XmlTag::model);
if (node.empty()) { if (node.empty()) {
return; return;
} }
XmlNode resNode = node.child("resources"); XmlNode resNode = node.child(XmlTag::resources);
for (XmlNode currentNode = resNode.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (auto &currentNode : resNode.children()) {
const std::string &currentNodeName = currentNode.name(); const std::string currentNodeName = currentNode.name();
if (currentNodeName == D3MF::XmlTag::object) { if (currentNodeName == XmlTag::object) {
ReadObject(currentNode);; ReadObject(currentNode);
} else if (currentNodeName == D3MF::XmlTag::basematerials) { } else if (currentNodeName == XmlTag::basematerials) {
ReadBaseMaterials(currentNode); ReadBaseMaterials(currentNode);
} else if (currentNodeName == D3MF::XmlTag::meta) { } else if (currentNodeName == XmlTag::meta) {
ReadMetadata(currentNode); ReadMetadata(currentNode);
} }
} }
XmlNode buildNode = node.child("build"); XmlNode buildNode = node.child(XmlTag::build);
for (XmlNode currentNode = buildNode.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (auto &currentNode : buildNode.children()) {
const std::string &currentNodeName = currentNode.name(); const std::string currentNodeName = currentNode.name();
if (currentNodeName == D3MF::XmlTag::item) { if (currentNodeName == XmlTag::item) {
int objectId = -1; int objectId = -1;
std::string transformationMatrixStr; std::string transformationMatrixStr;
aiMatrix4x4 transformationMatrix; aiMatrix4x4 transformationMatrix;
@ -186,10 +195,9 @@ public:
} }
} }
// import the metadata // import the metadata
if (!mMetaData.empty()) { if (!mMetaData.empty()) {
const size_t numMeta(mMetaData.size()); const size_t numMeta = mMetaData.size();
scene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta)); scene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta));
for (size_t i = 0; i < numMeta; ++i) { for (size_t i = 0; i < numMeta; ++i) {
aiString val(mMetaData[i].value); aiString val(mMetaData[i].value);
@ -201,22 +209,22 @@ public:
scene->mNumMeshes = static_cast<unsigned int>(mMeshCount); scene->mNumMeshes = static_cast<unsigned int>(mMeshCount);
if (scene->mNumMeshes != 0) { if (scene->mNumMeshes != 0) {
scene->mMeshes = new aiMesh *[scene->mNumMeshes](); scene->mMeshes = new aiMesh *[scene->mNumMeshes]();
for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) { for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) {
if (it->second->getType() == ResourceType::RT_Object) { if (it->second->getType() == ResourceType::RT_Object) {
Object *obj = static_cast<Object*>(it->second); Object *obj = static_cast<Object *>(it->second);
ai_assert(nullptr != obj);
for (unsigned int i = 0; i < obj->mMeshes.size(); ++i) { for (unsigned int i = 0; i < obj->mMeshes.size(); ++i) {
scene->mMeshes[obj->mMeshIndex[i]] = obj->mMeshes[i]; scene->mMeshes[obj->mMeshIndex[i]] = obj->mMeshes[i];
} }
} }
} }
} }
// import the materials // import the materials
scene->mNumMaterials = static_cast<unsigned int>(mMaterialCount); scene->mNumMaterials = mMaterialCount;
if (scene->mNumMaterials != 0) { if (scene->mNumMaterials != 0) {
scene->mMaterials = new aiMaterial *[scene->mNumMaterials]; scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) { for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) {
if (it->second->getType() == ResourceType::RT_BaseMaterials) { if (it->second->getType() == ResourceType::RT_BaseMaterials) {
BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second); BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
for (unsigned int i = 0; i < baseMaterials->mMaterials.size(); ++i) { for (unsigned int i = 0; i < baseMaterials->mMaterials.size(); ++i) {
@ -228,35 +236,36 @@ public:
} }
private: private:
void addObjectToNode(aiNode *parent, Object *obj, aiMatrix4x4 nodeTransform) {
ai_assert(nullptr != obj);
void addObjectToNode(aiNode* parent, Object* obj, aiMatrix4x4 nodeTransform) {
aiNode *sceneNode = new aiNode(obj->mName); aiNode *sceneNode = new aiNode(obj->mName);
sceneNode->mNumMeshes = static_cast<unsigned int>(obj->mMeshes.size()); sceneNode->mNumMeshes = static_cast<unsigned int>(obj->mMeshes.size());
sceneNode->mMeshes = new unsigned int[sceneNode->mNumMeshes]; sceneNode->mMeshes = new unsigned int[sceneNode->mNumMeshes];
std::copy(obj->mMeshIndex.begin(), obj->mMeshIndex.end(), sceneNode->mMeshes); std::copy(obj->mMeshIndex.begin(), obj->mMeshIndex.end(), sceneNode->mMeshes);
sceneNode->mTransformation = nodeTransform; sceneNode->mTransformation = nodeTransform;
if (nullptr != parent) {
parent->addChildren(1, &sceneNode); parent->addChildren(1, &sceneNode);
}
for (size_t i = 0; i < obj->mComponents.size(); ++i) { for (size_t i = 0; i < obj->mComponents.size(); ++i) {
Component c = obj->mComponents[i]; Component c = obj->mComponents[i];
auto it = mResourcesDictionnary.find(c.mObjectId); auto it = mResourcesDictionnary.find(c.mObjectId);
if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) { if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
addObjectToNode(sceneNode, static_cast<Object*>(it->second), c.mTransformation); addObjectToNode(sceneNode, static_cast<Object *>(it->second), c.mTransformation);
} }
} }
} }
bool getNodeAttribute(const XmlNode& node, const std::string& attribute, std::string& value) { bool getNodeAttribute(const XmlNode &node, const std::string &attribute, std::string &value) {
pugi::xml_attribute objectAttribute = node.attribute(attribute.c_str()); pugi::xml_attribute objectAttribute = node.attribute(attribute.c_str());
if (!objectAttribute.empty()) { if (!objectAttribute.empty()) {
value = objectAttribute.as_string(); value = objectAttribute.as_string();
return true; return true;
} else {
return false;
} }
return false;
} }
bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &value) { bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &value) {
@ -265,9 +274,9 @@ private:
if (ret) { if (ret) {
value = std::atoi(strValue.c_str()); value = std::atoi(strValue.c_str());
return true; return true;
} else { }
return false;
} return false;
} }
aiMatrix4x4 parseTransformMatrix(std::string matrixStr) { aiMatrix4x4 parseTransformMatrix(std::string matrixStr) {
@ -287,7 +296,7 @@ private:
} }
} }
if (currentNumber.size() > 0) { if (currentNumber.size() > 0) {
float f = std::stof(currentNumber); const float f = std::stof(currentNumber);
numbers.push_back(f); numbers.push_back(f);
} }
@ -311,29 +320,26 @@ private:
transformMatrix.b4 = numbers[10]; transformMatrix.b4 = numbers[10];
transformMatrix.c4 = numbers[11]; transformMatrix.c4 = numbers[11];
transformMatrix.d4 = 1; transformMatrix.d4 = 1;
return transformMatrix; return transformMatrix;
} }
void ReadObject(XmlNode &node) { void ReadObject(XmlNode &node) {
int id = -1, pid = -1, pindex = -1; int id = -1, pid = -1, pindex = -1;
bool hasId = getNodeAttribute(node, D3MF::XmlTag::id, id); bool hasId = getNodeAttribute(node, XmlTag::id, id);
//bool hasType = getNodeAttribute(node, D3MF::XmlTag::type, type); not used currently bool hasPid = getNodeAttribute(node, XmlTag::pid, pid);
bool hasPid = getNodeAttribute(node, D3MF::XmlTag::pid, pid); bool hasPindex = getNodeAttribute(node, XmlTag::pindex, pindex);
bool hasPindex = getNodeAttribute(node, D3MF::XmlTag::pindex, pindex);
std::string idStr = to_string(id);
if (!hasId) { if (!hasId) {
return; return;
} }
Object *obj = new Object(id); Object *obj = new Object(id);
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == D3MF::XmlTag::mesh) { if (currentName == D3MF::XmlTag::mesh) {
auto mesh = ReadMesh(currentNode); auto mesh = ReadMesh(currentNode);
mesh->mName.Set(idStr); mesh->mName.Set(ai_to_string(id));
if (hasPid) { if (hasPid) {
auto it = mResourcesDictionnary.find(pid); auto it = mResourcesDictionnary.find(pid);
@ -347,8 +353,9 @@ private:
obj->mMeshIndex.push_back(mMeshCount); obj->mMeshIndex.push_back(mMeshCount);
mMeshCount++; mMeshCount++;
} else if (currentName == D3MF::XmlTag::components) { } else if (currentName == D3MF::XmlTag::components) {
for (XmlNode currentSubNode = currentNode.first_child(); currentSubNode; currentSubNode = currentSubNode.next_sibling()) { for (XmlNode &currentSubNode : currentNode.children()) {
if (currentSubNode.name() == D3MF::XmlTag::component) { const std::string subNodeName = currentSubNode.name();
if (subNodeName == D3MF::XmlTag::component) {
int objectId = -1; int objectId = -1;
std::string componentTransformStr; std::string componentTransformStr;
aiMatrix4x4 componentTransform; aiMatrix4x4 componentTransform;
@ -356,8 +363,9 @@ private:
componentTransform = parseTransformMatrix(componentTransformStr); componentTransform = parseTransformMatrix(componentTransformStr);
} }
if (getNodeAttribute(currentSubNode, D3MF::XmlTag::objectid, objectId)) if (getNodeAttribute(currentSubNode, D3MF::XmlTag::objectid, objectId)) {
obj->mComponents.push_back({ objectId, componentTransform }); obj->mComponents.push_back({ objectId, componentTransform });
}
} }
} }
} }
@ -369,21 +377,20 @@ private:
aiMesh *ReadMesh(XmlNode &node) { aiMesh *ReadMesh(XmlNode &node) {
aiMesh *mesh = new aiMesh(); aiMesh *mesh = new aiMesh();
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string currentName = currentNode.name();
if (currentName == D3MF::XmlTag::vertices) { if (currentName == XmlTag::vertices) {
ImportVertices(currentNode, mesh); ImportVertices(currentNode, mesh);
} else if (currentName == D3MF::XmlTag::triangles) { } else if (currentName == XmlTag::triangles) {
ImportTriangles(currentNode, mesh); ImportTriangles(currentNode, mesh);
} }
} }
return mesh; return mesh;
} }
void ReadMetadata(XmlNode &node) { void ReadMetadata(XmlNode &node) {
pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name.c_str()); pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name);
const std::string name = attribute.as_string(); const std::string name = attribute.as_string();
const std::string value = node.value(); const std::string value = node.value();
if (name.empty()) { if (name.empty()) {
@ -398,9 +405,9 @@ private:
void ImportVertices(XmlNode &node, aiMesh *mesh) { void ImportVertices(XmlNode &node, aiMesh *mesh) {
std::vector<aiVector3D> vertices; std::vector<aiVector3D> vertices;
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string currentName = currentNode.name();
if (currentName == D3MF::XmlTag::vertex) { if (currentName == XmlTag::vertex) {
vertices.push_back(ReadVertex(currentNode)); vertices.push_back(ReadVertex(currentNode));
} }
} }
@ -412,29 +419,28 @@ private:
aiVector3D ReadVertex(XmlNode &node) { aiVector3D ReadVertex(XmlNode &node) {
aiVector3D vertex; aiVector3D vertex;
vertex.x = ai_strtof(node.attribute(D3MF::XmlTag::x.c_str()).as_string(), nullptr); vertex.x = ai_strtof(node.attribute(XmlTag::x).as_string(), nullptr);
vertex.y = ai_strtof(node.attribute(D3MF::XmlTag::y.c_str()).as_string(), nullptr); vertex.y = ai_strtof(node.attribute(XmlTag::y).as_string(), nullptr);
vertex.z = ai_strtof(node.attribute(D3MF::XmlTag::z.c_str()).as_string(), nullptr); vertex.z = ai_strtof(node.attribute(XmlTag::z).as_string(), nullptr);
return vertex; return vertex;
} }
void ImportTriangles(XmlNode &node, aiMesh *mesh) { void ImportTriangles(XmlNode &node, aiMesh *mesh) {
std::vector<aiFace> faces; std::vector<aiFace> faces;
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string currentName = currentNode.name();
if (currentName == D3MF::XmlTag::triangle) { if (currentName == XmlTag::triangle) {
aiFace face = ReadTriangle(currentNode); aiFace face = ReadTriangle(currentNode);
faces.push_back(face); faces.push_back(face);
int pid, p1; int pid = 0, p1 = 0;
bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid); bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1); bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1);
if (hasPid && hasP1) { if (hasPid && hasP1) {
auto it = mResourcesDictionnary.find(pid); auto it = mResourcesDictionnary.find(pid);
if (it != mResourcesDictionnary.end()) if (it != mResourcesDictionnary.end()) {
{
if (it->second->getType() == ResourceType::RT_BaseMaterials) { if (it->second->getType() == ResourceType::RT_BaseMaterials) {
BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second); BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1]; mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
@ -457,9 +463,9 @@ private:
face.mNumIndices = 3; face.mNumIndices = 3;
face.mIndices = new unsigned int[face.mNumIndices]; face.mIndices = new unsigned int[face.mNumIndices];
face.mIndices[0] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v1.c_str()).as_string())); 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(D3MF::XmlTag::v2.c_str()).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(D3MF::XmlTag::v3.c_str()).as_string())); face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string()));
return face; return face;
} }
@ -467,14 +473,14 @@ private:
void ReadBaseMaterials(XmlNode &node) { void ReadBaseMaterials(XmlNode &node) {
int id = -1; int id = -1;
if (getNodeAttribute(node, D3MF::XmlTag::basematerials_id, id)) { if (getNodeAttribute(node, D3MF::XmlTag::basematerials_id, id)) {
BaseMaterials* baseMaterials = new BaseMaterials(id); BaseMaterials *baseMaterials = new BaseMaterials(id);
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) for (XmlNode &currentNode : node.children()) {
{ const std::string currentName = currentNode.name();
if (currentNode.name() == D3MF::XmlTag::basematerials_base) { if (currentName == XmlTag::basematerials_base) {
baseMaterials->mMaterialIndex.push_back(mMaterialCount); baseMaterials->mMaterialIndex.push_back(mMaterialCount);
baseMaterials->mMaterials.push_back(readMaterialDef(currentNode, id)); baseMaterials->mMaterials.push_back(readMaterialDef(currentNode, id));
mMaterialCount++; ++mMaterialCount;
} }
} }
@ -488,7 +494,7 @@ private:
} }
//format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1) //format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1)
const size_t len(strlen(color)); const size_t len = strlen(color);
if (9 != len && 7 != len) { if (9 != len && 7 != len) {
return false; return false;
} }
@ -517,7 +523,7 @@ private:
} }
void assignDiffuseColor(XmlNode &node, aiMaterial *mat) { void assignDiffuseColor(XmlNode &node, aiMaterial *mat) {
const char *color = node.attribute(D3MF::XmlTag::basematerials_displaycolor.c_str()).as_string(); const char *color = node.attribute(XmlTag::basematerials_displaycolor).as_string();
aiColor4D diffuse; aiColor4D diffuse;
if (parseColor(color, diffuse)) { if (parseColor(color, diffuse)) {
mat->AddProperty<aiColor4D>(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE); mat->AddProperty<aiColor4D>(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
@ -531,7 +537,7 @@ private:
bool hasName = getNodeAttribute(node, D3MF::XmlTag::basematerials_name, name); bool hasName = getNodeAttribute(node, D3MF::XmlTag::basematerials_name, name);
std::string stdMaterialName; std::string stdMaterialName;
std::string strId(to_string(basematerialsId)); const std::string strId(ai_to_string(basematerialsId));
stdMaterialName += "id"; stdMaterialName += "id";
stdMaterialName += strId; stdMaterialName += strId;
stdMaterialName += "_"; stdMaterialName += "_";
@ -539,7 +545,7 @@ private:
stdMaterialName += std::string(name); stdMaterialName += std::string(name);
} else { } else {
stdMaterialName += "basemat_"; stdMaterialName += "basemat_";
stdMaterialName += to_string(mMaterialCount - basematerialsId); stdMaterialName += ai_to_string(mMaterialCount - basematerialsId);
} }
aiString assimpMaterialName(stdMaterialName); aiString assimpMaterialName(stdMaterialName);
@ -556,13 +562,15 @@ private:
std::string value; std::string value;
}; };
std::vector<MetaEntry> mMetaData; std::vector<MetaEntry> mMetaData;
std::map<unsigned int, Resource*> mResourcesDictionnary; std::map<unsigned int, Resource *> mResourcesDictionnary;
unsigned int mMaterialCount, mMeshCount; unsigned int mMaterialCount, mMeshCount;
XmlParser *mXmlParser; XmlParser *mXmlParser;
}; };
} //namespace D3MF } //namespace D3MF
using namespace D3MF;
static const aiImporterDesc desc = { static const aiImporterDesc desc = {
"3mf Importer", "3mf Importer",
"", "",
@ -596,7 +604,7 @@ bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bo
if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) { if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) {
return false; return false;
} }
D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename); D3MFOpcPackage opcPackage(pIOHandler, filename);
return opcPackage.validate(); return opcPackage.validate();
} }
@ -612,11 +620,11 @@ const aiImporterDesc *D3MFImporter::GetInfo() const {
} }
void D3MFImporter::InternReadFile(const std::string &filename, aiScene *pScene, IOSystem *pIOHandler) { void D3MFImporter::InternReadFile(const std::string &filename, aiScene *pScene, IOSystem *pIOHandler) {
D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename); D3MFOpcPackage opcPackage(pIOHandler, filename);
XmlParser xmlParser; XmlParser xmlParser;
if (xmlParser.parse(opcPackage.RootStream())) { if (xmlParser.parse(opcPackage.RootStream())) {
D3MF::XmlSerializer xmlSerializer(&xmlParser); XmlSerializer xmlSerializer(&xmlParser);
xmlSerializer.ImportXml(pScene); xmlSerializer.ImportXml(pScene);
} }
} }

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -47,9 +47,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
/// @brief The 3MF-importer class.
class D3MFImporter : public BaseImporter { class D3MFImporter : public BaseImporter {
public: public:
// BaseImporter interface
D3MFImporter(); D3MFImporter();
~D3MFImporter(); ~D3MFImporter();
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const; bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const;

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -103,9 +103,9 @@ public:
std::string name = currentNode.name(); std::string name = currentNode.name();
if (name == "Relationship") { if (name == "Relationship") {
OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship()); OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship());
relPtr->id = currentNode.attribute(XmlTag::RELS_ATTRIB_ID.c_str()).as_string(); relPtr->id = currentNode.attribute(XmlTag::RELS_ATTRIB_ID).as_string();
relPtr->type = currentNode.attribute(XmlTag::RELS_ATTRIB_TYPE.c_str()).as_string(); relPtr->type = currentNode.attribute(XmlTag::RELS_ATTRIB_TYPE).as_string();
relPtr->target = currentNode.attribute(XmlTag::RELS_ATTRIB_TARGET.c_str()).as_string(); relPtr->target = currentNode.attribute(XmlTag::RELS_ATTRIB_TARGET).as_string();
if (validateRels(relPtr)) { if (validateRels(relPtr)) {
m_relationShips.push_back(relPtr); m_relationShips.push_back(relPtr);
} }
@ -156,7 +156,7 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
mRootStream = mZipArchive->Open(rootFile.c_str()); mRootStream = mZipArchive->Open(rootFile.c_str());
ai_assert(mRootStream != nullptr); ai_assert(mRootStream != nullptr);
if (nullptr == mRootStream) { if (nullptr == mRootStream) {
throw DeadlyExportError("Cannot open root-file in archive : " + rootFile); throw DeadlyImportError("Cannot open root-file in archive : " + rootFile);
} }
} else if (file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) { } else if (file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) {
@ -188,7 +188,7 @@ bool D3MFOpcPackage::validate() {
std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) { std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
XmlParser xmlParser; XmlParser xmlParser;
if (!xmlParser.parse(stream)) { if (!xmlParser.parse(stream)) {
return ""; return std::string();
} }
OpcPackageRelationshipReader reader(xmlParser); OpcPackageRelationshipReader reader(xmlParser);

View File

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

View File

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

View File

@ -2,8 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -117,16 +116,16 @@ public:
Mask = 0xf, Mask = 0xf,
}; };
inline constexpr uint8_t GetType() const { return (flags & Mask); } inline uint8_t GetType() const { return (flags & Mask); }
}; };
// Represents an AC3D object // Represents an AC3D object
struct Object { struct Object {
Object() : Object() :
type(World), type(World),
name(""), name(),
children(), children(),
texture(""), texture(),
texRepeat(1.f, 1.f), texRepeat(1.f, 1.f),
texOffset(0.0f, 0.0f), texOffset(0.0f, 0.0f),
rotation(), rotation(),

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -39,19 +39,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
*/ */
/// \file AMFImporter.cpp
/// \brief AMF-format files importer for Assimp: main algorithm implementation.
/// \date 2016
/// \author smal.root@gmail.com
#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER #ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
// Header files, Assimp. // Header files, Assimp.
#include "AMFImporter.hpp" #include "AMFImporter.hpp"
#include "AMFImporter_Macro.hpp"
#include <assimp/DefaultIOSystem.h> #include <assimp/DefaultIOSystem.h>
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
#include <assimp/StringUtils.h>
// Header files, stdlib. // Header files, stdlib.
#include <memory> #include <memory>
@ -306,13 +301,14 @@ void AMFImporter::ParseNode_Root() {
throw DeadlyImportError("Root node \"amf\" not found."); throw DeadlyImportError("Root node \"amf\" not found.");
} }
XmlNode node = *root; XmlNode node = *root;
mUnit = node.attribute("unit").as_string(); mUnit = ai_tolower(std::string(node.attribute("unit").as_string()));
mVersion = node.attribute("version").as_string(); mVersion = node.attribute("version").as_string();
// Read attributes for node <amf>. // Read attributes for node <amf>.
// Check attributes // Check attributes
if (!mUnit.empty()) { if (!mUnit.empty()) {
if ((mUnit != "inch") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) { if ((mUnit != "inch") && (mUnit != "millimeters") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) {
Throw_IncorrectAttrValue("unit", mUnit); Throw_IncorrectAttrValue("unit", mUnit);
} }
} }
@ -407,20 +403,20 @@ void AMFImporter::ParseNode_Instance(XmlNode &node) {
if (!node.empty()) { if (!node.empty()) {
ParseHelper_Node_Enter(ne); ParseHelper_Node_Enter(ne);
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (auto &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "deltax") { if (currentName == "deltax") {
als.Delta.x = (ai_real)std::atof(currentNode.value()); XmlParser::getValueAsFloat(currentNode, als.Delta.x);
} else if (currentName == "deltay") { } else if (currentName == "deltay") {
als.Delta.y = (ai_real)std::atof(currentNode.value()); XmlParser::getValueAsFloat(currentNode, als.Delta.y);
} else if (currentName == "deltaz") { } else if (currentName == "deltaz") {
als.Delta.z = (ai_real)std::atof(currentNode.value()); XmlParser::getValueAsFloat(currentNode, als.Delta.z);
} else if (currentName == "rx") { } else if (currentName == "rx") {
als.Delta.x = (ai_real)std::atof(currentNode.value()); XmlParser::getValueAsFloat(currentNode, als.Delta.x);
} else if (currentName == "ry") { } else if (currentName == "ry") {
als.Delta.y = (ai_real)std::atof(currentNode.value()); XmlParser::getValueAsFloat(currentNode, als.Delta.y);
} else if (currentName == "rz") { } else if (currentName == "rz") {
als.Delta.z = (ai_real)std::atof(currentNode.value()); XmlParser::getValueAsFloat(currentNode, als.Delta.z);
} }
} }
ParseHelper_Node_Exit(); ParseHelper_Node_Exit();
@ -456,7 +452,7 @@ void AMFImporter::ParseNode_Object(XmlNode &node) {
// Check for child nodes // Check for child nodes
if (!node.empty()) { if (!node.empty()) {
ParseHelper_Node_Enter(ne); ParseHelper_Node_Enter(ne);
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (auto &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "color") { if (currentName == "color") {
ParseNode_Color(currentNode); ParseNode_Color(currentNode);
@ -521,10 +517,6 @@ bool AMFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool p
return false; return false;
} }
void AMFImporter::GetExtensionList(std::set<std::string> &pExtensionList) {
pExtensionList.insert("amf");
}
const aiImporterDesc *AMFImporter::GetInfo() const { const aiImporterDesc *AMFImporter::GetInfo() const {
return &Description; return &Description;
} }

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -277,7 +277,6 @@ public:
void ParseHelper_Node_Enter(AMFNodeElementBase *child); void ParseHelper_Node_Enter(AMFNodeElementBase *child);
void ParseHelper_Node_Exit(); void ParseHelper_Node_Exit();
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const; bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const;
void GetExtensionList(std::set<std::string> &pExtensionList);
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler); void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
const aiImporterDesc *GetInfo() const; const aiImporterDesc *GetInfo() const;
bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const; bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const;

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -39,16 +39,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
*/ */
/// \file AMFImporter_Geometry.cpp
/// \brief Parsing data from geometry nodes.
/// \date 2016
/// \author smal.root@gmail.com
#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER #ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
#include "AMFImporter.hpp" #include "AMFImporter.hpp"
#include "AMFImporter_Macro.hpp"
#include <assimp/ParsingUtils.h> #include <assimp/ParsingUtils.h>
namespace Assimp { namespace Assimp {
@ -61,12 +54,12 @@ namespace Assimp {
void AMFImporter::ParseNode_Mesh(XmlNode &node) { void AMFImporter::ParseNode_Mesh(XmlNode &node) {
AMFNodeElementBase *ne = nullptr; AMFNodeElementBase *ne = nullptr;
// create new mesh object.
ne = new AMFMesh(mNodeElement_Cur);
// Check for child nodes // Check for child nodes
if (0 != ASSIMP_stricmp(node.name(), "mesh")) { if (0 != ASSIMP_stricmp(node.name(), "mesh")) {
return; return;
} }
// create new mesh object.
ne = new AMFMesh(mNodeElement_Cur);
bool found_verts = false, found_volumes = false; bool found_verts = false, found_volumes = false;
if (!node.empty()) { if (!node.empty()) {
ParseHelper_Node_Enter(ne); ParseHelper_Node_Enter(ne);
@ -103,18 +96,18 @@ void AMFImporter::ParseNode_Vertices(XmlNode &node) {
// create new mesh object. // create new mesh object.
ne = new AMFVertices(mNodeElement_Cur); ne = new AMFVertices(mNodeElement_Cur);
// Check for child nodes // Check for child nodes
pugi::xml_node vertexNode = node.child("vertex"); if (node.empty()) {
if (!vertexNode.empty()) {
ParseHelper_Node_Enter(ne);
ParseNode_Vertex(vertexNode);
ParseHelper_Node_Exit();
} else {
mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element mNodeElement_Cur->Child.push_back(ne); // Add element to child list of current element
} // if(!mReader->isEmptyElement()) else return;
}
ParseHelper_Node_Enter(ne);
for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (currentName == "vertex") {
ParseNode_Vertex(currentNode);
}
}
ParseHelper_Node_Exit();
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
} }
@ -166,27 +159,25 @@ void AMFImporter::ParseNode_Vertex(XmlNode &node) {
// X, Y, or Z coordinate, respectively, of a vertex position in space. // X, Y, or Z coordinate, respectively, of a vertex position in space.
void AMFImporter::ParseNode_Coordinates(XmlNode &node) { void AMFImporter::ParseNode_Coordinates(XmlNode &node) {
AMFNodeElementBase *ne = nullptr; AMFNodeElementBase *ne = nullptr;
// create new color object.
ne = new AMFCoordinates(mNodeElement_Cur);
AMFCoordinates &als = *((AMFCoordinates *)ne); // alias for convenience
if (!node.empty()) { if (!node.empty()) {
ne = new AMFCoordinates(mNodeElement_Cur);
ParseHelper_Node_Enter(ne); ParseHelper_Node_Enter(ne);
for (XmlNode &currentNode : node.children()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); // create new color object.
if (currentName == "X") { AMFCoordinates &als = *((AMFCoordinates *)ne); // alias for convenience
const std::string &currentName = ai_tolower(currentNode.name());
if (currentName == "x") {
XmlParser::getValueAsFloat(currentNode, als.Coordinate.x); XmlParser::getValueAsFloat(currentNode, als.Coordinate.x);
} else if (currentName == "Y") { } else if (currentName == "y") {
XmlParser::getValueAsFloat(currentNode, als.Coordinate.y); XmlParser::getValueAsFloat(currentNode, als.Coordinate.y);
} else if (currentName == "Z") { } else if (currentName == "z") {
XmlParser::getValueAsFloat(currentNode, als.Coordinate.z); XmlParser::getValueAsFloat(currentNode, als.Coordinate.z);
} }
} }
ParseHelper_Node_Exit(); ParseHelper_Node_Exit();
} else { } else {
mNodeElement_Cur->Child.push_back(ne); mNodeElement_Cur->Child.push_back(new AMFCoordinates(mNodeElement_Cur));
} }
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph. mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
@ -194,7 +185,7 @@ void AMFImporter::ParseNode_Coordinates(XmlNode &node) {
// <volume // <volume
// materialid="" - Which material to use. // materialid="" - Which material to use.
// type="" - What this volume describes can be “region” or “support”. If none specified, “object” is assumed. If support, then the geometric // type="" - What this volume describes can be "region" or "support". If none specified, "object" is assumed. If support, then the geometric
// requirements 1-8 listed in section 5 do not need to be maintained. // requirements 1-8 listed in section 5 do not need to be maintained.
// > // >
// </volume> // </volume>
@ -216,7 +207,7 @@ void AMFImporter::ParseNode_Volume(XmlNode &node) {
bool col_read = false; bool col_read = false;
if (!node.empty()) { if (!node.empty()) {
ParseHelper_Node_Enter(ne); ParseHelper_Node_Enter(ne);
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (auto &currentNode : node.children()) {
const std::string currentName = currentNode.name(); const std::string currentName = currentNode.name();
if (currentName == "color") { if (currentName == "color") {
if (col_read) Throw_MoreThanOnceDefined(currentName, "color", "Only one color can be defined for <volume>."); if (col_read) Throw_MoreThanOnceDefined(currentName, "color", "Only one color can be defined for <volume>.");
@ -258,7 +249,8 @@ void AMFImporter::ParseNode_Triangle(XmlNode &node) {
bool col_read = false; bool col_read = false;
if (!node.empty()) { if (!node.empty()) {
ParseHelper_Node_Enter(ne); ParseHelper_Node_Enter(ne);
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { std::string v;
for (auto &currentNode : node.children()) {
const std::string currentName = currentNode.name(); const std::string currentName = currentNode.name();
if (currentName == "color") { if (currentName == "color") {
if (col_read) Throw_MoreThanOnceDefined(currentName, "color", "Only one color can be defined for <triangle>."); if (col_read) Throw_MoreThanOnceDefined(currentName, "color", "Only one color can be defined for <triangle>.");
@ -269,11 +261,14 @@ void AMFImporter::ParseNode_Triangle(XmlNode &node) {
} else if (currentName == "map") { } else if (currentName == "map") {
ParseNode_TexMap(currentNode, true); ParseNode_TexMap(currentNode, true);
} else if (currentName == "v1") { } else if (currentName == "v1") {
als.V[0] = std::atoi(currentNode.value()); XmlParser::getValueAsString(currentNode, v);
als.V[0] = std::atoi(v.c_str());
} else if (currentName == "v2") { } else if (currentName == "v2") {
als.V[1] = std::atoi(currentNode.value()); XmlParser::getValueAsString(currentNode, v);
als.V[1] = std::atoi(v.c_str());
} else if (currentName == "v3") { } else if (currentName == "v3") {
als.V[2] = std::atoi(currentNode.value()); XmlParser::getValueAsString(currentNode, v);
als.V[2] = std::atoi(v.c_str());
} }
} }
ParseHelper_Node_Exit(); ParseHelper_Node_Exit();

View File

@ -1,164 +0,0 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/// \file AMFImporter_Macro.hpp
/// \brief Useful macrodefines.
/// \date 2016
/// \author smal.root@gmail.com
#pragma once
#ifndef AMFIMPORTER_MACRO_HPP_INCLUDED
#define AMFIMPORTER_MACRO_HPP_INCLUDED
/// \def MACRO_ATTRREAD_LOOPBEG
/// Begin of loop that read attributes values.
#define MACRO_ATTRREAD_LOOPBEG \
for(int idx = 0, idx_end = mReader->getAttributeCount(); idx < idx_end; idx++) \
{ \
std::string an(mReader->getAttributeName(idx));
/// \def MACRO_ATTRREAD_LOOPEND
/// End of loop that read attributes values.
#define MACRO_ATTRREAD_LOOPEND \
Throw_IncorrectAttr(an); \
}
/// \def MACRO_ATTRREAD_LOOPEND_WSKIP
/// End of loop that read attributes values. Difference from \ref MACRO_ATTRREAD_LOOPEND in that: current macro skip unknown attributes, but
/// \ref MACRO_ATTRREAD_LOOPEND throw an exception.
#define MACRO_ATTRREAD_LOOPEND_WSKIP \
continue; \
}
/// \def MACRO_ATTRREAD_CHECK_REF
/// Check current attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then
/// "continue" will called.
/// \param [in] pAttrName - attribute name.
/// \param [out] pVarName - output variable name.
/// \param [in] pFunction - function which read attribute value and write it to pVarName.
#define MACRO_ATTRREAD_CHECK_REF(pAttrName, pVarName, pFunction) \
if(an == pAttrName) \
{ \
pFunction(idx, pVarName); \
continue; \
}
/// \def MACRO_ATTRREAD_CHECK_RET
/// Check current attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction.
/// If result was read then "continue" will called.
/// \param [in] pAttrName - attribute name.
/// \param [out] pVarName - output variable name.
/// \param [in] pFunction - function which read attribute value and write it to pVarName.
#define MACRO_ATTRREAD_CHECK_RET(pAttrName, pVarName, pFunction) \
if(an == pAttrName) \
{ \
pVarName = pFunction(idx); \
continue; \
}
/// \def MACRO_NODECHECK_LOOPBEGIN(pNodeName)
/// Begin of loop of parsing child nodes. Do not add ';' at end.
/// \param [in] pNodeName - current node name.
#define MACRO_NODECHECK_LOOPBEGIN(pNodeName) \
do { \
bool close_found = false; \
\
while(mReader->read()) \
{ \
if(mReader->getNodeType() == irr::io::EXN_ELEMENT) \
{
/// \def MACRO_NODECHECK_LOOPEND(pNodeName)
/// End of loop of parsing child nodes.
/// \param [in] pNodeName - current node name.
#define MACRO_NODECHECK_LOOPEND(pNodeName) \
XML_CheckNode_SkipUnsupported(pNodeName); \
}/* if(mReader->getNodeType() == irr::io::EXN_ELEMENT) */ \
else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) \
{ \
if(XML_CheckNode_NameEqual(pNodeName)) \
{ \
close_found = true; \
\
break; \
} \
}/* else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) */ \
}/* while(mReader->read()) */ \
\
if(!close_found) Throw_CloseNotFound(pNodeName); \
\
} while(false)
/// \def MACRO_NODECHECK_READCOMP_F
/// Check current node name and if it equal to requested then read value. Result write to output variable of type "float".
/// If result was read then "continue" will called. Also check if node data already read then raise exception.
/// \param [in] pNodeName - node name.
/// \param [in, out] pReadFlag - read flag.
/// \param [out] pVarName - output variable name.
#define MACRO_NODECHECK_READCOMP_F(pNodeName, pReadFlag, pVarName) \
if(XML_CheckNode_NameEqual(pNodeName)) \
{ \
/* Check if field already read before. */ \
if(pReadFlag) Throw_MoreThanOnceDefined(pNodeName, "Only one component can be defined."); \
/* Read color component and assign it to object. */ \
pVarName = XML_ReadNode_GetVal_AsFloat(); \
pReadFlag = true; \
continue; \
}
/// \def MACRO_NODECHECK_READCOMP_U32
/// Check current node name and if it equal to requested then read value. Result write to output variable of type "uint32_t".
/// If result was read then "continue" will called. Also check if node data already read then raise exception.
/// \param [in] pNodeName - node name.
/// \param [in, out] pReadFlag - read flag.
/// \param [out] pVarName - output variable name.
#define MACRO_NODECHECK_READCOMP_U32(pNodeName, pReadFlag, pVarName) \
if(XML_CheckNode_NameEqual(pNodeName)) \
{ \
/* Check if field already read before. */ \
if(pReadFlag) Throw_MoreThanOnceDefined(pNodeName, "Only one component can be defined."); \
/* Read color component and assign it to object. */ \
pVarName = XML_ReadNode_GetVal_AsU32(); \
pReadFlag = true; \
continue; \
}
#endif // AMFIMPORTER_MACRO_HPP_INCLUDED

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -65,48 +65,45 @@ namespace Assimp {
// Red, Greed, Blue and Alpha (transparency) component of a color in sRGB space, values ranging from 0 to 1. The // Red, Greed, Blue and Alpha (transparency) component of a color in sRGB space, values ranging from 0 to 1. The
// values can be specified as constants, or as a formula depending on the coordinates. // values can be specified as constants, or as a formula depending on the coordinates.
void AMFImporter::ParseNode_Color(XmlNode &node) { void AMFImporter::ParseNode_Color(XmlNode &node) {
std::string profile = node.attribute("profile").as_string(); if (node.empty()) {
return;
// create new color object. }
AMFNodeElementBase *ne = new AMFColor(mNodeElement_Cur);
AMFColor& als = *((AMFColor*)ne);// alias for convenience
als.Profile = profile; const std::string &profile = node.attribute("profile").as_string();
if (!node.empty()) { bool read_flag[4] = { false, false, false, false };
ParseHelper_Node_Enter(ne); AMFNodeElementBase *ne = new AMFColor(mNodeElement_Cur);
bool read_flag[4] = { false, false, false, false }; AMFColor &als = *((AMFColor *)ne); // alias for convenience
for (pugi::xml_node &child : node.children()) { ParseHelper_Node_Enter(ne);
std::string name = child.name(); for (pugi::xml_node &child : node.children()) {
if ( name == "r") { // create new color object.
read_flag[0] = true; als.Profile = profile;
XmlParser::getValueAsFloat(child, als.Color.r);
} else if (name == "g") { const std::string &name = child.name();
read_flag[1] = true; if ( name == "r") {
XmlParser::getValueAsFloat(child, als.Color.g); read_flag[0] = true;
} else if (name == "b") { XmlParser::getValueAsFloat(child, als.Color.r);
read_flag[2] = true; } else if (name == "g") {
XmlParser::getValueAsFloat(child, als.Color.b); read_flag[1] = true;
} else if (name == "a") { XmlParser::getValueAsFloat(child, als.Color.g);
read_flag[3] = true; } else if (name == "b") {
XmlParser::getValueAsFloat(child, als.Color.a); read_flag[2] = true;
} XmlParser::getValueAsFloat(child, als.Color.b);
ParseHelper_Node_Exit(); } else if (name == "a") {
read_flag[3] = true;
XmlParser::getValueAsFloat(child, als.Color.a);
} }
// check that all components was defined // check if <a> is absent. Then manually add "a == 1".
if (!(read_flag[0] && read_flag[1] && read_flag[2])) { if (!read_flag[3]) {
throw DeadlyImportError("Not all color components are defined."); als.Color.a = 1;
} }
}
// check if <a> is absent. Then manually add "a == 1". als.Composed = false;
if (!read_flag[3]) { mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
als.Color.a = 1; ParseHelper_Node_Exit();
} // check that all components was defined
} else { if (!(read_flag[0] && read_flag[1] && read_flag[2])) {
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element throw DeadlyImportError("Not all color components are defined.");
} }
als.Composed = false;
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
} }
// <material // <material
@ -158,38 +155,36 @@ void AMFImporter::ParseNode_Material(XmlNode &node) {
// Multi elements - Yes. // Multi elements - Yes.
// Parent element - <amf>. // Parent element - <amf>.
void AMFImporter::ParseNode_Texture(XmlNode &node) { void AMFImporter::ParseNode_Texture(XmlNode &node) {
std::string id = node.attribute("id").as_string(); const std::string id = node.attribute("id").as_string();
uint32_t width = node.attribute("width").as_uint(); const uint32_t width = node.attribute("width").as_uint();
uint32_t height = node.attribute("height").as_uint(); const uint32_t height = node.attribute("height").as_uint();
uint32_t depth = node.attribute("depth").as_uint(); uint32_t depth = node.attribute("depth").as_uint();
std::string type = node.attribute("type").as_string(); const std::string type = node.attribute("type").as_string();
bool tiled = node.attribute("tiled").as_bool(); bool tiled = node.attribute("tiled").as_bool();
// create new texture object.
AMFNodeElementBase *ne = new AMFTexture(mNodeElement_Cur);
AMFTexture& als = *((AMFTexture*)ne);// alias for convenience
if (node.empty()) { if (node.empty()) {
return; return;
} }
std::string enc64_data = node.value(); // create new texture object.
// Check for child nodes AMFNodeElementBase *ne = new AMFTexture(mNodeElement_Cur);
AMFTexture& als = *((AMFTexture*)ne);// alias for convenience
std::string enc64_data;
XmlParser::getValueAsString(node, enc64_data);
// Check for child nodes
// check that all components was defined // check that all components was defined
if (id.empty()) { if (id.empty()) {
throw DeadlyImportError("ID for texture must be defined."); throw DeadlyImportError("ID for texture must be defined.");
} }
if (width < 1) { if (width < 1) {
throw DeadlyImportError("INvalid width for texture."); throw DeadlyImportError("Invalid width for texture.");
} }
if (height < 1) { if (height < 1) {
throw DeadlyImportError("Invalid height for texture."); throw DeadlyImportError("Invalid height for texture.");
} }
if (depth < 1) {
throw DeadlyImportError("Invalid depth for texture.");
}
if (type != "grayscale") { if (type != "grayscale") {
throw DeadlyImportError("Invalid type for texture."); throw DeadlyImportError("Invalid type for texture.");
} }
@ -203,7 +198,9 @@ void AMFImporter::ParseNode_Texture(XmlNode &node) {
als.Depth = depth; als.Depth = depth;
als.Tiled = tiled; als.Tiled = tiled;
ParseHelper_Decode_Base64(enc64_data, als.Data); ParseHelper_Decode_Base64(enc64_data, als.Data);
if (depth == 0) {
depth = (uint32_t)(als.Data.size() / (width * height));
}
// check data size // check data size
if ((width * height * depth) != als.Data.size()) { if ((width * height * depth) != als.Data.size()) {
throw DeadlyImportError("Texture has incorrect data size."); throw DeadlyImportError("Texture has incorrect data size.");
@ -233,20 +230,18 @@ void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) {
AMFTexMap &als = *((AMFTexMap *)ne); // AMFTexMap &als = *((AMFTexMap *)ne); //
std::string rtexid, gtexid, btexid, atexid; std::string rtexid, gtexid, btexid, atexid;
if (!node.empty()) { if (!node.empty()) {
ParseHelper_Node_Enter(ne); for (pugi::xml_attribute &attr : node.attributes()) {
for (XmlNode &currentNode : node.children()) { const std::string &currentAttr = attr.name();
const std::string &currentName = currentNode.name(); if (currentAttr == "rtexid") {
if (currentName == "rtexid") { rtexid = attr.as_string();
XmlParser::getValueAsString(node, rtexid); } else if (currentAttr == "gtexid") {
} else if (currentName == "gtexid") { gtexid = attr.as_string();
XmlParser::getValueAsString(node, gtexid); } else if (currentAttr == "btexid") {
} else if (currentName == "btexid") { btexid = attr.as_string();
XmlParser::getValueAsString(node, btexid); } else if (currentAttr == "atexid") {
} else if (currentName == "atexid") { atexid = attr.as_string();
XmlParser::getValueAsString(node, atexid);
} }
} }
ParseHelper_Node_Exit();
} }
// create new texture coordinates object, alias for convenience // create new texture coordinates object, alias for convenience
@ -256,7 +251,6 @@ void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) {
} }
// Check for children nodes // Check for children nodes
//XML_CheckNode_MustHaveChildren();
if (node.children().begin() == node.children().end()) { if (node.children().begin() == node.children().end()) {
throw DeadlyImportError("Invalid children definition."); throw DeadlyImportError("Invalid children definition.");
} }
@ -264,28 +258,31 @@ void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) {
bool read_flag[6] = { false, false, false, false, false, false }; bool read_flag[6] = { false, false, false, false, false, false };
if (!pUseOldName) { if (!pUseOldName) {
for (pugi::xml_attribute &attr : node.attributes()) { ParseHelper_Node_Enter(ne);
const std::string name = attr.name(); for ( XmlNode &currentNode : node.children()) {
const std::string &name = currentNode.name();
if (name == "utex1") { if (name == "utex1") {
read_flag[0] = true; read_flag[0] = true;
als.TextureCoordinate[0].x = attr.as_float(); XmlParser::getValueAsFloat(node, als.TextureCoordinate[0].x);
} else if (name == "utex2") { } else if (name == "utex2") {
read_flag[1] = true; read_flag[1] = true;
als.TextureCoordinate[1].x = attr.as_float(); XmlParser::getValueAsFloat(node, als.TextureCoordinate[1].x);
} else if (name == "utex3") { } else if (name == "utex3") {
read_flag[2] = true; read_flag[2] = true;
als.TextureCoordinate[2].x = attr.as_float(); XmlParser::getValueAsFloat(node, als.TextureCoordinate[2].x);
} else if (name == "vtex1") { } else if (name == "vtex1") {
read_flag[3] = true; read_flag[3] = true;
als.TextureCoordinate[0].y = attr.as_float(); XmlParser::getValueAsFloat(node, als.TextureCoordinate[0].y);
} else if (name == "vtex2") { } else if (name == "vtex2") {
read_flag[4] = true; read_flag[4] = true;
als.TextureCoordinate[1].y = attr.as_float(); XmlParser::getValueAsFloat(node, als.TextureCoordinate[1].y);
} else if (name == "vtex3") { } else if (name == "vtex3") {
read_flag[5] = true; read_flag[5] = true;
als.TextureCoordinate[0].y = attr.as_float(); XmlParser::getValueAsFloat(node, als.TextureCoordinate[2].y);
} }
} }
ParseHelper_Node_Exit();
} else { } else {
for (pugi::xml_attribute &attr : node.attributes()) { for (pugi::xml_attribute &attr : node.attributes()) {
const std::string name = attr.name(); const std::string name = attr.name();

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -240,7 +240,7 @@ struct AMFVertices : public AMFNodeElementBase {
/// Structure that define volume node. /// Structure that define volume node.
struct AMFVolume : public AMFNodeElementBase { struct AMFVolume : public AMFNodeElementBase {
std::string MaterialID; ///< Which material to use. std::string MaterialID; ///< Which material to use.
std::string Type; ///< What this volume describes can be “region” or “support”. If none specified, “object” is assumed. std::string Type; ///< What this volume describes can be "region" or "support". If none specified, "object" is assumed.
/// Constructor. /// Constructor.
/// \param [in] pParent - pointer to parent node. /// \param [in] pParent - pointer to parent node.

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -62,12 +62,14 @@ aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*
// Check if stored data are supported. // Check if stored data are supported.
if (!Composition.empty()) { if (!Composition.empty()) {
throw DeadlyImportError("IME. GetColor for composition"); throw DeadlyImportError("IME. GetColor for composition");
} else if (Color->Composed) {
throw DeadlyImportError("IME. GetColor, composed color");
} else {
tcol = Color->Color;
} }
if (Color->Composed) {
throw DeadlyImportError("IME. GetColor, composed color");
}
tcol = Color->Color;
// Check if default color must be used // Check if default color must be used
if ((tcol.r == 0) && (tcol.g == 0) && (tcol.b == 0) && (tcol.a == 0)) { if ((tcol.r == 0) && (tcol.g == 0) && (tcol.b == 0) && (tcol.a == 0)) {
tcol.r = 0.5f; tcol.r = 0.5f;
@ -79,13 +81,13 @@ aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*
return tcol; return tcol;
} }
void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &pNodeElement, std::vector<aiVector3D> &pVertexCoordinateArray, void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &nodeElement, std::vector<aiVector3D> &vertexCoordinateArray,
std::vector<AMFColor *> &pVertexColorArray) const { std::vector<AMFColor *> &pVertexColorArray) const {
AMFVertices *vn = nullptr; AMFVertices *vn = nullptr;
size_t col_idx; size_t col_idx;
// All data stored in "vertices", search for it. // All data stored in "vertices", search for it.
for (AMFNodeElementBase *ne_child : pNodeElement.Child) { for (AMFNodeElementBase *ne_child : nodeElement.Child) {
if (ne_child->Type == AMFNodeElementBase::ENET_Vertices) { if (ne_child->Type == AMFNodeElementBase::ENET_Vertices) {
vn = (AMFVertices*)ne_child; vn = (AMFVertices*)ne_child;
} }
@ -97,7 +99,7 @@ void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &pNodeElem
} }
// all coordinates stored as child and we need to reserve space for future push_back's. // all coordinates stored as child and we need to reserve space for future push_back's.
pVertexCoordinateArray.reserve(vn->Child.size()); vertexCoordinateArray.reserve(vn->Child.size());
// colors count equal vertices count. // colors count equal vertices count.
pVertexColorArray.resize(vn->Child.size()); pVertexColorArray.resize(vn->Child.size());
@ -112,7 +114,7 @@ void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &pNodeElem
for (AMFNodeElementBase *vtx : vn_child->Child) { for (AMFNodeElementBase *vtx : vn_child->Child) {
if (vtx->Type == AMFNodeElementBase::ENET_Coordinates) { if (vtx->Type == AMFNodeElementBase::ENET_Coordinates) {
pVertexCoordinateArray.push_back(((AMFCoordinates *)vtx)->Coordinate); vertexCoordinateArray.push_back(((AMFCoordinates *)vtx)->Coordinate);
continue; continue;
} }
@ -329,8 +331,8 @@ void AMFImporter::Postprocess_AddMetadata(const AMFMetaDataArray &metadataList,
sceneNode.mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(metadataList.size())); sceneNode.mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(metadataList.size()));
size_t meta_idx(0); size_t meta_idx(0);
for (const AMFMetadata &metadata : metadataList) { for (const AMFMetadata *metadata : metadataList) {
sceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx++), metadata.Type, aiString(metadata.Value)); sceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx++), metadata->Type, aiString(metadata->Value));
} }
} }
@ -426,10 +428,10 @@ void AMFImporter::Postprocess_BuildMeshSet(const AMFMesh &pNodeElement, const st
if (pBiggerThan != nullptr) { if (pBiggerThan != nullptr) {
bool found = false; bool found = false;
const size_t biggerThan = *pBiggerThan;
for (const SComplexFace &face : pFaceList) { for (const SComplexFace &face : pFaceList) {
for (size_t idx_vert = 0; idx_vert < face.Face.mNumIndices; idx_vert++) { for (size_t idx_vert = 0; idx_vert < face.Face.mNumIndices; idx_vert++) {
if (face.Face.mIndices[idx_vert] > *pBiggerThan) { if (face.Face.mIndices[idx_vert] > biggerThan) {
rv = face.Face.mIndices[idx_vert]; rv = face.Face.mIndices[idx_vert];
found = true; found = true;
break; break;
@ -873,7 +875,7 @@ nl_clean_loop:
pScene->mNumMaterials = static_cast<unsigned int>(mTexture_Converted.size()); pScene->mNumMaterials = static_cast<unsigned int>(mTexture_Converted.size());
pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials]; pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials];
for (const SPP_Texture &tex_convd : mTexture_Converted) { for (const SPP_Texture &tex_convd : mTexture_Converted) {
const aiString texture_id(AI_EMBEDDED_TEXNAME_PREFIX + to_string(idx)); const aiString texture_id(AI_EMBEDDED_TEXNAME_PREFIX + ai_to_string(idx));
const int mode = aiTextureOp_Multiply; const int mode = aiTextureOp_Multiply;
const int repeat = tex_convd.Tiled ? 1 : 0; const int repeat = tex_convd.Tiled ? 1 : 0;

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team

View File

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

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
@ -685,7 +685,7 @@ void Parser::ParseLV3MapBlock(Texture &map) {
// Files with 'None' as map name are produced by // Files with 'None' as map name are produced by
// an Maja to ASE exporter which name I forgot .. // an Maja to ASE exporter which name I forgot ..
ASSIMP_LOG_WARN("ASE: Skipping invalid map entry"); ASSIMP_LOG_WARN("ASE: Skipping invalid map entry");
map.mMapName = ""; map.mMapName = std::string();
} }
continue; continue;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,7 +4,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team

View File

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

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -66,19 +66,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// zlib is needed for compressed blend files // zlib is needed for compressed blend files
#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND #ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB # ifdef ASSIMP_BUILD_NO_OWN_ZLIB
#include <zlib.h> # include <zlib.h>
#else # else
#include "../contrib/zlib/zlib.h" # include "../contrib/zlib/zlib.h"
#endif # endif
#endif #endif
namespace Assimp { namespace Assimp {
template <> template <>
const char *LogFunctions<BlenderImporter>::Prefix() { const char *LogFunctions<BlenderImporter>::Prefix() {
static auto prefix = "BLEND: "; static auto prefix = "BLEND: ";
return prefix; return prefix;
} }
} // namespace Assimp } // namespace Assimp
using namespace Assimp; using namespace Assimp;
@ -86,7 +88,7 @@ using namespace Assimp::Blender;
using namespace Assimp::Formatter; using namespace Assimp::Formatter;
static const aiImporterDesc blenderDesc = { static const aiImporterDesc blenderDesc = {
"Blender 3D Importer \nhttp://www.blender3d.org", "Blender 3D Importer (http://www.blender3d.org)",
"", "",
"", "",
"No animation support yet", "No animation support yet",
@ -122,17 +124,12 @@ bool BlenderImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bo
return true; return true;
} }
else if ((!extension.length() || checkSig) && pIOHandler) { if ((!extension.length() || checkSig) && pIOHandler) {
// note: this won't catch compressed files // note: this won't catch compressed files
return SearchFileHeaderForToken(pIOHandler, pFile, TokensForSearch, 1); return SearchFileHeaderForToken(pIOHandler, pFile, TokensForSearch, 1);
} }
return false;
}
// ------------------------------------------------------------------------------------------------ return false;
// List all extensions handled by this loader
void BlenderImporter::GetExtensionList(std::set<std::string> &app) {
app.insert("blend");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -252,7 +249,7 @@ void BlenderImporter::InternReadFile(const std::string &pFile,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderImporter::ParseBlendFile(FileDatabase &out, std::shared_ptr<IOStream> stream) { void BlenderImporter::ParseBlendFile(FileDatabase &out, std::shared_ptr<IOStream> stream) {
out.reader = std::shared_ptr<StreamReaderAny>(new StreamReaderAny(stream, out.little)); out.reader = std::make_shared<StreamReaderAny>(stream, out.little);
DNAParser dna_reader(out); DNAParser dna_reader(out);
const DNA *dna = nullptr; const DNA *dna = nullptr;

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -110,7 +110,6 @@ public:
protected: protected:
const aiImporterDesc* GetInfo () const; const aiImporterDesc* GetInfo () const;
void GetExtensionList(std::set<std::string>& app);
void SetupProperties(const Importer* pImp); void SetupProperties(const Importer* pImp);
void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
void ParseBlendFile(Blender::FileDatabase& out, std::shared_ptr<IOStream> stream); void ParseBlendFile(Blender::FileDatabase& out, std::shared_ptr<IOStream> stream);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef ASSIMP_BUILD_NO_COB_IMPORTER #ifndef ASSIMP_BUILD_NO_COB_IMPORTER
#include "AssetLib/COB/COBLoader.h" #include "AssetLib/COB/COBLoader.h"
#include "AssetLib/COB/COBScene.h" #include "AssetLib/COB/COBScene.h"
#include "PostProcessing/ConvertToLHProcess.h" #include "PostProcessing/ConvertToLHProcess.h"
@ -90,11 +91,15 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
COBImporter::COBImporter() {} COBImporter::COBImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
COBImporter::~COBImporter() {} COBImporter::~COBImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
@ -466,8 +471,9 @@ void COBImporter::UnsupportedChunk_Ascii(LineSplitter &splitter, const ChunkInfo
// missing the next line. // missing the next line.
splitter.get_stream().IncPtr(nfo.size); splitter.get_stream().IncPtr(nfo.size);
splitter.swallow_next_increment(); splitter.swallow_next_increment();
} else } else {
ThrowException(error); ThrowException(error);
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -790,25 +796,12 @@ void COBImporter::ReadBitM_Ascii(Scene & /*out*/, LineSplitter &splitter, const
if (nfo.version > 1) { if (nfo.version > 1) {
return UnsupportedChunk_Ascii(splitter, nfo, "BitM"); return UnsupportedChunk_Ascii(splitter, nfo, "BitM");
} }
/*
"\nThumbNailHdrSize %ld"
"\nThumbHeader: %02hx 02hx %02hx "
"\nColorBufSize %ld"
"\nColorBufZipSize %ld"
"\nZippedThumbnail: %02hx 02hx %02hx "
*/
const unsigned int head = strtoul10((++splitter)[1]); const unsigned int head = strtoul10((++splitter)[1]);
if (head != sizeof(Bitmap::BitmapHeader)) { if (head != sizeof(Bitmap::BitmapHeader)) {
ASSIMP_LOG_WARN("Unexpected ThumbNailHdrSize, skipping this chunk"); ASSIMP_LOG_WARN("Unexpected ThumbNailHdrSize, skipping this chunk");
return; return;
} }
/*union {
Bitmap::BitmapHeader data;
char opaq[sizeof Bitmap::BitmapHeader()];
};*/
// ReadHexOctets(opaq,head,(++splitter)[1]);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -884,7 +877,10 @@ void COBImporter::ReadBinaryFile(Scene &out, StreamReaderLE *reader) {
while (1) { while (1) {
std::string type; std::string type;
type += reader->GetI1(), type += reader->GetI1(), type += reader->GetI1(), type += reader->GetI1(); type += reader->GetI1();
type += reader->GetI1();
type += reader->GetI1();
type += reader->GetI1();
ChunkInfo nfo; ChunkInfo nfo;
nfo.version = reader->GetI2() * 10; nfo.version = reader->GetI2() * 10;
@ -906,14 +902,7 @@ void COBImporter::ReadBinaryFile(Scene &out, StreamReaderLE *reader) {
ReadCame_Binary(out, *reader, nfo); ReadCame_Binary(out, *reader, nfo);
} else if (type == "Mat1") { } else if (type == "Mat1") {
ReadMat1_Binary(out, *reader, nfo); ReadMat1_Binary(out, *reader, nfo);
} } else if (type == "Unit") {
/* else if (type == "Bone") {
ReadBone_Binary(out,*reader,nfo);
}
else if (type == "Chan") {
ReadChan_Binary(out,*reader,nfo);
}*/
else if (type == "Unit") {
ReadUnit_Binary(out, *reader, nfo); ReadUnit_Binary(out, *reader, nfo);
} else if (type == "OLay") { } else if (type == "OLay") {
// ignore layer index silently. // ignore layer index silently.
@ -923,8 +912,9 @@ void COBImporter::ReadBinaryFile(Scene &out, StreamReaderLE *reader) {
return UnsupportedChunk_Binary(*reader, nfo, type.c_str()); return UnsupportedChunk_Binary(*reader, nfo, type.c_str());
} else if (type == "END ") { } else if (type == "END ") {
return; return;
} else } else {
UnsupportedChunk_Binary(*reader, nfo, type.c_str()); UnsupportedChunk_Binary(*reader, nfo, type.c_str());
}
} }
} }

View File

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

View File

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

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team

View File

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

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -129,7 +129,7 @@ inline std::string MakeUniqueId(const std::unordered_set<std::string> &idSet, co
// Select a number to append // Select a number to append
size_t idnum = 1; size_t idnum = 1;
do { do {
result = idPrefix + '_' + to_string(idnum) + postfix; result = idPrefix + '_' + ai_to_string(idnum) + postfix;
++idnum; ++idnum;
} while (!IsUniqueId(idSet, result)); } while (!IsUniqueId(idSet, result));
} }
@ -1017,7 +1017,7 @@ void ColladaExporter::WriteGeometry(size_t pIndex) {
// texture coords // texture coords
for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
if (mesh->HasTextureCoords(static_cast<unsigned int>(a))) { if (mesh->HasTextureCoords(static_cast<unsigned int>(a))) {
WriteFloatArray(geometryId + "-tex" + to_string(a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2, WriteFloatArray(geometryId + "-tex" + ai_to_string(a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2,
(ai_real *)mesh->mTextureCoords[a], mesh->mNumVertices); (ai_real *)mesh->mTextureCoords[a], mesh->mNumVertices);
} }
} }
@ -1025,7 +1025,7 @@ void ColladaExporter::WriteGeometry(size_t pIndex) {
// vertex colors // vertex colors
for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
if (mesh->HasVertexColors(static_cast<unsigned int>(a))) if (mesh->HasVertexColors(static_cast<unsigned int>(a)))
WriteFloatArray(geometryId + "-color" + to_string(a), FloatType_Color, (ai_real *)mesh->mColors[a], mesh->mNumVertices); WriteFloatArray(geometryId + "-color" + ai_to_string(a), FloatType_Color, (ai_real *)mesh->mColors[a], mesh->mNumVertices);
} }
// assemble vertex structure // assemble vertex structure
@ -1724,7 +1724,7 @@ ColladaExporter::NameIdPair ColladaExporter::AddObjectIndexToMaps(AiObjectType t
case AiObjectType::Camera: idStr = std::string("camera_"); break; case AiObjectType::Camera: idStr = std::string("camera_"); break;
case AiObjectType::Count: throw std::logic_error("ColladaExporter::AiObjectType::Count is not an object type"); case AiObjectType::Count: throw std::logic_error("ColladaExporter::AiObjectType::Count is not an object type");
} }
idStr.append(to_string(index)); idStr.append(ai_to_string(index));
} else { } else {
idStr = XMLIDEncode(name); idStr = XMLIDEncode(name);
} }

View File

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

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -80,16 +80,16 @@ void ToCamelCase(std::string &text) {
return; return;
// Capitalise first character // Capitalise first character
auto it = text.begin(); auto it = text.begin();
(*it) = ToUpper(*it); (*it) = ai_toupper(*it);
++it; ++it;
for (/*started above*/; it != text.end(); /*iterated below*/) { for (/*started above*/; it != text.end(); /*iterated below*/) {
if ((*it) == '_') { if ((*it) == '_') {
it = text.erase(it); it = text.erase(it);
if (it != text.end()) if (it != text.end())
(*it) = ToUpper(*it); (*it) = ai_toupper(*it);
} else { } else {
// Make lower case // Make lower case
(*it) = ToLower(*it); (*it) = ai_tolower(*it);
++it; ++it;
} }
} }

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/material.h> #include <assimp/material.h>
#include <assimp/mesh.h> #include <assimp/mesh.h>
#include <stdint.h> #include <cstdint>
#include <map> #include <map>
#include <set> #include <set>
#include <vector> #include <vector>
@ -206,7 +206,8 @@ struct SemanticMappingTable {
std::string mMatName; std::string mMatName;
/// List of semantic map commands, grouped by effect semantic name /// List of semantic map commands, grouped by effect semantic name
std::map<std::string, InputSemanticMapEntry> mMap; using InputSemanticMap = std::map<std::string, InputSemanticMapEntry>;
InputSemanticMap mMap;
/// For std::find /// For std::find
bool operator==(const std::string &s) const { bool operator==(const std::string &s) const {

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -63,6 +63,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
using namespace Assimp::Formatter; using namespace Assimp::Formatter;
using namespace Assimp::Collada;
static const aiImporterDesc desc = { static const aiImporterDesc desc = {
"Collada Importer", "Collada Importer",
@ -74,7 +75,7 @@ static const aiImporterDesc desc = {
3, 3,
1, 1,
5, 5,
"dae zae" "dae xml zae"
}; };
static const float kMillisecondsFromSeconds = 1000.f; static const float kMillisecondsFromSeconds = 1000.f;
@ -271,7 +272,7 @@ aiNode *ColladaLoader::BuildHierarchy(const ColladaParser &pParser, const Collad
node->mTransformation = pParser.CalculateResultTransform(pNode->mTransforms); node->mTransformation = pParser.CalculateResultTransform(pNode->mTransforms);
// now resolve node instances // now resolve node instances
std::vector<const Collada::Node *> instances; std::vector<const Node*> instances;
ResolveNodeInstances(pParser, pNode, instances); ResolveNodeInstances(pParser, pNode, instances);
// add children. first the *real* ones // add children. first the *real* ones
@ -298,8 +299,8 @@ aiNode *ColladaLoader::BuildHierarchy(const ColladaParser &pParser, const Collad
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Resolve node instances // Resolve node instances
void ColladaLoader::ResolveNodeInstances(const ColladaParser &pParser, const Collada::Node *pNode, void ColladaLoader::ResolveNodeInstances(const ColladaParser &pParser, const Node *pNode,
std::vector<const Collada::Node *> &resolved) { std::vector<const Node*> &resolved) {
// reserve enough storage // reserve enough storage
resolved.reserve(pNode->mNodeInstances.size()); resolved.reserve(pNode->mNodeInstances.size());
@ -307,7 +308,7 @@ void ColladaLoader::ResolveNodeInstances(const ColladaParser &pParser, const Col
for (const auto &nodeInst : pNode->mNodeInstances) { for (const auto &nodeInst : pNode->mNodeInstances) {
// find the corresponding node in the library // find the corresponding node in the library
const ColladaParser::NodeLibrary::const_iterator itt = pParser.mNodeLibrary.find(nodeInst.mNode); const ColladaParser::NodeLibrary::const_iterator itt = pParser.mNodeLibrary.find(nodeInst.mNode);
const Collada::Node *nd = itt == pParser.mNodeLibrary.end() ? nullptr : (*itt).second; const Node *nd = itt == pParser.mNodeLibrary.end() ? nullptr : (*itt).second;
// FIX for http://sourceforge.net/tracker/?func=detail&aid=3054873&group_id=226462&atid=1067632 // FIX for http://sourceforge.net/tracker/?func=detail&aid=3054873&group_id=226462&atid=1067632
// need to check for both name and ID to catch all. To avoid breaking valid files, // need to check for both name and ID to catch all. To avoid breaking valid files,
@ -326,13 +327,13 @@ void ColladaLoader::ResolveNodeInstances(const ColladaParser &pParser, const Col
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Resolve UV channels // Resolve UV channels
void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler &sampler, const Collada::SemanticMappingTable &table) { void ColladaLoader::ApplyVertexToEffectSemanticMapping(Sampler &sampler, const SemanticMappingTable &table) {
std::map<std::string, Collada::InputSemanticMapEntry>::const_iterator it = table.mMap.find(sampler.mUVChannel); SemanticMappingTable::InputSemanticMap::const_iterator it = table.mMap.find(sampler.mUVChannel);
if (it == table.mMap.end()) { if (it == table.mMap.end()) {
return; return;
} }
if (it->second.mType != Collada::IT_Texcoord) { if (it->second.mType != IT_Texcoord) {
ASSIMP_LOG_ERROR("Collada: Unexpected effect input mapping"); ASSIMP_LOG_ERROR("Collada: Unexpected effect input mapping");
} }
@ -341,8 +342,8 @@ void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler &sampler
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Builds lights for the given node and references them // Builds lights for the given node and references them
void ColladaLoader::BuildLightsForNode(const ColladaParser &pParser, const Collada::Node *pNode, aiNode *pTarget) { void ColladaLoader::BuildLightsForNode(const ColladaParser &pParser, const Node *pNode, aiNode *pTarget) {
for (const Collada::LightInstance &lid : pNode->mLights) { for (const LightInstance &lid : pNode->mLights) {
// find the referred light // find the referred light
ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find(lid.mLight); ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find(lid.mLight);
if (srcLightIt == pParser.mLightLibrary.end()) { if (srcLightIt == pParser.mLightLibrary.end()) {
@ -406,8 +407,8 @@ void ColladaLoader::BuildLightsForNode(const ColladaParser &pParser, const Colla
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Builds cameras for the given node and references them // Builds cameras for the given node and references them
void ColladaLoader::BuildCamerasForNode(const ColladaParser &pParser, const Collada::Node *pNode, aiNode *pTarget) { void ColladaLoader::BuildCamerasForNode(const ColladaParser &pParser, const Node *pNode, aiNode *pTarget) {
for (const Collada::CameraInstance &cid : pNode->mCameras) { for (const CameraInstance &cid : pNode->mCameras) {
// find the referred light // find the referred light
ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find(cid.mCamera); ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find(cid.mCamera);
if (srcCameraIt == pParser.mCameraLibrary.end()) { if (srcCameraIt == pParser.mCameraLibrary.end()) {
@ -461,15 +462,15 @@ void ColladaLoader::BuildCamerasForNode(const ColladaParser &pParser, const Coll
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Builds meshes for the given node and references them // Builds meshes for the given node and references them
void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Collada::Node *pNode, aiNode *pTarget) { void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node *pNode, aiNode *pTarget) {
// accumulated mesh references by this node // accumulated mesh references by this node
std::vector<size_t> newMeshRefs; std::vector<size_t> newMeshRefs;
newMeshRefs.reserve(pNode->mMeshes.size()); newMeshRefs.reserve(pNode->mMeshes.size());
// add a mesh for each subgroup in each collada mesh // add a mesh for each subgroup in each collada mesh
for (const Collada::MeshInstance &mid : pNode->mMeshes) { for (const MeshInstance &mid : pNode->mMeshes) {
const Collada::Mesh *srcMesh = nullptr; const Mesh *srcMesh = nullptr;
const Collada::Controller *srcController = nullptr; const Controller *srcController = nullptr;
// find the referred mesh // find the referred mesh
ColladaParser::MeshLibrary::const_iterator srcMeshIt = pParser.mMeshLibrary.find(mid.mMeshOrController); ColladaParser::MeshLibrary::const_iterator srcMeshIt = pParser.mMeshLibrary.find(mid.mMeshOrController);
@ -503,7 +504,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Colla
// find material assigned to this submesh // find material assigned to this submesh
std::string meshMaterial; std::string meshMaterial;
std::map<std::string, Collada::SemanticMappingTable>::const_iterator meshMatIt = mid.mMaterials.find(submesh.mMaterial); std::map<std::string, SemanticMappingTable>::const_iterator meshMatIt = mid.mMaterials.find(submesh.mMaterial);
const Collada::SemanticMappingTable *table = nullptr; const Collada::SemanticMappingTable *table = nullptr;
if (meshMatIt != mid.mMaterials.end()) { if (meshMatIt != mid.mMaterials.end()) {
@ -557,7 +558,12 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Colla
faceStart += submesh.mNumFaces; faceStart += submesh.mNumFaces;
// assign the material index // assign the material index
dstMesh->mMaterialIndex = matIdx; std::map<std::string, size_t>::const_iterator subMatIt = mMaterialIndexByName.find(submesh.mMaterial);
if (subMatIt != mMaterialIndexByName.end()) {
dstMesh->mMaterialIndex = static_cast<unsigned int>(subMatIt->second);
} else {
dstMesh->mMaterialIndex = matIdx;
}
if (dstMesh->mName.length == 0) { if (dstMesh->mName.length == 0) {
dstMesh->mName = mid.mMeshOrController; dstMesh->mName = mid.mMeshOrController;
} }
@ -586,15 +592,15 @@ aiMesh *ColladaLoader::findMesh(const std::string &meshid) {
return nullptr; return nullptr;
} }
for (unsigned int i = 0; i < mMeshes.size(); ++i) { for (auto & mMeshe : mMeshes) {
if (std::string(mMeshes[i]->mName.data) == meshid) { if (std::string(mMeshe->mName.data) == meshid) {
return mMeshes[i]; return mMeshe;
} }
} }
for (unsigned int i = 0; i < mTargetMeshes.size(); ++i) { for (auto & mTargetMeshe : mTargetMeshes) {
if (std::string(mTargetMeshes[i]->mName.data) == meshid) { if (std::string(mTargetMeshe->mName.data) == meshid) {
return mTargetMeshes[i]; return mTargetMeshe;
} }
} }
@ -603,8 +609,8 @@ aiMesh *ColladaLoader::findMesh(const std::string &meshid) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh // Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh
aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Collada::Mesh *pSrcMesh, const Collada::SubMesh &pSubMesh, aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrcMesh, const SubMesh &pSubMesh,
const Collada::Controller *pSrcController, size_t pStartVertex, size_t pStartFace) { const Controller *pSrcController, size_t pStartVertex, size_t pStartFace) {
std::unique_ptr<aiMesh> dstMesh(new aiMesh); std::unique_ptr<aiMesh> dstMesh(new aiMesh);
if (useColladaName) { if (useColladaName) {
@ -642,7 +648,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Collada::M
std::copy(pSrcMesh->mBitangents.begin() + pStartVertex, pSrcMesh->mBitangents.begin() + pStartVertex + numVertices, dstMesh->mBitangents); std::copy(pSrcMesh->mBitangents.begin() + pStartVertex, pSrcMesh->mBitangents.begin() + pStartVertex + numVertices, dstMesh->mBitangents);
} }
// same for texturecoords, as many as we have // same for texture coords, as many as we have
// empty slots are not allowed, need to pack and adjust UV indexes accordingly // 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) { for (size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
if (pSrcMesh->mTexCoords[a].size() >= pStartVertex + numVertices) { if (pSrcMesh->mTexCoords[a].size() >= pStartVertex + numVertices) {
@ -682,11 +688,11 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Collada::M
// create morph target meshes if any // create morph target meshes if any
std::vector<aiMesh *> targetMeshes; std::vector<aiMesh *> targetMeshes;
std::vector<float> targetWeights; std::vector<float> targetWeights;
Collada::MorphMethod method = Collada::Normalized; Collada::MorphMethod method = Normalized;
for (std::map<std::string, Collada::Controller>::const_iterator it = pParser.mControllerLibrary.begin(); for (std::map<std::string, Controller>::const_iterator it = pParser.mControllerLibrary.begin();
it != pParser.mControllerLibrary.end(); ++it) { it != pParser.mControllerLibrary.end(); ++it) {
const Collada::Controller &c = it->second; const Controller &c = it->second;
const Collada::Mesh *baseMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, c.mMeshId); const Collada::Mesh *baseMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, c.mMeshId);
if (c.mType == Collada::Morph && baseMesh->mName == pSrcMesh->mName) { if (c.mType == Collada::Morph && baseMesh->mName == pSrcMesh->mName) {
@ -705,8 +711,8 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Collada::M
throw DeadlyImportError("target weight data must not be textual "); throw DeadlyImportError("target weight data must not be textual ");
} }
for (unsigned int i = 0; i < targetData.mStrings.size(); ++i) { for (const auto & mString : targetData.mStrings) {
const Collada::Mesh *targetMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, targetData.mStrings.at(i)); const Mesh *targetMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, mString);
aiMesh *aimesh = findMesh(useColladaName ? targetMesh->mName : targetMesh->mId); aiMesh *aimesh = findMesh(useColladaName ? targetMesh->mName : targetMesh->mId);
if (!aimesh) { if (!aimesh) {
@ -718,12 +724,12 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Collada::M
} }
targetMeshes.push_back(aimesh); targetMeshes.push_back(aimesh);
} }
for (unsigned int i = 0; i < weightData.mValues.size(); ++i) { for (float mValue : weightData.mValues) {
targetWeights.push_back(weightData.mValues.at(i)); targetWeights.push_back(mValue);
} }
} }
} }
if (targetMeshes.size() > 0 && targetWeights.size() == targetMeshes.size()) { if (!targetMeshes.empty() && targetWeights.size() == targetMeshes.size()) {
std::vector<aiAnimMesh *> animMeshes; std::vector<aiAnimMesh *> animMeshes;
for (unsigned int i = 0; i < targetMeshes.size(); ++i) { for (unsigned int i = 0; i < targetMeshes.size(); ++i) {
aiMesh *targetMesh = targetMeshes.at(i); aiMesh *targetMesh = targetMeshes.at(i);
@ -733,7 +739,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Collada::M
animMesh->mName = targetMesh->mName; animMesh->mName = targetMesh->mName;
animMeshes.push_back(animMesh); animMeshes.push_back(animMesh);
} }
dstMesh->mMethod = (method == Collada::Relative) ? aiMorphingMethod_MORPH_RELATIVE : aiMorphingMethod_MORPH_NORMALIZED; dstMesh->mMethod = (method == Relative) ? aiMorphingMethod_MORPH_RELATIVE : aiMorphingMethod_MORPH_NORMALIZED;
dstMesh->mAnimMeshes = new aiAnimMesh *[animMeshes.size()]; dstMesh->mAnimMeshes = new aiAnimMesh *[animMeshes.size()];
dstMesh->mNumAnimMeshes = static_cast<unsigned int>(animMeshes.size()); dstMesh->mNumAnimMeshes = static_cast<unsigned int>(animMeshes.size());
for (unsigned int i = 0; i < animMeshes.size(); ++i) { for (unsigned int i = 0; i < animMeshes.size(); ++i) {
@ -757,18 +763,20 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Collada::M
const Collada::Accessor &weightsAcc = pParser.ResolveLibraryReference(pParser.mAccessorLibrary, pSrcController->mWeightInputWeights.mAccessor); const Collada::Accessor &weightsAcc = pParser.ResolveLibraryReference(pParser.mAccessorLibrary, pSrcController->mWeightInputWeights.mAccessor);
const Collada::Data &weights = pParser.ResolveLibraryReference(pParser.mDataLibrary, weightsAcc.mSource); const Collada::Data &weights = pParser.ResolveLibraryReference(pParser.mDataLibrary, weightsAcc.mSource);
if (!jointNames.mIsStringArray || jointMatrices.mIsStringArray || weights.mIsStringArray) if (!jointNames.mIsStringArray || jointMatrices.mIsStringArray || weights.mIsStringArray) {
throw DeadlyImportError("Data type mismatch while resolving mesh joints"); throw DeadlyImportError("Data type mismatch while resolving mesh joints");
}
// sanity check: we rely on the vertex weights always coming as pairs of BoneIndex-WeightIndex // sanity check: we rely on the vertex weights always coming as pairs of BoneIndex-WeightIndex
if (pSrcController->mWeightInputJoints.mOffset != 0 || pSrcController->mWeightInputWeights.mOffset != 1) if (pSrcController->mWeightInputJoints.mOffset != 0 || pSrcController->mWeightInputWeights.mOffset != 1) {
throw DeadlyImportError("Unsupported vertex_weight addressing scheme. "); throw DeadlyImportError("Unsupported vertex_weight addressing scheme. ");
}
// create containers to collect the weights for each bone // create containers to collect the weights for each bone
size_t numBones = jointNames.mStrings.size(); size_t numBones = jointNames.mStrings.size();
std::vector<std::vector<aiVertexWeight>> dstBones(numBones); std::vector<std::vector<aiVertexWeight>> dstBones(numBones);
// build a temporary array of pointers to the start of each vertex's weights // build a temporary array of pointers to the start of each vertex's weights
typedef std::vector<std::pair<size_t, size_t>> IndexPairVector; using IndexPairVector = std::vector<std::pair<size_t, size_t>>;
std::vector<IndexPairVector::const_iterator> weightStartPerVertex; std::vector<IndexPairVector::const_iterator> weightStartPerVertex;
weightStartPerVertex.resize(pSrcController->mWeightCounts.size(), pSrcController->mWeights.end()); weightStartPerVertex.resize(pSrcController->mWeightCounts.size(), pSrcController->mWeights.end());
@ -807,8 +815,8 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Collada::M
// count the number of bones which influence vertices of the current submesh // count the number of bones which influence vertices of the current submesh
size_t numRemainingBones = 0; size_t numRemainingBones = 0;
for (std::vector<std::vector<aiVertexWeight>>::const_iterator it = dstBones.begin(); it != dstBones.end(); ++it) { for (const auto & dstBone : dstBones) {
if (it->size() > 0) { if (!dstBone.empty()) {
++numRemainingBones; ++numRemainingBones;
} }
} }
@ -867,12 +875,12 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Collada::M
// and replace the bone's name by the node's name so that the user can use the standard // and replace the bone's name by the node's name so that the user can use the standard
// find-by-name method to associate nodes with bones. // find-by-name method to associate nodes with bones.
const Collada::Node *bnode = FindNode(pParser.mRootNode, bone->mName.data); const Collada::Node *bnode = FindNode(pParser.mRootNode, bone->mName.data);
if (!bnode) { if (nullptr == bnode) {
bnode = FindNodeBySID(pParser.mRootNode, bone->mName.data); bnode = FindNodeBySID(pParser.mRootNode, bone->mName.data);
} }
// assign the name that we would have assigned for the source node // assign the name that we would have assigned for the source node
if (bnode) { if (nullptr != bnode) {
bone->mName.Set(FindNameForNode(bnode)); bone->mName.Set(FindNameForNode(bnode));
} else { } else {
ASSIMP_LOG_WARN_F("ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\"."); ASSIMP_LOG_WARN_F("ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\".");
@ -973,8 +981,8 @@ void ColladaLoader::StoreAnimations(aiScene *pScene, const ColladaParser &pParse
std::set<std::string> animTargets; std::set<std::string> animTargets;
animTargets.insert(templateAnim->mChannels[0]->mNodeName.C_Str()); animTargets.insert(templateAnim->mChannels[0]->mNodeName.C_Str());
bool collectedAnimationsHaveDifferentChannels = true; bool collectedAnimationsHaveDifferentChannels = true;
for (size_t b = 0; b < collectedAnimIndices.size(); ++b) { for (unsigned long long collectedAnimIndice : collectedAnimIndices) {
aiAnimation *srcAnimation = mAnims[collectedAnimIndices[b]]; aiAnimation *srcAnimation = mAnims[(int)collectedAnimIndice];
std::string channelName = std::string(srcAnimation->mChannels[0]->mNodeName.C_Str()); std::string channelName = std::string(srcAnimation->mChannels[0]->mNodeName.C_Str());
if (animTargets.find(channelName) == animTargets.end()) { if (animTargets.find(channelName) == animTargets.end()) {
animTargets.insert(channelName); animTargets.insert(channelName);
@ -984,8 +992,9 @@ void ColladaLoader::StoreAnimations(aiScene *pScene, const ColladaParser &pParse
} }
} }
if (!collectedAnimationsHaveDifferentChannels) if (!collectedAnimationsHaveDifferentChannels) {
continue; continue;
}
// if there are other animations which fit the template anim, combine all channels into a single anim // if there are other animations which fit the template anim, combine all channels into a single anim
if (!collectedAnimIndices.empty()) { if (!collectedAnimIndices.empty()) {
@ -1032,16 +1041,18 @@ void ColladaLoader::StoreAnimations(aiScene *pScene, const ColladaParser &pParse
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructs the animations for the given source anim // Constructs the animations for the given source anim
void ColladaLoader::StoreAnimations(aiScene *pScene, const ColladaParser &pParser, const Collada::Animation *pSrcAnim, const std::string &pPrefix) { void ColladaLoader::StoreAnimations(aiScene *pScene, const ColladaParser &pParser, const Animation *pSrcAnim, const std::string &pPrefix) {
std::string animName = pPrefix.empty() ? pSrcAnim->mName : pPrefix + "_" + pSrcAnim->mName; std::string animName = pPrefix.empty() ? pSrcAnim->mName : pPrefix + "_" + pSrcAnim->mName;
// create nested animations, if given // create nested animations, if given
for (std::vector<Collada::Animation *>::const_iterator it = pSrcAnim->mSubAnims.begin(); it != pSrcAnim->mSubAnims.end(); ++it) for (auto mSubAnim : pSrcAnim->mSubAnims) {
StoreAnimations(pScene, pParser, *it, animName); StoreAnimations(pScene, pParser, mSubAnim, animName);
}
// create animation channels, if any // create animation channels, if any
if (!pSrcAnim->mChannels.empty()) if (!pSrcAnim->mChannels.empty()) {
CreateAnimation(pScene, pParser, pSrcAnim, animName); CreateAnimation(pScene, pParser, pSrcAnim, animName);
}
} }
struct MorphTimeValues { struct MorphTimeValues {
@ -1057,7 +1068,7 @@ void insertMorphTimeValue(std::vector<MorphTimeValues> &values, float time, floa
MorphTimeValues::key k; MorphTimeValues::key k;
k.mValue = value; k.mValue = value;
k.mWeight = weight; k.mWeight = weight;
if (values.size() == 0 || time < values[0].mTime) { if (values.empty() || time < values[0].mTime) {
MorphTimeValues val; MorphTimeValues val;
val.mTime = time; val.mTime = time;
val.mKeys.push_back(k); val.mKeys.push_back(k);
@ -1083,13 +1094,13 @@ void insertMorphTimeValue(std::vector<MorphTimeValues> &values, float time, floa
return; return;
} }
} }
// should not get here
} }
float getWeightAtKey(const std::vector<MorphTimeValues> &values, int key, unsigned int value) { static float getWeightAtKey(const std::vector<MorphTimeValues> &values, int key, unsigned int value) {
for (unsigned int i = 0; i < values[key].mKeys.size(); i++) { for (auto mKey : values[key].mKeys) {
if (values[key].mKeys[i].mValue == value) if (mKey.mValue == value) {
return values[key].mKeys[i].mWeight; return mKey.mWeight;
}
} }
// no value at key found, try to interpolate if present at other keys. if not, return zero // no value at key found, try to interpolate if present at other keys. if not, return zero
// TODO: interpolation // TODO: interpolation
@ -1098,7 +1109,7 @@ float getWeightAtKey(const std::vector<MorphTimeValues> &values, int key, unsign
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructs the animation for the given source anim // Constructs the animation for the given source anim
void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParser, const Collada::Animation *pSrcAnim, const std::string &pName) { void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParser, const Animation *pSrcAnim, const std::string &pName) {
// collect a list of animatable nodes // collect a list of animatable nodes
std::vector<const aiNode *> nodes; std::vector<const aiNode *> nodes;
CollectNodes(pScene->mRootNode, nodes); CollectNodes(pScene->mRootNode, nodes);
@ -1106,23 +1117,23 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
std::vector<aiNodeAnim *> anims; std::vector<aiNodeAnim *> anims;
std::vector<aiMeshMorphAnim *> morphAnims; std::vector<aiMeshMorphAnim *> morphAnims;
for (std::vector<const aiNode *>::const_iterator nit = nodes.begin(); nit != nodes.end(); ++nit) { for (auto node : nodes) {
// find all the collada anim channels which refer to the current node // find all the collada anim channels which refer to the current node
std::vector<Collada::ChannelEntry> entries; std::vector<ChannelEntry> entries;
std::string nodeName = (*nit)->mName.data; std::string nodeName = node->mName.data;
// find the collada node corresponding to the aiNode // find the collada node corresponding to the aiNode
const Collada::Node *srcNode = FindNode(pParser.mRootNode, nodeName); const Node *srcNode = FindNode(pParser.mRootNode, nodeName);
if (!srcNode) { if (!srcNode) {
continue; continue;
} }
// now check all channels if they affect the current node // now check all channels if they affect the current node
std::string targetID, subElement; std::string targetID, subElement;
for (std::vector<Collada::AnimationChannel>::const_iterator cit = pSrcAnim->mChannels.begin(); for (std::vector<AnimationChannel>::const_iterator cit = pSrcAnim->mChannels.begin();
cit != pSrcAnim->mChannels.end(); ++cit) { cit != pSrcAnim->mChannels.end(); ++cit) {
const Collada::AnimationChannel &srcChannel = *cit; const AnimationChannel &srcChannel = *cit;
Collada::ChannelEntry entry; ChannelEntry entry;
// we expect the animation target to be of type "nodeName/transformID.subElement". Ignore all others // we expect the animation target to be of type "nodeName/transformID.subElement". Ignore all others
// find the slash that separates the node name - there should be only one // find the slash that separates the node name - there should be only one
@ -1137,24 +1148,28 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
entry.mChannel = &(*cit); entry.mChannel = &(*cit);
entry.mTargetId = srcChannel.mTarget.substr(targetPos + pSrcAnim->mName.length(), entry.mTargetId = srcChannel.mTarget.substr(targetPos + pSrcAnim->mName.length(),
srcChannel.mTarget.length() - targetPos - pSrcAnim->mName.length()); srcChannel.mTarget.length() - targetPos - pSrcAnim->mName.length());
if (entry.mTargetId.front() == '-') if (entry.mTargetId.front() == '-') {
entry.mTargetId = entry.mTargetId.substr(1); entry.mTargetId = entry.mTargetId.substr(1);
}
entries.push_back(entry); entries.push_back(entry);
continue; continue;
} }
if (srcChannel.mTarget.find('/', slashPos + 1) != std::string::npos) if (srcChannel.mTarget.find('/', slashPos + 1) != std::string::npos) {
continue; continue;
}
targetID.clear(); targetID.clear();
targetID = srcChannel.mTarget.substr(0, slashPos); targetID = srcChannel.mTarget.substr(0, slashPos);
if (targetID != srcNode->mID) if (targetID != srcNode->mID) {
continue; continue;
}
// find the dot that separates the transformID - there should be only one or zero // find the dot that separates the transformID - there should be only one or zero
std::string::size_type dotPos = srcChannel.mTarget.find('.'); std::string::size_type dotPos = srcChannel.mTarget.find('.');
if (dotPos != std::string::npos) { if (dotPos != std::string::npos) {
if (srcChannel.mTarget.find('.', dotPos + 1) != std::string::npos) if (srcChannel.mTarget.find('.', dotPos + 1) != std::string::npos) {
continue; continue;
}
entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1, dotPos - slashPos - 1); entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1, dotPos - slashPos - 1);
@ -1171,7 +1186,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
else else
ASSIMP_LOG_WARN_F("Unknown anim subelement <", subElement, ">. Ignoring"); ASSIMP_LOG_WARN_F("Unknown anim subelement <", subElement, ">. Ignoring");
} else { } else {
// no subelement following, transformId is remaining string // no sub-element following, transformId is remaining string
entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1); entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1);
} }
@ -1222,11 +1237,11 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
entry.mTransformIndex = a; entry.mTransformIndex = a;
if (entry.mTransformIndex == SIZE_MAX) { if (entry.mTransformIndex == SIZE_MAX) {
if (entry.mTransformId.find("morph-weights") != std::string::npos) { if (entry.mTransformId.find("morph-weights") == std::string::npos) {
entry.mTargetId = entry.mTransformId;
entry.mTransformId = "";
} else
continue; continue;
}
entry.mTargetId = entry.mTransformId;
entry.mTransformId = std::string();
} }
entry.mChannel = &(*cit); entry.mChannel = &(*cit);
@ -1234,21 +1249,22 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
} }
// if there's no channel affecting the current node, we skip it // if there's no channel affecting the current node, we skip it
if (entries.empty()) if (entries.empty()) {
continue; continue;
}
// resolve the data pointers for all anim channels. Find the minimum time while we're at it // resolve the data pointers for all anim channels. Find the minimum time while we're at it
ai_real startTime = ai_real(1e20), endTime = ai_real(-1e20); ai_real startTime = ai_real(1e20), endTime = ai_real(-1e20);
for (std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it) { for (ChannelEntry & e : entries) {
Collada::ChannelEntry &e = *it;
e.mTimeAccessor = &pParser.ResolveLibraryReference(pParser.mAccessorLibrary, e.mChannel->mSourceTimes); e.mTimeAccessor = &pParser.ResolveLibraryReference(pParser.mAccessorLibrary, e.mChannel->mSourceTimes);
e.mTimeData = &pParser.ResolveLibraryReference(pParser.mDataLibrary, e.mTimeAccessor->mSource); e.mTimeData = &pParser.ResolveLibraryReference(pParser.mDataLibrary, e.mTimeAccessor->mSource);
e.mValueAccessor = &pParser.ResolveLibraryReference(pParser.mAccessorLibrary, e.mChannel->mSourceValues); e.mValueAccessor = &pParser.ResolveLibraryReference(pParser.mAccessorLibrary, e.mChannel->mSourceValues);
e.mValueData = &pParser.ResolveLibraryReference(pParser.mDataLibrary, e.mValueAccessor->mSource); e.mValueData = &pParser.ResolveLibraryReference(pParser.mDataLibrary, e.mValueAccessor->mSource);
// time count and value count must match // time count and value count must match
if (e.mTimeAccessor->mCount != e.mValueAccessor->mCount) if (e.mTimeAccessor->mCount != e.mValueAccessor->mCount) {
throw DeadlyImportError("Time count / value count mismatch in animation channel \"", e.mChannel->mTarget, "\"."); throw DeadlyImportError("Time count / value count mismatch in animation channel \"", e.mChannel->mTarget, "\".");
}
if (e.mTimeAccessor->mCount > 0) { if (e.mTimeAccessor->mCount > 0) {
// find bounding times // find bounding times
@ -1266,18 +1282,18 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
// and apply them to the transform chain. Then the node's present transformation can be calculated. // and apply them to the transform chain. Then the node's present transformation can be calculated.
ai_real time = startTime; ai_real time = startTime;
while (1) { while (1) {
for (std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it) { for (ChannelEntry & e : entries) {
Collada::ChannelEntry &e = *it;
// find the keyframe behind the current point in time // find the keyframe behind the current point in time
size_t pos = 0; size_t pos = 0;
ai_real postTime = 0.0; ai_real postTime = 0.0;
while (1) { while (1) {
if (pos >= e.mTimeAccessor->mCount) if (pos >= e.mTimeAccessor->mCount) {
break; break;
}
postTime = ReadFloat(*e.mTimeAccessor, *e.mTimeData, pos, 0); postTime = ReadFloat(*e.mTimeAccessor, *e.mTimeData, pos, 0);
if (postTime >= time) if (postTime >= time) {
break; break;
}
++pos; ++pos;
} }
@ -1285,8 +1301,9 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
// read values from there // read values from there
ai_real temp[16]; ai_real temp[16];
for (size_t c = 0; c < e.mValueAccessor->mSize; ++c) for (size_t c = 0; c < e.mValueAccessor->mSize; ++c) {
temp[c] = ReadFloat(*e.mValueAccessor, *e.mValueData, pos, c); temp[c] = ReadFloat(*e.mValueAccessor, *e.mValueData, pos, c);
}
// if not exactly at the key time, interpolate with previous value set // if not exactly at the key time, interpolate with previous value set
if (postTime > time && pos > 0) { if (postTime > time && pos > 0) {
@ -1312,9 +1329,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
// find next point in time to evaluate. That's the closest frame larger than the current in any channel // find next point in time to evaluate. That's the closest frame larger than the current in any channel
ai_real nextTime = ai_real(1e20); ai_real nextTime = ai_real(1e20);
for (std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it) { for (ChannelEntry & channelElement : entries) {
Collada::ChannelEntry &channelElement = *it;
// find the next time value larger than the current // find the next time value larger than the current
size_t pos = 0; size_t pos = 0;
while (pos < channelElement.mTimeAccessor->mCount) { while (pos < channelElement.mTimeAccessor->mCount) {
@ -1329,7 +1344,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
// https://github.com/assimp/assimp/issues/458 // https://github.com/assimp/assimp/issues/458
// Sub-sample axis-angle channels if the delta between two consecutive // Sub-sample axis-angle channels if the delta between two consecutive
// key-frame angles is >= 180 degrees. // key-frame angles is >= 180 degrees.
if (transforms[channelElement.mTransformIndex].mType == Collada::TF_ROTATE && channelElement.mSubElement == 3 && pos > 0 && pos < channelElement.mTimeAccessor->mCount) { if (transforms[channelElement.mTransformIndex].mType == TF_ROTATE && channelElement.mSubElement == 3 && pos > 0 && pos < channelElement.mTimeAccessor->mCount) {
const ai_real cur_key_angle = ReadFloat(*channelElement.mValueAccessor, *channelElement.mValueData, pos, 0); const ai_real cur_key_angle = ReadFloat(*channelElement.mValueAccessor, *channelElement.mValueData, pos, 0);
const ai_real last_key_angle = ReadFloat(*channelElement.mValueAccessor, *channelElement.mValueData, pos - 1, 0); const ai_real last_key_angle = ReadFloat(*channelElement.mValueAccessor, *channelElement.mValueData, pos - 1, 0);
const ai_real cur_key_time = ReadFloat(*channelElement.mTimeAccessor, *channelElement.mTimeData, pos, 0); const ai_real cur_key_time = ReadFloat(*channelElement.mTimeAccessor, *channelElement.mTimeData, pos, 0);
@ -1347,17 +1362,15 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
} }
// no more keys on any channel after the current time -> we're done // no more keys on any channel after the current time -> we're done
if (nextTime > 1e19) if (nextTime > 1e19) {
break; break;
}
// else construct next keyframe at this following time point // else construct next key-frame at this following time point
time = nextTime; time = nextTime;
} }
} }
// there should be some keyframes, but we aren't that fixated on valid input data
// ai_assert( resultTrafos.size() > 0);
// build an animation channel for the given node out of these trafo keys // build an animation channel for the given node out of these trafo keys
if (!resultTrafos.empty()) { if (!resultTrafos.empty()) {
aiNodeAnim *dstAnim = new aiNodeAnim; aiNodeAnim *dstAnim = new aiNodeAnim;
@ -1386,16 +1399,16 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
} }
if (!entries.empty() && entries.front().mTimeAccessor->mCount > 0) { if (!entries.empty() && entries.front().mTimeAccessor->mCount > 0) {
std::vector<Collada::ChannelEntry> morphChannels; std::vector<ChannelEntry> morphChannels;
for (std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it) { for (ChannelEntry & e : entries) {
Collada::ChannelEntry &e = *it;
// skip non-transform types // skip non-transform types
if (e.mTargetId.empty()) if (e.mTargetId.empty()) {
continue; continue;
}
if (e.mTargetId.find("morph-weights") != std::string::npos) if (e.mTargetId.find("morph-weights") != std::string::npos) {
morphChannels.push_back(e); morphChannels.push_back(e);
}
} }
if (!morphChannels.empty()) { if (!morphChannels.empty()) {
// either 1) morph weight animation count should contain morph target count channels // either 1) morph weight animation count should contain morph target count channels
@ -1407,13 +1420,14 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
std::vector<MorphTimeValues> morphTimeValues; std::vector<MorphTimeValues> morphTimeValues;
int morphAnimChannelIndex = 0; int morphAnimChannelIndex = 0;
for (std::vector<Collada::ChannelEntry>::iterator it = morphChannels.begin(); it != morphChannels.end(); ++it) { for (ChannelEntry & e : morphChannels) {
Collada::ChannelEntry &e = *it;
std::string::size_type apos = e.mTargetId.find('('); std::string::size_type apos = e.mTargetId.find('(');
std::string::size_type bpos = e.mTargetId.find(')'); std::string::size_type bpos = e.mTargetId.find(')');
if (apos == std::string::npos || bpos == std::string::npos)
// unknown way to specify weight -> ignore this animation // If unknown way to specify weight -> ignore this animation
if (apos == std::string::npos || bpos == std::string::npos) {
continue; continue;
}
// weight target can be in format Weight_M_N, Weight_N, WeightN, or some other way // weight target can be in format Weight_M_N, Weight_N, WeightN, or some other way
// we ignore the name and just assume the channels are in the right order // we ignore the name and just assume the channels are in the right order
@ -1457,13 +1471,13 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
std::copy(morphAnims.begin(), morphAnims.end(), anim->mMorphMeshChannels); std::copy(morphAnims.begin(), morphAnims.end(), anim->mMorphMeshChannels);
} }
anim->mDuration = 0.0f; anim->mDuration = 0.0f;
for (size_t a = 0; a < anims.size(); ++a) { for (auto & a : anims) {
anim->mDuration = std::max(anim->mDuration, anims[a]->mPositionKeys[anims[a]->mNumPositionKeys - 1].mTime); anim->mDuration = std::max(anim->mDuration, a->mPositionKeys[a->mNumPositionKeys - 1].mTime);
anim->mDuration = std::max(anim->mDuration, anims[a]->mRotationKeys[anims[a]->mNumRotationKeys - 1].mTime); anim->mDuration = std::max(anim->mDuration, a->mRotationKeys[a->mNumRotationKeys - 1].mTime);
anim->mDuration = std::max(anim->mDuration, anims[a]->mScalingKeys[anims[a]->mNumScalingKeys - 1].mTime); anim->mDuration = std::max(anim->mDuration, a->mScalingKeys[a->mNumScalingKeys - 1].mTime);
} }
for (size_t a = 0; a < morphAnims.size(); ++a) { for (auto & morphAnim : morphAnims) {
anim->mDuration = std::max(anim->mDuration, morphAnims[a]->mKeys[morphAnims[a]->mNumKeys - 1].mTime); anim->mDuration = std::max(anim->mDuration, morphAnim->mKeys[morphAnim->mNumKeys - 1].mTime);
} }
anim->mTicksPerSecond = 1000.0; anim->mTicksPerSecond = 1000.0;
mAnims.push_back(anim); mAnims.push_back(anim);
@ -1472,10 +1486,12 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Add a texture to a material structure // Add a texture to a material structure
void ColladaLoader::AddTexture(aiMaterial &mat, const ColladaParser &pParser, void ColladaLoader::AddTexture(aiMaterial &mat,
const Collada::Effect &effect, const ColladaParser &pParser,
const Collada::Sampler &sampler, const Effect &effect,
aiTextureType type, unsigned int idx) { const Sampler &sampler,
aiTextureType type,
unsigned int idx) {
// first of all, basic file name // first of all, basic file name
const aiString name = FindFilenameForEffectTexture(pParser, effect, sampler.mName); const aiString name = FindFilenameForEffectTexture(pParser, effect, sampler.mName);
mat.AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, type, idx); mat.AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, type, idx);
@ -1574,7 +1590,7 @@ void ColladaLoader::FillMaterials(const ColladaParser &pParser, aiScene * /*pSce
shadeMode = effect.mDoubleSided; shadeMode = effect.mDoubleSided;
mat.AddProperty<int>(&shadeMode, 1, AI_MATKEY_TWOSIDED); mat.AddProperty<int>(&shadeMode, 1, AI_MATKEY_TWOSIDED);
// wireframe? // wire-frame?
shadeMode = effect.mWireframe; shadeMode = effect.mWireframe;
mat.AddProperty<int>(&shadeMode, 1, AI_MATKEY_ENABLE_WIREFRAME); mat.AddProperty<int>(&shadeMode, 1, AI_MATKEY_ENABLE_WIREFRAME);
@ -1652,12 +1668,12 @@ void ColladaLoader::BuildMaterials(ColladaParser &pParser, aiScene * /*pScene*/)
for (ColladaParser::MaterialLibrary::const_iterator matIt = pParser.mMaterialLibrary.begin(); for (ColladaParser::MaterialLibrary::const_iterator matIt = pParser.mMaterialLibrary.begin();
matIt != pParser.mMaterialLibrary.end(); ++matIt) { matIt != pParser.mMaterialLibrary.end(); ++matIt) {
const Collada::Material &material = matIt->second; const Material &material = matIt->second;
// a material is only a reference to an effect // a material is only a reference to an effect
ColladaParser::EffectLibrary::iterator effIt = pParser.mEffectLibrary.find(material.mEffect); ColladaParser::EffectLibrary::iterator effIt = pParser.mEffectLibrary.find(material.mEffect);
if (effIt == pParser.mEffectLibrary.end()) if (effIt == pParser.mEffectLibrary.end())
continue; continue;
Collada::Effect &effect = effIt->second; Effect &effect = effIt->second;
// create material // create material
aiMaterial *mat = new aiMaterial; aiMaterial *mat = new aiMaterial;
@ -1666,7 +1682,7 @@ void ColladaLoader::BuildMaterials(ColladaParser &pParser, aiScene * /*pScene*/)
// store the material // store the material
mMaterialIndexByName[matIt->first] = newMats.size(); mMaterialIndexByName[matIt->first] = newMats.size();
newMats.push_back(std::pair<Collada::Effect *, aiMaterial *>(&effect, mat)); newMats.push_back(std::pair<Effect *, aiMaterial *>(&effect, mat));
} }
// ScenePreprocessor generates a default material automatically if none is there. // ScenePreprocessor generates a default material automatically if none is there.
// All further code here in this loader works well without a valid material so // All further code here in this loader works well without a valid material so
@ -1674,17 +1690,16 @@ void ColladaLoader::BuildMaterials(ColladaParser &pParser, aiScene * /*pScene*/)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Resolves the texture name for the given effect texture entry // Resolves the texture name for the given effect texture entry and loads the texture data
// and loads the texture data
aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParser, aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParser,
const Collada::Effect &pEffect, const std::string &pName) { const Effect &pEffect, const std::string &pName) {
aiString result; aiString result;
// recurse through the param references until we end up at an image // recurse through the param references until we end up at an image
std::string name = pName; std::string name = pName;
while (1) { while (1) {
// the given string is a param entry. Find it // the given string is a param entry. Find it
Collada::Effect::ParamLibrary::const_iterator it = pEffect.mParams.find(name); 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 // if not found, we're at the end of the recursion. The resulting string should be the image ID
if (it == pEffect.mParams.end()) if (it == pEffect.mParams.end())
break; break;
@ -1712,10 +1727,6 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
tex->mFilename.Set(imIt->second.mFileName.c_str()); tex->mFilename.Set(imIt->second.mFileName.c_str());
result.Set(imIt->second.mFileName); result.Set(imIt->second.mFileName);
// TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
// result.data[0] = '*';
// result.length = 1 + ASSIMP_itoa10(result.data + 1, static_cast<unsigned int>(MAXLEN - 1), static_cast<int32_t>(mTextures.size()));
// setup format hint // setup format hint
if (imIt->second.mEmbeddedFormat.length() >= HINTMAXTEXTURELEN) { if (imIt->second.mEmbeddedFormat.length() >= HINTMAXTEXTURELEN) {
ASSIMP_LOG_WARN("Collada: texture format hint is too long, truncating to 3 characters"); ASSIMP_LOG_WARN("Collada: texture format hint is too long, truncating to 3 characters");
@ -1744,7 +1755,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads a float value from an accessor and its data array. // Reads a float value from an accessor and its data array.
ai_real ColladaLoader::ReadFloat(const Collada::Accessor &pAccessor, const Collada::Data &pData, size_t pIndex, size_t pOffset) const { ai_real ColladaLoader::ReadFloat(const Accessor &pAccessor, const Data &pData, size_t pIndex, size_t pOffset) const {
size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset + pOffset; size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset + pOffset;
ai_assert(pos < pData.mValues.size()); ai_assert(pos < pData.mValues.size());
return pData.mValues[pos]; return pData.mValues[pos];
@ -1752,7 +1763,7 @@ ai_real ColladaLoader::ReadFloat(const Collada::Accessor &pAccessor, const Colla
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads a string value from an accessor and its data array. // Reads a string value from an accessor and its data array.
const std::string &ColladaLoader::ReadString(const Collada::Accessor &pAccessor, const Collada::Data &pData, size_t pIndex) const { const std::string &ColladaLoader::ReadString(const Accessor &pAccessor, const Data &pData, size_t pIndex) const {
size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset; size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset;
ai_assert(pos < pData.mStrings.size()); ai_assert(pos < pData.mStrings.size());
return pData.mStrings[pos]; return pData.mStrings[pos];
@ -1769,12 +1780,12 @@ void ColladaLoader::CollectNodes(const aiNode *pNode, std::vector<const aiNode *
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Finds a node in the collada scene by the given name // Finds a node in the collada scene by the given name
const Collada::Node *ColladaLoader::FindNode(const Collada::Node *pNode, const std::string &pName) const { const Node *ColladaLoader::FindNode(const Node *pNode, const std::string &pName) const {
if (pNode->mName == pName || pNode->mID == pName) if (pNode->mName == pName || pNode->mID == pName)
return pNode; return pNode;
for (size_t a = 0; a < pNode->mChildren.size(); ++a) { for (auto a : pNode->mChildren) {
const Collada::Node *node = FindNode(pNode->mChildren[a], pName); const Collada::Node *node = FindNode(a, pName);
if (node) { if (node) {
return node; return node;
} }
@ -1785,7 +1796,7 @@ const Collada::Node *ColladaLoader::FindNode(const Collada::Node *pNode, const s
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Finds a node in the collada scene by the given SID // Finds a node in the collada scene by the given SID
const Collada::Node *ColladaLoader::FindNodeBySID(const Collada::Node *pNode, const std::string &pSID) const { const Node *ColladaLoader::FindNodeBySID(const Node *pNode, const std::string &pSID) const {
if (nullptr == pNode) { if (nullptr == pNode) {
return nullptr; return nullptr;
} }
@ -1794,8 +1805,8 @@ const Collada::Node *ColladaLoader::FindNodeBySID(const Collada::Node *pNode, co
return pNode; return pNode;
} }
for (size_t a = 0; a < pNode->mChildren.size(); ++a) { for (auto a : pNode->mChildren) {
const Collada::Node *node = FindNodeBySID(pNode->mChildren[a], pSID); const Collada::Node *node = FindNodeBySID(a, pSID);
if (node) { if (node) {
return node; return node;
} }
@ -1807,7 +1818,7 @@ const Collada::Node *ColladaLoader::FindNodeBySID(const Collada::Node *pNode, co
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Finds a proper unique name for a node derived from the collada-node's properties. // Finds a proper unique name for a node derived from the collada-node's properties.
// The name must be unique for proper node-bone association. // The name must be unique for proper node-bone association.
std::string ColladaLoader::FindNameForNode(const Collada::Node *pNode) { std::string ColladaLoader::FindNameForNode(const Node *pNode) {
// If explicitly requested, just use the collada name. // If explicitly requested, just use the collada name.
if (useColladaName) { if (useColladaName) {
if (!pNode->mName.empty()) { if (!pNode->mName.empty()) {

View File

@ -4,7 +4,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -45,8 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_COLLADALOADER_H_INC #ifndef AI_COLLADALOADER_H_INC
#define AI_COLLADALOADER_H_INC #define AI_COLLADALOADER_H_INC
#include <assimp/BaseImporter.h>
#include "ColladaParser.h" #include "ColladaParser.h"
#include <assimp/BaseImporter.h>
struct aiNode; struct aiNode;
struct aiCamera; struct aiCamera;
@ -54,28 +54,24 @@ struct aiLight;
struct aiTexture; struct aiTexture;
struct aiAnimation; struct aiAnimation;
namespace Assimp namespace Assimp {
{
struct ColladaMeshIndex struct ColladaMeshIndex {
{
std::string mMeshID; std::string mMeshID;
size_t mSubMesh; size_t mSubMesh;
std::string mMaterial; std::string mMaterial;
ColladaMeshIndex( const std::string& pMeshID, size_t pSubMesh, const std::string& pMaterial) ColladaMeshIndex(const std::string &pMeshID, size_t pSubMesh, const std::string &pMaterial) :
: mMeshID( pMeshID), mSubMesh( pSubMesh), mMaterial( pMaterial) mMeshID(pMeshID), mSubMesh(pSubMesh), mMaterial(pMaterial) {
{ } ai_assert(!pMeshID.empty());
}
bool operator < (const ColladaMeshIndex& p) const bool operator<(const ColladaMeshIndex &p) const {
{ if (mMeshID == p.mMeshID) {
if( mMeshID == p.mMeshID) if (mSubMesh == p.mSubMesh)
{
if( mSubMesh == p.mSubMesh)
return mMaterial < p.mMaterial; return mMaterial < p.mMaterial;
else else
return mSubMesh < p.mSubMesh; return mSubMesh < p.mSubMesh;
} else } else {
{
return mMeshID < p.mMeshID; return mMeshID < p.mMeshID;
} }
} }
@ -84,105 +80,102 @@ struct ColladaMeshIndex
/** Loader class to read Collada scenes. Collada is over-engineered to death, with every new iteration bringing /** Loader class to read Collada scenes. Collada is over-engineered to death, with every new iteration bringing
* more useless stuff, so I limited the data to what I think is useful for games. * more useless stuff, so I limited the data to what I think is useful for games.
*/ */
class ColladaLoader : public BaseImporter class ColladaLoader : public BaseImporter {
{
public: public:
/// The class constructor.
ColladaLoader(); ColladaLoader();
~ColladaLoader();
/// The class destructor.
~ColladaLoader() override;
public: /// Returns whether the class can handle the format of the given file.
/** Returns whether the class can handle the format of the given file. /// @see BaseImporter::CanRead() for more details.
* See BaseImporter::CanRead() for details. */ bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override;
bool CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const override;
protected: protected:
/** Return importer meta information. /// See #BaseImporter::GetInfo for the details
* See #BaseImporter::GetInfo for the details const aiImporterDesc *GetInfo() const override;
*/
const aiImporterDesc* GetInfo () const override;
void SetupProperties(const Importer* pImp) override; /// See #BaseImporter::SetupProperties for the details
void SetupProperties(const Importer *pImp) override;
/** Imports the given file into the given scene structure. /// See #BaseImporter::InternReadFile for the details
* See BaseImporter::InternReadFile() for details void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
*/
void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override;
/** Recursively constructs a scene node for the given parser node and returns it. */ /** Recursively constructs a scene node for the given parser node and returns it. */
aiNode* BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode); aiNode *BuildHierarchy(const ColladaParser &pParser, const Collada::Node *pNode);
/** Resolve node instances */ /** Resolve node instances */
void ResolveNodeInstances( const ColladaParser& pParser, const Collada::Node* pNode, void ResolveNodeInstances(const ColladaParser &pParser, const Collada::Node *pNode,
std::vector<const Collada::Node*>& resolved); std::vector<const Collada::Node *> &resolved);
/** Builds meshes for the given node and references them */ /** Builds meshes for the given node and references them */
void BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode, void BuildMeshesForNode(const ColladaParser &pParser, const Collada::Node *pNode,
aiNode* pTarget); aiNode *pTarget);
aiMesh *findMesh(const std::string& meshid); aiMesh *findMesh(const std::string &meshid);
/** Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh */ /** Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh */
aiMesh* CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh, aiMesh *CreateMesh(const ColladaParser &pParser, const Collada::Mesh *pSrcMesh, const Collada::SubMesh &pSubMesh,
const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace); const Collada::Controller *pSrcController, size_t pStartVertex, size_t pStartFace);
/** Builds cameras for the given node and references them */ /** Builds cameras for the given node and references them */
void BuildCamerasForNode( const ColladaParser& pParser, const Collada::Node* pNode, void BuildCamerasForNode(const ColladaParser &pParser, const Collada::Node *pNode,
aiNode* pTarget); aiNode *pTarget);
/** Builds lights for the given node and references them */ /** Builds lights for the given node and references them */
void BuildLightsForNode( const ColladaParser& pParser, const Collada::Node* pNode, void BuildLightsForNode(const ColladaParser &pParser, const Collada::Node *pNode,
aiNode* pTarget); aiNode *pTarget);
/** Stores all meshes in the given scene */ /** Stores all meshes in the given scene */
void StoreSceneMeshes( aiScene* pScene); void StoreSceneMeshes(aiScene *pScene);
/** Stores all materials in the given scene */ /** Stores all materials in the given scene */
void StoreSceneMaterials( aiScene* pScene); void StoreSceneMaterials(aiScene *pScene);
/** Stores all lights in the given scene */ /** Stores all lights in the given scene */
void StoreSceneLights( aiScene* pScene); void StoreSceneLights(aiScene *pScene);
/** Stores all cameras in the given scene */ /** Stores all cameras in the given scene */
void StoreSceneCameras( aiScene* pScene); void StoreSceneCameras(aiScene *pScene);
/** Stores all textures in the given scene */ /** Stores all textures in the given scene */
void StoreSceneTextures( aiScene* pScene); void StoreSceneTextures(aiScene *pScene);
/** Stores all animations /** Stores all animations
* @param pScene target scene to store the anims * @param pScene target scene to store the anims
*/ */
void StoreAnimations( aiScene* pScene, const ColladaParser& pParser); void StoreAnimations(aiScene *pScene, const ColladaParser &pParser);
/** Stores all animations for the given source anim and its nested child animations /** Stores all animations for the given source anim and its nested child animations
* @param pScene target scene to store the anims * @param pScene target scene to store the anims
* @param pSrcAnim the source animation to process * @param pSrcAnim the source animation to process
* @param pPrefix Prefix to the name in case of nested animations * @param pPrefix Prefix to the name in case of nested animations
*/ */
void StoreAnimations( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string& pPrefix); void StoreAnimations(aiScene *pScene, const ColladaParser &pParser, const Collada::Animation *pSrcAnim, const std::string &pPrefix);
/** Constructs the animation for the given source anim */ /** Constructs the animation for the given source anim */
void CreateAnimation( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string& pName); void CreateAnimation(aiScene *pScene, const ColladaParser &pParser, const Collada::Animation *pSrcAnim, const std::string &pName);
/** Constructs materials from the collada material definitions */ /** Constructs materials from the collada material definitions */
void BuildMaterials( ColladaParser& pParser, aiScene* pScene); void BuildMaterials(ColladaParser &pParser, aiScene *pScene);
/** Fill materials from the collada material definitions */ /** Fill materials from the collada material definitions */
void FillMaterials( const ColladaParser& pParser, aiScene* pScene); void FillMaterials(const ColladaParser &pParser, aiScene *pScene);
/** Resolve UV channel mappings*/ /** Resolve UV channel mappings*/
void ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler, void ApplyVertexToEffectSemanticMapping(Collada::Sampler &sampler,
const Collada::SemanticMappingTable& table); const Collada::SemanticMappingTable &table);
/** Add a texture and all of its sampling properties to a material*/ /** Add a texture and all of its sampling properties to a material*/
void AddTexture ( aiMaterial& mat, const ColladaParser& pParser, void AddTexture(aiMaterial &mat, const ColladaParser &pParser,
const Collada::Effect& effect, const Collada::Effect &effect,
const Collada::Sampler& sampler, const Collada::Sampler &sampler,
aiTextureType type, unsigned int idx = 0); aiTextureType type, unsigned int idx = 0);
/** Resolves the texture name for the given effect texture entry */ /** Resolves the texture name for the given effect texture entry */
aiString FindFilenameForEffectTexture( const ColladaParser& pParser, aiString FindFilenameForEffectTexture(const ColladaParser &pParser,
const Collada::Effect& pEffect, const std::string& pName); const Collada::Effect &pEffect, const std::string &pName);
/** Reads a float value from an accessor and its data array. /** Reads a float value from an accessor and its data array.
* @param pAccessor The accessor to use for reading * @param pAccessor The accessor to use for reading
@ -191,7 +184,7 @@ protected:
* @param pOffset Offset into the element, for multipart elements such as vectors or matrices * @param pOffset Offset into the element, for multipart elements such as vectors or matrices
* @return the specified value * @return the specified value
*/ */
ai_real ReadFloat( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex, size_t pOffset) const; ai_real ReadFloat(const Collada::Accessor &pAccessor, const Collada::Data &pData, size_t pIndex, size_t pOffset) const;
/** Reads a string value from an accessor and its data array. /** Reads a string value from an accessor and its data array.
* @param pAccessor The accessor to use for reading * @param pAccessor The accessor to use for reading
@ -199,18 +192,18 @@ protected:
* @param pIndex The index of the element to retrieve * @param pIndex The index of the element to retrieve
* @return the specified value * @return the specified value
*/ */
const std::string& ReadString( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex) const; const std::string &ReadString(const Collada::Accessor &pAccessor, const Collada::Data &pData, size_t pIndex) const;
/** Recursively collects all nodes into the given array */ /** Recursively collects all nodes into the given array */
void CollectNodes( const aiNode* pNode, std::vector<const aiNode*>& poNodes) const; void CollectNodes(const aiNode *pNode, std::vector<const aiNode *> &poNodes) const;
/** Finds a node in the collada scene by the given name */ /** Finds a node in the collada scene by the given name */
const Collada::Node* FindNode( const Collada::Node* pNode, const std::string& pName) const; const Collada::Node *FindNode(const Collada::Node *pNode, const std::string &pName) const;
/** Finds a node in the collada scene by the given SID */ /** Finds a node in the collada scene by the given SID */
const Collada::Node* FindNodeBySID( const Collada::Node* pNode, const std::string& pSID) const; const Collada::Node *FindNodeBySID(const Collada::Node *pNode, const std::string &pSID) const;
/** Finds a proper name for a node derived from the collada-node's properties */ /** Finds a proper name for a node derived from the collada-node's properties */
std::string FindNameForNode( const Collada::Node* pNode); std::string FindNameForNode(const Collada::Node *pNode);
protected: protected:
/** Filename, for a verbose error message */ /** Filename, for a verbose error message */
@ -223,25 +216,25 @@ protected:
std::map<std::string, size_t> mMaterialIndexByName; std::map<std::string, size_t> mMaterialIndexByName;
/** Accumulated meshes for the target scene */ /** Accumulated meshes for the target scene */
std::vector<aiMesh*> mMeshes; std::vector<aiMesh *> mMeshes;
/** Accumulated morph target meshes */ /** Accumulated morph target meshes */
std::vector<aiMesh*> mTargetMeshes; std::vector<aiMesh *> mTargetMeshes;
/** Temporary material list */ /** Temporary material list */
std::vector<std::pair<Collada::Effect*, aiMaterial*> > newMats; std::vector<std::pair<Collada::Effect *, aiMaterial *>> newMats;
/** Temporary camera list */ /** Temporary camera list */
std::vector<aiCamera*> mCameras; std::vector<aiCamera *> mCameras;
/** Temporary light list */ /** Temporary light list */
std::vector<aiLight*> mLights; std::vector<aiLight *> mLights;
/** Temporary texture list */ /** Temporary texture list */
std::vector<aiTexture*> mTextures; std::vector<aiTexture *> mTextures;
/** Accumulated animations for the target scene */ /** Accumulated animations for the target scene */
std::vector<aiAnimation*> mAnims; std::vector<aiAnimation *> mAnims;
bool noSkeletonMesh; bool noSkeletonMesh;
bool ignoreUpDirection; bool ignoreUpDirection;

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/light.h> #include <assimp/light.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <memory>
using namespace Assimp; using namespace Assimp;
using namespace Assimp::Collada; using namespace Assimp::Collada;
@ -158,9 +159,9 @@ ColladaParser::ColladaParser(IOSystem *pIOHandler, const std::string &pFile) :
if (colladaNode.empty()) { if (colladaNode.empty()) {
return; return;
} }
ReadContents(colladaNode);
// read embedded textures // Read content and embedded textures
ReadContents(colladaNode);
if (zip_archive && zip_archive->isOpen()) { if (zip_archive && zip_archive->isOpen()) {
ReadEmbeddedTextures(*zip_archive); ReadEmbeddedTextures(*zip_archive);
} }
@ -169,11 +170,11 @@ ColladaParser::ColladaParser(IOSystem *pIOHandler, const std::string &pFile) :
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
ColladaParser::~ColladaParser() { ColladaParser::~ColladaParser() {
for (NodeLibrary::iterator it = mNodeLibrary.begin(); it != mNodeLibrary.end(); ++it) { for (auto & it : mNodeLibrary) {
delete it->second; delete it.second;
} }
for (MeshLibrary::iterator it = mMeshLibrary.begin(); it != mMeshLibrary.end(); ++it) { for (auto & it : mMeshLibrary) {
delete it->second; delete it.second;
} }
} }
@ -289,7 +290,7 @@ void ColladaParser::ReadContents(XmlNode &node) {
// Reads the structure of the file // Reads the structure of the file
void ColladaParser::ReadStructure(XmlNode &node) { void ColladaParser::ReadStructure(XmlNode &node) {
for (XmlNode &currentNode : node.children()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = std::string(currentNode.name()); const std::string &currentName = currentNode.name();
if (currentName == "asset") { if (currentName == "asset") {
ReadAssetInfo(currentNode); ReadAssetInfo(currentNode);
} else if (currentName == "library_animations") { } else if (currentName == "library_animations") {
@ -334,7 +335,7 @@ void ColladaParser::ReadAssetInfo(XmlNode &node) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "unit") { if (currentName == "unit") {
mUnitSize = 1.f; mUnitSize = 1.f;
XmlParser::getFloatAttribute(node, "meter", mUnitSize); XmlParser::getRealAttribute(currentNode, "meter", mUnitSize);
} else if (currentName == "up_axis") { } else if (currentName == "up_axis") {
std::string v; std::string v;
if (!XmlParser::getValueAsString(currentNode, v)) { if (!XmlParser::getValueAsString(currentNode, v)) {
@ -371,7 +372,7 @@ void ColladaParser::ReadMetaDataItem(XmlNode &node, StringMetaData &metadata) {
return; return;
} }
trim(v); v = ai_trim(v);
aiString aistr; aiString aistr;
aistr.Set(v); aistr.Set(v);
@ -396,7 +397,7 @@ void ColladaParser::ReadAnimationClipLibrary(XmlNode &node) {
std::string animName; std::string animName;
if (!XmlParser::getStdStrAttribute(node, "name", animName)) { if (!XmlParser::getStdStrAttribute(node, "name", animName)) {
if (!XmlParser::getStdStrAttribute( node, "id", animName )) { if (!XmlParser::getStdStrAttribute( node, "id", animName )) {
animName = std::string("animation_") + to_string(mAnimationClipLibrary.size()); animName = std::string("animation_") + ai_to_string(mAnimationClipLibrary.size());
} }
} }
@ -407,7 +408,7 @@ void ColladaParser::ReadAnimationClipLibrary(XmlNode &node) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "instance_animation") { if (currentName == "instance_animation") {
std::string url; std::string url;
readUrlAttribute(node, url); readUrlAttribute(currentNode, url);
clip.second.push_back(url); clip.second.push_back(url);
} }
@ -419,8 +420,8 @@ void ColladaParser::ReadAnimationClipLibrary(XmlNode &node) {
void ColladaParser::PostProcessControllers() { void ColladaParser::PostProcessControllers() {
std::string meshId; std::string meshId;
for (ControllerLibrary::iterator it = mControllerLibrary.begin(); it != mControllerLibrary.end(); ++it) { for (auto & it : mControllerLibrary) {
meshId = it->second.mMeshId; meshId = it.second.mMeshId;
if (meshId.empty()) { if (meshId.empty()) {
continue; continue;
} }
@ -431,7 +432,7 @@ void ColladaParser::PostProcessControllers() {
findItr = mControllerLibrary.find(meshId); findItr = mControllerLibrary.find(meshId);
} }
it->second.mMeshId = meshId; it.second.mMeshId = meshId;
} }
} }
@ -444,22 +445,19 @@ void ColladaParser::PostProcessRootAnimations() {
} }
Animation temp; Animation temp;
for (AnimationClipLibrary::iterator it = mAnimationClipLibrary.begin(); it != mAnimationClipLibrary.end(); ++it) { for (auto & it : mAnimationClipLibrary) {
std::string clipName = it->first; std::string clipName = it.first;
Animation *clip = new Animation(); Animation *clip = new Animation();
clip->mName = clipName; clip->mName = clipName;
temp.mSubAnims.push_back(clip); temp.mSubAnims.push_back(clip);
for (std::vector<std::string>::iterator a = it->second.begin(); a != it->second.end(); ++a) { for (std::string animationID : it.second) {
std::string animationID = *a;
AnimationLibrary::iterator animation = mAnimationLibrary.find(animationID); AnimationLibrary::iterator animation = mAnimationLibrary.find(animationID);
if (animation != mAnimationLibrary.end()) { if (animation != mAnimationLibrary.end()) {
Animation *pSourceAnimation = animation->second; Animation *pSourceAnimation = animation->second;
pSourceAnimation->CollectChannelsRecursively(clip->mChannels); pSourceAnimation->CollectChannelsRecursively(clip->mChannels);
} }
} }
@ -495,7 +493,7 @@ void ColladaParser::ReadAnimation(XmlNode &node, Collada::Animation *pParent) {
// an <animation> element may be a container for grouping sub-elements or an animation channel // an <animation> element may be a container for grouping sub-elements or an animation channel
// this is the channel collection by ID, in case it has channels // this is the channel collection by ID, in case it has channels
using ChannelMap = std::map<std::string, AnimationChannel> ; using ChannelMap = std::map<std::string, AnimationChannel>;
ChannelMap channels; ChannelMap channels;
// this is the anim container in case we're a container // this is the anim container in case we're a container
Animation *anim = nullptr; Animation *anim = nullptr;
@ -531,17 +529,17 @@ void ColladaParser::ReadAnimation(XmlNode &node, Collada::Animation *pParent) {
// have it read into a channel // have it read into a channel
ChannelMap::iterator newChannel = channels.insert(std::make_pair(id, AnimationChannel())).first; ChannelMap::iterator newChannel = channels.insert(std::make_pair(id, AnimationChannel())).first;
ReadAnimationSampler(currentNode, newChannel->second); ReadAnimationSampler(currentNode, newChannel->second);
} else if (currentName == "channel") { }
std::string source_name, target; } else if (currentName == "channel") {
XmlParser::getStdStrAttribute(currentNode, "source", source_name); std::string source_name, target;
XmlParser::getStdStrAttribute(currentNode, "target", target); XmlParser::getStdStrAttribute(currentNode, "source", source_name);
if (source_name[0] == '#') { XmlParser::getStdStrAttribute(currentNode, "target", target);
source_name = source_name.substr(1, source_name.size() - 1); if (source_name[0] == '#') {
} source_name = source_name.substr(1, source_name.size() - 1);
ChannelMap::iterator cit = channels.find(source_name); }
if (cit != channels.end()) { ChannelMap::iterator cit = channels.find(source_name);
cit->second.mTarget = target; if (cit != channels.end()) {
} cit->second.mTarget = target;
} }
} }
} }
@ -554,8 +552,8 @@ void ColladaParser::ReadAnimation(XmlNode &node, Collada::Animation *pParent) {
pParent->mSubAnims.push_back(anim); pParent->mSubAnims.push_back(anim);
} }
for (ChannelMap::const_iterator it = channels.begin(); it != channels.end(); ++it) { for (const auto & channel : channels) {
anim->mChannels.push_back(it->second); anim->mChannels.push_back(channel.second);
} }
if (idAttr) { if (idAttr) {
@ -610,50 +608,62 @@ void ColladaParser::ReadControllerLibrary(XmlNode &node) {
if (currentName != "controller") { if (currentName != "controller") {
continue; continue;
} }
std::string id = node.attribute("id").as_string(); std::string id;
mControllerLibrary[id] = Controller(); if (XmlParser::getStdStrAttribute(currentNode, "id", id)) {
ReadController(node, mControllerLibrary[id]); mControllerLibrary[id] = Controller();
ReadController(currentNode, mControllerLibrary[id]);
}
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads a controller into the given mesh structure // Reads a controller into the given mesh structure
void ColladaParser::ReadController(XmlNode &node, Collada::Controller &pController) { void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controller) {
// initial values // initial values
pController.mType = Skin; controller.mType = Skin;
pController.mMethod = Normalized; controller.mMethod = Normalized;
for (XmlNode &currentNode : node.children()) {
XmlNodeIterator xmlIt(node);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode;
while (xmlIt.getNext(currentNode)) {
//for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "morph") { if (currentName == "morph") {
pController.mType = Morph; controller.mType = Morph;
pController.mMeshId = currentNode.attribute("source").as_string(); controller.mMeshId = currentNode.attribute("source").as_string();
int methodIndex = currentNode.attribute("method").as_int(); int methodIndex = currentNode.attribute("method").as_int();
if (methodIndex > 0) { if (methodIndex > 0) {
std::string method; std::string method;
XmlParser::getValueAsString(currentNode, method); XmlParser::getValueAsString(currentNode, method);
if (method == "RELATIVE") { if (method == "RELATIVE") {
pController.mMethod = Relative; controller.mMethod = Relative;
} }
} }
} else if (currentName == "skin") { } else if (currentName == "skin") {
pController.mMeshId = currentNode.attribute("source").as_string(); std::string id;
if (XmlParser::getStdStrAttribute(currentNode, "source", id)) {
controller.mMeshId = id.substr(1, id.size()-1);
}
} else if (currentName == "bind_shape_matrix") { } else if (currentName == "bind_shape_matrix") {
std::string v; std::string v;
XmlParser::getValueAsString(currentNode, v); XmlParser::getValueAsString(currentNode, v);
const char *content = v.c_str(); const char *content = v.c_str();
for (unsigned int a = 0; a < 16; a++) { for (unsigned int a = 0; a < 16; a++) {
SkipSpacesAndLineEnd(&content);
// read a number // read a number
content = fast_atoreal_move<ai_real>(content, pController.mBindShapeMatrix[a]); content = fast_atoreal_move<ai_real>(content, controller.mBindShapeMatrix[a]);
// skip whitespace after it // skip whitespace after it
SkipSpacesAndLineEnd(&content); SkipSpacesAndLineEnd(&content);
} }
} else if (currentName == "source") { } else if (currentName == "source") {
ReadSource(currentNode); ReadSource(currentNode);
} else if (currentName == "joints") { } else if (currentName == "joints") {
ReadControllerJoints(currentNode, pController); ReadControllerJoints(currentNode, controller);
} else if (currentName == "vertex_weights") { } else if (currentName == "vertex_weights") {
ReadControllerWeights(currentNode, pController); ReadControllerWeights(currentNode, controller);
} else if (currentName == "targets") { } else if (currentName == "targets") {
for (XmlNode currentChildNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (XmlNode currentChildNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
const std::string &currentChildName = currentChildNode.name(); const std::string &currentChildName = currentChildNode.name();
@ -661,9 +671,9 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &pControll
const char *semantics = currentChildNode.attribute("semantic").as_string(); const char *semantics = currentChildNode.attribute("semantic").as_string();
const char *source = currentChildNode.attribute("source").as_string(); const char *source = currentChildNode.attribute("source").as_string();
if (strcmp(semantics, "MORPH_TARGET") == 0) { if (strcmp(semantics, "MORPH_TARGET") == 0) {
pController.mMorphTarget = source + 1; controller.mMorphTarget = source + 1;
} else if (strcmp(semantics, "MORPH_WEIGHT") == 0) { } else if (strcmp(semantics, "MORPH_WEIGHT") == 0) {
pController.mMorphWeight = source + 1; controller.mMorphWeight = source + 1;
} }
} }
} }
@ -701,6 +711,7 @@ void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pC
// Read vertex count from attributes and resize the array accordingly // Read vertex count from attributes and resize the array accordingly
int vertexCount=0; int vertexCount=0;
XmlParser::getIntAttribute(node, "count", vertexCount); XmlParser::getIntAttribute(node, "count", vertexCount);
pController.mWeightCounts.resize(vertexCount);
for (XmlNode &currentNode : node.children()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
@ -726,7 +737,7 @@ void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pC
throw DeadlyImportError("Unknown semantic \"", attrSemantic, "\" in <vertex_weights> data <input> element"); throw DeadlyImportError("Unknown semantic \"", attrSemantic, "\" in <vertex_weights> data <input> element");
} }
} else if (currentName == "vcount" && vertexCount > 0) { } else if (currentName == "vcount" && vertexCount > 0) {
const char *text = currentNode.value(); const char *text = currentNode.text().as_string();
size_t numWeights = 0; size_t numWeights = 0;
for (std::vector<size_t>::iterator it = pController.mWeightCounts.begin(); it != pController.mWeightCounts.end(); ++it) { for (std::vector<size_t>::iterator it = pController.mWeightCounts.begin(); it != pController.mWeightCounts.end(); ++it) {
if (*text == 0) { if (*text == 0) {
@ -763,18 +774,15 @@ void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pC
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads the image library contents // Reads the image library contents
void ColladaParser::ReadImageLibrary(XmlNode &node) { void ColladaParser::ReadImageLibrary(XmlNode &node) {
if (node.empty()) {
return;
}
for (XmlNode &currentNode : node.children()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "image") { if (currentName == "image") {
std::string id = currentNode.attribute("id").as_string(); std::string id;
mImageLibrary[id] = Image(); if (XmlParser::getStdStrAttribute( currentNode, "id", id )) {
mImageLibrary[id] = Image();
// read on from there // read on from there
ReadImage(currentNode, mImageLibrary[id]); ReadImage(currentNode, mImageLibrary[id]);
}
} }
} }
} }
@ -793,7 +801,7 @@ void ColladaParser::ReadImage(XmlNode &node, Collada::Image &pImage) {
if (!currentNode.empty()) { if (!currentNode.empty()) {
// element content is filename - hopefully // element content is filename - hopefully
const char *sz = currentNode.text().as_string(); const char *sz = currentNode.text().as_string();
if (sz) { if (nullptr != sz) {
aiString filepath(sz); aiString filepath(sz);
UriDecodePath(filepath); UriDecodePath(filepath);
pImage.mFileName = filepath.C_Str(); pImage.mFileName = filepath.C_Str();
@ -843,10 +851,6 @@ void ColladaParser::ReadImage(XmlNode &node, Collada::Image &pImage) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads the material library // Reads the material library
void ColladaParser::ReadMaterialLibrary(XmlNode &node) { void ColladaParser::ReadMaterialLibrary(XmlNode &node) {
if (node.empty()) {
return;
}
std::map<std::string, int> names; std::map<std::string, int> names;
for (XmlNode &currentNode : node.children()) { for (XmlNode &currentNode : node.children()) {
std::string id = currentNode.attribute("id").as_string(); std::string id = currentNode.attribute("id").as_string();
@ -873,10 +877,6 @@ void ColladaParser::ReadMaterialLibrary(XmlNode &node) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads the light library // Reads the light library
void ColladaParser::ReadLightLibrary(XmlNode &node) { void ColladaParser::ReadLightLibrary(XmlNode &node) {
if (node.empty()) {
return;
}
for (XmlNode &currentNode : node.children()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "light") { if (currentName == "light") {
@ -891,10 +891,6 @@ void ColladaParser::ReadLightLibrary(XmlNode &node) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads the camera library // Reads the camera library
void ColladaParser::ReadCameraLibrary(XmlNode &node) { void ColladaParser::ReadCameraLibrary(XmlNode &node) {
if (node.empty()) {
return;
}
for (XmlNode &currentNode : node.children()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "camera") { if (currentName == "camera") {
@ -961,33 +957,33 @@ void ColladaParser::ReadLight(XmlNode &node, Collada::Light &pLight) {
content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.b); content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.b);
SkipSpacesAndLineEnd(&content); SkipSpacesAndLineEnd(&content);
} else if (currentName == "constant_attenuation") { } else if (currentName == "constant_attenuation") {
XmlParser::getFloatAttribute(currentNode, "constant_attenuation", pLight.mAttConstant); XmlParser::getRealAttribute(currentNode, "constant_attenuation", pLight.mAttConstant);
} else if (currentName == "linear_attenuation") { } else if (currentName == "linear_attenuation") {
XmlParser::getFloatAttribute(currentNode, "linear_attenuation", pLight.mAttLinear); XmlParser::getRealAttribute(currentNode, "linear_attenuation", pLight.mAttLinear);
} else if (currentName == "quadratic_attenuation") { } else if (currentName == "quadratic_attenuation") {
XmlParser::getFloatAttribute(currentNode, "quadratic_attenuation", pLight.mAttQuadratic); XmlParser::getRealAttribute(currentNode, "quadratic_attenuation", pLight.mAttQuadratic);
} else if (currentName == "falloff_angle") { } else if (currentName == "falloff_angle") {
XmlParser::getFloatAttribute(currentNode, "falloff_angle", pLight.mFalloffAngle); XmlParser::getRealAttribute(currentNode, "falloff_angle", pLight.mFalloffAngle);
} else if (currentName == "falloff_exponent") { } else if (currentName == "falloff_exponent") {
XmlParser::getFloatAttribute(currentNode, "falloff_exponent", pLight.mFalloffExponent); XmlParser::getRealAttribute(currentNode, "falloff_exponent", pLight.mFalloffExponent);
} }
// FCOLLADA extensions // FCOLLADA extensions
// ------------------------------------------------------- // -------------------------------------------------------
else if (currentName == "outer_cone") { else if (currentName == "outer_cone") {
XmlParser::getFloatAttribute(currentNode, "outer_cone", pLight.mOuterAngle); XmlParser::getRealAttribute(currentNode, "outer_cone", pLight.mOuterAngle);
} else if (currentName == "penumbra_angle") { // ... and this one is even deprecated } else if (currentName == "penumbra_angle") { // ... and this one is even deprecated
XmlParser::getFloatAttribute(currentNode, "penumbra_angle", pLight.mPenumbraAngle); XmlParser::getRealAttribute(currentNode, "penumbra_angle", pLight.mPenumbraAngle);
} else if (currentName == "intensity") { } else if (currentName == "intensity") {
XmlParser::getFloatAttribute(currentNode, "intensity", pLight.mIntensity); XmlParser::getRealAttribute(currentNode, "intensity", pLight.mIntensity);
} else if (currentName == "falloff") { } else if (currentName == "falloff") {
XmlParser::getFloatAttribute(currentNode, "falloff", pLight.mOuterAngle); XmlParser::getRealAttribute(currentNode, "falloff", pLight.mOuterAngle);
} else if (currentName == "hotspot_beam") { } else if (currentName == "hotspot_beam") {
XmlParser::getFloatAttribute(currentNode, "hotspot_beam", pLight.mFalloffAngle); XmlParser::getRealAttribute(currentNode, "hotspot_beam", pLight.mFalloffAngle);
} }
// OpenCOLLADA extensions // OpenCOLLADA extensions
// ------------------------------------------------------- // -------------------------------------------------------
else if (currentName == "decay_falloff") { else if (currentName == "decay_falloff") {
XmlParser::getFloatAttribute(currentNode, "decay_falloff", pLight.mOuterAngle); XmlParser::getRealAttribute(currentNode, "decay_falloff", pLight.mOuterAngle);
} }
} }
} }
@ -1166,15 +1162,15 @@ void ColladaParser::ReadSamplerProperties(XmlNode &node, Sampler &out) {
} else if (currentName == "mirrorV") { } else if (currentName == "mirrorV") {
XmlParser::getBoolAttribute(currentNode, currentName.c_str(), out.mMirrorV); XmlParser::getBoolAttribute(currentNode, currentName.c_str(), out.mMirrorV);
} else if (currentName == "repeatU") { } else if (currentName == "repeatU") {
XmlParser::getFloatAttribute(currentNode, currentName.c_str(), out.mTransform.mScaling.x); XmlParser::getRealAttribute(currentNode, currentName.c_str(), out.mTransform.mScaling.x);
} else if (currentName == "repeatV") { } else if (currentName == "repeatV") {
XmlParser::getFloatAttribute(currentNode, currentName.c_str(), out.mTransform.mScaling.y); XmlParser::getRealAttribute(currentNode, currentName.c_str(), out.mTransform.mScaling.y);
} else if (currentName == "offsetU") { } else if (currentName == "offsetU") {
XmlParser::getFloatAttribute(currentNode, currentName.c_str(), out.mTransform.mTranslation.x); XmlParser::getRealAttribute(currentNode, currentName.c_str(), out.mTransform.mTranslation.x);
} else if (currentName == "offsetV") { } else if (currentName == "offsetV") {
XmlParser::getFloatAttribute(currentNode, currentName.c_str(), out.mTransform.mTranslation.y); XmlParser::getRealAttribute(currentNode, currentName.c_str(), out.mTransform.mTranslation.y);
} else if (currentName == "rotateUV") { } else if (currentName == "rotateUV") {
XmlParser::getFloatAttribute(currentNode, currentName.c_str(), out.mTransform.mRotation); XmlParser::getRealAttribute(currentNode, currentName.c_str(), out.mTransform.mRotation);
} else if (currentName == "blend_mode") { } else if (currentName == "blend_mode") {
std::string v; std::string v;
XmlParser::getValueAsString(currentNode, v); XmlParser::getValueAsString(currentNode, v);
@ -1194,14 +1190,14 @@ void ColladaParser::ReadSamplerProperties(XmlNode &node, Sampler &out) {
// OKINO extensions // OKINO extensions
// ------------------------------------------------------- // -------------------------------------------------------
else if (currentName == "weighting") { else if (currentName == "weighting") {
XmlParser::getFloatAttribute(currentNode, currentName.c_str(), out.mWeighting); XmlParser::getRealAttribute(currentNode, currentName.c_str(), out.mWeighting);
} else if (currentName == "mix_with_previous_layer") { } else if (currentName == "mix_with_previous_layer") {
XmlParser::getFloatAttribute(currentNode, currentName.c_str(), out.mMixWithPrevious); XmlParser::getRealAttribute(currentNode, currentName.c_str(), out.mMixWithPrevious);
} }
// MAX3D extensions // MAX3D extensions
// ------------------------------------------------------- // -------------------------------------------------------
else if (currentName == "amount") { else if (currentName == "amount") {
XmlParser::getFloatAttribute(currentNode, currentName.c_str(), out.mWeighting); XmlParser::getRealAttribute(currentNode, currentName.c_str(), out.mWeighting);
} }
} }
} }
@ -1419,7 +1415,7 @@ void ColladaParser::ReadDataArray(XmlNode &node) {
XmlParser::getUIntAttribute(node, "count", count); XmlParser::getUIntAttribute(node, "count", count);
std::string v; std::string v;
XmlParser::getValueAsString(node, v); XmlParser::getValueAsString(node, v);
trim(v); v = ai_trim(v);
const char *content = v.c_str(); const char *content = v.c_str();
// read values and store inside an array in the data library // read values and store inside an array in the data library
@ -1738,14 +1734,16 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
// and read all indices into a temporary array // and read all indices into a temporary array
std::vector<size_t> indices; std::vector<size_t> indices;
if (expectedPointCount > 0) if (expectedPointCount > 0) {
indices.reserve(expectedPointCount * numOffsets); indices.reserve(expectedPointCount * numOffsets);
}
if (pNumPrimitives > 0) // It is possible to not contain any indices // It is possible to not contain any indices
{ if (pNumPrimitives > 0) {
std::string v; std::string v;
XmlParser::getValueAsString(node, v); XmlParser::getValueAsString(node, v);
const char *content = v.c_str(); const char *content = v.c_str();
SkipSpacesAndLineEnd(&content);
while (*content != 0) { while (*content != 0) {
// read a value. // read a value.
// Hack: (thom) Some exporters put negative indices sometimes. We just try to carry on anyways. // Hack: (thom) Some exporters put negative indices sometimes. We just try to carry on anyways.
@ -1772,21 +1770,24 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
// find the data for all sources // find the data for all sources
for (std::vector<InputChannel>::iterator it = pMesh.mPerVertexData.begin(); it != pMesh.mPerVertexData.end(); ++it) { for (std::vector<InputChannel>::iterator it = pMesh.mPerVertexData.begin(); it != pMesh.mPerVertexData.end(); ++it) {
InputChannel &input = *it; InputChannel &input = *it;
if (input.mResolved) if (input.mResolved) {
continue; continue;
}
// find accessor // find accessor
input.mResolved = &ResolveLibraryReference(mAccessorLibrary, input.mAccessor); input.mResolved = &ResolveLibraryReference(mAccessorLibrary, input.mAccessor);
// resolve accessor's data pointer as well, if necessary // resolve accessor's data pointer as well, if necessary
const Accessor *acc = input.mResolved; const Accessor *acc = input.mResolved;
if (!acc->mData) if (!acc->mData) {
acc->mData = &ResolveLibraryReference(mDataLibrary, acc->mSource); acc->mData = &ResolveLibraryReference(mDataLibrary, acc->mSource);
}
} }
// and the same for the per-index channels // and the same for the per-index channels
for (std::vector<InputChannel>::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it) { for (std::vector<InputChannel>::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it) {
InputChannel &input = *it; InputChannel &input = *it;
if (input.mResolved) if (input.mResolved) {
continue; continue;
}
// ignore vertex pointer, it doesn't refer to an accessor // ignore vertex pointer, it doesn't refer to an accessor
if (input.mType == IT_Vertex) { if (input.mType == IT_Vertex) {
@ -1801,8 +1802,9 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
input.mResolved = &ResolveLibraryReference(mAccessorLibrary, input.mAccessor); input.mResolved = &ResolveLibraryReference(mAccessorLibrary, input.mAccessor);
// resolve accessor's data pointer as well, if necessary // resolve accessor's data pointer as well, if necessary
const Accessor *acc = input.mResolved; const Accessor *acc = input.mResolved;
if (!acc->mData) if (!acc->mData) {
acc->mData = &ResolveLibraryReference(mDataLibrary, acc->mSource); acc->mData = &ResolveLibraryReference(mDataLibrary, acc->mSource);
}
} }
// For continued primitives, the given count does not come all in one <p>, but only one primitive per <p> // For continued primitives, the given count does not come all in one <p>, but only one primitive per <p>
@ -1884,11 +1886,13 @@ void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t n
ai_assert((baseOffset + numOffsets - 1) < indices.size()); ai_assert((baseOffset + numOffsets - 1) < indices.size());
// extract per-vertex channels using the global per-vertex offset // extract per-vertex channels using the global per-vertex offset
for (std::vector<InputChannel>::iterator it = pMesh.mPerVertexData.begin(); it != pMesh.mPerVertexData.end(); ++it) for (std::vector<InputChannel>::iterator it = pMesh.mPerVertexData.begin(); it != pMesh.mPerVertexData.end(); ++it) {
ExtractDataObjectFromChannel(*it, indices[baseOffset + perVertexOffset], pMesh); ExtractDataObjectFromChannel(*it, indices[baseOffset + perVertexOffset], pMesh);
}
// and extract per-index channels using there specified offset // and extract per-index channels using there specified offset
for (std::vector<InputChannel>::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it) for (std::vector<InputChannel>::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it) {
ExtractDataObjectFromChannel(*it, indices[baseOffset + it->mOffset], pMesh); ExtractDataObjectFromChannel(*it, indices[baseOffset + it->mOffset], pMesh);
}
// store the vertex-data index for later assignment of bone vertex weights // store the vertex-data index for later assignment of bone vertex weights
pMesh.mFacePosIndices.push_back(indices[baseOffset + perVertexOffset]); pMesh.mFacePosIndices.push_back(indices[baseOffset + perVertexOffset]);
@ -1912,8 +1916,9 @@ void ColladaParser::ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset,
// Extracts a single object from an input channel and stores it in the appropriate mesh data array // Extracts a single object from an input channel and stores it in the appropriate mesh data array
void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, size_t pLocalIndex, Mesh &pMesh) { void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, size_t pLocalIndex, Mesh &pMesh) {
// ignore vertex referrer - we handle them that separate // ignore vertex referrer - we handle them that separate
if (pInput.mType == IT_Vertex) if (pInput.mType == IT_Vertex) {
return; return;
}
const Accessor &acc = *pInput.mResolved; const Accessor &acc = *pInput.mResolved;
if (pLocalIndex >= acc.mCount) { if (pLocalIndex >= acc.mCount) {
@ -1926,86 +1931,93 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, siz
// assemble according to the accessors component sub-offset list. We don't care, yet, // assemble according to the accessors component sub-offset list. We don't care, yet,
// what kind of object exactly we're extracting here // what kind of object exactly we're extracting here
ai_real obj[4]; ai_real obj[4];
for (size_t c = 0; c < 4; ++c) for (size_t c = 0; c < 4; ++c) {
obj[c] = dataObject[acc.mSubOffset[c]]; obj[c] = dataObject[acc.mSubOffset[c]];
}
// now we reinterpret it according to the type we're reading here // now we reinterpret it according to the type we're reading here
switch (pInput.mType) { switch (pInput.mType) {
case IT_Position: // ignore all position streams except 0 - there can be only one position case IT_Position: // ignore all position streams except 0 - there can be only one position
if (pInput.mIndex == 0) if (pInput.mIndex == 0) {
pMesh.mPositions.push_back(aiVector3D(obj[0], obj[1], obj[2])); pMesh.mPositions.push_back(aiVector3D(obj[0], obj[1], obj[2]));
else } else {
ASSIMP_LOG_ERROR("Collada: just one vertex position stream supported"); ASSIMP_LOG_ERROR("Collada: just one vertex position stream supported");
break;
case IT_Normal:
// pad to current vertex count if necessary
if (pMesh.mNormals.size() < pMesh.mPositions.size() - 1)
pMesh.mNormals.insert(pMesh.mNormals.end(), pMesh.mPositions.size() - pMesh.mNormals.size() - 1, aiVector3D(0, 1, 0));
// ignore all normal streams except 0 - there can be only one normal
if (pInput.mIndex == 0)
pMesh.mNormals.push_back(aiVector3D(obj[0], obj[1], obj[2]));
else
ASSIMP_LOG_ERROR("Collada: just one vertex normal stream supported");
break;
case IT_Tangent:
// pad to current vertex count if necessary
if (pMesh.mTangents.size() < pMesh.mPositions.size() - 1)
pMesh.mTangents.insert(pMesh.mTangents.end(), pMesh.mPositions.size() - pMesh.mTangents.size() - 1, aiVector3D(1, 0, 0));
// ignore all tangent streams except 0 - there can be only one tangent
if (pInput.mIndex == 0)
pMesh.mTangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
else
ASSIMP_LOG_ERROR("Collada: just one vertex tangent stream supported");
break;
case IT_Bitangent:
// pad to current vertex count if necessary
if (pMesh.mBitangents.size() < pMesh.mPositions.size() - 1)
pMesh.mBitangents.insert(pMesh.mBitangents.end(), pMesh.mPositions.size() - pMesh.mBitangents.size() - 1, aiVector3D(0, 0, 1));
// ignore all bitangent streams except 0 - there can be only one bitangent
if (pInput.mIndex == 0)
pMesh.mBitangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
else
ASSIMP_LOG_ERROR("Collada: just one vertex bitangent stream supported");
break;
case IT_Texcoord:
// up to 4 texture coord sets are fine, ignore the others
if (pInput.mIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS) {
// pad to current vertex count if necessary
if (pMesh.mTexCoords[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
pMesh.mTexCoords[pInput.mIndex].insert(pMesh.mTexCoords[pInput.mIndex].end(),
pMesh.mPositions.size() - pMesh.mTexCoords[pInput.mIndex].size() - 1, aiVector3D(0, 0, 0));
pMesh.mTexCoords[pInput.mIndex].push_back(aiVector3D(obj[0], obj[1], obj[2]));
if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) /* hack ... consider cleaner solution */
pMesh.mNumUVComponents[pInput.mIndex] = 3;
} else {
ASSIMP_LOG_ERROR("Collada: too many texture coordinate sets. Skipping.");
}
break;
case IT_Color:
// up to 4 color sets are fine, ignore the others
if (pInput.mIndex < AI_MAX_NUMBER_OF_COLOR_SETS) {
// pad to current vertex count if necessary
if (pMesh.mColors[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
pMesh.mColors[pInput.mIndex].insert(pMesh.mColors[pInput.mIndex].end(),
pMesh.mPositions.size() - pMesh.mColors[pInput.mIndex].size() - 1, aiColor4D(0, 0, 0, 1));
aiColor4D result(0, 0, 0, 1);
for (size_t i = 0; i < pInput.mResolved->mSize; ++i) {
result[static_cast<unsigned int>(i)] = obj[pInput.mResolved->mSubOffset[i]];
} }
pMesh.mColors[pInput.mIndex].push_back(result); break;
} else { case IT_Normal:
ASSIMP_LOG_ERROR("Collada: too many vertex color sets. Skipping."); // pad to current vertex count if necessary
} if (pMesh.mNormals.size() < pMesh.mPositions.size() - 1)
pMesh.mNormals.insert(pMesh.mNormals.end(), pMesh.mPositions.size() - pMesh.mNormals.size() - 1, aiVector3D(0, 1, 0));
break; // ignore all normal streams except 0 - there can be only one normal
default: if (pInput.mIndex == 0) {
// IT_Invalid and IT_Vertex pMesh.mNormals.push_back(aiVector3D(obj[0], obj[1], obj[2]));
ai_assert(false && "shouldn't ever get here"); } else {
ASSIMP_LOG_ERROR("Collada: just one vertex normal stream supported");
}
break;
case IT_Tangent:
// pad to current vertex count if necessary
if (pMesh.mTangents.size() < pMesh.mPositions.size() - 1)
pMesh.mTangents.insert(pMesh.mTangents.end(), pMesh.mPositions.size() - pMesh.mTangents.size() - 1, aiVector3D(1, 0, 0));
// ignore all tangent streams except 0 - there can be only one tangent
if (pInput.mIndex == 0) {
pMesh.mTangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
} else {
ASSIMP_LOG_ERROR("Collada: just one vertex tangent stream supported");
}
break;
case IT_Bitangent:
// pad to current vertex count if necessary
if (pMesh.mBitangents.size() < pMesh.mPositions.size() - 1) {
pMesh.mBitangents.insert(pMesh.mBitangents.end(), pMesh.mPositions.size() - pMesh.mBitangents.size() - 1, aiVector3D(0, 0, 1));
}
// ignore all bitangent streams except 0 - there can be only one bitangent
if (pInput.mIndex == 0) {
pMesh.mBitangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
} else {
ASSIMP_LOG_ERROR("Collada: just one vertex bitangent stream supported");
}
break;
case IT_Texcoord:
// up to 4 texture coord sets are fine, ignore the others
if (pInput.mIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS) {
// pad to current vertex count if necessary
if (pMesh.mTexCoords[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
pMesh.mTexCoords[pInput.mIndex].insert(pMesh.mTexCoords[pInput.mIndex].end(),
pMesh.mPositions.size() - pMesh.mTexCoords[pInput.mIndex].size() - 1, aiVector3D(0, 0, 0));
pMesh.mTexCoords[pInput.mIndex].push_back(aiVector3D(obj[0], obj[1], obj[2]));
if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) {
pMesh.mNumUVComponents[pInput.mIndex] = 3;
}
} else {
ASSIMP_LOG_ERROR("Collada: too many texture coordinate sets. Skipping.");
}
break;
case IT_Color:
// up to 4 color sets are fine, ignore the others
if (pInput.mIndex < AI_MAX_NUMBER_OF_COLOR_SETS) {
// pad to current vertex count if necessary
if (pMesh.mColors[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
pMesh.mColors[pInput.mIndex].insert(pMesh.mColors[pInput.mIndex].end(),
pMesh.mPositions.size() - pMesh.mColors[pInput.mIndex].size() - 1, aiColor4D(0, 0, 0, 1));
aiColor4D result(0, 0, 0, 1);
for (size_t i = 0; i < pInput.mResolved->mSize; ++i) {
result[static_cast<unsigned int>(i)] = obj[pInput.mResolved->mSubOffset[i]];
}
pMesh.mColors[pInput.mIndex].push_back(result);
} else {
ASSIMP_LOG_ERROR("Collada: too many vertex color sets. Skipping.");
}
break;
default:
// IT_Invalid and IT_Vertex
ai_assert(false && "shouldn't ever get here");
} }
} }

View File

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

View File

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

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team

View File

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

View File

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

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -473,7 +473,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
catch (const DeadlyImportError& e) catch (const DeadlyImportError& e)
{ {
if (!is64bits && (length > std::numeric_limits<std::uint32_t>::max())) { if (!is64bits && (length > std::numeric_limits<std::uint32_t>::max())) {
throw DeadlyImportError("The FBX file is invalid. This may be because the content is too big for this older version (", to_string(version), ") of the FBX format. (", e.what(), ")"); throw DeadlyImportError("The FBX file is invalid. This may be because the content is too big for this older version (", ai_to_string(version), ") of the FBX format. (", e.what(), ")");
} }
throw; throw;
} }

View File

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

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -62,16 +62,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef ASSIMP_FBX_USE_UNORDERED_MULTIMAP #ifdef ASSIMP_FBX_USE_UNORDERED_MULTIMAP
# include <unordered_map> # include <unordered_map>
# include <unordered_set> # include <unordered_set>
# if _MSC_VER > 1600 # if defined(_MSC_VER) && _MSC_VER <= 1600
# define fbx_unordered_map unordered_map
# define fbx_unordered_multimap unordered_multimap
# define fbx_unordered_set unordered_set
# define fbx_unordered_multiset unordered_multiset
# else
# define fbx_unordered_map tr1::unordered_map # define fbx_unordered_map tr1::unordered_map
# define fbx_unordered_multimap tr1::unordered_multimap # define fbx_unordered_multimap tr1::unordered_multimap
# define fbx_unordered_set tr1::unordered_set # define fbx_unordered_set tr1::unordered_set
# define fbx_unordered_multiset tr1::unordered_multiset # define fbx_unordered_multiset tr1::unordered_multiset
# else
# define fbx_unordered_map unordered_map
# define fbx_unordered_multimap unordered_multimap
# define fbx_unordered_set unordered_set
# define fbx_unordered_multiset unordered_multiset
# endif # endif
#endif #endif

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -3440,7 +3440,7 @@ void FBXConverter::ConvertGlobalSettings() {
mSceneOut->mMetaData->Set(12, "TimeSpanStart", doc.GlobalSettings().TimeSpanStart()); mSceneOut->mMetaData->Set(12, "TimeSpanStart", doc.GlobalSettings().TimeSpanStart());
mSceneOut->mMetaData->Set(13, "TimeSpanStop", doc.GlobalSettings().TimeSpanStop()); mSceneOut->mMetaData->Set(13, "TimeSpanStop", doc.GlobalSettings().TimeSpanStop());
mSceneOut->mMetaData->Set(14, "CustomFrameRate", doc.GlobalSettings().CustomFrameRate()); mSceneOut->mMetaData->Set(14, "CustomFrameRate", doc.GlobalSettings().CustomFrameRate());
mSceneOut->mMetaData->Set(15, AI_METADATA_SOURCE_FORMAT_VERSION, aiString(to_string(doc.FBXVersion()))); mSceneOut->mMetaData->Set(15, AI_METADATA_SOURCE_FORMAT_VERSION, aiString(ai_to_string(doc.FBXVersion())));
if (hasGenerator) { if (hasGenerator) {
mSceneOut->mMetaData->Set(16, AI_METADATA_SOURCE_GENERATOR, aiString(doc.Creator())); mSceneOut->mMetaData->Set(16, AI_METADATA_SOURCE_GENERATOR, aiString(doc.Creator()));
} }
@ -3454,42 +3454,42 @@ void FBXConverter::TransferDataToScene() {
// many C++ users seem to know this, so pointing it out to avoid // many C++ users seem to know this, so pointing it out to avoid
// confusion why this code works. // confusion why this code works.
if (mMeshes.size()) { if (!mMeshes.empty()) {
mSceneOut->mMeshes = new aiMesh *[mMeshes.size()](); mSceneOut->mMeshes = new aiMesh *[mMeshes.size()]();
mSceneOut->mNumMeshes = static_cast<unsigned int>(mMeshes.size()); mSceneOut->mNumMeshes = static_cast<unsigned int>(mMeshes.size());
std::swap_ranges(mMeshes.begin(), mMeshes.end(), mSceneOut->mMeshes); std::swap_ranges(mMeshes.begin(), mMeshes.end(), mSceneOut->mMeshes);
} }
if (materials.size()) { if (!materials.empty()) {
mSceneOut->mMaterials = new aiMaterial *[materials.size()](); mSceneOut->mMaterials = new aiMaterial *[materials.size()]();
mSceneOut->mNumMaterials = static_cast<unsigned int>(materials.size()); mSceneOut->mNumMaterials = static_cast<unsigned int>(materials.size());
std::swap_ranges(materials.begin(), materials.end(), mSceneOut->mMaterials); std::swap_ranges(materials.begin(), materials.end(), mSceneOut->mMaterials);
} }
if (animations.size()) { if (!animations.empty()) {
mSceneOut->mAnimations = new aiAnimation *[animations.size()](); mSceneOut->mAnimations = new aiAnimation *[animations.size()]();
mSceneOut->mNumAnimations = static_cast<unsigned int>(animations.size()); mSceneOut->mNumAnimations = static_cast<unsigned int>(animations.size());
std::swap_ranges(animations.begin(), animations.end(), mSceneOut->mAnimations); std::swap_ranges(animations.begin(), animations.end(), mSceneOut->mAnimations);
} }
if (lights.size()) { if (!lights.empty()) {
mSceneOut->mLights = new aiLight *[lights.size()](); mSceneOut->mLights = new aiLight *[lights.size()]();
mSceneOut->mNumLights = static_cast<unsigned int>(lights.size()); mSceneOut->mNumLights = static_cast<unsigned int>(lights.size());
std::swap_ranges(lights.begin(), lights.end(), mSceneOut->mLights); std::swap_ranges(lights.begin(), lights.end(), mSceneOut->mLights);
} }
if (cameras.size()) { if (!cameras.empty()) {
mSceneOut->mCameras = new aiCamera *[cameras.size()](); mSceneOut->mCameras = new aiCamera *[cameras.size()]();
mSceneOut->mNumCameras = static_cast<unsigned int>(cameras.size()); mSceneOut->mNumCameras = static_cast<unsigned int>(cameras.size());
std::swap_ranges(cameras.begin(), cameras.end(), mSceneOut->mCameras); std::swap_ranges(cameras.begin(), cameras.end(), mSceneOut->mCameras);
} }
if (textures.size()) { if (!textures.empty()) {
mSceneOut->mTextures = new aiTexture *[textures.size()](); mSceneOut->mTextures = new aiTexture *[textures.size()]();
mSceneOut->mNumTextures = static_cast<unsigned int>(textures.size()); mSceneOut->mNumTextures = static_cast<unsigned int>(textures.size());

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -426,7 +426,7 @@ void FBX::Node::WritePropertyNodeAscii(
char buffer[32]; char buffer[32];
FBX::Node node(name); FBX::Node node(name);
node.Begin(s, false, indent); node.Begin(s, false, indent);
std::string vsize = to_string(v.size()); std::string vsize = ai_to_string(v.size());
// *<size> { // *<size> {
s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n"); s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n");
// indent + 1 // indent + 1
@ -462,7 +462,7 @@ void FBX::Node::WritePropertyNodeAscii(
char buffer[32]; char buffer[32];
FBX::Node node(name); FBX::Node node(name);
node.Begin(s, false, indent); node.Begin(s, false, indent);
std::string vsize = to_string(v.size()); std::string vsize = ai_to_string(v.size());
// *<size> { // *<size> {
s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n"); s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n");
// indent + 1 // indent + 1

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -812,6 +812,18 @@ void FBXExporter::WriteDefinitions ()
// Geometry / FbxMesh // Geometry / FbxMesh
// <~~ aiMesh // <~~ aiMesh
count = mScene->mNumMeshes; count = mScene->mNumMeshes;
// Blendshapes are considered Geometry
int32_t bsDeformerCount=0;
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
aiMesh* m = mScene->mMeshes[mi];
if (m->mNumAnimMeshes > 0) {
count+=m->mNumAnimMeshes;
bsDeformerCount+=m->mNumAnimMeshes; // One deformer per blendshape
bsDeformerCount++; // Plus one master blendshape deformer
}
}
if (count) { if (count) {
n = FBX::Node("ObjectType", "Geometry"); n = FBX::Node("ObjectType", "Geometry");
n.AddChild("Count", count); n.AddChild("Count", count);
@ -978,7 +990,7 @@ void FBXExporter::WriteDefinitions ()
} }
// Deformer // Deformer
count = int32_t(count_deformers(mScene)); count = int32_t(count_deformers(mScene))+bsDeformerCount;
if (count) { if (count) {
n = FBX::Node("ObjectType", "Deformer"); n = FBX::Node("ObjectType", "Deformer");
n.AddChild("Count", count); n.AddChild("Count", count);
@ -1363,6 +1375,7 @@ void FBXExporter::WriteObjects ()
n.End(outstream, binary, indent, true); n.End(outstream, binary, indent, true);
} }
// aiMaterial // aiMaterial
material_uids.clear(); material_uids.clear();
for (size_t i = 0; i < mScene->mNumMaterials; ++i) { for (size_t i = 0; i < mScene->mNumMaterials; ++i) {
@ -1697,6 +1710,100 @@ void FBXExporter::WriteObjects ()
} }
} }
// Blendshapes, if any
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
const aiMesh* m = mScene->mMeshes[mi];
if (m->mNumAnimMeshes == 0) {
continue;
}
// make a deformer for this mesh
int64_t deformer_uid = generate_uid();
FBX::Node dnode("Deformer");
dnode.AddProperties(deformer_uid, m->mName.data + FBX::SEPARATOR + "Blendshapes", "BlendShape");
dnode.AddChild("Version", int32_t(101));
dnode.Dump(outstream, binary, indent);
// connect it
connections.emplace_back("C", "OO", deformer_uid, mesh_uids[mi]);
std::vector<int32_t> vertex_indices = vVertexIndice[mi];
for (unsigned int am = 0; am < m->mNumAnimMeshes; ++am) {
aiAnimMesh *pAnimMesh = m->mAnimMeshes[am];
std::string blendshape_name = pAnimMesh->mName.data;
// start the node record
FBX::Node bsnode("Geometry");
int64_t blendshape_uid = generate_uid();
mesh_uids.push_back(blendshape_uid);
bsnode.AddProperty(blendshape_uid);
bsnode.AddProperty(blendshape_name + FBX::SEPARATOR + "Blendshape");
bsnode.AddProperty("Shape");
bsnode.AddChild("Version", int32_t(100));
bsnode.Begin(outstream, binary, indent);
bsnode.DumpProperties(outstream, binary, indent);
bsnode.EndProperties(outstream, binary, indent);
bsnode.BeginChildren(outstream, binary, indent);
indent++;
if (pAnimMesh->HasPositions()) {
std::vector<int32_t>shape_indices;
std::vector<double>pPositionDiff;
std::vector<double>pNormalDiff;
for (unsigned int vt = 0; vt < vertex_indices.size(); ++vt) {
aiVector3D pDiff = (pAnimMesh->mVertices[vertex_indices[vt]] - m->mVertices[vertex_indices[vt]]);
if(pDiff.Length()>1e-8){
shape_indices.push_back(vertex_indices[vt]);
pPositionDiff.push_back(pDiff[0]);
pPositionDiff.push_back(pDiff[1]);
pPositionDiff.push_back(pDiff[2]);
if (pAnimMesh->HasNormals()) {
aiVector3D nDiff = (pAnimMesh->mNormals[vertex_indices[vt]] - m->mNormals[vertex_indices[vt]]);
pNormalDiff.push_back(nDiff[0]);
pNormalDiff.push_back(nDiff[1]);
pNormalDiff.push_back(nDiff[2]);
}
}
}
FBX::Node::WritePropertyNode(
"Indexes", shape_indices, outstream, binary, indent
);
FBX::Node::WritePropertyNode(
"Vertices", pPositionDiff, outstream, binary, indent
);
if (pNormalDiff.size()>0) {
FBX::Node::WritePropertyNode(
"Normals", pNormalDiff, outstream, binary, indent
);
}
}
indent--;
bsnode.End(outstream, binary, indent, true);
// Add blendshape Channel Deformer
FBX::Node sdnode("Deformer");
const int64_t blendchannel_uid = generate_uid();
sdnode.AddProperties(
blendchannel_uid, blendshape_name + FBX::SEPARATOR + "SubDeformer", "BlendShapeChannel"
);
sdnode.AddChild("Version", int32_t(100));
sdnode.AddChild("DeformPercent", float_t(0.0));
FBX::Node p("Properties70");
p.AddP70numberA("DeformPercent", 0.0);
sdnode.AddChild(p);
// TODO: Normally just one weight per channel, adding stub for later development
std::vector<float>fFullWeights;
fFullWeights.push_back(100.);
sdnode.AddChild("FullWeights", fFullWeights);
sdnode.Dump(outstream, binary, indent);
connections.emplace_back("C", "OO", blendchannel_uid, deformer_uid);
connections.emplace_back("C", "OO", blendshape_uid, blendchannel_uid);
}
}
// bones. // bones.
// //
// output structure: // output structure:

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -54,18 +54,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/ByteSwapper.h> #include <assimp/ByteSwapper.h>
#include <assimp/ParsingUtils.h> #include <assimp/ParsingUtils.h>
#include <algorithm> // std::transform
#include "FBXUtil.h" #include "FBXUtil.h"
namespace Assimp { namespace Assimp {
namespace FBX { namespace FBX {
using namespace Util; using namespace Util;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Material::Material(uint64_t id, const Element& element, const Document& doc, const std::string& name) Material::Material(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
: Object(id,element,name) Object(id,element,name) {
{
const Scope& sc = GetRequiredScope(element); const Scope& sc = GetRequiredScope(element);
const Element* const ShadingModel = sc["ShadingModel"]; const Element* const ShadingModel = sc["ShadingModel"];
@ -77,23 +75,21 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
if(ShadingModel) { if(ShadingModel) {
shading = ParseTokenAsString(GetRequiredToken(*ShadingModel,0)); shading = ParseTokenAsString(GetRequiredToken(*ShadingModel,0));
} } else {
else {
DOMWarning("shading mode not specified, assuming phong",&element); DOMWarning("shading mode not specified, assuming phong",&element);
shading = "phong"; shading = "phong";
} }
std::string templateName;
// lower-case shading because Blender (for example) writes "Phong" // lower-case shading because Blender (for example) writes "Phong"
std::transform(shading.data(), shading.data() + shading.size(), std::addressof(shading[0]), Assimp::ToLower<char>); for (size_t i = 0; i < shading.length(); ++i) {
shading[i] = static_cast<char>(tolower(shading[i]));
}
std::string templateName;
if(shading == "phong") { if(shading == "phong") {
templateName = "Material.FbxSurfacePhong"; templateName = "Material.FbxSurfacePhong";
} } else if(shading == "lambert") {
else if(shading == "lambert") {
templateName = "Material.FbxSurfaceLambert"; templateName = "Material.FbxSurfaceLambert";
} } else {
else {
DOMWarning("shading mode not recognized: " + shading,&element); DOMWarning("shading mode not recognized: " + shading,&element);
} }
@ -102,20 +98,19 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
// resolve texture links // resolve texture links
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID()); const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
for(const Connection* con : conns) { for(const Connection* con : conns) {
// texture link to properties, not objects // texture link to properties, not objects
if (!con->PropertyName().length()) { if ( 0 == con->PropertyName().length()) {
continue; continue;
} }
const Object* const ob = con->SourceObject(); const Object* const ob = con->SourceObject();
if(!ob) { if(nullptr == ob) {
DOMWarning("failed to read source object for texture link, ignoring",&element); DOMWarning("failed to read source object for texture link, ignoring",&element);
continue; continue;
} }
const Texture* const tex = dynamic_cast<const Texture*>(ob); const Texture* const tex = dynamic_cast<const Texture*>(ob);
if(!tex) { if(nullptr == tex) {
const LayeredTexture* const layeredTexture = dynamic_cast<const LayeredTexture*>(ob); const LayeredTexture* const layeredTexture = dynamic_cast<const LayeredTexture*>(ob);
if(!layeredTexture) { if(!layeredTexture) {
DOMWarning("source object for texture link is not a texture or layered texture, ignoring",&element); DOMWarning("source object for texture link is not a texture or layered texture, ignoring",&element);
@ -128,9 +123,7 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
layeredTextures[prop] = layeredTexture; layeredTextures[prop] = layeredTexture;
((LayeredTexture*)layeredTexture)->fillTexture(doc); ((LayeredTexture*)layeredTexture)->fillTexture(doc);
} } else {
else
{
const std::string& prop = con->PropertyName(); const std::string& prop = con->PropertyName();
if (textures.find(prop) != textures.end()) { if (textures.find(prop) != textures.end()) {
DOMWarning("duplicate texture link: " + prop,&element); DOMWarning("duplicate texture link: " + prop,&element);
@ -138,23 +131,20 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
textures[prop] = tex; textures[prop] = tex;
} }
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Material::~Material() Material::~Material() {
{ // empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Texture::Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name) Texture::Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
: Object(id,element,name) Object(id,element,name),
, uvScaling(1.0f,1.0f) uvScaling(1.0f,1.0f),
, media(0) media(0) {
{
const Scope& sc = GetRequiredScope(element); const Scope& sc = GetRequiredScope(element);
const Element* const Type = sc["Type"]; const Element* const Type = sc["Type"];
@ -194,8 +184,7 @@ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const
crop[1] = ParseTokenAsInt(GetRequiredToken(*Cropping,1)); crop[1] = ParseTokenAsInt(GetRequiredToken(*Cropping,1));
crop[2] = ParseTokenAsInt(GetRequiredToken(*Cropping,2)); crop[2] = ParseTokenAsInt(GetRequiredToken(*Cropping,2));
crop[3] = ParseTokenAsInt(GetRequiredToken(*Cropping,3)); crop[3] = ParseTokenAsInt(GetRequiredToken(*Cropping,3));
} } else {
else {
// vc8 doesn't support the crop() syntax in initialization lists // vc8 doesn't support the crop() syntax in initialization lists
// (and vc9 WARNS about the new (i.e. compliant) behaviour). // (and vc9 WARNS about the new (i.e. compliant) behaviour).
crop[0] = crop[1] = crop[2] = crop[3] = 0; crop[0] = crop[1] = crop[2] = crop[3] = 0;
@ -226,7 +215,7 @@ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID()); const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
for(const Connection* con : conns) { for(const Connection* con : conns) {
const Object* const ob = con->SourceObject(); const Object* const ob = con->SourceObject();
if(!ob) { if (nullptr == ob) {
DOMWarning("failed to read source object for texture link, ignoring",&element); DOMWarning("failed to read source object for texture link, ignoring",&element);
continue; continue;
} }
@ -240,46 +229,38 @@ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const
} }
Texture::~Texture() Texture::~Texture() {
{ // empty
} }
LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& /*doc*/, const std::string& name) LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& /*doc*/, const std::string& name) :
: Object(id,element,name) Object(id,element,name),
,blendMode(BlendMode_Modulate) blendMode(BlendMode_Modulate),
,alpha(1) alpha(1) {
{
const Scope& sc = GetRequiredScope(element); const Scope& sc = GetRequiredScope(element);
const Element* const BlendModes = sc["BlendModes"]; const Element* const BlendModes = sc["BlendModes"];
const Element* const Alphas = sc["Alphas"]; const Element* const Alphas = sc["Alphas"];
if (nullptr != BlendModes) {
if(BlendModes!=0)
{
blendMode = (BlendMode)ParseTokenAsInt(GetRequiredToken(*BlendModes,0)); blendMode = (BlendMode)ParseTokenAsInt(GetRequiredToken(*BlendModes,0));
} }
if(Alphas!=0) if (nullptr != Alphas) {
{
alpha = ParseTokenAsFloat(GetRequiredToken(*Alphas,0)); alpha = ParseTokenAsFloat(GetRequiredToken(*Alphas,0));
} }
} }
LayeredTexture::~LayeredTexture() LayeredTexture::~LayeredTexture() {
{ // empty
} }
void LayeredTexture::fillTexture(const Document& doc) void LayeredTexture::fillTexture(const Document& doc) {
{
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID()); const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
for(size_t i = 0; i < conns.size();++i) for(size_t i = 0; i < conns.size();++i) {
{
const Connection* con = conns.at(i); const Connection* con = conns.at(i);
const Object* const ob = con->SourceObject(); const Object* const ob = con->SourceObject();
if(!ob) { if (nullptr == ob) {
DOMWarning("failed to read source object for texture link, ignoring",&element); DOMWarning("failed to read source object for texture link, ignoring",&element);
continue; continue;
} }
@ -290,13 +271,11 @@ void LayeredTexture::fillTexture(const Document& doc)
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Video::Video(uint64_t id, const Element& element, const Document& doc, const std::string& name) Video::Video(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
: Object(id,element,name) Object(id,element,name),
, contentLength(0) contentLength(0),
, content(0) content(0) {
{
const Scope& sc = GetRequiredScope(element); const Scope& sc = GetRequiredScope(element);
const Element* const Type = sc["Type"]; const Element* const Type = sc["Type"];
@ -324,52 +303,43 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
if (!token.IsBinary()) { if (!token.IsBinary()) {
if (*data != '"') { if (*data != '"') {
DOMError("embedded content is not surrounded by quotation marks", &element); DOMError("embedded content is not surrounded by quotation marks", &element);
} } else {
else {
size_t targetLength = 0; size_t targetLength = 0;
auto numTokens = Content->Tokens().size(); auto numTokens = Content->Tokens().size();
// First time compute size (it could be large like 64Gb and it is good to allocate it once) // First time compute size (it could be large like 64Gb and it is good to allocate it once)
for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx) for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx) {
{
const Token& dataToken = GetRequiredToken(*Content, tokenIdx); const Token& dataToken = GetRequiredToken(*Content, tokenIdx);
size_t tokenLength = dataToken.end() - dataToken.begin() - 2; // ignore double quotes size_t tokenLength = dataToken.end() - dataToken.begin() - 2; // ignore double quotes
const char* base64data = dataToken.begin() + 1; const char* base64data = dataToken.begin() + 1;
const size_t outLength = Util::ComputeDecodedSizeBase64(base64data, tokenLength); const size_t outLength = Util::ComputeDecodedSizeBase64(base64data, tokenLength);
if (outLength == 0) if (outLength == 0) {
{
DOMError("Corrupted embedded content found", &element); DOMError("Corrupted embedded content found", &element);
} }
targetLength += outLength; targetLength += outLength;
} }
if (targetLength == 0) if (targetLength == 0) {
{
DOMError("Corrupted embedded content found", &element); DOMError("Corrupted embedded content found", &element);
} }
content = new uint8_t[targetLength]; content = new uint8_t[targetLength];
contentLength = static_cast<uint64_t>(targetLength); contentLength = static_cast<uint64_t>(targetLength);
size_t dst_offset = 0; size_t dst_offset = 0;
for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx) for (uint32_t tokenIdx = 0; tokenIdx < numTokens; ++tokenIdx) {
{
const Token& dataToken = GetRequiredToken(*Content, tokenIdx); const Token& dataToken = GetRequiredToken(*Content, tokenIdx);
size_t tokenLength = dataToken.end() - dataToken.begin() - 2; // ignore double quotes size_t tokenLength = dataToken.end() - dataToken.begin() - 2; // ignore double quotes
const char* base64data = dataToken.begin() + 1; const char* base64data = dataToken.begin() + 1;
dst_offset += Util::DecodeBase64(base64data, tokenLength, content + dst_offset, targetLength - dst_offset); dst_offset += Util::DecodeBase64(base64data, tokenLength, content + dst_offset, targetLength - dst_offset);
} }
if (targetLength != dst_offset) if (targetLength != dst_offset) {
{
delete[] content; delete[] content;
contentLength = 0; contentLength = 0;
DOMError("Corrupted embedded content found", &element); DOMError("Corrupted embedded content found", &element);
} }
} }
} } else if (static_cast<size_t>(token.end() - data) < 5) {
else if (static_cast<size_t>(token.end() - data) < 5) {
DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element); DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element);
} } else if (*data != 'R') {
else if (*data != 'R') {
DOMWarning("video content is not raw binary data, ignoring", &element); DOMWarning("video content is not raw binary data, ignoring", &element);
} } else {
else {
// read number of elements // read number of elements
uint32_t len = 0; uint32_t len = 0;
::memcpy(&len, data + 1, sizeof(len)); ::memcpy(&len, data + 1, sizeof(len));
@ -380,8 +350,7 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
content = new uint8_t[len]; content = new uint8_t[len];
::memcpy(content, data + 5, len); ::memcpy(content, data + 5, len);
} }
} catch (const runtime_error& runtimeError) } catch (const runtime_error& runtimeError) {
{
//we don't need the content data for contents that has already been loaded //we don't need the content data for contents that has already been loaded
ASSIMP_LOG_VERBOSE_DEBUG_F("Caught exception in FBXMaterial (likely because content was already loaded): ", ASSIMP_LOG_VERBOSE_DEBUG_F("Caught exception in FBXMaterial (likely because content was already loaded): ",
runtimeError.what()); runtimeError.what());
@ -392,14 +361,11 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
} }
Video::~Video() Video::~Video() {
{ delete[] content;
if(content) {
delete[] content;
}
} }
} //!FBX } //!FBX
} //!Assimp } //!Assimp
#endif #endif // ASSIMP_BUILD_NO_FBX_IMPORTER

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