Merge branch 'assimp:master' into master

pull/4057/head
Madrich 2021-08-31 11:55:29 +02:00 committed by GitHub
commit 43a3c4a05e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1199 changed files with 72081 additions and 8727 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

@ -1,8 +1,8 @@
--- ---
name: Bug report name: Bug report
about: Create a report to help us improve about: Create a report to help us improve
title: '' title: 'Bug:'
labels: '' labels: 'Bug'
assignees: '' assignees: ''
--- ---
@ -23,16 +23,10 @@ A clear and concise description of what you expected to happen.
**Screenshots** **Screenshots**
If applicable, add screenshots to help explain your problem. If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):** **Platform (please complete the following information):**
- OS: [e.g. iOS] - OS: [e.g. iOS]
- Browser [e.g. chrome, safari] - Browser [e.g. chrome, safari]
- Version [e.g. 22] - Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context** **Additional context**
Add any other context about the problem here. Add any other context about the problem here.

View File

@ -2,7 +2,7 @@
name: Feature request name: Feature request
about: Suggest an idea for this project about: Suggest an idea for this project
title: '' title: ''
labels: '' labels: 'Feature-Request'
assignees: '' assignees: ''
--- ---

View File

@ -0,0 +1,25 @@
---
name: Technical debt
about: Create a report to help us to fix and detect tech debts
title: ''
labels: 'Techdebt'
assignees: ''
---
**Describe the technical debt**
A clear and concise description of what the tech debt is about.
**Better solution**
A clear and concise description of what you would expect.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View File

@ -69,6 +69,12 @@ jobs:
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
if: contains(matrix.name, 'windows') if: contains(matrix.name, 'windows')

8
.gitignore vendored
View File

@ -18,11 +18,14 @@ build
*.VC.db-wal *.VC.db-wal
*.VC.opendb *.VC.opendb
*.ipch *.ipch
.vs/
out/
CMakeSettings.json
# Output # Output
bin/ bin/
lib/ lib/
x64/
# QtCreator # QtCreator
CMakeLists.txt.user CMakeLists.txt.user
@ -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,16 +38,16 @@ 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)
IF(ASSIMP_HUNTER_ENABLED) IF(ASSIMP_HUNTER_ENABLED)
include("cmake/HunterGate.cmake") include("cmake-modules/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.311.tar.gz"
SHA1 "64024b7b95b4c86d50ae05b926814448c93a70a0" SHA1 "1a82b9b73055879181cb1466b2ab5d48ee8ae410"
) )
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 )
# Use subset of Windows.h
ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN )
IF(MSVC)
OPTION ( ASSIMP_BUILD_ASSIMP_VIEW OPTION ( ASSIMP_BUILD_ASSIMP_VIEW
"If the Assimp view tool is built. (requires DirectX)" "If the Assimp view tool is built. (requires DirectX)"
OFF ) OFF )
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)
@ -271,6 +268,8 @@ ELSEIF(MSVC)
ADD_COMPILE_OPTIONS(/wd4351) ADD_COMPILE_OPTIONS(/wd4351)
ENDIF() ENDIF()
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od") SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od")
SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF")
ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
IF(NOT ASSIMP_HUNTER_ENABLED) IF(NOT ASSIMP_HUNTER_ENABLED)
SET(CMAKE_CXX_STANDARD 11) SET(CMAKE_CXX_STANDARD 11)
@ -337,9 +336,9 @@ INCLUDE (FindPkgMacros)
INCLUDE (PrecompiledHeader) INCLUDE (PrecompiledHeader)
# Set Assimp project output directory variables. # Set Assimp project output directory variables.
SET(ASSIMP_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") SET(ASSIMP_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE STRING "Path for runtime output files")
SET(ASSIMP_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") SET(ASSIMP_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE STRING "Path for library output files")
SET(ASSIMP_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib") SET(ASSIMP_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" CACHE STRING "Path for archive output files")
# Macro used to set the output directories of a target to the # Macro used to set the output directories of a target to the
# respective Assimp output directories. # respective Assimp output directories.
@ -398,14 +397,14 @@ set(GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
IF(ASSIMP_HUNTER_ENABLED) IF(ASSIMP_HUNTER_ENABLED)
set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}") set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}")
set(CMAKE_CONFIG_TEMPLATE_FILE "cmake/assimp-hunter-config.cmake.in") set(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-hunter-config.cmake.in")
set(NAMESPACE "${PROJECT_NAME}::") set(NAMESPACE "${PROJECT_NAME}::")
set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake") set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake") set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake")
ELSE() ELSE()
set(CONFIG_INSTALL_DIR "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}") set(CONFIG_INSTALL_DIR "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}")
set(CMAKE_CONFIG_TEMPLATE_FILE "cmake/assimp-plain-config.cmake.in") set(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-plain-config.cmake.in")
string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWERCASE) string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWERCASE)
set(NAMESPACE "${PROJECT_NAME_LOWERCASE}::") set(NAMESPACE "${PROJECT_NAME_LOWERCASE}::")
set(TARGETS_EXPORT_NAME "${PROJECT_NAME_LOWERCASE}Targets") set(TARGETS_EXPORT_NAME "${PROJECT_NAME_LOWERCASE}Targets")
@ -455,6 +454,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()
@ -524,12 +529,12 @@ ENDIF()
MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER ) MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER )
SET ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER OFF CACHE BOOL SET ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER OFF CACHE BOOL
"Build the C4D importer, which relies on the non-free Melange SDK." "Build the C4D importer, which relies on the non-free Cineware SDK."
) )
IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
IF ( MSVC ) IF ( MSVC )
SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/includes") SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/includes")
# pick the correct prebuilt library # pick the correct prebuilt library
IF(MSVC15) IF(MSVC15)
@ -548,28 +553,117 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
) )
ENDIF() ENDIF()
SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/libraries/win") SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/libraries/win")
SET(C4D_DEBUG_LIBRARIES SET(C4D_DEBUG_LIBRARIES
"${C4D_LIB_BASE_PATH}/melangelib${C4D_LIB_POSTFIX}/melangelib_debug.lib" "${C4D_LIB_BASE_PATH}/cinewarelib${C4D_LIB_POSTFIX}/cinewarelib_debug.lib"
"${C4D_LIB_BASE_PATH}/jpeglib${C4D_LIB_POSTFIX}/jpeglib_debug.lib" "${C4D_LIB_BASE_PATH}/jpeglib${C4D_LIB_POSTFIX}/jpeglib_debug.lib"
) )
SET(C4D_RELEASE_LIBRARIES SET(C4D_RELEASE_LIBRARIES
"${C4D_LIB_BASE_PATH}/melangelib${C4D_LIB_POSTFIX}/melangelib_release.lib" "${C4D_LIB_BASE_PATH}/cinewarelib${C4D_LIB_POSTFIX}/cinewarelib_release.lib"
"${C4D_LIB_BASE_PATH}/jpeglib${C4D_LIB_POSTFIX}/jpeglib_release.lib" "${C4D_LIB_BASE_PATH}/jpeglib${C4D_LIB_POSTFIX}/jpeglib_release.lib"
) )
# winsock and winmm are necessary dependencies of melange (this is undocumented, but true.) # winsock and winmm are necessary (and undocumented) dependencies of Cineware SDK because
# it can be used to communicate with a running Cinema 4D instance
SET(C4D_EXTRA_LIBRARIES WSock32.lib Winmm.lib) SET(C4D_EXTRA_LIBRARIES WSock32.lib Winmm.lib)
ELSE () ELSE ()
MESSAGE( FATAL_ERROR MESSAGE( FATAL_ERROR
"C4D is currently only available on Windows with melange SDK installed in contrib/Melange" "C4D is currently only available on Windows with Cineware SDK installed in contrib/Cineware"
) )
ENDIF () ENDIF ()
ELSE () 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 +677,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://ricardoreis.net/trilib-2/)
* [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.
@ -67,7 +68,7 @@ The source code is organized in the following way:
code/Common The base implementation for importers and the infrastructure code/Common The base implementation for importers and the infrastructure
code/PostProcessing The post-processing steps code/PostProcessing The post-processing steps
code/<FormatName> Implementation for import and export for the format code/AssetLib/<FormatName> Implementation for import and export for the format
### Where to get help ### ### Where to get help ###
For more information, visit [our website](http://assimp.org/). Or check out the `./doc`- folder, which contains the official documentation in HTML format. For more information, visit [our website](http://assimp.org/). Or check out the `./doc`- folder, which contains the official documentation in HTML format.
@ -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

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -68,8 +68,8 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
unsigned int idx(NotSet); unsigned int idx(NotSet);
for (unsigned int i = 0; i < mScene->mMaterials.size(); ++i) { for (unsigned int i = 0; i < mScene->mMaterials.size(); ++i) {
std::string s = mScene->mMaterials[i].mName; std::string s = mScene->mMaterials[i].mName;
for (std::string::iterator it = s.begin(); it != s.end(); ++it) { for (char & it : s) {
*it = static_cast<char>(::tolower(*it)); it = static_cast<char>(::tolower(static_cast<unsigned char>(it)));
} }
if (std::string::npos == s.find("default")) continue; if (std::string::npos == s.find("default")) continue;
@ -79,12 +79,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
mScene->mMaterials[i].mDiffuse.r != mScene->mMaterials[i].mDiffuse.r !=
mScene->mMaterials[i].mDiffuse.b) continue; mScene->mMaterials[i].mDiffuse.b) continue;
if (mScene->mMaterials[i].sTexDiffuse.mMapName.length() != 0 || if (ContainsTextures(i)) {
mScene->mMaterials[i].sTexBump.mMapName.length() != 0 ||
mScene->mMaterials[i].sTexOpacity.mMapName.length() != 0 ||
mScene->mMaterials[i].sTexEmissive.mMapName.length() != 0 ||
mScene->mMaterials[i].sTexSpecular.mMapName.length() != 0 ||
mScene->mMaterials[i].sTexShininess.mMapName.length() != 0) {
continue; continue;
} }
idx = i; idx = i;
@ -212,7 +207,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;
} }
@ -378,7 +379,7 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type
// TODO: handle embedded textures properly // TODO: handle embedded textures properly
if (path.data[0] == '*') { if (path.data[0] == '*') {
ASSIMP_LOG_ERROR("Ignoring embedded texture for export: " + std::string(path.C_Str())); ASSIMP_LOG_ERROR("Ignoring embedded texture for export: ", path.C_Str());
return; return;
} }
@ -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 */
@ -358,16 +348,16 @@ struct Texture {
// empty // empty
} }
Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(std::move(other.mTextureBlend)), Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(other.mTextureBlend),
mMapName(std::move(other.mMapName)), mMapName(std::move(other.mMapName)),
mOffsetU(std::move(other.mOffsetU)), mOffsetU(other.mOffsetU),
mOffsetV(std::move(other.mOffsetV)), mOffsetV(other.mOffsetV),
mScaleU(std::move(other.mScaleU)), mScaleU(other.mScaleU),
mScaleV(std::move(other.mScaleV)), mScaleV(other.mScaleV),
mRotation(std::move(other.mRotation)), mRotation(other.mRotation),
mMapMode(std::move(other.mMapMode)), mMapMode(other.mMapMode),
bPrivate(std::move(other.bPrivate)), bPrivate(other.bPrivate),
iUVSrc(std::move(other.iUVSrc)) { iUVSrc(other.iUVSrc) {
// empty // empty
} }
@ -376,16 +366,16 @@ struct Texture {
return *this; return *this;
} }
mTextureBlend = std::move(other.mTextureBlend); mTextureBlend = other.mTextureBlend;
mMapName = std::move(other.mMapName); mMapName = std::move(other.mMapName);
mOffsetU = std::move(other.mOffsetU); mOffsetU = other.mOffsetU;
mOffsetV = std::move(other.mOffsetV); mOffsetV = other.mOffsetV;
mScaleU = std::move(other.mScaleU); mScaleU = other.mScaleU;
mScaleV = std::move(other.mScaleV); mScaleV = other.mScaleV;
mRotation = std::move(other.mRotation); mRotation = other.mRotation;
mMapMode = std::move(other.mMapMode); mMapMode = other.mMapMode;
bPrivate = std::move(other.bPrivate); bPrivate = other.bPrivate;
iUVSrc = std::move(other.iUVSrc); iUVSrc = other.iUVSrc;
return *this; return *this;
} }
@ -471,13 +461,13 @@ struct Material {
//! Move constructor. This is explicitly written because MSVC doesn't support defaulting it //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
Material(Material &&other) AI_NO_EXCEPT : mName(std::move(other.mName)), Material(Material &&other) AI_NO_EXCEPT : mName(std::move(other.mName)),
mDiffuse(std::move(other.mDiffuse)), mDiffuse(other.mDiffuse),
mSpecularExponent(std::move(other.mSpecularExponent)), mSpecularExponent(other.mSpecularExponent),
mShininessStrength(std::move(other.mShininessStrength)), mShininessStrength(other.mShininessStrength),
mSpecular(std::move(other.mSpecular)), mSpecular(other.mSpecular),
mAmbient(std::move(other.mAmbient)), mAmbient(other.mAmbient),
mShading(std::move(other.mShading)), mShading(other.mShading),
mTransparency(std::move(other.mTransparency)), mTransparency(other.mTransparency),
sTexDiffuse(std::move(other.sTexDiffuse)), sTexDiffuse(std::move(other.sTexDiffuse)),
sTexOpacity(std::move(other.sTexOpacity)), sTexOpacity(std::move(other.sTexOpacity)),
sTexSpecular(std::move(other.sTexSpecular)), sTexSpecular(std::move(other.sTexSpecular)),
@ -485,10 +475,10 @@ struct Material {
sTexBump(std::move(other.sTexBump)), sTexBump(std::move(other.sTexBump)),
sTexEmissive(std::move(other.sTexEmissive)), sTexEmissive(std::move(other.sTexEmissive)),
sTexShininess(std::move(other.sTexShininess)), sTexShininess(std::move(other.sTexShininess)),
mBumpHeight(std::move(other.mBumpHeight)), mBumpHeight(other.mBumpHeight),
mEmissive(std::move(other.mEmissive)), mEmissive(other.mEmissive),
sTexAmbient(std::move(other.sTexAmbient)), sTexAmbient(std::move(other.sTexAmbient)),
mTwoSided(std::move(other.mTwoSided)) { mTwoSided(other.mTwoSided) {
// empty // empty
} }
@ -498,13 +488,13 @@ struct Material {
} }
mName = std::move(other.mName); mName = std::move(other.mName);
mDiffuse = std::move(other.mDiffuse); mDiffuse = other.mDiffuse;
mSpecularExponent = std::move(other.mSpecularExponent); mSpecularExponent = other.mSpecularExponent;
mShininessStrength = std::move(other.mShininessStrength), mShininessStrength = other.mShininessStrength,
mSpecular = std::move(other.mSpecular); mSpecular = other.mSpecular;
mAmbient = std::move(other.mAmbient); mAmbient = other.mAmbient;
mShading = std::move(other.mShading); mShading = other.mShading;
mTransparency = std::move(other.mTransparency); mTransparency = other.mTransparency;
sTexDiffuse = std::move(other.sTexDiffuse); sTexDiffuse = std::move(other.sTexDiffuse);
sTexOpacity = std::move(other.sTexOpacity); sTexOpacity = std::move(other.sTexOpacity);
sTexSpecular = std::move(other.sTexSpecular); sTexSpecular = std::move(other.sTexSpecular);
@ -512,10 +502,10 @@ struct Material {
sTexBump = std::move(other.sTexBump); sTexBump = std::move(other.sTexBump);
sTexEmissive = std::move(other.sTexEmissive); sTexEmissive = std::move(other.sTexEmissive);
sTexShininess = std::move(other.sTexShininess); sTexShininess = std::move(other.sTexShininess);
mBumpHeight = std::move(other.mBumpHeight); mBumpHeight = other.mBumpHeight;
mEmissive = std::move(other.mEmissive); mEmissive = other.mEmissive;
sTexAmbient = std::move(other.sTexAmbient); sTexAmbient = std::move(other.sTexAmbient);
mTwoSided = std::move(other.mTwoSided); mTwoSided = other.mTwoSided;
return *this; return *this;
} }

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.
@ -143,7 +143,13 @@ void Discreet3DSImporter::SetupProperties(const Importer * /*pImp*/) {
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void Discreet3DSImporter::InternReadFile(const std::string &pFile, void Discreet3DSImporter::InternReadFile(const std::string &pFile,
aiScene *pScene, IOSystem *pIOHandler) { aiScene *pScene, IOSystem *pIOHandler) {
StreamReaderLE theStream(pIOHandler->Open(pFile, "rb"));
auto theFile = pIOHandler->Open(pFile, "rb");
if (!theFile) {
throw DeadlyImportError("3DS: Could not open ", pFile);
}
StreamReaderLE theStream(theFile);
// We should have at least one chunk // We should have at least one chunk
if (theStream.GetRemainingSize() < 16) { if (theStream.GetRemainingSize() < 16) {
@ -164,7 +170,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 +272,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;
@ -298,7 +305,7 @@ void Discreet3DSImporter::ParseEditorChunk() {
// print the version number // print the version number
char buff[10]; char buff[10];
ASSIMP_itoa10(buff, stream->GetI2()); ASSIMP_itoa10(buff, stream->GetI2());
ASSIMP_LOG_INFO_F(std::string("3DS file format version: "), buff); ASSIMP_LOG_INFO("3DS file format version: ", buff);
} break; } break;
}; };
ASSIMP_3DS_END_CHUNK(); ASSIMP_3DS_END_CHUNK();
@ -323,7 +330,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;
@ -927,7 +934,7 @@ void Discreet3DSImporter::ParseFaceChunk() {
} }
} }
if (0xcdcdcdcd == idx) { if (0xcdcdcdcd == idx) {
ASSIMP_LOG_ERROR_F("3DS: Unknown material: ", sz); ASSIMP_LOG_ERROR("3DS: Unknown material: ", sz);
} }
// Now continue and read all material indices // Now continue and read all material indices

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.
@ -208,6 +208,15 @@ protected:
*/ */
void ReplaceDefaultMaterial(); void ReplaceDefaultMaterial();
bool ContainsTextures(unsigned int i) const {
return !mScene->mMaterials[i].sTexDiffuse.mMapName.empty() ||
!mScene->mMaterials[i].sTexBump.mMapName.empty() ||
!mScene->mMaterials[i].sTexOpacity.mMapName.empty() ||
!mScene->mMaterials[i].sTexEmissive.mMapName.empty() ||
!mScene->mMaterials[i].sTexSpecular.mMapName.empty() ||
!mScene->mMaterials[i].sTexShininess.mMapName.empty() ;
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Convert the whole scene /** Convert the whole scene
*/ */

View File

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

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

View File

@ -2,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.
@ -47,17 +46,40 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
// ---------------------------------------------------------------------------
/// @brief The 3MF-importer class.
///
/// Implements the basic topology import and embedded textures.
// ---------------------------------------------------------------------------
class D3MFImporter : public BaseImporter { class D3MFImporter : public BaseImporter {
public: public:
// BaseImporter interface /// @brief The default class constructor.
D3MFImporter(); D3MFImporter();
~D3MFImporter();
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const; /// @brief The class destructor.
void SetupProperties(const Importer *pImp); ~D3MFImporter() override;
const aiImporterDesc *GetInfo() const;
/// @brief Performs the data format detection.
/// @param pFile The filename to check.
/// @param pIOHandler The used IO-System.
/// @param checkSig true for signature checking.
/// @return true for can be loaded, false for not.
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override;
/// @brief Not used
/// @param pImp Not used
void SetupProperties(const Importer *pImp) override;
/// @brief The importer description getter.
/// @return The info
const aiImporterDesc *GetInfo() const override;
protected: protected:
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler); /// @brief Internal read function, performs the file parsing.
/// @param pFile The filename
/// @param pScene The scene to load in.
/// @param pIOHandler The io-system
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
}; };
} // 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.
@ -43,14 +43,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "D3MFOpcPackage.h" #include "D3MFOpcPackage.h"
#include <assimp/Exceptional.h> #include <assimp/Exceptional.h>
#include <assimp/XmlParser.h> #include <assimp/XmlParser.h>
#include <assimp/ZipArchiveIOSystem.h> #include <assimp/ZipArchiveIOSystem.h>
#include <assimp/ai_assert.h> #include <assimp/ai_assert.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/IOStream.hpp> #include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/texture.h>
#include "3MFXmlTags.h" #include "3MFXmlTags.h"
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
@ -64,11 +63,12 @@ namespace Assimp {
namespace D3MF { namespace D3MF {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
typedef std::shared_ptr<OpcPackageRelationship> OpcPackageRelationshipPtr; using OpcPackageRelationshipPtr = std::shared_ptr<OpcPackageRelationship>;
class OpcPackageRelationshipReader { class OpcPackageRelationshipReader {
public: public:
OpcPackageRelationshipReader(XmlParser &parser) { OpcPackageRelationshipReader(XmlParser &parser) :
m_relationShips() {
XmlNode root = parser.getRootNode(); XmlNode root = parser.getRootNode();
ParseRootNode(root); ParseRootNode(root);
} }
@ -91,6 +91,7 @@ public:
if (relPtr->id.empty() || relPtr->type.empty() || relPtr->target.empty()) { if (relPtr->id.empty() || relPtr->type.empty() || relPtr->target.empty()) {
return false; return false;
} }
return true; return true;
} }
@ -100,12 +101,12 @@ public:
} }
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
std::string name = currentNode.name(); const 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);
} }
@ -116,11 +117,23 @@ public:
std::vector<OpcPackageRelationshipPtr> m_relationShips; std::vector<OpcPackageRelationshipPtr> m_relationShips;
}; };
static bool IsEmbeddedTexture( const std::string &filename ) {
const std::string extension = BaseImporter::GetExtension(filename);
if (extension == "jpg" || extension == "png") {
std::string::size_type pos = filename.find("thumbnail");
if (pos == std::string::npos) {
return false;
}
return true;
}
return false;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) : D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
mRootStream(nullptr), mRootStream(nullptr),
mZipArchive() { mZipArchive() {
mZipArchive.reset(new ZipArchiveIOSystem(pIOHandler, rFile)); mZipArchive = new ZipArchiveIOSystem(pIOHandler, rFile);
if (!mZipArchive->isOpen()) { if (!mZipArchive->isOpen()) {
throw DeadlyImportError("Failed to open file ", rFile, "."); throw DeadlyImportError("Failed to open file ", rFile, ".");
} }
@ -141,7 +154,7 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
} }
std::string rootFile = ReadPackageRootRelationship(fileStream); std::string rootFile = ReadPackageRootRelationship(fileStream);
if (rootFile.size() > 0 && rootFile[0] == '/') { if (!rootFile.empty() && rootFile[0] == '/') {
rootFile = rootFile.substr(1); rootFile = rootFile.substr(1);
if (rootFile[0] == '/') { if (rootFile[0] == '/') {
// deal with zip-bug // deal with zip-bug
@ -156,39 +169,48 @@ 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) {
ASSIMP_LOG_WARN_F("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES", file); ASSIMP_LOG_WARN("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES", file);
} else if (IsEmbeddedTexture(file)) {
IOStream *fileStream = mZipArchive->Open(file.c_str());
LoadEmbeddedTextures(fileStream, file);
mZipArchive->Close(fileStream);
} else { } else {
ASSIMP_LOG_WARN_F("Ignored file of unknown type: ", file); ASSIMP_LOG_WARN("Ignored file of unknown type: ", file);
} }
} }
} }
D3MFOpcPackage::~D3MFOpcPackage() { D3MFOpcPackage::~D3MFOpcPackage() {
mZipArchive->Close(mRootStream); mZipArchive->Close(mRootStream);
delete mZipArchive;
mZipArchive = nullptr;
} }
IOStream *D3MFOpcPackage::RootStream() const { IOStream *D3MFOpcPackage::RootStream() const {
return mRootStream; return mRootStream;
} }
static const std::string ModelRef = "3D/3dmodel.model"; const std::vector<aiTexture *> &D3MFOpcPackage::GetEmbeddedTextures() const {
return mEmbeddedTextures;
}
static const char *const ModelRef = "3D/3dmodel.model";
bool D3MFOpcPackage::validate() { bool D3MFOpcPackage::validate() {
if (nullptr == mRootStream || nullptr == mZipArchive) { if (nullptr == mRootStream || nullptr == mZipArchive) {
return false; return false;
} }
return mZipArchive->Exists(ModelRef.c_str()); return mZipArchive->Exists(ModelRef);
} }
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);
@ -204,6 +226,31 @@ std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
return (*itr)->target; return (*itr)->target;
} }
void D3MFOpcPackage::LoadEmbeddedTextures(IOStream *fileStream, const std::string &filename) {
if (nullptr == fileStream) {
return;
}
const size_t size = fileStream->FileSize();
if (0 == size) {
return;
}
unsigned char *data = new unsigned char[size];
fileStream->Read(data, 1, size);
aiTexture *texture = new aiTexture;
std::string embName = "*" + filename;
texture->mFilename.Set(embName.c_str());
texture->mWidth = static_cast<unsigned int>(size);
texture->mHeight = 0;
texture->achFormatHint[0] = 'p';
texture->achFormatHint[1] = 'n';
texture->achFormatHint[2] = 'g';
texture->achFormatHint[3] = '\0';
texture->pcData = (aiTexel*) data;
mEmbeddedTextures.emplace_back(texture);
}
} // Namespace D3MF } // Namespace 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.
@ -46,8 +46,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string> #include <string>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
struct aiTexture;
namespace Assimp { namespace Assimp {
class ZipArchiveIOSystem;
class ZipArchiveIOSystem;
namespace D3MF { namespace D3MF {
@ -63,16 +66,19 @@ public:
~D3MFOpcPackage(); ~D3MFOpcPackage();
IOStream* RootStream() const; IOStream* RootStream() const;
bool validate(); bool validate();
const std::vector<aiTexture*> &GetEmbeddedTextures() const;
protected: protected:
std::string ReadPackageRootRelationship(IOStream* stream); std::string ReadPackageRootRelationship(IOStream* stream);
void LoadEmbeddedTextures(IOStream *fileStream, const std::string &filename);
private: private:
IOStream* mRootStream; IOStream* mRootStream;
std::unique_ptr<ZipArchiveIOSystem> mZipArchive; ZipArchiveIOSystem *mZipArchive;
std::vector<aiTexture *> mEmbeddedTextures;
}; };
} // Namespace D3MF } // namespace D3MF
} // Namespace Assimp } // namespace Assimp
#endif // D3MFOPCPACKAGE_H #endif // D3MFOPCPACKAGE_H

View File

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

View File

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

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, assimp team
All rights reserved. All rights reserved.
@ -116,7 +116,7 @@ inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *name
buffer = AcSkipToNextToken(buffer); buffer = AcSkipToNextToken(buffer);
if (0 != name_length) { if (0 != name_length) {
if (0 != strncmp(buffer, name, name_length) || !IsSpace(buffer[name_length])) { if (0 != strncmp(buffer, name, name_length) || !IsSpace(buffer[name_length])) {
ASSIMP_LOG_ERROR("AC3D: Unexpexted token. " + std::string(name) + " was expected."); ASSIMP_LOG_ERROR("AC3D: Unexpected token. ", name, " was expected.");
return buffer; return buffer;
} }
buffer += name_length + 1; buffer += name_length + 1;
@ -492,7 +492,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
default: default:
// Coerce unknowns to a polygon and warn // Coerce unknowns to a polygon and warn
ASSIMP_LOG_WARN_F("AC3D: The type flag of a surface is unknown: ", (*it).flags); ASSIMP_LOG_WARN("AC3D: The type flag of a surface is unknown: ", (*it).flags);
(*it).flags &= ~(Surface::Mask); (*it).flags &= ~(Surface::Mask);
// fallthrough // fallthrough
@ -690,7 +690,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
if (object.subDiv) { if (object.subDiv) {
if (configEvalSubdivision) { if (configEvalSubdivision) {
std::unique_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE)); std::unique_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE));
ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: " + object.name); ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: ", object.name);
std::vector<aiMesh *> cpy(meshes.size() - oldm, nullptr); std::vector<aiMesh *> cpy(meshes.size() - oldm, nullptr);
div->Subdivide(&meshes[oldm], cpy.size(), &cpy.front(), object.subDiv, true); div->Subdivide(&meshes[oldm], cpy.size(), &cpy.front(), object.subDiv, true);
@ -698,7 +698,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
// previous meshes are deleted vy Subdivide(). // previous meshes are deleted vy Subdivide().
} else { } else {
ASSIMP_LOG_INFO("AC3D: Letting the subdivision surface untouched due to my configuration: " + object.name); ASSIMP_LOG_INFO("AC3D: Letting the subdivision surface untouched due to my configuration: ", object.name);
} }
} }
} }
@ -782,7 +782,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
unsigned int version = HexDigitToDecimal(buffer[4]); unsigned int version = HexDigitToDecimal(buffer[4]);
char msg[3]; char msg[3];
ASSIMP_itoa10(msg, 3, version); ASSIMP_itoa10(msg, 3, version);
ASSIMP_LOG_INFO_F("AC3D file format version: ", msg); ASSIMP_LOG_INFO("AC3D file format version: ", msg);
std::vector<Material> materials; std::vector<Material> materials;
materials.reserve(5); materials.reserve(5);

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>
@ -210,7 +205,7 @@ void AMFImporter::ParseHelper_FixTruncatedFloatString(const char *pInStr, std::s
} }
static bool ParseHelper_Decode_Base64_IsBase64(const char pChar) { static bool ParseHelper_Decode_Base64_IsBase64(const char pChar) {
return (isalnum(pChar) || (pChar == '+') || (pChar == '/')); return (isalnum((unsigned char)pChar) || (pChar == '+') || (pChar == '/'));
} }
void AMFImporter::ParseHelper_Decode_Base64(const std::string &pInputBase64, std::vector<uint8_t> &pOutputData) const { void AMFImporter::ParseHelper_Decode_Base64(const std::string &pInputBase64, std::vector<uint8_t> &pOutputData) const {
@ -273,7 +268,8 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) {
mXmlParser = new XmlParser(); mXmlParser = new XmlParser();
if (!mXmlParser->parse(file.get())) { if (!mXmlParser->parse(file.get())) {
delete mXmlParser; delete mXmlParser;
throw DeadlyImportError("Failed to create XML reader for file" + pFile + "."); mXmlParser = nullptr;
throw DeadlyImportError("Failed to create XML reader for file ", pFile, ".");
} }
// Start reading, search for root tag <amf> // Start reading, search for root tag <amf>
@ -306,13 +302,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 +404,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 +453,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 +518,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,18 +65,20 @@ 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. const std::string &profile = node.attribute("profile").as_string();
AMFNodeElementBase *ne = new AMFColor(mNodeElement_Cur);
AMFColor& als = *((AMFColor*)ne);// alias for convenience
als.Profile = profile;
if (!node.empty()) {
ParseHelper_Node_Enter(ne);
bool read_flag[4] = { false, false, false, false }; bool read_flag[4] = { false, false, false, false };
AMFNodeElementBase *ne = new AMFColor(mNodeElement_Cur);
AMFColor &als = *((AMFColor *)ne); // alias for convenience
ParseHelper_Node_Enter(ne);
for (pugi::xml_node &child : node.children()) { for (pugi::xml_node &child : node.children()) {
std::string name = child.name(); // create new color object.
als.Profile = profile;
const std::string &name = child.name();
if ( name == "r") { if ( name == "r") {
read_flag[0] = true; read_flag[0] = true;
XmlParser::getValueAsFloat(child, als.Color.r); XmlParser::getValueAsFloat(child, als.Color.r);
@ -90,23 +92,18 @@ void AMFImporter::ParseNode_Color(XmlNode &node) {
read_flag[3] = true; read_flag[3] = true;
XmlParser::getValueAsFloat(child, als.Color.a); XmlParser::getValueAsFloat(child, als.Color.a);
} }
ParseHelper_Node_Exit();
}
// check that all components was defined
if (!(read_flag[0] && read_flag[1] && read_flag[2])) {
throw DeadlyImportError("Not all color components are defined.");
}
// check if <a> is absent. Then manually add "a == 1". // check if <a> is absent. Then manually add "a == 1".
if (!read_flag[3]) { if (!read_flag[3]) {
als.Color.a = 1; als.Color.a = 1;
} }
} else {
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
} }
als.Composed = false; als.Composed = false;
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.
ParseHelper_Node_Exit();
// check that all components was defined
if (!(read_flag[0] && read_flag[1] && read_flag[2])) {
throw DeadlyImportError("Not all color components are defined.");
}
} }
// <material // <material
@ -158,23 +155,24 @@ 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();
if (node.empty()) {
return;
}
// create new texture object. // create new texture object.
AMFNodeElementBase *ne = new AMFTexture(mNodeElement_Cur); AMFNodeElementBase *ne = new AMFTexture(mNodeElement_Cur);
AMFTexture& als = *((AMFTexture*)ne);// alias for convenience AMFTexture& als = *((AMFTexture*)ne);// alias for convenience
if (node.empty()) { std::string enc64_data;
return; XmlParser::getValueAsString(node, enc64_data);
}
std::string enc64_data = node.value();
// Check for child nodes // Check for child nodes
// check that all components was defined // check that all components was defined
@ -182,14 +180,11 @@ void AMFImporter::ParseNode_Texture(XmlNode &node) {
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
@ -614,7 +614,7 @@ void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes,
node->mNumChildren++; node->mNumChildren++;
// What we did is so great, it is at least worth a debug message // What we did is so great, it is at least worth a debug message
ASSIMP_LOG_VERBOSE_DEBUG("ASE: Generating separate target node (" + snode->mName + ")"); ASSIMP_LOG_VERBOSE_DEBUG("ASE: Generating separate target node (", snode->mName, ")");
} }
} }

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
@ -498,6 +498,12 @@ void Parser::ParseLV1MaterialListBlock() {
ParseLV2MaterialBlock(sMat); ParseLV2MaterialBlock(sMat);
continue; continue;
} }
if( iDepth == 1 ){
// CRUDE HACK: support missing brace after "Ascii Scene Exporter v2.51"
LogWarning("Missing closing brace in material list");
--filePtr;
return;
}
} }
AI_ASE_HANDLE_TOP_LEVEL_SECTION(); AI_ASE_HANDLE_TOP_LEVEL_SECTION();
} }
@ -671,7 +677,7 @@ void Parser::ParseLV3MapBlock(Texture &map) {
if (!ParseString(temp, "*MAP_CLASS")) if (!ParseString(temp, "*MAP_CLASS"))
SkipToNextToken(); SkipToNextToken();
if (temp != "Bitmap" && temp != "Normal Bump") { if (temp != "Bitmap" && temp != "Normal Bump") {
ASSIMP_LOG_WARN_F("ASE: Skipping unknown map type: ", temp); ASSIMP_LOG_WARN("ASE: Skipping unknown map type: ", temp);
parsePath = false; parsePath = false;
} }
continue; continue;
@ -685,7 +691,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;
@ -1119,7 +1125,7 @@ void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode &mesh) {
"this is no spot light or target camera"); "this is no spot light or target camera");
} }
} else { } else {
ASSIMP_LOG_ERROR("ASE: Unknown node transformation: " + temp); ASSIMP_LOG_ERROR("ASE: Unknown node transformation: ", temp);
// mode = 0 // mode = 0
} }
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.
@ -95,8 +95,8 @@ struct Material : public D3DS::Material {
Material(Material &&other) AI_NO_EXCEPT Material(Material &&other) AI_NO_EXCEPT
: D3DS::Material(std::move(other)), : D3DS::Material(std::move(other)),
avSubMaterials(std::move(other.avSubMaterials)), avSubMaterials(std::move(other.avSubMaterials)),
pcInstance(std::move(other.pcInstance)), pcInstance(other.pcInstance),
bNeed(std::move(other.bNeed)) { bNeed(other.bNeed) {
other.pcInstance = nullptr; other.pcInstance = nullptr;
} }
@ -108,8 +108,8 @@ struct Material : public D3DS::Material {
//D3DS::Material::operator=(std::move(other)); //D3DS::Material::operator=(std::move(other));
avSubMaterials = std::move(other.avSubMaterials); avSubMaterials = std::move(other.avSubMaterials);
pcInstance = std::move(other.pcInstance); pcInstance = other.pcInstance;
bNeed = std::move(other.bNeed); bNeed = other.bNeed;
other.pcInstance = nullptr; other.pcInstance = 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.

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.
@ -172,7 +172,7 @@ inline size_t Write<aiQuaternion>(IOStream *stream, const aiQuaternion &v) {
t += Write<float>(stream, v.z); t += Write<float>(stream, v.z);
ai_assert(t == 16); ai_assert(t == 16);
return 16; return t;
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------

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.
@ -671,7 +671,7 @@ void AssbinImporter::ReadBinaryScene(IOStream *stream, aiScene *scene) {
void AssbinImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { void AssbinImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
IOStream *stream = pIOHandler->Open(pFile, "rb"); IOStream *stream = pIOHandler->Open(pFile, "rb");
if (nullptr == stream) { if (nullptr == stream) {
return; throw DeadlyImportError("ASSBIN: Could not open ", pFile);
} }
// signature // signature

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

@ -41,12 +41,17 @@ public:
enum { enum {
Flag_DoNotIndent = 0x1, Flag_DoNotIndent = 0x1,
Flag_WriteSpecialFloats = 0x2, Flag_WriteSpecialFloats = 0x2,
Flag_SkipWhitespaces = 0x4
}; };
JSONWriter(Assimp::IOStream &out, unsigned int flags = 0u) : JSONWriter(Assimp::IOStream &out, unsigned int flags = 0u) :
out(out), first(), flags(flags) { out(out), indent (""), newline("\n"), space(" "), buff (), first(false), flags(flags) {
// make sure that all formatting happens using the standard, C locale and not the user's current locale // make sure that all formatting happens using the standard, C locale and not the user's current locale
buff.imbue(std::locale("C")); buff.imbue(std::locale("C"));
if (flags & Flag_SkipWhitespaces) {
newline = "";
space = "";
}
} }
~JSONWriter() { ~JSONWriter() {
@ -70,7 +75,7 @@ public:
void Key(const std::string &name) { void Key(const std::string &name) {
AddIndentation(); AddIndentation();
Delimit(); Delimit();
buff << '\"' + name + "\": "; buff << '\"' + name + "\":" << space;
} }
template <typename Literal> template <typename Literal>
@ -78,12 +83,12 @@ public:
AddIndentation(); AddIndentation();
Delimit(); Delimit();
LiteralToString(buff, name) << '\n'; LiteralToString(buff, name) << newline;
} }
template <typename Literal> template <typename Literal>
void SimpleValue(const Literal &s) { void SimpleValue(const Literal &s) {
LiteralToString(buff, s) << '\n'; LiteralToString(buff, s) << newline;
} }
void SimpleValue(const void *buffer, size_t len) { void SimpleValue(const void *buffer, size_t len) {
@ -102,7 +107,7 @@ public:
} }
} }
buff << '\"' << cur_out << "\"\n"; buff << '\"' << cur_out << "\"" << newline;
delete[] cur_out; delete[] cur_out;
} }
@ -115,7 +120,7 @@ public:
} }
} }
first = true; first = true;
buff << "{\n"; buff << "{" << newline;
PushIndent(); PushIndent();
} }
@ -123,7 +128,7 @@ public:
PopIndent(); PopIndent();
AddIndentation(); AddIndentation();
first = false; first = false;
buff << "}\n"; buff << "}" << newline;
} }
void StartArray(bool is_element = false) { void StartArray(bool is_element = false) {
@ -135,19 +140,19 @@ public:
} }
} }
first = true; first = true;
buff << "[\n"; buff << "[" << newline;
PushIndent(); PushIndent();
} }
void EndArray() { void EndArray() {
PopIndent(); PopIndent();
AddIndentation(); AddIndentation();
buff << "]\n"; buff << "]" << newline;
first = false; first = false;
} }
void AddIndentation() { void AddIndentation() {
if (!(flags & Flag_DoNotIndent)) { if (!(flags & Flag_DoNotIndent) && !(flags & Flag_SkipWhitespaces)) {
buff << indent; buff << indent;
} }
} }
@ -156,7 +161,7 @@ public:
if (!first) { if (!first) {
buff << ','; buff << ',';
} else { } else {
buff << ' '; buff << space;
first = false; first = false;
} }
} }
@ -227,7 +232,9 @@ private:
private: private:
Assimp::IOStream &out; Assimp::IOStream &out;
std::string indent, newline; std::string indent;
std::string newline;
std::string space;
std::stringstream buff; std::stringstream buff;
bool first; bool first;
@ -765,7 +772,7 @@ void Write(JSONWriter &out, const aiScene &ai) {
out.EndObj(); out.EndObj();
} }
void ExportAssimp2Json(const char *file, Assimp::IOSystem *io, const aiScene *scene, const Assimp::ExportProperties *) { void ExportAssimp2Json(const char *file, Assimp::IOSystem *io, const aiScene *scene, const Assimp::ExportProperties *pProperties) {
std::unique_ptr<Assimp::IOStream> str(io->Open(file, "wt")); std::unique_ptr<Assimp::IOStream> str(io->Open(file, "wt"));
if (!str) { if (!str) {
throw DeadlyExportError("could not open output file"); throw DeadlyExportError("could not open output file");
@ -782,7 +789,12 @@ void ExportAssimp2Json(const char *file, Assimp::IOSystem *io, const aiScene *sc
splitter.Execute(scenecopy_tmp); splitter.Execute(scenecopy_tmp);
// XXX Flag_WriteSpecialFloats is turned on by default, right now we don't have a configuration interface for exporters // XXX Flag_WriteSpecialFloats is turned on by default, right now we don't have a configuration interface for exporters
JSONWriter s(*str, JSONWriter::Flag_WriteSpecialFloats);
unsigned int flags = JSONWriter::Flag_WriteSpecialFloats;
if (pProperties->GetPropertyBool("JSON_SKIP_WHITESPACES", false)) {
flags |= JSONWriter::Flag_SkipWhitespaces;
}
JSONWriter s(*str, flags);
Write(s, *scenecopy_tmp); Write(s, *scenecopy_tmp);
} catch (...) { } catch (...) {

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.
@ -598,8 +598,11 @@ static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene,
if (!mesh->mTextureCoords[a]) if (!mesh->mTextureCoords[a])
break; break;
ioprintf(io, "\t\t<TextureCoords num=\"%u\" set=\"%u\" num_components=\"%u\"> \n", mesh->mNumVertices, ioprintf(io, "\t\t<TextureCoords num=\"%u\" set=\"%u\" name=\"%s\" num_components=\"%u\"> \n",
a, mesh->mNumUVComponents[a]); mesh->mNumVertices,
a,
mesh->mTextureCoordsNames[a].C_Str(),
mesh->mNumUVComponents[a]);
if (!shortened) { if (!shortened) {
if (mesh->mNumUVComponents[a] == 3) { if (mesh->mNumUVComponents[a] == 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

@ -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.
@ -143,9 +143,9 @@ AI_WONT_RETURN void B3DImporter::Oops() {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AI_WONT_RETURN void B3DImporter::Fail(string str) { AI_WONT_RETURN void B3DImporter::Fail(const string &str) {
#ifdef DEBUG_B3D #ifdef DEBUG_B3D
ASSIMP_LOG_ERROR_F("Error in B3D file data: ", str); ASSIMP_LOG_ERROR("Error in B3D file data: ", str);
#endif #endif
throw DeadlyImportError("B3D Importer - error in B3D file data: ", str); throw DeadlyImportError("B3D Importer - error in B3D file data: ", str);
} }
@ -233,7 +233,7 @@ string B3DImporter::ReadChunk() {
tag += char(ReadByte()); tag += char(ReadByte());
} }
#ifdef DEBUG_B3D #ifdef DEBUG_B3D
ASSIMP_LOG_DEBUG_F("ReadChunk: ", tag); ASSIMP_LOG_DEBUG("ReadChunk: ", tag);
#endif #endif
unsigned sz = (unsigned)ReadInt(); unsigned sz = (unsigned)ReadInt();
_stack.push_back(_pos + sz); _stack.push_back(_pos + sz);
@ -397,7 +397,7 @@ void B3DImporter::ReadTRIS(int v0) {
matid = 0; matid = 0;
} else if (matid < 0 || matid >= (int)_materials.size()) { } else if (matid < 0 || matid >= (int)_materials.size()) {
#ifdef DEBUG_B3D #ifdef DEBUG_B3D
ASSIMP_LOG_ERROR_F("material id=", matid); ASSIMP_LOG_ERROR("material id=", matid);
#endif #endif
Fail("Bad material id"); Fail("Bad material id");
} }
@ -417,7 +417,7 @@ void B3DImporter::ReadTRIS(int v0) {
int i2 = ReadInt() + v0; int i2 = ReadInt() + v0;
if (i0 < 0 || i0 >= (int)_vertices.size() || i1 < 0 || i1 >= (int)_vertices.size() || i2 < 0 || i2 >= (int)_vertices.size()) { if (i0 < 0 || i0 >= (int)_vertices.size() || i1 < 0 || i1 >= (int)_vertices.size() || i2 < 0 || i2 >= (int)_vertices.size()) {
#ifdef DEBUG_B3D #ifdef DEBUG_B3D
ASSIMP_LOG_ERROR_F("Bad triangle index: i0=", i0, ", i1=", i1, ", i2=", i2); ASSIMP_LOG_ERROR("Bad triangle index: i0=", i0, ", i1=", i1, ", i2=", i2);
#endif #endif
Fail("Bad triangle index"); Fail("Bad triangle index");
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.
@ -96,7 +96,7 @@ private:
}; };
AI_WONT_RETURN void Oops() AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void Oops() AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Fail( std::string str ) AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void Fail(const std::string &str) AI_WONT_RETURN_SUFFIX;
void ReadTEXS(); void ReadTEXS();
void ReadBRUS(); void ReadBRUS();

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
@ -359,7 +359,7 @@ void BVHLoader::ReadMotion(aiScene * /*pScene*/) {
std::string BVHLoader::GetNextToken() { std::string BVHLoader::GetNextToken() {
// skip any preceding whitespace // skip any preceding whitespace
while (mReader != mBuffer.end()) { while (mReader != mBuffer.end()) {
if (!isspace(*mReader)) if (!isspace((unsigned char)*mReader))
break; break;
// count lines // count lines
@ -372,7 +372,7 @@ std::string BVHLoader::GetNextToken() {
// collect all chars till the next whitespace. BVH is easy in respect to that. // collect all chars till the next whitespace. BVH is easy in respect to that.
std::string token; std::string token;
while (mReader != mBuffer.end()) { while (mReader != mBuffer.end()) {
if (isspace(*mReader)) if (isspace((unsigned char)*mReader))
break; break;
token.push_back(*mReader); token.push_back(*mReader);

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.
@ -198,9 +198,9 @@ void DNAParser::Parse() {
s.size = offset; s.size = offset;
} }
ASSIMP_LOG_DEBUG_F("BlenderDNA: Got ", dna.structures.size(), " structures with totally ", fields, " fields"); ASSIMP_LOG_DEBUG("BlenderDNA: Got ", dna.structures.size(), " structures with totally ", fields, " fields");
#ifdef ASSIMP_BUILD_BLENDER_DEBUG #if ASSIMP_BUILD_BLENDER_DEBUG_DNA
dna.DumpToFile(); dna.DumpToFile();
#endif #endif
@ -208,7 +208,7 @@ void DNAParser::Parse() {
dna.RegisterConverters(); dna.RegisterConverters();
} }
#ifdef ASSIMP_BUILD_BLENDER_DEBUG #if ASSIMP_BUILD_BLENDER_DEBUG_DNA
#include <fstream> #include <fstream>
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -237,7 +237,7 @@ void DNA ::DumpToFile() {
ASSIMP_LOG_INFO("BlenderDNA: Dumped dna to dna.txt"); ASSIMP_LOG_INFO("BlenderDNA: Dumped dna to dna.txt");
} }
#endif #endif // ASSIMP_BUILD_BLENDER_DEBUG_DNA
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
/*static*/ void DNA ::ExtractArraySize( /*static*/ void DNA ::ExtractArraySize(

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.
@ -59,6 +59,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define ASSIMP_BUILD_BLENDER_DEBUG #define ASSIMP_BUILD_BLENDER_DEBUG
#endif #endif
// set this to non-zero to dump BlenderDNA stuff to dna.txt.
// you could set it on the assimp build command line too without touching it here.
// !!! please make sure this is set to 0 in the repo !!!
#ifndef ASSIMP_BUILD_BLENDER_DEBUG_DNA
#define ASSIMP_BUILD_BLENDER_DEBUG_DNA 0
#endif
// #define ASSIMP_BUILD_BLENDER_NO_STATS // #define ASSIMP_BUILD_BLENDER_NO_STATS
namespace Assimp { namespace Assimp {
@ -495,7 +502,7 @@ public:
const Structure &structure, const Structure &structure,
const FileDatabase &db) const; const FileDatabase &db) const;
#ifdef ASSIMP_BUILD_BLENDER_DEBUG #if ASSIMP_BUILD_BLENDER_DEBUG_DNA
// -------------------------------------------------------- // --------------------------------------------------------
/** Dump the DNA to a text file. This is for debugging purposes. /** Dump the DNA to a text file. This is for debugging purposes.
* The output file is `dna.txt` in the current working folder*/ * The output file is `dna.txt` in the current working folder*/

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.
@ -565,7 +565,7 @@ template <> bool Structure :: ResolvePointer<std::shared_ptr,ElemBase>(std::shar
// this might happen if DNA::RegisterConverters hasn't been called so far // this might happen if DNA::RegisterConverters hasn't been called so far
// or if the target type is not contained in `our` DNA. // or if the target type is not contained in `our` DNA.
out.reset(); out.reset();
ASSIMP_LOG_WARN_F( "Failed to find a converter for the `",s.name,"` structure" ); ASSIMP_LOG_WARN( "Failed to find a converter for the `",s.name,"` structure" );
return false; return false;
} }

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");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -238,9 +235,9 @@ void BlenderImporter::InternReadFile(const std::string &pFile,
stream->Read(magic, 3, 1); stream->Read(magic, 3, 1);
magic[3] = '\0'; magic[3] = '\0';
LogInfo((format(), "Blender version is ", magic[0], ".", magic + 1, LogInfo("Blender version is ", magic[0], ".", magic + 1,
" (64bit: ", file.i64bit ? "true" : "false", " (64bit: ", file.i64bit ? "true" : "false",
", little endian: ", file.little ? "true" : "false", ")")); ", little endian: ", file.little ? "true" : "false", ")");
ParseBlendFile(file, stream); ParseBlendFile(file, stream);
@ -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;
@ -313,7 +310,7 @@ void BlenderImporter::ExtractScene(Scene &out, const FileDatabase &file) {
ss.Convert(out, file); ss.Convert(out, file);
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
ASSIMP_LOG_INFO_F( ASSIMP_LOG_INFO(
"(Stats) Fields read: ", file.stats().fields_read, "(Stats) Fields read: ", file.stats().fields_read,
", pointers resolved: ", file.stats().pointers_resolved, ", pointers resolved: ", file.stats().pointers_resolved,
", cache hits: ", file.stats().cache_hits, ", cache hits: ", file.stats().cache_hits,
@ -423,9 +420,9 @@ void BlenderImporter::ResolveImage(aiMaterial *out, const Material *mat, const M
--s; --s;
} }
curTex->achFormatHint[0] = s + 1 > e ? '\0' : (char)::tolower(s[1]); curTex->achFormatHint[0] = s + 1 > e ? '\0' : (char)::tolower((unsigned char)s[1]);
curTex->achFormatHint[1] = s + 2 > e ? '\0' : (char)::tolower(s[2]); curTex->achFormatHint[1] = s + 2 > e ? '\0' : (char)::tolower((unsigned char)s[2]);
curTex->achFormatHint[2] = s + 3 > e ? '\0' : (char)::tolower(s[3]); curTex->achFormatHint[2] = s + 3 > e ? '\0' : (char)::tolower((unsigned char)s[3]);
curTex->achFormatHint[3] = '\0'; curTex->achFormatHint[3] = '\0';
// tex->mHeight = 0; // tex->mHeight = 0;
@ -437,7 +434,7 @@ void BlenderImporter::ResolveImage(aiMaterial *out, const Material *mat, const M
curTex->pcData = reinterpret_cast<aiTexel *>(ch); curTex->pcData = reinterpret_cast<aiTexel *>(ch);
LogInfo("Reading embedded texture, original file was " + std::string(img->name)); LogInfo("Reading embedded texture, original file was ", img->name);
} else { } else {
name = aiString(img->name); name = aiString(img->name);
} }
@ -519,7 +516,7 @@ void BlenderImporter::ResolveTexture(aiMaterial *out, const Material *mat, const
case Tex::Type_POINTDENSITY: case Tex::Type_POINTDENSITY:
case Tex::Type_VOXELDATA: case Tex::Type_VOXELDATA:
LogWarn(std::string("Encountered a texture with an unsupported type: ") + dispnam); LogWarn("Encountered a texture with an unsupported type: ", dispnam);
AddSentinelTexture(out, mat, tex, conv_data); AddSentinelTexture(out, mat, tex, conv_data);
break; break;
@ -682,7 +679,7 @@ void BlenderImporter::BuildMaterials(ConversionData &conv_data) {
BuildDefaultMaterial(conv_data); BuildDefaultMaterial(conv_data);
for (std::shared_ptr<Material> mat : conv_data.materials_raw) { for (const std::shared_ptr<Material> &mat : conv_data.materials_raw) {
// reset per material global counters // reset per material global counters
for (size_t i = 0; i < sizeof(conv_data.next_texture) / sizeof(conv_data.next_texture[0]); ++i) { for (size_t i = 0; i < sizeof(conv_data.next_texture) / sizeof(conv_data.next_texture[0]); ++i) {
@ -755,7 +752,7 @@ void BlenderImporter::CheckActualType(const ElemBase *dt, const char *check) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderImporter::NotSupportedObjectType(const Object *obj, const char *type) { void BlenderImporter::NotSupportedObjectType(const Object *obj, const char *type) {
LogWarn((format(), "Object `", obj->id.name, "` - type is unsupported: `", type, "`, skipping")); LogWarn("Object `", obj->id.name, "` - type is unsupported: `", type, "`, skipping");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

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.
@ -90,7 +90,7 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode &out, ConversionData &conv_d
const Structure *s = conv_data.db.dna.Get(cur->dna_type); const Structure *s = conv_data.db.dna.Get(cur->dna_type);
if (!s) { if (!s) {
ASSIMP_LOG_WARN_F("BlendModifier: could not resolve DNA name: ", cur->dna_type); ASSIMP_LOG_WARN("BlendModifier: could not resolve DNA name: ", cur->dna_type);
continue; continue;
} }
@ -132,7 +132,7 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode &out, ConversionData &conv_d
} }
} }
if (curgod) { if (curgod) {
ASSIMP_LOG_WARN_F("Couldn't find a handler for modifier: ", dat.name); ASSIMP_LOG_WARN("Couldn't find a handler for modifier: ", dat.name);
} }
} }
@ -140,7 +140,7 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode &out, ConversionData &conv_d
// object, we still can't say whether our modifier implementations were // object, we still can't say whether our modifier implementations were
// able to fully do their job. // able to fully do their job.
if (ful) { if (ful) {
ASSIMP_LOG_DEBUG_F("BlendModifier: found handlers for ", cnt, " of ", ful, " modifiers on `", orig_object.id.name, ASSIMP_LOG_DEBUG("BlendModifier: found handlers for ", cnt, " of ", ful, " modifiers on `", orig_object.id.name,
"`, check log messages above for errors"); "`, check log messages above for errors");
} }
} }
@ -248,7 +248,7 @@ void BlenderModifier_Mirror ::DoIt(aiNode &out, ConversionData &conv_data, const
out.mMeshes = nind; out.mMeshes = nind;
out.mNumMeshes *= 2; out.mNumMeshes *= 2;
ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Mirror` modifier to `", ASSIMP_LOG_INFO("BlendModifier: Applied the `Mirror` modifier to `",
orig_object.id.name, "`"); orig_object.id.name, "`");
} }
@ -277,7 +277,7 @@ void BlenderModifier_Subdivision ::DoIt(aiNode &out, ConversionData &conv_data,
break; break;
default: default:
ASSIMP_LOG_WARN_F("BlendModifier: Unrecognized subdivision algorithm: ", mir.subdivType); ASSIMP_LOG_WARN("BlendModifier: Unrecognized subdivision algorithm: ", mir.subdivType);
return; return;
}; };
@ -292,7 +292,7 @@ void BlenderModifier_Subdivision ::DoIt(aiNode &out, ConversionData &conv_data,
subd->Subdivide(meshes, out.mNumMeshes, tempmeshes.get(), std::max(mir.renderLevels, mir.levels), true); subd->Subdivide(meshes, out.mNumMeshes, tempmeshes.get(), std::max(mir.renderLevels, mir.levels), true);
std::copy(tempmeshes.get(), tempmeshes.get() + out.mNumMeshes, meshes); std::copy(tempmeshes.get(), tempmeshes.get() + out.mNumMeshes, meshes);
ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Subdivision` modifier to `", ASSIMP_LOG_INFO("BlendModifier: Applied the `Subdivision` modifier to `",
orig_object.id.name, "`"); orig_object.id.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.
@ -86,7 +86,7 @@ public:
const Scene& /*in*/, const Scene& /*in*/,
const Object& /*orig_object*/ const Object& /*orig_object*/
) { ) {
ASSIMP_LOG_INFO_F("This modifier is not supported, skipping: ",orig_modifier.dna_type ); ASSIMP_LOG_INFO("This modifier is not supported, skipping: ",orig_modifier.dna_type );
return; return;
} }
}; };

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.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -51,7 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif #endif
#include "C4DImporter.h" #include "C4DImporter.h"
#include <assimp/TinyFormatter.h>
#include <memory> #include <memory>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/scene.h> #include <assimp/scene.h>
@ -65,7 +64,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "c4d_file.h" #include "c4d_file.h"
#include "default_alien_overloads.h" #include "default_alien_overloads.h"
using namespace melange; namespace {
aiString aiStringFrom(cineware::String const & cinestring) {
aiString result;
cinestring.GetCString(result.data, MAXLEN-1);
result.length = static_cast<ai_uint32>(cinestring.GetLength());
return result;
}
}
using namespace Assimp;
using namespace cineware;
// overload this function and fill in your own unique data // overload this function and fill in your own unique data
void GetWriterInfo(int &id, String &appname) { void GetWriterInfo(int &id, String &appname) {
@ -73,9 +84,6 @@ void GetWriterInfo(int &id, String &appname) {
appname = "Open Asset Import Library"; appname = "Open Asset Import Library";
} }
using namespace Assimp;
using namespace Assimp::Formatter;
namespace Assimp { namespace Assimp {
template<> const char* LogFunctions<C4DImporter>::Prefix() { template<> const char* LogFunctions<C4DImporter>::Prefix() {
static auto prefix = "C4D: "; static auto prefix = "C4D: ";
@ -97,17 +105,6 @@ static const aiImporterDesc desc = {
}; };
// ------------------------------------------------------------------------------------------------
C4DImporter::C4DImporter()
: BaseImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------
C4DImporter::~C4DImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
const std::string& extension = GetExtension(pFile); const std::string& extension = GetExtension(pFile);
@ -125,11 +122,6 @@ const aiImporterDesc* C4DImporter::GetInfo () const {
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------
void C4DImporter::SetupProperties(const Importer* /*pImp*/) {
// nothing to be done for the moment
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
@ -154,8 +146,14 @@ void C4DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
ThrowException("failed to read document " + pFile); ThrowException("failed to read document " + pFile);
} }
// Generate the root-node
pScene->mRootNode = new aiNode("<C4DRoot>"); pScene->mRootNode = new aiNode("<C4DRoot>");
// convert left-handed to right-handed
pScene->mRootNode->mTransformation.a1 = 0.01f;
pScene->mRootNode->mTransformation.b2 = 0.01f;
pScene->mRootNode->mTransformation.c3 = -0.01f;
// first convert all materials // first convert all materials
ReadMaterials(doc->GetFirstMaterial()); ReadMaterials(doc->GetFirstMaterial());
@ -199,8 +197,8 @@ void C4DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader) { bool C4DImporter::ReadShader(aiMaterial* out, BaseShader* shader) {
// based on Melange sample code (C4DImportExport.cpp) // based on Cineware sample code (C4DImportExport.cpp)
while(shader) { while(shader) {
if(shader->GetType() == Xlayer) { if(shader->GetType() == Xlayer) {
BaseContainer* container = shader->GetDataInstance(); BaseContainer* container = shader->GetDataInstance();
@ -242,13 +240,11 @@ bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader) {
lsl = lsl->GetNext(); lsl = lsl->GetNext();
} }
} else if ( shader->GetType() == Xbitmap ) { } else if ( shader->GetType() == Xbitmap ) {
aiString path; auto const path = aiStringFrom(shader->GetFileName().GetString());
shader->GetFileName().GetString().GetCString(path.data, MAXLEN-1);
path.length = ::strlen(path.data);
out->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0)); out->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0));
return true; return true;
} else { } else {
LogWarn("ignoring shader type: " + std::string(GetObjectTypeName(shader->GetType()))); LogWarn("ignoring shader type: ", GetObjectTypeName(shader->GetType()));
} }
shader = shader->GetNext(); shader = shader->GetNext();
} }
@ -257,18 +253,15 @@ bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader) {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void C4DImporter::ReadMaterials(melange::BaseMaterial* mat) { void C4DImporter::ReadMaterials(BaseMaterial* mat) {
// based on Melange sample code // based on Cineware sample code
while (mat) { while (mat) {
const String& name = mat->GetName();
if (mat->GetType() == Mmaterial) { if (mat->GetType() == Mmaterial) {
aiMaterial* out = new aiMaterial(); aiMaterial* out = new aiMaterial();
material_mapping[mat] = static_cast<unsigned int>(materials.size()); material_mapping[mat] = static_cast<unsigned int>(materials.size());
materials.push_back(out); materials.push_back(out);
aiString ai_name; auto const ai_name = aiStringFrom(mat->GetName());
name.GetCString(ai_name.data, MAXLEN-1);
ai_name.length = ::strlen(ai_name.data);
out->AddProperty(&ai_name, AI_MATKEY_NAME); out->AddProperty(&ai_name, AI_MATKEY_NAME);
Material& m = dynamic_cast<Material&>(*mat); Material& m = dynamic_cast<Material&>(*mat);
@ -294,7 +287,7 @@ void C4DImporter::ReadMaterials(melange::BaseMaterial* mat) {
ReadShader(out, shader); ReadShader(out, shader);
} }
} else { } else {
LogWarn("ignoring plugin material: " + std::string(GetObjectTypeName(mat->GetType()))); LogWarn("ignoring plugin material: ", GetObjectTypeName(mat->GetType()));
} }
mat = mat->GetNext(); mat = mat->GetNext();
} }
@ -305,19 +298,15 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) {
ai_assert(parent != nullptr ); ai_assert(parent != nullptr );
std::vector<aiNode*> nodes; std::vector<aiNode*> nodes;
// based on Melange sample code // based on Cineware sample code
while (object) { while (object) {
const String& name = object->GetName();
const LONG type = object->GetType(); const LONG type = object->GetType();
const Matrix& ml = object->GetMl(); const Matrix& ml = object->GetMl();
aiString string;
name.GetCString(string.data, MAXLEN-1);
string.length = ::strlen(string.data);
aiNode* const nd = new aiNode(); aiNode* const nd = new aiNode();
nd->mParent = parent; nd->mParent = parent;
nd->mName = string; nd->mName = aiStringFrom(object->GetName());
nd->mTransformation.a1 = ml.v1.x; nd->mTransformation.a1 = ml.v1.x;
nd->mTransformation.b1 = ml.v1.y; nd->mTransformation.b1 = ml.v1.y;
@ -352,7 +341,7 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) {
meshes.push_back(mesh); meshes.push_back(mesh);
} }
} else { } else {
LogWarn("ignoring object: " + std::string(GetObjectTypeName(type))); LogWarn("ignoring object: ", GetObjectTypeName(type));
} }
RecurseHierarchy(object->GetDown(), nd); RecurseHierarchy(object->GetDown(), nd);
@ -370,7 +359,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
ai_assert(object != nullptr); ai_assert(object != nullptr);
ai_assert( object->GetType() == Opolygon ); ai_assert( object->GetType() == Opolygon );
// based on Melange sample code // based on Cineware sample code
PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object); PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object);
ai_assert(polyObject != nullptr); ai_assert(polyObject != nullptr);
@ -618,4 +607,3 @@ unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj) {
} }
#endif // ASSIMP_BUILD_NO_C4D_IMPORTER #endif // ASSIMP_BUILD_NO_C4D_IMPORTER

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,
@ -56,8 +56,8 @@ struct aiMaterial;
struct aiImporterDesc; struct aiImporterDesc;
namespace melange { namespace cineware {
class BaseObject; // c4d_file.h class BaseObject;
class PolygonObject; class PolygonObject;
class BaseMaterial; class BaseMaterial;
class BaseShader; class BaseShader;
@ -71,43 +71,34 @@ namespace Assimp {
} }
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
/** Importer class to load Cinema4D files using the Melange library to be obtained from /** Importer class to load Cinema4D files using the Cineware library to be obtained from
* www.plugincafe.com * https://developers.maxon.net
* *
* Note that Melange is not free software. */ * Note that Cineware is not free software. */
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter> { class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter> {
public: public:
C4DImporter(); bool CanRead( const std::string& pFile, IOSystem*, bool checkSig) const override;
~C4DImporter();
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const;
protected: protected:
// -------------------- const aiImporterDesc* GetInfo () const override;
const aiImporterDesc* GetInfo () const;
// -------------------- void InternReadFile( const std::string& pFile, aiScene*, IOSystem* ) override;
void SetupProperties(const Importer* pImp);
// --------------------
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler);
private: private:
void ReadMaterials(melange::BaseMaterial* mat); void ReadMaterials(cineware::BaseMaterial* mat);
void RecurseHierarchy(melange::BaseObject* object, aiNode* parent); void RecurseHierarchy(cineware::BaseObject* object, aiNode* parent);
aiMesh* ReadMesh(melange::BaseObject* object); aiMesh* ReadMesh(cineware::BaseObject* object);
unsigned int ResolveMaterial(melange::PolygonObject* obj); unsigned int ResolveMaterial(cineware::PolygonObject* obj);
bool ReadShader(aiMaterial* out, melange::BaseShader* shader); bool ReadShader(aiMaterial* out, cineware::BaseShader* shader);
std::vector<aiMesh*> meshes; std::vector<aiMesh*> meshes;
std::vector<aiMaterial*> materials; std::vector<aiMaterial*> materials;
typedef std::map<melange::BaseMaterial*, unsigned int> MaterialMap; typedef std::map<cineware::BaseMaterial*, unsigned int> MaterialMap;
MaterialMap material_mapping; MaterialMap material_mapping;
}; // !class C4DImporter }; // !class C4DImporter

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.
@ -132,7 +137,13 @@ void COBImporter::SetupProperties(const Importer * /*pImp*/) {
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
COB::Scene scene; COB::Scene scene;
std::unique_ptr<StreamReaderLE> stream(new StreamReaderLE(pIOHandler->Open(pFile, "rb")));
auto file = pIOHandler->Open(pFile, "rb");
if (!file) {
ThrowException("Could not open " + pFile);
}
std::unique_ptr<StreamReaderLE> stream(new StreamReaderLE(file));
// check header // check header
char head[32]; char head[32];
@ -141,7 +152,7 @@ void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
ThrowException("Could not found magic id: `Caligari`"); ThrowException("Could not found magic id: `Caligari`");
} }
ASSIMP_LOG_INFO_F("File format tag: ", std::string(head + 9, 6)); ASSIMP_LOG_INFO("File format tag: ", std::string(head + 9, 6));
if (head[16] != 'L') { if (head[16] != 'L') {
ThrowException("File is big-endian, which is not supported"); ThrowException("File is big-endian, which is not supported");
} }
@ -219,7 +230,7 @@ void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertTexture(std::shared_ptr<Texture> tex, aiMaterial *out, aiTextureType type) { void ConvertTexture(const std::shared_ptr<Texture> &tex, aiMaterial *out, aiTextureType type) {
const aiString path(tex->path); const aiString path(tex->path);
out->AddProperty(&path, AI_MATKEY_TEXTURE(type, 0)); out->AddProperty(&path, AI_MATKEY_TEXTURE(type, 0));
out->AddProperty(&tex->transform, 1, AI_MATKEY_UVTRANSFORM(type, 0)); out->AddProperty(&tex->transform, 1, AI_MATKEY_UVTRANSFORM(type, 0));
@ -290,8 +301,7 @@ aiNode *COBImporter::BuildNodes(const Node &root, const Scene &scin, aiScene *fi
} }
std::unique_ptr<const Material> defmat; std::unique_ptr<const Material> defmat;
if (!min) { if (!min) {
ASSIMP_LOG_VERBOSE_DEBUG(format() << "Could not resolve material index " ASSIMP_LOG_VERBOSE_DEBUG("Could not resolve material index ", reflist.first, " - creating default material for this slot");
<< reflist.first << " - creating default material for this slot");
defmat.reset(min = new Material()); defmat.reset(min = new Material());
} }
@ -466,8 +476,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);
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -515,7 +526,7 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk
++splitter; ++splitter;
if (!splitter.match_start("mat# ")) { if (!splitter.match_start("mat# ")) {
ASSIMP_LOG_WARN_F("Expected `mat#` line in `Mat1` chunk ", nfo.id); ASSIMP_LOG_WARN("Expected `mat#` line in `Mat1` chunk ", nfo.id);
return; return;
} }
@ -527,7 +538,7 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk
++splitter; ++splitter;
if (!splitter.match_start("shader: ")) { if (!splitter.match_start("shader: ")) {
ASSIMP_LOG_WARN_F("Expected `mat#` line in `Mat1` chunk ", nfo.id); ASSIMP_LOG_WARN("Expected `mat#` line in `Mat1` chunk ", nfo.id);
return; return;
} }
std::string shader = std::string(splitter[1]); std::string shader = std::string(splitter[1]);
@ -538,12 +549,12 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk
} else if (shader == "phong") { } else if (shader == "phong") {
mat.shader = Material::PHONG; mat.shader = Material::PHONG;
} else if (shader != "flat") { } else if (shader != "flat") {
ASSIMP_LOG_WARN_F("Unknown value for `shader` in `Mat1` chunk ", nfo.id); ASSIMP_LOG_WARN("Unknown value for `shader` in `Mat1` chunk ", nfo.id);
} }
++splitter; ++splitter;
if (!splitter.match_start("rgb ")) { if (!splitter.match_start("rgb ")) {
ASSIMP_LOG_WARN_F("Expected `rgb` line in `Mat1` chunk ", nfo.id); ASSIMP_LOG_WARN("Expected `rgb` line in `Mat1` chunk ", nfo.id);
} }
const char *rgb = splitter[1]; const char *rgb = splitter[1];
@ -551,7 +562,7 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk
++splitter; ++splitter;
if (!splitter.match_start("alpha ")) { if (!splitter.match_start("alpha ")) {
ASSIMP_LOG_WARN_F("Expected `alpha` line in `Mat1` chunk ", nfo.id); ASSIMP_LOG_WARN("Expected `alpha` line in `Mat1` chunk ", nfo.id);
} }
const char *tokens[10]; const char *tokens[10];
@ -571,7 +582,7 @@ void COBImporter::ReadUnit_Ascii(Scene &out, LineSplitter &splitter, const Chunk
} }
++splitter; ++splitter;
if (!splitter.match_start("Units ")) { if (!splitter.match_start("Units ")) {
ASSIMP_LOG_WARN_F("Expected `Units` line in `Unit` chunk ", nfo.id); ASSIMP_LOG_WARN("Expected `Units` line in `Unit` chunk ", nfo.id);
return; return;
} }
@ -582,12 +593,12 @@ void COBImporter::ReadUnit_Ascii(Scene &out, LineSplitter &splitter, const Chunk
const unsigned int t = strtoul10(splitter[1]); const unsigned int t = strtoul10(splitter[1]);
nd->unit_scale = t >= sizeof(units) / sizeof(units[0]) ? ( nd->unit_scale = t >= sizeof(units) / sizeof(units[0]) ? (
ASSIMP_LOG_WARN_F(t, " is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id), 1.f) : ASSIMP_LOG_WARN(t, " is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id), 1.f) :
units[t]; units[t];
return; return;
} }
} }
ASSIMP_LOG_WARN_F("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist"); ASSIMP_LOG_WARN("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -616,13 +627,13 @@ void COBImporter::ReadLght_Ascii(Scene &out, LineSplitter &splitter, const Chunk
} else if (splitter.match_start("Spot ")) { } else if (splitter.match_start("Spot ")) {
msh.ltype = Light::SPOT; msh.ltype = Light::SPOT;
} else { } else {
ASSIMP_LOG_WARN_F("Unknown kind of light source in `Lght` chunk ", nfo.id, " : ", *splitter); ASSIMP_LOG_WARN("Unknown kind of light source in `Lght` chunk ", nfo.id, " : ", *splitter);
msh.ltype = Light::SPOT; msh.ltype = Light::SPOT;
} }
++splitter; ++splitter;
if (!splitter.match_start("color ")) { if (!splitter.match_start("color ")) {
ASSIMP_LOG_WARN_F("Expected `color` line in `Lght` chunk ", nfo.id); ASSIMP_LOG_WARN("Expected `color` line in `Lght` chunk ", nfo.id);
} }
const char *rgb = splitter[1]; const char *rgb = splitter[1];
@ -630,14 +641,14 @@ void COBImporter::ReadLght_Ascii(Scene &out, LineSplitter &splitter, const Chunk
SkipSpaces(&rgb); SkipSpaces(&rgb);
if (strncmp(rgb, "cone angle", 10) != 0) { if (strncmp(rgb, "cone angle", 10) != 0) {
ASSIMP_LOG_WARN_F("Expected `cone angle` entity in `color` line in `Lght` chunk ", nfo.id); ASSIMP_LOG_WARN("Expected `cone angle` entity in `color` line in `Lght` chunk ", nfo.id);
} }
SkipSpaces(rgb + 10, &rgb); SkipSpaces(rgb + 10, &rgb);
msh.angle = fast_atof(&rgb); msh.angle = fast_atof(&rgb);
SkipSpaces(&rgb); SkipSpaces(&rgb);
if (strncmp(rgb, "inner angle", 11) != 0) { if (strncmp(rgb, "inner angle", 11) != 0) {
ASSIMP_LOG_WARN_F("Expected `inner angle` entity in `color` line in `Lght` chunk ", nfo.id); ASSIMP_LOG_WARN("Expected `inner angle` entity in `color` line in `Lght` chunk ", nfo.id);
} }
SkipSpaces(rgb + 11, &rgb); SkipSpaces(rgb + 11, &rgb);
msh.inner_angle = fast_atof(&rgb); msh.inner_angle = fast_atof(&rgb);
@ -790,25 +801,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 +882,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 +907,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,9 +917,10 @@ 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());
} }
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -1037,7 +1032,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene &out, StreamReaderLE &reader, const
mat.type = Material::METAL; mat.type = Material::METAL;
break; break;
default: default:
ASSIMP_LOG_ERROR_F("Unrecognized shader type in `Mat1` chunk with id ", nfo.id); ASSIMP_LOG_ERROR("Unrecognized shader type in `Mat1` chunk with id ", nfo.id);
mat.type = Material::FLAT; mat.type = Material::FLAT;
} }
@ -1052,7 +1047,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene &out, StreamReaderLE &reader, const
mat.autofacet = Material::SMOOTH; mat.autofacet = Material::SMOOTH;
break; break;
default: default:
ASSIMP_LOG_ERROR_F("Unrecognized faceting mode in `Mat1` chunk with id ", nfo.id); ASSIMP_LOG_ERROR("Unrecognized faceting mode in `Mat1` chunk with id ", nfo.id);
mat.autofacet = Material::FACETED; mat.autofacet = Material::FACETED;
} }
mat.autofacet_angle = static_cast<float>(reader.GetI1()); mat.autofacet_angle = static_cast<float>(reader.GetI1());
@ -1180,13 +1175,13 @@ void COBImporter::ReadUnit_Binary(COB::Scene &out, StreamReaderLE &reader, const
if (nd->id == nfo.parent_id) { if (nd->id == nfo.parent_id) {
const unsigned int t = reader.GetI2(); const unsigned int t = reader.GetI2();
nd->unit_scale = t >= sizeof(units) / sizeof(units[0]) ? ( nd->unit_scale = t >= sizeof(units) / sizeof(units[0]) ? (
ASSIMP_LOG_WARN_F(t, " is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id), 1.f) : ASSIMP_LOG_WARN(t, " is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id), 1.f) :
units[t]; units[t];
return; return;
} }
} }
ASSIMP_LOG_WARN_F("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist"); ASSIMP_LOG_WARN("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
} }
#endif // ASSIMP_BUILD_NO_COB_IMPORTER #endif // ASSIMP_BUILD_NO_COB_IMPORTER

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;
@ -134,14 +135,15 @@ bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool
// XML - too generic, we need to open the file and search for typical keywords // XML - too generic, we need to open the file and search for typical keywords
if (extension == "xml" || !extension.length() || checkSig) { if (extension == "xml" || !extension.length() || checkSig) {
/* If CanRead() is called in order to check whether we // If CanRead() is called in order to check whether we
* support a specific file extension in general pIOHandler // support a specific file extension in general pIOHandler
* might be nullptr and it's our duty to return true here. // might be nullptr and it's our duty to return true here.
*/ if (nullptr == pIOHandler) {
if (!pIOHandler) {
return true; return true;
} }
static const char *tokens[] = { "<collada" }; static const char* tokens[] = {
"<collada"
};
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
} }
@ -271,7 +273,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 +300,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 +309,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,
@ -316,7 +318,7 @@ void ColladaLoader::ResolveNodeInstances(const ColladaParser &pParser, const Col
nd = FindNode(pParser.mRootNode, nodeInst.mNode); nd = FindNode(pParser.mRootNode, nodeInst.mNode);
} }
if (nullptr == nd) { if (nullptr == nd) {
ASSIMP_LOG_ERROR_F("Collada: Unable to resolve reference to instanced node ", nodeInst.mNode); ASSIMP_LOG_ERROR("Collada: Unable to resolve reference to instanced node ", nodeInst.mNode);
} else { } else {
// attach this node to the list of children // attach this node to the list of children
resolved.push_back(nd); resolved.push_back(nd);
@ -326,13 +328,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,12 +343,12 @@ 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()) {
ASSIMP_LOG_WARN_F("Collada: Unable to find light for ID \"", lid.mLight, "\". Skipping."); ASSIMP_LOG_WARN("Collada: Unable to find light for ID \"", lid.mLight, "\". Skipping.");
continue; continue;
} }
const Collada::Light *srcLight = &srcLightIt->second; const Collada::Light *srcLight = &srcLightIt->second;
@ -406,12 +408,12 @@ 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()) {
ASSIMP_LOG_WARN_F("Collada: Unable to find camera for ID \"", cid.mCamera, "\". Skipping."); ASSIMP_LOG_WARN("Collada: Unable to find camera for ID \"", cid.mCamera, "\". Skipping.");
continue; continue;
} }
const Collada::Camera *srcCamera = &srcCameraIt->second; const Collada::Camera *srcCamera = &srcCameraIt->second;
@ -461,15 +463,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);
@ -485,7 +487,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Colla
} }
if (nullptr == srcMesh) { if (nullptr == srcMesh) {
ASSIMP_LOG_WARN_F("Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping."); ASSIMP_LOG_WARN("Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping.");
continue; continue;
} }
} else { } else {
@ -503,14 +505,14 @@ 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()) {
table = &meshMatIt->second; table = &meshMatIt->second;
meshMaterial = table->mMatName; meshMaterial = table->mMatName;
} else { } else {
ASSIMP_LOG_WARN_F("Collada: No material specified for subgroup <", submesh.mMaterial, "> in geometry <", ASSIMP_LOG_WARN("Collada: No material specified for subgroup <", submesh.mMaterial, "> in geometry <",
mid.mMeshOrController, ">."); mid.mMeshOrController, ">.");
if (!mid.mMaterials.empty()) { if (!mid.mMaterials.empty()) {
meshMaterial = mid.mMaterials.begin()->second.mMatName; meshMaterial = mid.mMaterials.begin()->second.mMatName;
@ -557,7 +559,12 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Colla
faceStart += submesh.mNumFaces; faceStart += submesh.mNumFaces;
// assign the material index // assign the material index
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; dstMesh->mMaterialIndex = matIdx;
}
if (dstMesh->mName.length == 0) { if (dstMesh->mName.length == 0) {
dstMesh->mName = mid.mMeshOrController; dstMesh->mName = mid.mMeshOrController;
} }
@ -567,7 +574,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Colla
// now place all mesh references we gathered in the target node // now place all mesh references we gathered in the target node
pTarget->mNumMeshes = static_cast<unsigned int>(newMeshRefs.size()); pTarget->mNumMeshes = static_cast<unsigned int>(newMeshRefs.size());
if (newMeshRefs.size()) { if (!newMeshRefs.empty()) {
struct UIntTypeConverter { struct UIntTypeConverter {
unsigned int operator()(const size_t &v) const { unsigned int operator()(const size_t &v) const {
return static_cast<unsigned int>(v); return static_cast<unsigned int>(v);
@ -586,15 +593,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 +610,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) {
@ -613,6 +620,10 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Collada::M
dstMesh->mName = pSrcMesh->mId; dstMesh->mName = pSrcMesh->mId;
} }
if (pSrcMesh->mPositions.empty()) {
return dstMesh.release();
}
// count the vertices addressed by its faces // count the vertices addressed by its faces
const size_t numVertices = std::accumulate(pSrcMesh->mFaceSize.begin() + pStartFace, const size_t numVertices = std::accumulate(pSrcMesh->mFaceSize.begin() + pStartFace,
pSrcMesh->mFaceSize.begin() + pStartFace + pSubMesh.mNumFaces, size_t(0)); pSrcMesh->mFaceSize.begin() + pStartFace + pSubMesh.mNumFaces, size_t(0));
@ -642,7 +653,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 +693,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 +716,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 +729,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 +744,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 +768,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 +820,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,15 +880,15 @@ 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("ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\".");
} }
// and insert bone // and insert bone
@ -973,8 +986,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 +997,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 +1046,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 +1073,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 +1099,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 +1114,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 +1122,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 +1153,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);
@ -1169,9 +1189,9 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
else if (subElement == "Z") else if (subElement == "Z")
entry.mSubElement = 2; entry.mSubElement = 2;
else else
ASSIMP_LOG_WARN_F("Unknown anim subelement <", subElement, ">. Ignoring"); ASSIMP_LOG_WARN("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,33 +1242,34 @@ 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);
entries.push_back(entry); entries.push_back(entry);
} }
// 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 +1287,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 +1306,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 +1334,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 +1349,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 +1367,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,17 +1404,17 @@ 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
// or 2) one channel with morph target count arrays // or 2) one channel with morph target count arrays
@ -1407,13 +1425,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 +1476,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 +1491,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 +1595,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 +1673,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 +1687,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.emplace_back(&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 +1695,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;
@ -1696,7 +1716,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
// find the image referred by this name in the image library of the scene // find the image referred by this name in the image library of the scene
ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find(name); ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find(name);
if (imIt == pParser.mImageLibrary.end()) { if (imIt == pParser.mImageLibrary.end()) {
ASSIMP_LOG_WARN_F("Collada: Unable to resolve effect texture entry \"", pName, "\", ended up at ID \"", name, "\"."); ASSIMP_LOG_WARN("Collada: Unable to resolve effect texture entry \"", pName, "\", ended up at ID \"", name, "\".");
//set default texture file name //set default texture file name
result.Set(name + ".jpg"); result.Set(name + ".jpg");
@ -1712,10 +1732,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 +1760,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 +1768,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 +1785,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 +1801,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 +1810,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 +1823,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;
@ -70,7 +71,7 @@ static void ReportWarning(const char *msg, ...) {
ai_assert(iLen > 0); ai_assert(iLen > 0);
va_end(args); va_end(args);
ASSIMP_LOG_WARN_F("Validation warning: ", std::string(szBuffer, iLen)); ASSIMP_LOG_WARN("Validation warning: ", std::string(szBuffer, iLen));
} }
static bool FindCommonKey(const std::string &collada_key, const MetaKeyPairVector &key_renaming, size_t &found_index) { static bool FindCommonKey(const std::string &collada_key, const MetaKeyPairVector &key_renaming, size_t &found_index) {
@ -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;
} }
} }
@ -230,11 +231,7 @@ void ColladaParser::UriDecodePath(aiString &ss) {
// Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes... // Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes...
// I need to filter it without destroying linux paths starting with "/somewhere" // I need to filter it without destroying linux paths starting with "/somewhere"
#if defined(_MSC_VER)
if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') { if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') {
#else
if (ss.data[0] == '/' && isalpha(ss.data[1]) && ss.data[2] == ':') {
#endif
--ss.length; --ss.length;
::memmove(ss.data, ss.data + 1, ss.length); ::memmove(ss.data, ss.data + 1, ss.length);
ss.data[ss.length] = 0; ss.data[ss.length] = 0;
@ -289,7 +286,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 +331,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 +368,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);
@ -395,8 +392,8 @@ 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 +404,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 +416,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 +428,7 @@ void ColladaParser::PostProcessControllers() {
findItr = mControllerLibrary.find(meshId); findItr = mControllerLibrary.find(meshId);
} }
it->second.mMeshId = meshId; it.second.mMeshId = meshId;
} }
} }
@ -444,22 +441,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 (const 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 +489,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,6 +525,7 @@ 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") { } else if (currentName == "channel") {
std::string source_name, target; std::string source_name, target;
XmlParser::getStdStrAttribute(currentNode, "source", source_name); XmlParser::getStdStrAttribute(currentNode, "source", source_name);
@ -544,7 +539,6 @@ void ColladaParser::ReadAnimation(XmlNode &node, Collada::Animation *pParent) {
} }
} }
} }
}
// it turned out to have channels - add them // it turned out to have channels - add them
if (!channels.empty()) { if (!channels.empty()) {
@ -554,8 +548,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 +604,59 @@ void ColladaParser::ReadControllerLibrary(XmlNode &node) {
if (currentName != "controller") { if (currentName != "controller") {
continue; continue;
} }
std::string id = node.attribute("id").as_string(); std::string id;
if (XmlParser::getStdStrAttribute(currentNode, "id", id)) {
mControllerLibrary[id] = Controller(); mControllerLibrary[id] = Controller();
ReadController(node, mControllerLibrary[id]); 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, XmlNodeIterator::PreOrderMode);
XmlNode currentNode;
while (xmlIt.getNext(currentNode)) {
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 +664,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;
} }
} }
} }
@ -689,7 +692,7 @@ void ColladaParser::ReadControllerJoints(XmlNode &node, Collada::Controller &pCo
} else if (strcmp(attrSemantic, "INV_BIND_MATRIX") == 0) { } else if (strcmp(attrSemantic, "INV_BIND_MATRIX") == 0) {
pController.mJointOffsetMatrixSource = attrSource; pController.mJointOffsetMatrixSource = attrSource;
} else { } else {
throw DeadlyImportError("Unknown semantic \"" , attrSemantic , "\" in <joints> data <input> element"); throw DeadlyImportError("Unknown semantic \"", attrSemantic, "\" in <joints> data <input> element");
} }
} }
} }
@ -699,8 +702,9 @@ void ColladaParser::ReadControllerJoints(XmlNode &node, Collada::Controller &pCo
// Reads the joint weights for the given controller // Reads the joint weights for the given controller
void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pController) { void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pController) {
// 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();
@ -713,7 +717,7 @@ void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pC
// local URLS always start with a '#'. We don't support global URLs // local URLS always start with a '#'. We don't support global URLs
if (attrSource[0] != '#') { if (attrSource[0] != '#') {
throw DeadlyImportError( "Unsupported URL format in \"", attrSource, "\" in source attribute of <vertex_weights> data <input> element"); throw DeadlyImportError("Unsupported URL format in \"", attrSource, "\" in source attribute of <vertex_weights> data <input> element");
} }
channel.mAccessor = attrSource + 1; channel.mAccessor = attrSource + 1;
@ -726,7 +730,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,20 +767,17 @@ 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;
if (XmlParser::getStdStrAttribute(currentNode, "id", id)) {
mImageLibrary[id] = Image(); mImageLibrary[id] = Image();
// read on from there // read on from there
ReadImage(currentNode, mImageLibrary[id]); ReadImage(currentNode, mImageLibrary[id]);
} }
} }
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -793,7 +794,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 +844,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 +870,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 +884,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") {
@ -925,7 +914,7 @@ void ColladaParser::ReadMaterial(XmlNode &node, Collada::Material &pMaterial) {
if (currentName == "instance_effect") { if (currentName == "instance_effect") {
std::string url; std::string url;
readUrlAttribute(currentNode, url); readUrlAttribute(currentNode, url);
pMaterial.mEffect = url.c_str(); pMaterial.mEffect = url;
} }
} }
} }
@ -933,8 +922,7 @@ void ColladaParser::ReadMaterial(XmlNode &node, Collada::Material &pMaterial) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads a light entry into the given light // Reads a light entry into the given light
void ColladaParser::ReadLight(XmlNode &node, Collada::Light &pLight) { void ColladaParser::ReadLight(XmlNode &node, Collada::Light &pLight) {
XmlNodeIterator xmlIt(node); XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode; XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
@ -961,33 +949,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);
} }
} }
} }
@ -995,10 +983,8 @@ void ColladaParser::ReadLight(XmlNode &node, Collada::Light &pLight) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads a camera entry into the given light // Reads a camera entry into the given light
void ColladaParser::ReadCamera(XmlNode &node, Collada::Camera &camera) { void ColladaParser::ReadCamera(XmlNode &node, Collada::Camera &camera) {
XmlNodeIterator xmlIt(node); XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode; XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "orthographic") { if (currentName == "orthographic") {
@ -1054,11 +1040,10 @@ void ColladaParser::ReadEffect(XmlNode &node, Collada::Effect &pEffect) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads an COMMON effect profile // Reads an COMMON effect profile
void ColladaParser::ReadEffectProfileCommon(XmlNode &node, Collada::Effect &pEffect) { void ColladaParser::ReadEffectProfileCommon(XmlNode &node, Collada::Effect &pEffect) {
XmlNodeIterator xmlIt(node); XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode; XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string currentName = currentNode.name();
if (currentName == "newparam") { if (currentName == "newparam") {
// save ID // save ID
std::string sid = currentNode.attribute("sid").as_string(); std::string sid = currentNode.attribute("sid").as_string();
@ -1149,10 +1134,9 @@ void ColladaParser::ReadSamplerProperties(XmlNode &node, Sampler &out) {
if (node.empty()) { if (node.empty()) {
return; return;
} }
XmlNodeIterator xmlIt(node);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode;
XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
// MAYA extensions // MAYA extensions
@ -1166,15 +1150,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 +1178,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);
} }
} }
} }
@ -1212,10 +1196,9 @@ void ColladaParser::ReadEffectColor(XmlNode &node, aiColor4D &pColor, Sampler &p
if (node.empty()) { if (node.empty()) {
return; return;
} }
XmlNodeIterator xmlIt(node);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode;
XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == "color") { if (currentName == "color") {
@ -1277,8 +1260,7 @@ void ColladaParser::ReadEffectParam(XmlNode &node, Collada::EffectParam &pParam)
return; return;
} }
XmlNodeIterator xmlIt(node); XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode; XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
@ -1364,8 +1346,7 @@ void ColladaParser::ReadMesh(XmlNode &node, Mesh &pMesh) {
return; return;
} }
XmlNodeIterator xmlIt(node); XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode; XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
@ -1390,8 +1371,7 @@ void ColladaParser::ReadSource(XmlNode &node) {
std::string sourceID; std::string sourceID;
XmlParser::getStdStrAttribute(node, "id", sourceID); XmlParser::getStdStrAttribute(node, "id", sourceID);
XmlNodeIterator xmlIt(node); XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode; XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
@ -1419,7 +1399,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
@ -1453,9 +1433,8 @@ void ColladaParser::ReadDataArray(XmlNode &node) {
throw DeadlyImportError("Expected more values while reading float_array contents."); throw DeadlyImportError("Expected more values while reading float_array contents.");
} }
ai_real value;
// read a number // read a number
//SkipSpacesAndLineEnd(&content); ai_real value;
content = fast_atoreal_move<ai_real>(content, value); content = fast_atoreal_move<ai_real>(content, value);
data.mValues.push_back(value); data.mValues.push_back(value);
// skip whitespace after it // skip whitespace after it
@ -1494,8 +1473,7 @@ void ColladaParser::ReadAccessor(XmlNode &node, const std::string &pID) {
acc.mSource = source.c_str() + 1; // ignore the leading '#' acc.mSource = source.c_str() + 1; // ignore the leading '#'
acc.mSize = 0; // gets incremented with every param acc.mSize = 0; // gets incremented with every param
XmlNodeIterator xmlIt(node); XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode; XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
@ -1504,11 +1482,10 @@ void ColladaParser::ReadAccessor(XmlNode &node, const std::string &pID) {
std::string name; std::string name;
if (XmlParser::hasAttribute(currentNode, "name")) { if (XmlParser::hasAttribute(currentNode, "name")) {
XmlParser::getStdStrAttribute(currentNode, "name", name); XmlParser::getStdStrAttribute(currentNode, "name", name);
//name = mReader->getAttributeValue(attrName);
// analyse for common type components and store it's sub-offset in the corresponding field // analyse for common type components and store it's sub-offset in the corresponding field
/* Cartesian coordinates */ // Cartesian coordinates
if (name == "X") if (name == "X")
acc.mSubOffset[0] = acc.mParams.size(); acc.mSubOffset[0] = acc.mParams.size();
else if (name == "Y") else if (name == "Y")
@ -1612,8 +1589,7 @@ void ColladaParser::ReadIndexData(XmlNode &node, Mesh &pMesh) {
ai_assert(primType != Prim_Invalid); ai_assert(primType != Prim_Invalid);
// also a number of <input> elements, but in addition a <p> primitive collection and probably index counts for all primitives // also a number of <input> elements, but in addition a <p> primitive collection and probably index counts for all primitives
XmlNodeIterator xmlIt(node); XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
xmlIt.collectChildrenPreOrder(node);
XmlNode currentNode; XmlNode currentNode;
while (xmlIt.getNext(currentNode)) { while (xmlIt.getNext(currentNode)) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
@ -1690,11 +1666,8 @@ void ColladaParser::ReadInputChannel(XmlNode &node, std::vector<InputChannel> &p
// read set if texture coordinates // read set if texture coordinates
if (channel.mType == IT_Texcoord || channel.mType == IT_Color) { if (channel.mType == IT_Texcoord || channel.mType == IT_Color) {
int attrSet = -1; unsigned int attrSet = 0;
if (XmlParser::hasAttribute(node, "set")) { if (XmlParser::getUIntAttribute(node, "set", attrSet))
XmlParser::getIntAttribute(node, "set", attrSet);
}
channel.mIndex = attrSet; channel.mIndex = attrSet;
} }
@ -1738,14 +1711,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 +1747,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,9 +1779,10 @@ 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>
size_t numPrimitives = pNumPrimitives; size_t numPrimitives = pNumPrimitives;
@ -1884,11 +1863,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 +1893,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,16 +1908,18 @@ 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; break;
case IT_Normal: case IT_Normal:
// pad to current vertex count if necessary // pad to current vertex count if necessary
@ -1943,10 +1927,11 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, siz
pMesh.mNormals.insert(pMesh.mNormals.end(), pMesh.mPositions.size() - pMesh.mNormals.size() - 1, aiVector3D(0, 1, 0)); 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 // ignore all normal streams except 0 - there can be only one normal
if (pInput.mIndex == 0) if (pInput.mIndex == 0) {
pMesh.mNormals.push_back(aiVector3D(obj[0], obj[1], obj[2])); pMesh.mNormals.push_back(aiVector3D(obj[0], obj[1], obj[2]));
else } else {
ASSIMP_LOG_ERROR("Collada: just one vertex normal stream supported"); ASSIMP_LOG_ERROR("Collada: just one vertex normal stream supported");
}
break; break;
case IT_Tangent: case IT_Tangent:
// pad to current vertex count if necessary // pad to current vertex count if necessary
@ -1954,21 +1939,24 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, siz
pMesh.mTangents.insert(pMesh.mTangents.end(), pMesh.mPositions.size() - pMesh.mTangents.size() - 1, aiVector3D(1, 0, 0)); 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 // ignore all tangent streams except 0 - there can be only one tangent
if (pInput.mIndex == 0) if (pInput.mIndex == 0) {
pMesh.mTangents.push_back(aiVector3D(obj[0], obj[1], obj[2])); pMesh.mTangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
else } else {
ASSIMP_LOG_ERROR("Collada: just one vertex tangent stream supported"); ASSIMP_LOG_ERROR("Collada: just one vertex tangent stream supported");
}
break; break;
case IT_Bitangent: case IT_Bitangent:
// pad to current vertex count if necessary // pad to current vertex count if necessary
if (pMesh.mBitangents.size() < pMesh.mPositions.size() - 1) if (pMesh.mBitangents.size() < pMesh.mPositions.size() - 1) {
pMesh.mBitangents.insert(pMesh.mBitangents.end(), pMesh.mPositions.size() - pMesh.mBitangents.size() - 1, aiVector3D(0, 0, 1)); 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 // ignore all bitangent streams except 0 - there can be only one bitangent
if (pInput.mIndex == 0) if (pInput.mIndex == 0) {
pMesh.mBitangents.push_back(aiVector3D(obj[0], obj[1], obj[2])); pMesh.mBitangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
else } else {
ASSIMP_LOG_ERROR("Collada: just one vertex bitangent stream supported"); ASSIMP_LOG_ERROR("Collada: just one vertex bitangent stream supported");
}
break; break;
case IT_Texcoord: case IT_Texcoord:
// up to 4 texture coord sets are fine, ignore the others // up to 4 texture coord sets are fine, ignore the others
@ -1979,8 +1967,9 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, siz
pMesh.mPositions.size() - pMesh.mTexCoords[pInput.mIndex].size() - 1, aiVector3D(0, 0, 0)); pMesh.mPositions.size() - pMesh.mTexCoords[pInput.mIndex].size() - 1, aiVector3D(0, 0, 0));
pMesh.mTexCoords[pInput.mIndex].push_back(aiVector3D(obj[0], obj[1], obj[2])); 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 */ if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) {
pMesh.mNumUVComponents[pInput.mIndex] = 3; pMesh.mNumUVComponents[pInput.mIndex] = 3;
}
} else { } else {
ASSIMP_LOG_ERROR("Collada: too many texture coordinate sets. Skipping."); ASSIMP_LOG_ERROR("Collada: too many texture coordinate sets. Skipping.");
} }
@ -2170,10 +2159,10 @@ void ColladaParser::ReadNodeTransformation(XmlNode &node, Node *pNode, Transform
// read as many parameters and store in the transformation // read as many parameters and store in the transformation
for (unsigned int a = 0; a < sNumParameters[pType]; a++) { for (unsigned int a = 0; a < sNumParameters[pType]; a++) {
// skip whitespace before the number
SkipSpacesAndLineEnd(&content);
// read a number // read a number
content = fast_atoreal_move<ai_real>(content, tf.f[a]); content = fast_atoreal_move<ai_real>(content, tf.f[a]);
// skip whitespace after it
SkipSpacesAndLineEnd(&content);
} }
// place the transformation at the queue of the node // place the transformation at the queue of the node
@ -2215,8 +2204,8 @@ void ColladaParser::ReadMaterialVertexInputBinding(XmlNode &node, Collada::Seman
void ColladaParser::ReadEmbeddedTextures(ZipArchiveIOSystem &zip_archive) { void ColladaParser::ReadEmbeddedTextures(ZipArchiveIOSystem &zip_archive) {
// Attempt to load any undefined Collada::Image in ImageLibrary // Attempt to load any undefined Collada::Image in ImageLibrary
for (ImageLibrary::iterator it = mImageLibrary.begin(); it != mImageLibrary.end(); ++it) { for (auto & it : mImageLibrary) {
Collada::Image &image = (*it).second; Collada::Image &image = it.second;
if (image.mImageData.empty()) { if (image.mImageData.empty()) {
std::unique_ptr<IOStream> image_file(zip_archive.Open(image.mFileName.c_str())); std::unique_ptr<IOStream> image_file(zip_archive.Open(image.mFileName.c_str()));
@ -2388,7 +2377,7 @@ Collada::InputType ColladaParser::GetTypeForSemantic(const std::string &semantic
else if (semantic == "TANGENT" || semantic == "TEXTANGENT") else if (semantic == "TANGENT" || semantic == "TEXTANGENT")
return IT_Tangent; return IT_Tangent;
ASSIMP_LOG_WARN_F("Unknown vertex input type \"", semantic, "\". Ignoring."); ASSIMP_LOG_WARN("Unknown vertex input type \"", semantic, "\". Ignoring.");
return IT_Invalid; return IT_Invalid;
} }

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.
@ -135,7 +135,7 @@ public:
for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++); for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++);
splitter++; splitter++;
ASSIMP_LOG_VERBOSE_DEBUG((Formatter::format("DXF: skipped over control group ("),cnt," lines)")); ASSIMP_LOG_VERBOSE_DEBUG("DXF: skipped over control group (",cnt," lines)");
} }
} catch(std::logic_error&) { } catch(std::logic_error&) {
ai_assert(!splitter); ai_assert(!splitter);

View File

@ -3,9 +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,11 +61,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
// AutoCAD Binary DXF<CR><LF><SUB><NULL> // AutoCAD Binary DXF<CR><LF><SUB><NULL>
const std::string AI_DXF_BINARY_IDENT = std::string("AutoCAD Binary DXF\r\n\x1a\0"); static constexpr char AI_DXF_BINARY_IDENT[] = "AutoCAD Binary DXF\r\n\x1a";
const size_t AI_DXF_BINARY_IDENT_LEN = 24u; static constexpr size_t AI_DXF_BINARY_IDENT_LEN = sizeof AI_DXF_BINARY_IDENT;
// default vertex color that all uncolored vertices will receive // default vertex color that all uncolored vertices will receive
const aiColor4D AI_DXF_DEFAULT_COLOR(aiColor4D(0.6f, 0.6f, 0.6f, 0.6f)); static const aiColor4D AI_DXF_DEFAULT_COLOR(aiColor4D(0.6f, 0.6f, 0.6f, 0.6f));
// color indices for DXF - 16 are supported, the table is // color indices for DXF - 16 are supported, the table is
// taken directly from the DXF spec. // taken directly from the DXF spec.
@ -156,10 +154,10 @@ void DXFImporter::InternReadFile( const std::string& filename, aiScene* pScene,
} }
// Check whether this is a binary DXF file - we can't read binary DXF files :-( // Check whether this is a binary DXF file - we can't read binary DXF files :-(
char buff[AI_DXF_BINARY_IDENT_LEN+1] = {0}; char buff[AI_DXF_BINARY_IDENT_LEN] = {0};
file->Read(buff,AI_DXF_BINARY_IDENT_LEN,1); file->Read(buff,AI_DXF_BINARY_IDENT_LEN,1);
if (0 == strncmp(AI_DXF_BINARY_IDENT.c_str(),buff,AI_DXF_BINARY_IDENT_LEN)) { if (0 == memcmp(AI_DXF_BINARY_IDENT,buff,AI_DXF_BINARY_IDENT_LEN)) {
throw DeadlyImportError("DXF: Binary files are not supported at the moment"); throw DeadlyImportError("DXF: Binary files are not supported at the moment");
} }
@ -202,7 +200,7 @@ void DXFImporter::InternReadFile( const std::string& filename, aiScene* pScene,
// comments // comments
else if (reader.Is(999)) { else if (reader.Is(999)) {
ASSIMP_LOG_INFO_F("DXF Comment: ", reader.Value()); ASSIMP_LOG_INFO("DXF Comment: ", reader.Value());
} }
// don't read past the official EOF sign // don't read past the official EOF sign
@ -241,7 +239,7 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) {
} }
} }
ASSIMP_LOG_VERBOSE_DEBUG_F("DXF: Unexpanded polycount is ", icount, ", vertex count is ", vcount); ASSIMP_LOG_VERBOSE_DEBUG("DXF: Unexpanded polycount is ", icount, ", vertex count is ", vcount);
} }
if (! output.blocks.size() ) { if (! output.blocks.size() ) {
@ -372,7 +370,7 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc
// first check if the referenced blocks exists ... // first check if the referenced blocks exists ...
const DXF::BlockMap::const_iterator it = blocks_by_name.find(insert.name); const DXF::BlockMap::const_iterator it = blocks_by_name.find(insert.name);
if (it == blocks_by_name.end()) { if (it == blocks_by_name.end()) {
ASSIMP_LOG_ERROR_F("DXF: Failed to resolve block reference: ", insert.name,"; skipping" ); ASSIMP_LOG_ERROR("DXF: Failed to resolve block reference: ", insert.name,"; skipping" );
continue; continue;
} }
@ -473,7 +471,7 @@ void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output) {
++reader; ++reader;
} }
ASSIMP_LOG_VERBOSE_DEBUG_F("DXF: got ", output.blocks.size()," entries in BLOCKS" ); ASSIMP_LOG_VERBOSE_DEBUG("DXF: got ", output.blocks.size()," entries in BLOCKS" );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -549,7 +547,7 @@ void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output)
++reader; ++reader;
} }
ASSIMP_LOG_VERBOSE_DEBUG_F( "DXF: got ", block.lines.size()," polylines and ", block.insertions.size(), ASSIMP_LOG_VERBOSE_DEBUG( "DXF: got ", block.lines.size()," polylines and ", block.insertions.size(),
" inserted blocks in ENTITIES" ); " inserted blocks in ENTITIES" );
} }
@ -654,7 +652,7 @@ void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output)
//} //}
if (vguess && line.positions.size() != vguess) { if (vguess && line.positions.size() != vguess) {
ASSIMP_LOG_WARN_F("DXF: unexpected vertex count in polymesh: ", ASSIMP_LOG_WARN("DXF: unexpected vertex count in polymesh: ",
line.positions.size(),", expected ", vguess ); line.positions.size(),", expected ", vguess );
} }
@ -670,7 +668,7 @@ void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output)
// to set the 71 and 72 fields, respectively, to valid values. // to set the 71 and 72 fields, respectively, to valid values.
// So just fire a warning. // So just fire a warning.
if (iguess && line.counts.size() != iguess) { if (iguess && line.counts.size() != iguess) {
ASSIMP_LOG_WARN_F( "DXF: unexpected face count in polymesh: ", line.counts.size(),", expected ", iguess ); ASSIMP_LOG_WARN( "DXF: unexpected face count in polymesh: ", line.counts.size(),", expected ", iguess );
} }
} }
else if (!line.indices.size() && !line.counts.size()) { else if (!line.indices.size() && !line.counts.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.
@ -459,7 +459,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
/*Result ignored*/ ReadByte(input, cursor, input + length); /*Result ignored*/ ReadByte(input, cursor, input + length);
/*Result ignored*/ ReadByte(input, cursor, input + length); /*Result ignored*/ ReadByte(input, cursor, input + length);
const uint32_t version = ReadWord(input, cursor, input + length); const uint32_t version = ReadWord(input, cursor, input + length);
ASSIMP_LOG_DEBUG_F("FBX version: ", version); ASSIMP_LOG_DEBUG("FBX version: ", version);
const bool is64bits = version >= 7500; const bool is64bits = version >= 7500;
const char *end = input + length; const char *end = input + length;
try try
@ -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.
@ -811,7 +811,7 @@ bool FBXConverter::GenerateTransformationNodeChain(const Model &model, const std
// we need to generate a full node chain to accommodate for assimp's // we need to generate a full node chain to accommodate for assimp's
// lack to express pivots and offsets. // lack to express pivots and offsets.
if ((chainBits & chainMaskComplex) && doc.Settings().preservePivots) { if ((chainBits & chainMaskComplex) && doc.Settings().preservePivots) {
FBXImporter::LogInfo("generating full transformation chain for node: " + name); FBXImporter::LogInfo("generating full transformation chain for node: ", name);
// query the anim_chain_bits dictionary to find out which chain elements // query the anim_chain_bits dictionary to find out which chain elements
// have associated node animation channels. These can not be dropped // have associated node animation channels. These can not be dropped
@ -918,7 +918,7 @@ void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root
const std::vector<unsigned int> &indices = ConvertLine(*line, root_node); const std::vector<unsigned int> &indices = ConvertLine(*line, root_node);
std::copy(indices.begin(), indices.end(), std::back_inserter(meshes)); std::copy(indices.begin(), indices.end(), std::back_inserter(meshes));
} else { } else {
FBXImporter::LogWarn("ignoring unrecognized geometry: " + geo->Name()); FBXImporter::LogWarn("ignoring unrecognized geometry: ", geo->Name());
} }
} }
@ -944,7 +944,7 @@ FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *
const std::vector<aiVector3D> &vertices = mesh.GetVertices(); const std::vector<aiVector3D> &vertices = mesh.GetVertices();
const std::vector<unsigned int> &faces = mesh.GetFaceIndexCounts(); const std::vector<unsigned int> &faces = mesh.GetFaceIndexCounts();
if (vertices.empty() || faces.empty()) { if (vertices.empty() || faces.empty()) {
FBXImporter::LogWarn("ignoring empty geometry: " + mesh.Name()); FBXImporter::LogWarn("ignoring empty geometry: ", mesh.Name());
return temp; return temp;
} }
@ -971,7 +971,7 @@ std::vector<unsigned int> FBXConverter::ConvertLine(const LineGeometry &line, ai
const std::vector<aiVector3D> &vertices = line.GetVertices(); const std::vector<aiVector3D> &vertices = line.GetVertices();
const std::vector<int> &indices = line.GetIndices(); const std::vector<int> &indices = line.GetIndices();
if (vertices.empty() || indices.empty()) { if (vertices.empty() || indices.empty()) {
FBXImporter::LogWarn("ignoring empty line: " + line.Name()); FBXImporter::LogWarn("ignoring empty line: ", line.Name());
return temp; return temp;
} }
@ -1126,6 +1126,8 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c
*out_uv++ = aiVector3D(v.x, v.y, 0.0f); *out_uv++ = aiVector3D(v.x, v.y, 0.0f);
} }
out_mesh->mTextureCoordsNames[i] = mesh.GetTextureCoordChannelName(i);
out_mesh->mNumUVComponents[i] = 2; out_mesh->mNumUVComponents[i] = 2;
} }
@ -1542,10 +1544,10 @@ void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const
aiBone *bone = nullptr; aiBone *bone = nullptr;
if (bone_map.count(deformer_name)) { if (bone_map.count(deformer_name)) {
ASSIMP_LOG_VERBOSE_DEBUG_F("retrieved bone from lookup ", bone_name.C_Str(), ". Deformer:", deformer_name); ASSIMP_LOG_VERBOSE_DEBUG("retrieved bone from lookup ", bone_name.C_Str(), ". Deformer:", deformer_name);
bone = bone_map[deformer_name]; bone = bone_map[deformer_name];
} else { } else {
ASSIMP_LOG_VERBOSE_DEBUG_F("created new bone ", bone_name.C_Str(), ". Deformer: ", deformer_name); ASSIMP_LOG_VERBOSE_DEBUG("created new bone ", bone_name.C_Str(), ". Deformer: ", deformer_name);
bone = new aiBone(); bone = new aiBone();
bone->mName = bone_name; bone->mName = bone_name;
@ -1591,7 +1593,7 @@ void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const
bone_map.insert(std::pair<const std::string, aiBone *>(deformer_name, bone)); bone_map.insert(std::pair<const std::string, aiBone *>(deformer_name, bone));
} }
ASSIMP_LOG_DEBUG_F("bone research: Indicies size: ", out_indices.size()); ASSIMP_LOG_DEBUG("bone research: Indicies size: ", out_indices.size());
// lookup must be populated in case something goes wrong // lookup must be populated in case something goes wrong
// this also allocates bones to mesh instance outside // this also allocates bones to mesh instance outside
@ -1764,6 +1766,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const TextureMap
// XXX handle all kinds of UV transformations // XXX handle all kinds of UV transformations
uvTrafo.mScaling = tex->UVScaling(); uvTrafo.mScaling = tex->UVScaling();
uvTrafo.mTranslation = tex->UVTranslation(); uvTrafo.mTranslation = tex->UVTranslation();
uvTrafo.mRotation = tex->UVRotation();
out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, 0); out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, 0);
const PropertyTable &props = tex->Props(); const PropertyTable &props = tex->Props();
@ -1815,14 +1818,14 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const TextureMap
} }
} }
if (index == -1) { if (index == -1) {
FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); FBXImporter::LogWarn("did not find UV channel named ", uvSet, " in a mesh using this material");
continue; continue;
} }
if (uvIndex == -1) { if (uvIndex == -1) {
uvIndex = index; uvIndex = index;
} else { } else {
FBXImporter::LogWarn("the UV channel named " + uvSet + FBXImporter::LogWarn("the UV channel named ", uvSet,
" appears at different positions in meshes, results will be wrong"); " appears at different positions in meshes, results will be wrong");
} }
} }
@ -1839,7 +1842,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const TextureMap
} }
} }
if (index == -1) { if (index == -1) {
FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); FBXImporter::LogWarn("did not find UV channel named ", uvSet, " in a mesh using this material");
} }
if (uvIndex == -1) { if (uvIndex == -1) {
@ -1848,7 +1851,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const TextureMap
} }
if (uvIndex == -1) { if (uvIndex == -1) {
FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel"); FBXImporter::LogWarn("failed to resolve UV channel ", uvSet, ", using first UV channel");
uvIndex = 0; uvIndex = 0;
} }
} }
@ -1883,6 +1886,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const LayeredTex
// XXX handle all kinds of UV transformations // XXX handle all kinds of UV transformations
uvTrafo.mScaling = tex->UVScaling(); uvTrafo.mScaling = tex->UVScaling();
uvTrafo.mTranslation = tex->UVTranslation(); uvTrafo.mTranslation = tex->UVTranslation();
uvTrafo.mRotation = tex->UVRotation();
out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, texIndex); out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, texIndex);
const PropertyTable &props = tex->Props(); const PropertyTable &props = tex->Props();
@ -1934,14 +1938,14 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const LayeredTex
} }
} }
if (index == -1) { if (index == -1) {
FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); FBXImporter::LogWarn("did not find UV channel named ", uvSet, " in a mesh using this material");
continue; continue;
} }
if (uvIndex == -1) { if (uvIndex == -1) {
uvIndex = index; uvIndex = index;
} else { } else {
FBXImporter::LogWarn("the UV channel named " + uvSet + FBXImporter::LogWarn("the UV channel named ", uvSet,
" appears at different positions in meshes, results will be wrong"); " appears at different positions in meshes, results will be wrong");
} }
} }
@ -1958,7 +1962,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const LayeredTex
} }
} }
if (index == -1) { if (index == -1) {
FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); FBXImporter::LogWarn("did not find UV channel named ", uvSet, " in a mesh using this material");
} }
if (uvIndex == -1) { if (uvIndex == -1) {
@ -1967,7 +1971,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const LayeredTex
} }
if (uvIndex == -1) { if (uvIndex == -1) {
FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel"); FBXImporter::LogWarn("failed to resolve UV channel ", uvSet, ", using first UV channel");
uvIndex = 0; uvIndex = 0;
} }
} }
@ -2126,6 +2130,11 @@ void FBXConverter::SetShadingPropertiesCommon(aiMaterial *out_mat, const Propert
const aiColor3D &Emissive = GetColorPropertyFromMaterial(props, "Emissive", ok); const aiColor3D &Emissive = GetColorPropertyFromMaterial(props, "Emissive", ok);
if (ok) { if (ok) {
out_mat->AddProperty(&Emissive, 1, AI_MATKEY_COLOR_EMISSIVE); out_mat->AddProperty(&Emissive, 1, AI_MATKEY_COLOR_EMISSIVE);
} else {
const aiColor3D &emissiveColor = GetColorProperty(props, "Maya|emissive", ok);
if (ok) {
out_mat->AddProperty(&emissiveColor, 1, AI_MATKEY_COLOR_EMISSIVE);
}
} }
const aiColor3D &Ambient = GetColorPropertyFromMaterial(props, "Ambient", ok); const aiColor3D &Ambient = GetColorPropertyFromMaterial(props, "Ambient", ok);
@ -2207,6 +2216,52 @@ void FBXConverter::SetShadingPropertiesCommon(aiMaterial *out_mat, const Propert
if (ok) { if (ok) {
out_mat->AddProperty(&DispFactor, 1, "$mat.displacementscaling", 0, 0); out_mat->AddProperty(&DispFactor, 1, "$mat.displacementscaling", 0, 0);
} }
// PBR material information
const aiColor3D &baseColor = GetColorProperty(props, "Maya|base_color", ok);
if (ok) {
out_mat->AddProperty(&baseColor, 1, AI_MATKEY_BASE_COLOR);
}
const float useColorMap = PropertyGet<float>(props, "Maya|use_color_map", ok);
if (ok) {
out_mat->AddProperty(&useColorMap, 1, AI_MATKEY_USE_COLOR_MAP);
}
const float useMetallicMap = PropertyGet<float>(props, "Maya|use_metallic_map", ok);
if (ok) {
out_mat->AddProperty(&useMetallicMap, 1, AI_MATKEY_USE_METALLIC_MAP);
}
const float metallicFactor = PropertyGet<float>(props, "Maya|metallic", ok);
if (ok) {
out_mat->AddProperty(&metallicFactor, 1, AI_MATKEY_METALLIC_FACTOR);
}
const float useRoughnessMap = PropertyGet<float>(props, "Maya|use_roughness_map", ok);
if (ok) {
out_mat->AddProperty(&useRoughnessMap, 1, AI_MATKEY_USE_ROUGHNESS_MAP);
}
const float roughnessFactor = PropertyGet<float>(props, "Maya|roughness", ok);
if (ok) {
out_mat->AddProperty(&roughnessFactor, 1, AI_MATKEY_ROUGHNESS_FACTOR);
}
const float useEmissiveMap = PropertyGet<float>(props, "Maya|use_emissive_map", ok);
if (ok) {
out_mat->AddProperty(&useEmissiveMap, 1, AI_MATKEY_USE_EMISSIVE_MAP);
}
const float emissiveIntensity = PropertyGet<float>(props, "Maya|emissive_intensity", ok);
if (ok) {
out_mat->AddProperty(&emissiveIntensity, 1, AI_MATKEY_EMISSIVE_INTENSITY);
}
const float useAOMap = PropertyGet<float>(props, "Maya|use_ao_map", ok);
if (ok) {
out_mat->AddProperty(&useAOMap, 1, AI_MATKEY_USE_AO_MAP);
}
} }
void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTable &props, const TextureMap &_textures, const MeshGeometry *const mesh) { void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTable &props, const TextureMap &_textures, const MeshGeometry *const mesh) {
@ -2271,6 +2326,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa
// XXX handle all kinds of UV transformations // XXX handle all kinds of UV transformations
uvTrafo.mScaling = tex->UVScaling(); uvTrafo.mScaling = tex->UVScaling();
uvTrafo.mTranslation = tex->UVTranslation(); uvTrafo.mTranslation = tex->UVTranslation();
uvTrafo.mRotation = tex->UVRotation();
out_mat->AddProperty(&uvTrafo, 1, (name + "|uvtrafo").c_str(), aiTextureType_UNKNOWN, 0); out_mat->AddProperty(&uvTrafo, 1, (name + "|uvtrafo").c_str(), aiTextureType_UNKNOWN, 0);
int uvIndex = 0; int uvIndex = 0;
@ -2319,14 +2375,14 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa
} }
} }
if (index == -1) { if (index == -1) {
FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); FBXImporter::LogWarn("did not find UV channel named ", uvSet, " in a mesh using this material");
continue; continue;
} }
if (uvIndex == -1) { if (uvIndex == -1) {
uvIndex = index; uvIndex = index;
} else { } else {
FBXImporter::LogWarn("the UV channel named " + uvSet + " appears at different positions in meshes, results will be wrong"); FBXImporter::LogWarn("the UV channel named ", uvSet, " appears at different positions in meshes, results will be wrong");
} }
} }
} else { } else {
@ -2342,7 +2398,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa
} }
} }
if (index == -1) { if (index == -1) {
FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); FBXImporter::LogWarn("did not find UV channel named ", uvSet, " in a mesh using this material");
} }
if (uvIndex == -1) { if (uvIndex == -1) {
@ -2351,7 +2407,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa
} }
if (uvIndex == -1) { if (uvIndex == -1) {
FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel"); FBXImporter::LogWarn("failed to resolve UV channel ", uvSet, ", using first UV channel");
uvIndex = 0; uvIndex = 0;
} }
} }
@ -2546,7 +2602,7 @@ void FBXConverter::ConvertAnimationStack(const AnimationStack &st) {
anim->mMorphMeshChannels = new aiMeshMorphAnim *[numMorphMeshChannels]; anim->mMorphMeshChannels = new aiMeshMorphAnim *[numMorphMeshChannels];
anim->mNumMorphMeshChannels = numMorphMeshChannels; anim->mNumMorphMeshChannels = numMorphMeshChannels;
unsigned int i = 0; unsigned int i = 0;
for (auto morphAnimIt : morphAnimDatas) { for (const auto &morphAnimIt : morphAnimDatas) {
morphAnimData *animData = morphAnimIt.second; morphAnimData *animData = morphAnimIt.second;
unsigned int numKeys = static_cast<unsigned int>(animData->size()); unsigned int numKeys = static_cast<unsigned int>(animData->size());
aiMeshMorphAnim *meshMorphAnim = new aiMeshMorphAnim(); aiMeshMorphAnim *meshMorphAnim = new aiMeshMorphAnim();
@ -2574,7 +2630,7 @@ void FBXConverter::ConvertAnimationStack(const AnimationStack &st) {
// empty animations would fail validation, so drop them // empty animations would fail validation, so drop them
delete anim; delete anim;
animations.pop_back(); animations.pop_back();
FBXImporter::LogInfo("ignoring empty AnimationStack (using IK?): " + name); FBXImporter::LogInfo("ignoring empty AnimationStack (using IK?): ", name);
return; return;
} }
@ -2707,13 +2763,13 @@ void FBXConverter::GenerateNodeAnimations(std::vector<aiNodeAnim *> &node_anims,
ai_assert(node); ai_assert(node);
if (node->TargetProperty().empty()) { if (node->TargetProperty().empty()) {
FBXImporter::LogWarn("target property for animation curve not set: " + node->Name()); FBXImporter::LogWarn("target property for animation curve not set: ", node->Name());
continue; continue;
} }
curve_node = node; curve_node = node;
if (node->Curves().empty()) { if (node->Curves().empty()) {
FBXImporter::LogWarn("no animation curves assigned to AnimationCurveNode: " + node->Name()); FBXImporter::LogWarn("no animation curves assigned to AnimationCurveNode: ", node->Name());
continue; continue;
} }
@ -2748,7 +2804,7 @@ void FBXConverter::GenerateNodeAnimations(std::vector<aiNodeAnim *> &node_anims,
if (doc.Settings().optimizeEmptyAnimationCurves && if (doc.Settings().optimizeEmptyAnimationCurves &&
IsRedundantAnimationData(target, comp, (chain[i]->second))) { IsRedundantAnimationData(target, comp, (chain[i]->second))) {
FBXImporter::LogVerboseDebug("dropping redundant animation channel for node " + target.Name()); FBXImporter::LogVerboseDebug("dropping redundant animation channel for node ", target.Name());
continue; continue;
} }
@ -3440,7 +3496,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 +3510,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.

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