Merge remote-tracking branch 'upstream/master' into feature/collada-up_axis-api-improvements

pull/1499/head
Doug Stephen 2017-10-17 10:29:03 -05:00
commit 100fa76a90
234 changed files with 17830 additions and 3557 deletions

7
.gitattributes vendored
View File

@ -13,3 +13,10 @@ CHANGES text eol=lf
CREDITS text eol=lf CREDITS text eol=lf
LICENSE text eol=lf LICENSE text eol=lf
Readme.md text eol=lf Readme.md text eol=lf
# make sure that repo-specific settings (.gitignore, CI-setup,...)
# are excluded from the source-package generated via 'git archive'
.git* export-ignore
/.travis* export-ignore
/.coveralls* export-ignore
appveyor.yml export-ignore

View File

@ -1,6 +1,36 @@
function generate() function generate()
{ {
cmake -G "Unix Makefiles" -DASSIMP_NO_EXPORT=$TRAVIS_NO_EXPORT -DBUILD_SHARED_LIBS=$SHARED_BUILD -DASSIMP_COVERALLS=$ENABLE_COVERALLS OPTIONS="-DASSIMP_WERROR=ON"
if [ "$DISABLE_EXPORTERS" = "YES" ] ; then
OPTIONS="$OPTIONS -DASSIMP_NO_EXPORT=YES"
else
OPTIONS="$OPTIONS -DASSIMP_NO_EXPORT=NO"
fi
if [ "$SHARED_BUILD" = "ON" ] ; then
OPTIONS="$OPTIONS -DBUILD_SHARED_LIBS=ON"
else
OPTIONS="$OPTIONS -DBUILD_SHARED_LIBS=OFF"
fi
if [ "$ENABLE_COVERALLS" = "ON" ] ; then
OPTIONS="$OPTIONS -DASSIMP_COVERALLS=ON"
else
OPTIONS="$OPTIONS -DASSIMP_COVERALLS=OFF"
fi
if [ "$ASAN" = "ON" ] ; then
OPTIONS="$OPTIONS -DASSIMP_ASAN=ON"
else
OPTIONS="$OPTIONS -DASSIMP_ASAN=OFF"
fi
if [ "$UBSAN" = "ON" ] ; then
OPTIONS="$OPTIONS -DASSIMP_UBSAN=ON"
fi
cmake -G "Unix Makefiles" $OPTIONS
} }
if [ $ANDROID ]; then if [ $ANDROID ]; then

View File

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

12
CHANGES
View File

@ -1,6 +1,18 @@
---------------------------------------------------------------------- ----------------------------------------------------------------------
CHANGELOG CHANGELOG
---------------------------------------------------------------------- ----------------------------------------------------------------------
4.0.1 (2017-07-28)
- FIXES/HOUSEKEEPING:
- fix version test.
- Not compiling when using ASSIMP_DOUBLE_PRECISION
- Added support for python3
- Check if cmake is installed with brew
- Low performance in OptimizeMeshesProcess::ProcessNode with huge numbers of meshes
- Elapsed seconds not shown correctly
- StreamReader: fix out-of-range exception
- PPdPmdParser: fix compilation for clang
4.0.0 (2017-07-18) 4.0.0 (2017-07-18)
FEATURES: FEATURES:

View File

@ -34,7 +34,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#---------------------------------------------------------------------- #----------------------------------------------------------------------
SET(CMAKE_LEGACY_CYGWIN_WIN32 0) # Remove when CMake >= 2.8.4 is required SET(CMAKE_LEGACY_CYGWIN_WIN32 0) # Remove when CMake >= 2.8.4 is required
cmake_minimum_required( VERSION 2.8 ) CMAKE_MINIMUM_REQUIRED( VERSION 2.8 )
PROJECT( Assimp ) PROJECT( Assimp )
# All supported options ############################################### # All supported options ###############################################
@ -62,11 +62,11 @@ OPTION( ASSIMP_BUILD_ZLIB
"Build your own zlib" "Build your own zlib"
OFF OFF
) )
option( ASSIMP_BUILD_ASSIMP_TOOLS OPTION( ASSIMP_BUILD_ASSIMP_TOOLS
"If the supplementary tools for Assimp are built in addition to the library." "If the supplementary tools for Assimp are built in addition to the library."
ON ON
) )
option ( ASSIMP_BUILD_SAMPLES OPTION ( ASSIMP_BUILD_SAMPLES
"If the official samples are built as well (needs Glut)." "If the official samples are built as well (needs Glut)."
OFF OFF
) )
@ -75,10 +75,22 @@ OPTION ( ASSIMP_BUILD_TESTS
ON ON
) )
OPTION ( ASSIMP_COVERALLS OPTION ( ASSIMP_COVERALLS
"Eańable this to measure test coverage." "Enable this to measure test coverage."
OFF OFF
) )
option ( SYSTEM_IRRXML OPTION ( ASSIMP_WERROR
"Treat warnings as errors."
OFF
)
OPTION ( ASSIMP_ASAN
"Enable AddressSanitizer."
OFF
)
OPTION ( ASSIMP_UBSAN
"Enable Undefined Behavior sanitizer."
OFF
)
OPTION ( SYSTEM_IRRXML
"Use system installed Irrlicht/IrrXML library." "Use system installed Irrlicht/IrrXML library."
OFF OFF
) )
@ -88,11 +100,11 @@ OPTION ( BUILD_DOCS
) )
if (WIN32) if (WIN32)
add_definitions( -DWIN32_LEAN_AND_MEAN ) ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN )
endif() endif()
IF(MSVC) IF(MSVC)
set (CMAKE_PREFIX_PATH "D:\\libs\\devil") SET (CMAKE_PREFIX_PATH "D:\\libs\\devil")
OPTION( ASSIMP_INSTALL_PDB OPTION( ASSIMP_INSTALL_PDB
"Install MSVC debug files." "Install MSVC debug files."
ON ON
@ -100,21 +112,24 @@ IF(MSVC)
ENDIF(MSVC) ENDIF(MSVC)
IF(NOT BUILD_SHARED_LIBS) IF(NOT BUILD_SHARED_LIBS)
MESSAGE(STATUS "Shared libraries disabled")
SET(LINK_SEARCH_START_STATIC TRUE) SET(LINK_SEARCH_START_STATIC TRUE)
ELSE()
MESSAGE(STATUS "Shared libraries enabled")
ENDIF(NOT BUILD_SHARED_LIBS) ENDIF(NOT BUILD_SHARED_LIBS)
# Define here the needed parameters # Define here the needed parameters
SET (ASSIMP_VERSION_MAJOR 4) SET (ASSIMP_VERSION_MAJOR 4)
SET (ASSIMP_VERSION_MINOR 0) SET (ASSIMP_VERSION_MINOR 0)
SET (ASSIMP_VERSION_PATCH 0) # subversion revision? SET (ASSIMP_VERSION_PATCH 1)
SET (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}) SET (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH})
SET (ASSIMP_SOVERSION 4) SET (ASSIMP_SOVERSION 4)
SET (PROJECT_VERSION "${ASSIMP_VERSION}") SET (PROJECT_VERSION "${ASSIMP_VERSION}")
SET(ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources") SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" )
# Needed for openddl_parser config, no use of c++11 at this moment # Needed for openddl_parser config, no use of c++11 at this moment
add_definitions( -DOPENDDL_NO_USE_CPP11 ) ADD_DEFINITIONS( -DOPENDDL_NO_USE_CPP11 )
set_property( GLOBAL PROPERTY CXX_STANDARD 11 ) set_property( GLOBAL PROPERTY CXX_STANDARD 11 )
# Get the current working branch # Get the current working branch
@ -143,25 +158,19 @@ IF(ASSIMP_DOUBLE_PRECISION)
ADD_DEFINITIONS(-DASSIMP_DOUBLE_PRECISION) ADD_DEFINITIONS(-DASSIMP_DOUBLE_PRECISION)
ENDIF(ASSIMP_DOUBLE_PRECISION) ENDIF(ASSIMP_DOUBLE_PRECISION)
# Check for OpenMP support CONFIGURE_FILE(
find_package(OpenMP)
if (OPENMP_FOUND)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif()
configure_file(
${CMAKE_CURRENT_LIST_DIR}/revision.h.in ${CMAKE_CURRENT_LIST_DIR}/revision.h.in
${CMAKE_CURRENT_BINARY_DIR}/revision.h ${CMAKE_CURRENT_BINARY_DIR}/revision.h
) )
configure_file( CONFIGURE_FILE(
${CMAKE_CURRENT_LIST_DIR}/include/assimp/config.h.in ${CMAKE_CURRENT_LIST_DIR}/include/assimp/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/include/assimp/config.h ${CMAKE_CURRENT_BINARY_DIR}/include/assimp/config.h
) )
include_directories( INCLUDE_DIRECTORIES(
./ ./
include
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}/include ${CMAKE_CURRENT_BINARY_DIR}/include
) )
@ -179,7 +188,7 @@ IF( UNIX )
ENDIF() ENDIF()
# Use GNUInstallDirs for Unix predefined directories # Use GNUInstallDirs for Unix predefined directories
include(GNUInstallDirs) INCLUDE(GNUInstallDirs)
ENDIF( UNIX ) ENDIF( UNIX )
@ -192,20 +201,48 @@ IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW)
ELSEIF(MSVC) ELSEIF(MSVC)
# enable multi-core compilation with MSVC # enable multi-core compilation with MSVC
add_compile_options(/MP) add_compile_options(/MP)
# disable "elements of array '' will be default initialized" warning on MSVC2013
IF(MSVC12)
add_compile_options(/wd4351)
ENDIF()
ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -fPIC -Wall -Wno-long-long -pedantic -std=c++11" ) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -fPIC -Wall -Wno-long-long -std=c++11" )
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
ELSEIF( CMAKE_COMPILER_IS_MINGW ) ELSEIF( CMAKE_COMPILER_IS_MINGW )
SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall -Wno-long-long -pedantic -std=c++11" ) SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall -Wno-long-long -std=c++11" )
add_definitions( -U__STRICT_ANSI__ ) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
ADD_DEFINITIONS( -U__STRICT_ANSI__ )
ENDIF() ENDIF()
if (ASSIMP_COVERALLS) if (ASSIMP_COVERALLS)
include(Coveralls) MESSAGE(STATUS "Coveralls enabled")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") INCLUDE(Coveralls)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
endif() endif()
INCLUDE_DIRECTORIES( include ) if (ASSIMP_WERROR)
MESSAGE(STATUS "Treating warnings as errors")
IF (MSVC)
add_compile_options(/WX)
ELSE()
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
ENDIF()
endif()
if (ASSIMP_ASAN)
MESSAGE(STATUS "AddressSanitizer enabled")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
endif()
if (ASSIMP_UBSAN)
MESSAGE(STATUS "Undefined Behavior sanitizer enabled")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all")
endif()
INCLUDE (FindPkgMacros) INCLUDE (FindPkgMacros)
INCLUDE (PrecompiledHeader) INCLUDE (PrecompiledHeader)
@ -237,13 +274,13 @@ ENDIF()
# Only generate this target if no higher-level project already has # Only generate this target if no higher-level project already has
IF (NOT TARGET uninstall) IF (NOT TARGET uninstall)
# add make uninstall capability # add make uninstall capability
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
ENDIF() ENDIF()
# cmake configuration files # cmake configuration files
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE) CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE) CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT}) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT})
FIND_PACKAGE( DirectX ) FIND_PACKAGE( DirectX )
@ -265,9 +302,9 @@ ENDIF( NOT ASSIMP_BUILD_ZLIB )
IF( NOT ZLIB_FOUND ) IF( NOT ZLIB_FOUND )
message(STATUS "compiling zlib from souces") message(STATUS "compiling zlib from souces")
include(CheckIncludeFile) INCLUDE(CheckIncludeFile)
include(CheckTypeSize) INCLUDE(CheckTypeSize)
include(CheckFunctionExists) INCLUDE(CheckFunctionExists)
# compile from sources # compile from sources
add_subdirectory(contrib/zlib) add_subdirectory(contrib/zlib)
SET(ZLIB_FOUND 1) SET(ZLIB_FOUND 1)
@ -472,13 +509,25 @@ if(WIN32)
if(MSVC12 OR MSVC14) if(MSVC12 OR MSVC14)
add_custom_target(UpdateAssimpLibsDebugSymbolsAndDLLs COMMENT "Copying Assimp Libraries ..." VERBATIM) add_custom_target(UpdateAssimpLibsDebugSymbolsAndDLLs COMMENT "Copying Assimp Libraries ..." VERBATIM)
add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.dll VERBATIM) IF(CMAKE_GENERATOR MATCHES "^Visual Studio")
add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.exp VERBATIM) ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.dll VERBATIM)
add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.lib VERBATIM) ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.exp VERBATIM)
add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.dll VERBATIM) ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.lib VERBATIM)
add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.exp VERBATIM) ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.dll VERBATIM)
add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk VERBATIM) ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.exp VERBATIM)
add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.lib VERBATIM) ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk VERBATIM)
add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM) ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.lib VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
ELSE()
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mt.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.dll VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mt.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.exp VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mt.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.lib VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.dll VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.exp VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.lib VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
ENDIF()
ENDIF(MSVC12 OR MSVC14) ENDIF(MSVC12 OR MSVC14)
ENDIF (WIN32) ENDIF (WIN32)

View File

@ -1,5 +1,6 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
================================== ==================================
A library to import and export various 3d-model-formats including scene-post-processing to generate missing render data.
### Current build status ### ### Current build status ###
[![Linux Build Status](https://travis-ci.org/assimp/assimp.svg)](https://travis-ci.org/assimp/assimp) [![Linux Build Status](https://travis-ci.org/assimp/assimp.svg)](https://travis-ci.org/assimp/assimp)
[![Windows Build Status](https://ci.appveyor.com/api/projects/status/tmo433wax6u6cjp4?svg=true)](https://ci.appveyor.com/project/kimkulling/assimp) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/tmo433wax6u6cjp4?svg=true)](https://ci.appveyor.com/project/kimkulling/assimp)
@ -7,7 +8,6 @@ Open Asset Import Library (assimp)
<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>
<span class="badge-patreon"><a href="https://www.patreon.com/assimp" title="Donate to this project using Patreon"><img src="https://img.shields.io/badge/patreon-donate-yellow.svg" alt="Patreon donate button" /></a></span>
[![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)
<br> <br>
@ -18,6 +18,11 @@ Additionally, assimp features various __mesh post processing tools__: normals an
This is the development repo containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [Github Assimp Releases](https://github.com/assimp/assimp/releases). This is the development repo containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [Github Assimp Releases](https://github.com/assimp/assimp/releases).
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: 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>[![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)
@ -29,50 +34,67 @@ Please check our Wiki as well: https://github.com/assimp/assimp/wiki
A full list [is here](http://assimp.org/main_features_formats.html). A full list [is here](http://assimp.org/main_features_formats.html).
__Importers__: __Importers__:
- 3D
- 3DS - 3DS
- BLEND (Blender) - 3MF
- DAE/Collada - AC
- FBX - AC3D
- IFC-STEP - ACC
- AMJ
- ASE - ASE
- ASK
- B3D;
- BLEND (Blender)
- BVH
- COB
- CMS
- DAE/Collada
- DXF - DXF
- HMP - ENFF
- FBX
- glTF 1.0 + GLB
- glTF 2.0
- HMB
- IFC-STEP
- IRR / IRRMESH
- LWO
- LWS
- LXO
- MD2 - MD2
- MD3 - MD3
- MD5 - MD5
- MDC - MDC
- MDL - MDL
- NFF - MESH / MESH.XML
- PLY - MOT
- STL
- X
- OBJ
- OpenGEX
- SMD
- LWO
- LXO
- LWS
- TER
- AC3D
- MS3D - MS3D
- COB
- Q3BSP
- XGL
- CSM
- BVH
- B3D
- NDO - NDO
- Ogre Binary - NFF
- Ogre XML - OBJ
- Q3D - OFF
- ASSBIN (Assimp custom format) - OGEX
- glTF (partial) - PLY
- 3MF - PMX
- PRJ
- Q3O
- Q3S
- RAW
- SCN
- SIB
- SMD
- STL
- STP
- TER
- UC
- VTA
- X
- X3D
- XGL
- ZGL
Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default): Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default):
- C4D (https://github.com/acgessler/assimp-cinema4d) - C4D (https://github.com/assimp/assimp/wiki/Cinema4D-&-Melange)
__Exporters__: __Exporters__:
@ -85,7 +107,8 @@ __Exporters__:
- JSON (for WebGl, via https://github.com/acgessler/assimp2json) - JSON (for WebGl, via https://github.com/acgessler/assimp2json)
- ASSBIN - ASSBIN
- STEP - STEP
- glTF (partial) - glTF 1.0 (partial)
- glTF 2.0 (partial)
### Building ### ### Building ###
Take a look into the `INSTALL` file. Our build system is CMake, if you used CMake before there is a good chance you know what to do. Take a look into the `INSTALL` file. Our build system is CMake, if you used CMake before there is a good chance you know what to do.
@ -96,6 +119,8 @@ Take a look into the `INSTALL` file. Our build system is CMake, if you used CMak
* [.NET](port/AssimpNET/Readme.md) * [.NET](port/AssimpNET/Readme.md)
* [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)
* [JVM](https://github.com/kotlin-graphics/assimp) Full jvm port (currently supported obj, ply, stl, ~collada)
### 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.

View File

@ -10,32 +10,53 @@ branches:
only: only:
- master - master
matrix:
fast_finish: true
image:
- Visual Studio 2013
- Visual Studio 2015
- Visual Studio 2017
platform: platform:
- x86 - Win32
- x64 - x64
configuration: configuration: Release
- 14 2015
- 12 2013
#- MinGW
#- 10 2010 # only works for x86
init:
- if "%platform%" EQU "x64" ( for %%a in (2008 2010 MinGW) do ( if "%Configuration%"=="%%a" (echo "Skipping unsupported configuration" && exit /b 1 ) ) )
install: install:
# Make compiler command line tools available - set PATH=C:\Ruby24-x64\bin;%PATH%
- call c:\projects\assimp\scripts\appveyor\compiler_setup.bat - set CMAKE_DEFINES -DASSIMP_WERROR=ON
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2013" set CMAKE_GENERATOR_NAME=Visual Studio 12 2013
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017
- if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64
- cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%"
build_script: cache:
- cd c:\projects\assimp - code\assimp.dir\%CONFIGURATION%
- if "%platform%" equ "x64" (cmake CMakeLists.txt -G "Visual Studio %Configuration% Win64") - contrib\zlib\zlibstatic.dir\%CONFIGURATION%
- if "%platform%" equ "x86" (cmake CMakeLists.txt -G "Visual Studio %Configuration%") - contrib\zlib\zlib.dir\%CONFIGURATION%
- if "%platform%" equ "x64" (msbuild /m /p:Configuration=Release /p:Platform="x64" Assimp.sln) - tools\assimp_cmd\assimp_cmd.dir\%CONFIGURATION%
- if "%platform%" equ "x86" (msbuild /m /p:Configuration=Release /p:Platform="Win32" Assimp.sln) - tools\assimp_view\assimp_viewer.dir\%CONFIGURATION%
- test\unit.dir\%CONFIGURATION%
- bin\.mtime_cache
before_build:
- ruby scripts\AppVeyor\mtime_cache -g scripts\AppVeyor\cacheglobs.txt -c bin\.mtime_cache\cache.json
build:
parallel: true
project: Assimp.sln
after_build: after_build:
- 7z a assimp.7z c:\projects\assimp\bin\release\* c:\projects\assimp\lib\release\* - 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: artifacts:
- path: assimp.7z - path: assimp.7z

View File

@ -56,18 +56,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
static const unsigned int NotSet = 0xcdcdcdcd;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Setup final material indices, generae a default material if necessary // Setup final material indices, generae a default material if necessary
void Discreet3DSImporter::ReplaceDefaultMaterial() void Discreet3DSImporter::ReplaceDefaultMaterial()
{ {
// Try to find an existing material that matches the // Try to find an existing material that matches the
// typical default material setting: // typical default material setting:
// - no textures // - no textures
// - diffuse color (in grey!) // - diffuse color (in grey!)
// NOTE: This is here to workaround the fact that some // NOTE: This is here to workaround the fact that some
// exporters are writing a default material, too. // exporters are writing a default material, too.
unsigned int idx = 0xcdcdcdcd; 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;
@ -93,7 +94,9 @@ void Discreet3DSImporter::ReplaceDefaultMaterial()
} }
idx = i; idx = i;
} }
if (0xcdcdcdcd == idx)idx = (unsigned int)mScene->mMaterials.size(); if ( NotSet == idx ) {
idx = ( unsigned int )mScene->mMaterials.size();
}
// now iterate through all meshes and through all faces and // now iterate through all meshes and through all faces and
// find all faces that are using the default material // find all faces that are using the default material

View File

@ -1381,7 +1381,7 @@ void Discreet3DSImporter::ParseColorChunk( aiColor3D* out, bool acceptPercent )
bGamma = true; bGamma = true;
case Discreet3DS::CHUNK_RGBF: case Discreet3DS::CHUNK_RGBF:
if (sizeof(ai_real) * 3 > diff) { if (sizeof(float) * 3 > diff) {
*out = clrError; *out = clrError;
return; return;
} }

View File

@ -686,7 +686,6 @@ std::list<unsigned int> mesh_idx;
tmesh->mNumVertices = static_cast<unsigned int>(vert_arr.size()); tmesh->mNumVertices = static_cast<unsigned int>(vert_arr.size());
tmesh->mVertices = new aiVector3D[tmesh->mNumVertices]; tmesh->mVertices = new aiVector3D[tmesh->mNumVertices];
tmesh->mColors[0] = new aiColor4D[tmesh->mNumVertices]; tmesh->mColors[0] = new aiColor4D[tmesh->mNumVertices];
tmesh->mFaces = new aiFace[face_list_cur.size()];
memcpy(tmesh->mVertices, vert_arr.data(), tmesh->mNumVertices * sizeof(aiVector3D)); memcpy(tmesh->mVertices, vert_arr.data(), tmesh->mNumVertices * sizeof(aiVector3D));
memcpy(tmesh->mColors[0], col_arr.data(), tmesh->mNumVertices * sizeof(aiColor4D)); memcpy(tmesh->mColors[0], col_arr.data(), tmesh->mNumVertices * sizeof(aiColor4D));

View File

@ -139,6 +139,17 @@ inline size_t Write<aiVector3D>(IOStream * stream, const aiVector3D& v)
return t; return t;
} }
// -----------------------------------------------------------------------------------
// Serialize a color value
template <>
inline size_t Write<aiColor3D>(IOStream * stream, const aiColor3D& v)
{
size_t t = Write<float>(stream,v.r);
t += Write<float>(stream,v.g);
t += Write<float>(stream,v.b);
return t;
}
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Serialize a color value // Serialize a color value
template <> template <>
@ -325,7 +336,7 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
{ {
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE ); AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE );
size_t nb_metadata = (node->mMetaData != NULL ? node->mMetaData->mNumProperties : 0); unsigned int nb_metadata = (node->mMetaData != NULL ? node->mMetaData->mNumProperties : 0);
Write<aiString>(&chunk,node->mName); Write<aiString>(&chunk,node->mName);
Write<aiMatrix4x4>(&chunk,node->mTransformation); Write<aiMatrix4x4>(&chunk,node->mTransformation);
@ -639,9 +650,9 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
Write<float>(&chunk,l->mAttenuationQuadratic); Write<float>(&chunk,l->mAttenuationQuadratic);
} }
Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorDiffuse); Write<aiColor3D>(&chunk,l->mColorDiffuse);
Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorSpecular); Write<aiColor3D>(&chunk,l->mColorSpecular);
Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorAmbient); Write<aiColor3D>(&chunk,l->mColorAmbient);
if (l->mType == aiLightSource_SPOT) { if (l->mType == aiLightSource_SPOT) {
Write<float>(&chunk,l->mAngleInnerCone); Write<float>(&chunk,l->mAngleInnerCone);

View File

@ -71,7 +71,6 @@ class AssbinImporter : public BaseImporter
private: private:
bool shortened; bool shortened;
bool compressed; bool compressed;
protected:
public: public:
virtual bool CanRead( virtual bool CanRead(

View File

@ -82,6 +82,20 @@ static const aiImporterDesc desc = {
//#define DEBUG_B3D //#define DEBUG_B3D
template<typename T>
void DeleteAllBarePointers(std::vector<T>& x)
{
for(auto p : x)
{
delete p;
}
}
B3DImporter::~B3DImporter()
{
DeleteAllBarePointers(_animations);
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool B3DImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const{ bool B3DImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const{
@ -157,7 +171,8 @@ int B3DImporter::ReadByte(){
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
int B3DImporter::ReadInt(){ int B3DImporter::ReadInt(){
if( _pos+4<=_buf.size() ){ if( _pos+4<=_buf.size() ){
int n=*(int*)&_buf[_pos]; int n;
memcpy(&n, &_buf[_pos], 4);
_pos+=4; _pos+=4;
return n; return n;
} }
@ -168,7 +183,8 @@ int B3DImporter::ReadInt(){
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
float B3DImporter::ReadFloat(){ float B3DImporter::ReadFloat(){
if( _pos+4<=_buf.size() ){ if( _pos+4<=_buf.size() ){
float n=*(float*)&_buf[_pos]; float n;
memcpy(&n, &_buf[_pos], 4);
_pos+=4; _pos+=4;
return n; return n;
} }
@ -558,13 +574,19 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
void B3DImporter::ReadBB3D( aiScene *scene ){ void B3DImporter::ReadBB3D( aiScene *scene ){
_textures.clear(); _textures.clear();
_materials.clear(); _materials.clear();
_vertices.clear(); _vertices.clear();
_meshes.clear(); _meshes.clear();
DeleteAllBarePointers(_nodes);
_nodes.clear(); _nodes.clear();
_nodeAnims.clear(); _nodeAnims.clear();
DeleteAllBarePointers(_animations);
_animations.clear(); _animations.clear();
string t=ReadChunk(); string t=ReadChunk();

View File

@ -59,6 +59,8 @@ namespace Assimp{
class B3DImporter : public BaseImporter{ class B3DImporter : public BaseImporter{
public: public:
B3DImporter() = default;
virtual ~B3DImporter();
virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const; virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;

View File

@ -52,7 +52,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp namespace Assimp
{ {
template< > const std::string LogFunctions< BlenderBMeshConverter >::log_prefix = "BLEND_BMESH: "; template< > const char* LogFunctions< BlenderBMeshConverter >::Prefix()
{
static auto prefix = "BLEND_BMESH: ";
return prefix;
}
} }
using namespace Assimp; using namespace Assimp;

View File

@ -253,7 +253,7 @@ public:
* a compiler complain is the result. * a compiler complain is the result.
* @param dest Destination value to be written * @param dest Destination value to be written
* @param db File database, including input stream. */ * @param db File database, including input stream. */
template <typename T> inline void Convert (T& dest, const FileDatabase& db) const; template <typename T> void Convert (T& dest, const FileDatabase& db) const;
// -------------------------------------------------------- // --------------------------------------------------------
// generic converter // generic converter

View File

@ -589,7 +589,10 @@ template <> inline void Structure :: Convert<short> (short& dest,const FileData
{ {
// automatic rescaling from short to float and vice versa (seems to be used by normals) // automatic rescaling from short to float and vice versa (seems to be used by normals)
if (name == "float") { if (name == "float") {
dest = static_cast<short>(db.reader->GetF4() * 32767.f); float f = db.reader->GetF4();
if ( f > 1.0f )
f = 1.0f;
dest = static_cast<short>( f * 32767.f);
//db.reader->IncPtr(-4); //db.reader->IncPtr(-4);
return; return;
} }

View File

@ -74,7 +74,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif #endif
namespace Assimp { namespace Assimp {
template<> const std::string LogFunctions<BlenderImporter>::log_prefix = "BLEND: "; template<> const char* LogFunctions<BlenderImporter>::Prefix()
{
static auto prefix = "BLEND: ";
return prefix;
}
} }
using namespace Assimp; using namespace Assimp;

View File

@ -59,7 +59,11 @@ static const unsigned int BLEND_TESS_MAGIC = 0x83ed9ac3;
namspace Assimp namspace Assimp
{ {
template< > const std::string LogFunctions< BlenderTessellatorGL >::log_prefix = "BLEND_TESS_GL: "; template< > const char* LogFunctions< BlenderTessellatorGL >::Prefix()
{
static auto prefix = "BLEND_TESS_GL: ";
return prefix;
}
} }
using namespace Assimp; using namespace Assimp;
@ -252,7 +256,11 @@ void BlenderTessellatorGL::TessellateError( GLenum errorCode, void* )
namespace Assimp namespace Assimp
{ {
template< > const std::string LogFunctions< BlenderTessellatorP2T >::log_prefix = "BLEND_TESS_P2T: "; template< > const char* LogFunctions< BlenderTessellatorP2T >::Prefix()
{
static auto prefix = "BLEND_TESS_P2T: ";
return prefix;
}
} }
using namespace Assimp; using namespace Assimp;

View File

@ -393,7 +393,7 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiMesh* C4DImporter::ReadMesh(BaseObject* object) aiMesh* C4DImporter::ReadMesh(BaseObject* object)
{ {
assert(object != NULL && object->GetType() == Opolygon); ai_assert(object != NULL && object->GetType() == Opolygon);
// based on Melange sample code // based on Melange sample code
PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object); PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object);
@ -635,7 +635,7 @@ unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj)
TextureTag& ttag = dynamic_cast<TextureTag&>(*tag); TextureTag& ttag = dynamic_cast<TextureTag&>(*tag);
BaseMaterial* const mat = ttag.GetMaterial(); BaseMaterial* const mat = ttag.GetMaterial();
assert(mat != NULL); ai_assert(mat != NULL);
const MaterialMap::const_iterator it = material_mapping.find(mat); const MaterialMap::const_iterator it = material_mapping.find(mat);
if(it == material_mapping.end()) { if(it == material_mapping.end()) {

View File

@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h" #include "BaseImporter.h"
#include "LogAux.h" #include "LogAux.h"
#include <set> #include <map>
struct aiNode; struct aiNode;
struct aiMesh; struct aiMesh;
struct aiMaterial; struct aiMaterial;

View File

@ -61,6 +61,7 @@ SET( PUBLIC_HEADERS
${HEADER_PATH}/color4.inl ${HEADER_PATH}/color4.inl
${CMAKE_CURRENT_BINARY_DIR}/../include/assimp/config.h ${CMAKE_CURRENT_BINARY_DIR}/../include/assimp/config.h
${HEADER_PATH}/defs.h ${HEADER_PATH}/defs.h
${HEADER_PATH}/Defines.h
${HEADER_PATH}/cfileio.h ${HEADER_PATH}/cfileio.h
${HEADER_PATH}/light.h ${HEADER_PATH}/light.h
${HEADER_PATH}/material.h ${HEADER_PATH}/material.h
@ -661,6 +662,14 @@ ADD_ASSIMP_IMPORTER( GLTF
glTFImporter.h glTFImporter.h
glTFExporter.h glTFExporter.h
glTFExporter.cpp glTFExporter.cpp
glTF2Asset.h
glTF2Asset.inl
glTF2AssetWriter.h
glTF2AssetWriter.inl
glTF2Importer.cpp
glTF2Importer.h
glTF2Exporter.h
glTF2Exporter.cpp
) )
ADD_ASSIMP_IMPORTER( 3MF ADD_ASSIMP_IMPORTER( 3MF
@ -934,6 +943,7 @@ if (ASSIMP_ANDROID_JNIIOSYSTEM)
endif(ASSIMP_ANDROID_JNIIOSYSTEM) endif(ASSIMP_ANDROID_JNIIOSYSTEM)
if(MSVC AND ASSIMP_INSTALL_PDB) if(MSVC AND ASSIMP_INSTALL_PDB)
IF(CMAKE_GENERATOR MATCHES "^Visual Studio")
install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb
DESTINATION ${ASSIMP_LIB_INSTALL_DIR} DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
CONFIGURATIONS Debug CONFIGURATIONS Debug
@ -942,6 +952,16 @@ if(MSVC AND ASSIMP_INSTALL_PDB)
DESTINATION ${ASSIMP_LIB_INSTALL_DIR} DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
CONFIGURATIONS RelWithDebInfo CONFIGURATIONS RelWithDebInfo
) )
ELSE()
install(FILES ${Assimp_BINARY_DIR}/code/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb
DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
CONFIGURATIONS Debug
)
install(FILES ${Assimp_BINARY_DIR}/code/assimp${LIBRARY_SUFFIX}.pdb
DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
CONFIGURATIONS RelWithDebInfo
)
ENDIF()
endif () endif ()
if (ASSIMP_COVERALLS) if (ASSIMP_COVERALLS)

View File

@ -866,8 +866,8 @@ void ColladaExporter::WriteController( size_t pIndex)
std::vector<ai_real> bind_poses; std::vector<ai_real> bind_poses;
bind_poses.reserve(mesh->mNumBones * 16); bind_poses.reserve(mesh->mNumBones * 16);
for( size_t i = 0; i < mesh->mNumBones; ++i) for(unsigned int i = 0; i < mesh->mNumBones; ++i)
for( size_t j = 0; j < 4; ++j) for( unsigned int j = 0; j < 4; ++j)
bind_poses.insert(bind_poses.end(), mesh->mBones[i]->mOffsetMatrix[j], mesh->mBones[i]->mOffsetMatrix[j] + 4); bind_poses.insert(bind_poses.end(), mesh->mBones[i]->mOffsetMatrix[j], mesh->mBones[i]->mOffsetMatrix[j] + 4);
WriteFloatArray( idstr + "-skin-bind_poses", FloatType_Mat4x4, (const ai_real*) bind_poses.data(), bind_poses.size() / 16); WriteFloatArray( idstr + "-skin-bind_poses", FloatType_Mat4x4, (const ai_real*) bind_poses.data(), bind_poses.size() / 16);
@ -924,11 +924,11 @@ void ColladaExporter::WriteController( size_t pIndex)
ai_uint weight_index = 0; ai_uint weight_index = 0;
std::vector<ai_int> joint_weight_indices(2 * joint_weight_indices_length, (ai_int)-1); std::vector<ai_int> joint_weight_indices(2 * joint_weight_indices_length, (ai_int)-1);
for( size_t i = 0; i < mesh->mNumBones; ++i) for( unsigned int i = 0; i < mesh->mNumBones; ++i)
for( size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j) for( unsigned j = 0; j < mesh->mBones[i]->mNumWeights; ++j)
{ {
unsigned int vId = mesh->mBones[i]->mWeights[j].mVertexId; unsigned int vId = mesh->mBones[i]->mWeights[j].mVertexId;
for( size_t k = 0; k < num_influences[vId]; ++k) for( ai_uint k = 0; k < num_influences[vId]; ++k)
{ {
if (joint_weight_indices[2 * (accum_influences[vId] + k)] == -1) if (joint_weight_indices[2 * (accum_influences[vId] + k)] == -1)
{ {

View File

@ -128,7 +128,10 @@ protected:
/// Enters a new xml element, which increases the indentation /// Enters a new xml element, which increases the indentation
void PushTag() { startstr.append( " "); } void PushTag() { startstr.append( " "); }
/// Leaves an element, decreasing the indentation /// Leaves an element, decreasing the indentation
void PopTag() { ai_assert( startstr.length() > 1); startstr.erase( startstr.length() - 2); } void PopTag() {
ai_assert( startstr.length() > 1);
startstr.erase( startstr.length() - 2);
}
/// Creates a mesh ID for the given mesh /// Creates a mesh ID for the given mesh
std::string GetMeshId( size_t pIndex) const { std::string GetMeshId( size_t pIndex) const {

View File

@ -119,7 +119,7 @@ bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, boo
* might be NULL and it's our duty to return true here. * might be NULL and it's our duty to return true here.
*/ */
if (!pIOHandler)return true; if (!pIOHandler)return true;
const char* tokens[] = {"collada"}; const char* tokens[] = {"<collada"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
} }
return false; return false;
@ -674,7 +674,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
// 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::MorphMethod method = Collada::Normalized;
for(std::map<std::string, Collada::Controller>::const_iterator it = pParser.mControllerLibrary.begin(); for(std::map<std::string, Collada::Controller>::const_iterator it = pParser.mControllerLibrary.begin();
it != pParser.mControllerLibrary.end(); it++) it != pParser.mControllerLibrary.end(); it++)
@ -728,7 +728,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
? aiMorphingMethod_MORPH_RELATIVE ? aiMorphingMethod_MORPH_RELATIVE
: aiMorphingMethod_MORPH_NORMALIZED; : aiMorphingMethod_MORPH_NORMALIZED;
dstMesh->mAnimMeshes = new aiAnimMesh*[animMeshes.size()]; dstMesh->mAnimMeshes = new aiAnimMesh*[animMeshes.size()];
dstMesh->mNumAnimMeshes = 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++)
dstMesh->mAnimMeshes[i] = animMeshes.at(i); dstMesh->mAnimMeshes[i] = animMeshes.at(i);
} }
@ -1377,9 +1377,9 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
{ {
aiNodeAnim* dstAnim = new aiNodeAnim; aiNodeAnim* dstAnim = new aiNodeAnim;
dstAnim->mNodeName = nodeName; dstAnim->mNodeName = nodeName;
dstAnim->mNumPositionKeys = resultTrafos.size(); dstAnim->mNumPositionKeys = static_cast<unsigned int>(resultTrafos.size());
dstAnim->mNumRotationKeys= resultTrafos.size(); dstAnim->mNumRotationKeys = static_cast<unsigned int>(resultTrafos.size());
dstAnim->mNumScalingKeys = resultTrafos.size(); dstAnim->mNumScalingKeys = static_cast<unsigned int>(resultTrafos.size());
dstAnim->mPositionKeys = new aiVectorKey[resultTrafos.size()]; dstAnim->mPositionKeys = new aiVectorKey[resultTrafos.size()];
dstAnim->mRotationKeys = new aiQuatKey[resultTrafos.size()]; dstAnim->mRotationKeys = new aiQuatKey[resultTrafos.size()];
dstAnim->mScalingKeys = new aiVectorKey[resultTrafos.size()]; dstAnim->mScalingKeys = new aiVectorKey[resultTrafos.size()];
@ -1445,11 +1445,11 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
++morphAnimChannelIndex; ++morphAnimChannelIndex;
} }
morphAnim->mNumKeys = morphTimeValues.size(); morphAnim->mNumKeys = static_cast<unsigned int>(morphTimeValues.size());
morphAnim->mKeys = new aiMeshMorphKey[morphAnim->mNumKeys]; morphAnim->mKeys = new aiMeshMorphKey[morphAnim->mNumKeys];
for (unsigned int key = 0; key < morphAnim->mNumKeys; key++) for (unsigned int key = 0; key < morphAnim->mNumKeys; key++)
{ {
morphAnim->mKeys[key].mNumValuesAndWeights = morphChannels.size(); morphAnim->mKeys[key].mNumValuesAndWeights = static_cast<unsigned int>(morphChannels.size());
morphAnim->mKeys[key].mValues = new unsigned int [morphChannels.size()]; morphAnim->mKeys[key].mValues = new unsigned int [morphChannels.size()];
morphAnim->mKeys[key].mWeights = new double [morphChannels.size()]; morphAnim->mKeys[key].mWeights = new double [morphChannels.size()];
@ -1470,13 +1470,13 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
{ {
aiAnimation* anim = new aiAnimation; aiAnimation* anim = new aiAnimation;
anim->mName.Set( pName); anim->mName.Set( pName);
anim->mNumChannels = anims.size(); anim->mNumChannels = static_cast<unsigned int>(anims.size());
if (anim->mNumChannels > 0) if (anim->mNumChannels > 0)
{ {
anim->mChannels = new aiNodeAnim*[anims.size()]; anim->mChannels = new aiNodeAnim*[anims.size()];
std::copy( anims.begin(), anims.end(), anim->mChannels); std::copy( anims.begin(), anims.end(), anim->mChannels);
} }
anim->mNumMorphMeshChannels = morphAnims.size(); anim->mNumMorphMeshChannels = static_cast<unsigned int>(morphAnims.size());
if (anim->mNumMorphMeshChannels > 0) if (anim->mNumMorphMeshChannels > 0)
{ {
anim->mMorphMeshChannels = new aiMeshMorphAnim*[anim->mNumMorphMeshChannels]; anim->mMorphMeshChannels = new aiMeshMorphAnim*[anim->mNumMorphMeshChannels];

View File

@ -2231,7 +2231,7 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
} }
#ifdef ASSIMP_BUILD_DEBUG #ifdef ASSIMP_BUILD_DEBUG
if (primType != Prim_TriFans && primType != Prim_TriStrips && if (primType != Prim_TriFans && primType != Prim_TriStrips && primType != Prim_LineStrip &&
primType != Prim_Lines) { // this is ONLY to workaround a bug in SketchUp 15.3.331 where it writes the wrong 'count' when it writes out the 'lines'. primType != Prim_Lines) { // this is ONLY to workaround a bug in SketchUp 15.3.331 where it writes the wrong 'count' when it writes out the 'lines'.
ai_assert(actualPrimitives == numPrimitives); ai_assert(actualPrimitives == numPrimitives);
} }
@ -2400,6 +2400,10 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pP
size_t numberOfVertices = indices.size() / numOffsets; size_t numberOfVertices = indices.size() / numOffsets;
numPrimitives = numberOfVertices - 2; numPrimitives = numberOfVertices - 2;
} }
if (pPrimType == Prim_LineStrip) {
size_t numberOfVertices = indices.size() / numOffsets;
numPrimitives = numberOfVertices - 1;
}
pMesh->mFaceSize.reserve( numPrimitives); pMesh->mFaceSize.reserve( numPrimitives);
pMesh->mFacePosIndices.reserve( indices.size() / numOffsets); pMesh->mFacePosIndices.reserve( indices.size() / numOffsets);
@ -2416,6 +2420,11 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pP
for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
CopyVertex(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); CopyVertex(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
break; break;
case Prim_LineStrip:
numPoints = 2;
for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
CopyVertex(currentVertex, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
break;
case Prim_Triangles: case Prim_Triangles:
numPoints = 3; numPoints = 3;
for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)

View File

@ -95,14 +95,10 @@ public:
XmlSerializer(XmlReader* xmlReader) XmlSerializer(XmlReader* xmlReader)
: xmlReader(xmlReader) : xmlReader(xmlReader)
{ {
// empty
} }
void ImportXml(aiScene* scene) void ImportXml(aiScene* scene) {
{
scene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
scene->mRootNode = new aiNode(); scene->mRootNode = new aiNode();
std::vector<aiNode*> children; std::vector<aiNode*> children;

View File

@ -49,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/ai_assert.h> #include <assimp/ai_assert.h>
#include <cstdlib>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <map> #include <map>
@ -228,7 +229,7 @@ ZipFile::~ZipFile() {
size_t ZipFile::Read(void* pvBuffer, size_t pSize, size_t pCount) { size_t ZipFile::Read(void* pvBuffer, size_t pSize, size_t pCount) {
const size_t size = pSize * pCount; const size_t size = pSize * pCount;
assert(size <= m_Size); ai_assert(size <= m_Size);
std::memcpy(pvBuffer, m_Buffer, size); std::memcpy(pvBuffer, m_Buffer, size);

View File

@ -90,6 +90,7 @@ void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*, const ExportPr
void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneGLTF(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneGLTF(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneGLB(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneGLB(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneGLTF2(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
@ -144,6 +145,8 @@ Exporter::ExportFormatEntry gExporters[] =
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType), aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType),
Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB, Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB,
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType), aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType),
Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf2", &ExportSceneGLTF2,
aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType),
#endif #endif
#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER #ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER

View File

@ -50,12 +50,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXDocument.h" #include "FBXDocument.h"
#include "FBXImporter.h" #include "FBXImporter.h"
#include "FBXDocumentUtil.h" #include "FBXDocumentUtil.h"
#include "FBXProperties.h"
namespace Assimp { namespace Assimp {
namespace FBX { namespace FBX {
using namespace Util; using namespace Util;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& /*doc*/) AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& /*doc*/)
@ -88,17 +87,16 @@ AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::s
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationCurve::~AnimationCurve() AnimationCurve::~AnimationCurve()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc, AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name,
const char* const * target_prop_whitelist /*= NULL*/, size_t whitelist_size /*= 0*/) const Document& doc, const char* const * target_prop_whitelist /*= NULL*/,
size_t whitelist_size /*= 0*/)
: Object(id, element, name) : Object(id, element, name)
, target() , target()
, doc(doc) , doc(doc)
@ -155,18 +153,16 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons
props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false); props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationCurveNode::~AnimationCurveNode() AnimationCurveNode::~AnimationCurveNode()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const AnimationCurveMap& AnimationCurveNode::Curves() const const AnimationCurveMap& AnimationCurveNode::Curves() const
{ {
if(curves.empty()) { if ( curves.empty() ) {
// resolve attached animation curves // resolve attached animation curves
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve"); const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve");
@ -196,7 +192,6 @@ const AnimationCurveMap& AnimationCurveNode::Curves() const
return curves; return curves;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc) AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc)
: Object(id, element, name) : Object(id, element, name)
@ -208,14 +203,12 @@ AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::s
props = GetPropertyTable(doc,"AnimationLayer.FbxAnimLayer",element,sc, true); props = GetPropertyTable(doc,"AnimationLayer.FbxAnimLayer",element,sc, true);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationLayer::~AnimationLayer() AnimationLayer::~AnimationLayer()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/, AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/,
size_t whitelist_size /*= 0*/) const size_t whitelist_size /*= 0*/) const
@ -299,14 +292,13 @@ AnimationStack::AnimationStack(uint64_t id, const Element& element, const std::s
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationStack::~AnimationStack() AnimationStack::~AnimationStack()
{ {
// empty
} }
} //!FBX } //!FBX
} //!Assimp } //!Assimp
#endif #endif // ASSIMP_BUILD_NO_FBX_IMPORTER

View File

@ -56,47 +56,46 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
namespace FBX { namespace FBX {
enum Flag //enum Flag
{ //{
e_unknown_0 = 1 << 0, // e_unknown_0 = 1 << 0,
e_unknown_1 = 1 << 1, // e_unknown_1 = 1 << 1,
e_unknown_2 = 1 << 2, // e_unknown_2 = 1 << 2,
e_unknown_3 = 1 << 3, // e_unknown_3 = 1 << 3,
e_unknown_4 = 1 << 4, // e_unknown_4 = 1 << 4,
e_unknown_5 = 1 << 5, // e_unknown_5 = 1 << 5,
e_unknown_6 = 1 << 6, // e_unknown_6 = 1 << 6,
e_unknown_7 = 1 << 7, // e_unknown_7 = 1 << 7,
e_unknown_8 = 1 << 8, // e_unknown_8 = 1 << 8,
e_unknown_9 = 1 << 9, // e_unknown_9 = 1 << 9,
e_unknown_10 = 1 << 10, // e_unknown_10 = 1 << 10,
e_unknown_11 = 1 << 11, // e_unknown_11 = 1 << 11,
e_unknown_12 = 1 << 12, // e_unknown_12 = 1 << 12,
e_unknown_13 = 1 << 13, // e_unknown_13 = 1 << 13,
e_unknown_14 = 1 << 14, // e_unknown_14 = 1 << 14,
e_unknown_15 = 1 << 15, // e_unknown_15 = 1 << 15,
e_unknown_16 = 1 << 16, // e_unknown_16 = 1 << 16,
e_unknown_17 = 1 << 17, // e_unknown_17 = 1 << 17,
e_unknown_18 = 1 << 18, // e_unknown_18 = 1 << 18,
e_unknown_19 = 1 << 19, // e_unknown_19 = 1 << 19,
e_unknown_20 = 1 << 20, // e_unknown_20 = 1 << 20,
e_unknown_21 = 1 << 21, // e_unknown_21 = 1 << 21,
e_unknown_22 = 1 << 22, // e_unknown_22 = 1 << 22,
e_unknown_23 = 1 << 23, // e_unknown_23 = 1 << 23,
e_flag_field_size_64_bit = 1 << 24, // Not sure what is // e_flag_field_size_64_bit = 1 << 24, // Not sure what is
e_unknown_25 = 1 << 25, // e_unknown_25 = 1 << 25,
e_unknown_26 = 1 << 26, // e_unknown_26 = 1 << 26,
e_unknown_27 = 1 << 27, // e_unknown_27 = 1 << 27,
e_unknown_28 = 1 << 28, // e_unknown_28 = 1 << 28,
e_unknown_29 = 1 << 29, // e_unknown_29 = 1 << 29,
e_unknown_30 = 1 << 30, // e_unknown_30 = 1 << 30,
e_unknown_31 = 1 << 31 // e_unknown_31 = 1 << 31
}; //};
//
bool check_flag(uint32_t flags, Flag to_check) //bool check_flag(uint32_t flags, Flag to_check)
{ //{
return (flags & to_check) != 0; // return (flags & to_check) != 0;
} //}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int offset) Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int offset)
: :
@ -152,7 +151,8 @@ uint32_t ReadWord(const char* input, const char*& cursor, const char* end)
TokenizeError("cannot ReadWord, out of bounds",input, cursor); TokenizeError("cannot ReadWord, out of bounds",input, cursor);
} }
uint32_t word = *reinterpret_cast<const uint32_t*>(cursor); uint32_t word;
memcpy(&word, cursor, 4);
AI_SWAP4(word); AI_SWAP4(word);
cursor += k_to_read; cursor += k_to_read;
@ -341,10 +341,10 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, const char* end, uint32_t const flags) bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, const char* end, bool const is64bits)
{ {
// the first word contains the offset at which this block ends // the first word contains the offset at which this block ends
const uint64_t end_offset = /*check_flag(flags, e_flag_field_size_64_bit) ? ReadDoubleWord(input, cursor, end) : */ReadWord(input, cursor, end); const uint64_t end_offset = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
// we may get 0 if reading reached the end of the file - // we may get 0 if reading reached the end of the file -
// fbx files have a mysterious extra footer which I don't know // fbx files have a mysterious extra footer which I don't know
@ -362,10 +362,10 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
} }
// the second data word contains the number of properties in the scope // the second data word contains the number of properties in the scope
const uint64_t prop_count = /*check_flag(flags, e_flag_field_size_64_bit) ? ReadDoubleWord(input, cursor, end) : */ReadWord(input, cursor, end); const uint64_t prop_count = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
// the third data word contains the length of the property list // the third data word contains the length of the property list
const uint64_t prop_length = /*check_flag(flags, e_flag_field_size_64_bit) ? ReadDoubleWord(input, cursor, end) :*/ ReadWord(input, cursor, end); const uint64_t prop_length = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
// now comes the name of the scope/key // now comes the name of the scope/key
const char* sbeg, *send; const char* sbeg, *send;
@ -392,7 +392,7 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
// at the end of each nested block, there is a NUL record to indicate // at the end of each nested block, there is a NUL record to indicate
// that the sub-scope exists (i.e. to distinguish between P: and P : {}) // that the sub-scope exists (i.e. to distinguish between P: and P : {})
// this NUL record is 13 bytes long on 32 bit version and 25 bytes long on 64 bit. // this NUL record is 13 bytes long on 32 bit version and 25 bytes long on 64 bit.
const size_t sentinel_block_length = /*check_flag(flags, e_flag_field_size_64_bit) ? (sizeof(uint64_t) * 3 + 1) : */(sizeof(uint32_t) * 3 + 1); const size_t sentinel_block_length = is64bits ? (sizeof(uint64_t)* 3 + 1) : (sizeof(uint32_t)* 3 + 1);
if (Offset(input, cursor) < end_offset) { if (Offset(input, cursor) < end_offset) {
if (end_offset - Offset(input, cursor) < sentinel_block_length) { if (end_offset - Offset(input, cursor) < sentinel_block_length) {
@ -403,7 +403,7 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
// XXX this is vulnerable to stack overflowing .. // XXX this is vulnerable to stack overflowing ..
while(Offset(input, cursor) < end_offset - sentinel_block_length) { while(Offset(input, cursor) < end_offset - sentinel_block_length) {
ReadScope(output_tokens, input, cursor, input + end_offset - sentinel_block_length, flags); ReadScope(output_tokens, input, cursor, input + end_offset - sentinel_block_length, is64bits);
} }
output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) )); output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) ));
@ -426,6 +426,7 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// TODO: Test FBX Binary files newer than the 7500 version to check if the 64 bits address behaviour is consistent
void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int length) void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int length)
{ {
ai_assert(input); ai_assert(input);
@ -438,19 +439,17 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int le
TokenizeError("magic bytes not found",0); TokenizeError("magic bytes not found",0);
} }
const char* cursor = input + 18;
//uint32_t offset = 0x15; /*Result ignored*/ ReadByte(input, cursor, input + length);
const char* cursor = input + 0x15; /*Result ignored*/ ReadByte(input, cursor, input + length);
/*Result ignored*/ ReadByte(input, cursor, input + length);
const uint32_t flags = ReadWord(input, cursor, input + length); /*Result ignored*/ ReadByte(input, cursor, input + length);
/*Result ignored*/ ReadByte(input, cursor, input + length);
const uint8_t padding_0 = ReadByte(input, cursor, input + length); // unused const uint32_t version = ReadWord(input, cursor, input + length);
(void) padding_0; const bool is64bits = version >= 7500;
const uint8_t padding_1 = ReadByte(input, cursor, input + length); // unused
(void) padding_1;
while (cursor < input + length) while (cursor < input + length)
{ {
if(!ReadScope(output_tokens, input, cursor, input + length, flags)) { if (!ReadScope(output_tokens, input, cursor, input + length, is64bits)) {
break; break;
} }
} }

View File

@ -66,4 +66,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# endif # endif
#endif #endif
#endif #endif // INCLUDED_AI_FBX_COMPILECONFIG_H

View File

@ -55,9 +55,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "StringComparison.h" #include "StringComparison.h"
#include <assimp/scene.h> #include <assimp/scene.h>
#include <tuple> #include <tuple>
#include <memory> #include <memory>
#include <iterator> #include <iterator>
#include <vector> #include <vector>
@ -949,8 +949,7 @@ std::string Converter::NameTransformationChainNode( const std::string& name, Tra
return name + std::string( MAGIC_NODE_TAG ) + "_" + NameTransformationComp( comp ); return name + std::string( MAGIC_NODE_TAG ) + "_" + NameTransformationComp( comp );
} }
void Converter::GenerateTransformationNodeChain( const Model& model, void Converter::GenerateTransformationNodeChain( const Model& model, std::vector<aiNode*>& output_nodes )
std::vector<aiNode*>& output_nodes )
{ {
const PropertyTable& props = model.Props(); const PropertyTable& props = model.Props();
const Model::RotOrder rot = model.RotationOrder(); const Model::RotOrder rot = model.RotationOrder();
@ -1065,6 +1064,10 @@ void Converter::GenerateTransformationNodeChain( const Model& model,
continue; continue;
} }
if ( comp == TransformationComp_PostRotation ) {
chain[ i ] = chain[ i ].Inverse();
}
aiNode* nd = new aiNode(); aiNode* nd = new aiNode();
output_nodes.push_back( nd ); output_nodes.push_back( nd );
@ -1093,7 +1096,7 @@ void Converter::SetupNodeMetadata( const Model& model, aiNode& nd )
DirectPropertyMap unparsedProperties = props.GetUnparsedProperties(); DirectPropertyMap unparsedProperties = props.GetUnparsedProperties();
// create metadata on node // create metadata on node
std::size_t numStaticMetaData = 2; const std::size_t numStaticMetaData = 2;
aiMetadata* data = aiMetadata::Alloc( static_cast<unsigned int>(unparsedProperties.size() + numStaticMetaData) ); aiMetadata* data = aiMetadata::Alloc( static_cast<unsigned int>(unparsedProperties.size() + numStaticMetaData) );
nd.mMetaData = data; nd.mMetaData = data;
int index = 0; int index = 0;
@ -2368,8 +2371,13 @@ void Converter::ConvertAnimationStack( const AnimationStack& st )
int64_t start_time = st.LocalStart(); int64_t start_time = st.LocalStart();
int64_t stop_time = st.LocalStop(); int64_t stop_time = st.LocalStop();
double start_timeF = CONVERT_FBX_TIME( start_time ); bool has_local_startstop = start_time != 0 || stop_time != 0;
double stop_timeF = CONVERT_FBX_TIME( stop_time ); if ( !has_local_startstop ) {
// no time range given, so accept every keyframe and use the actual min/max time
// the numbers are INT64_MIN/MAX, the 20000 is for safety because GenerateNodeAnimations uses an epsilon of 10000
start_time = -9223372036854775807ll + 20000;
stop_time = 9223372036854775807ll - 20000;
}
try { try {
for( const NodeMap::value_type& kv : node_map ) { for( const NodeMap::value_type& kv : node_map ) {
@ -2401,27 +2409,23 @@ void Converter::ConvertAnimationStack( const AnimationStack& st )
return; return;
} }
//adjust relative timing for animation double start_time_fps = has_local_startstop ? (CONVERT_FBX_TIME(start_time) * anim_fps) : min_time;
{ double stop_time_fps = has_local_startstop ? (CONVERT_FBX_TIME(stop_time) * anim_fps) : max_time;
double start_fps = start_timeF * anim_fps;
for ( unsigned int c = 0; c < anim->mNumChannels; c++ ) // adjust relative timing for animation
{ for ( unsigned int c = 0; c < anim->mNumChannels; c++ ) {
aiNodeAnim* channel = anim->mChannels[ c ]; aiNodeAnim* channel = anim->mChannels[ c ];
for ( uint32_t i = 0; i < channel->mNumPositionKeys; i++ ) for ( uint32_t i = 0; i < channel->mNumPositionKeys; i++ )
channel->mPositionKeys[ i ].mTime -= start_fps; channel->mPositionKeys[ i ].mTime -= start_time_fps;
for ( uint32_t i = 0; i < channel->mNumRotationKeys; i++ ) for ( uint32_t i = 0; i < channel->mNumRotationKeys; i++ )
channel->mRotationKeys[ i ].mTime -= start_fps; channel->mRotationKeys[ i ].mTime -= start_time_fps;
for ( uint32_t i = 0; i < channel->mNumScalingKeys; i++ ) for ( uint32_t i = 0; i < channel->mNumScalingKeys; i++ )
channel->mScalingKeys[ i ].mTime -= start_fps; channel->mScalingKeys[ i ].mTime -= start_time_fps;
}
max_time -= min_time;
} }
// for some mysterious reason, mDuration is simply the maximum key -- the // for some mysterious reason, mDuration is simply the maximum key -- the
// validator always assumes animations to start at zero. // validator always assumes animations to start at zero.
anim->mDuration = ( stop_timeF - start_timeF ) * anim_fps; anim->mDuration = stop_time_fps - start_time_fps;
anim->mTicksPerSecond = anim_fps; anim->mTicksPerSecond = anim_fps;
} }
@ -3119,7 +3123,6 @@ void Converter::InterpolateKeys( aiVectorKey* valOut, const KeyTimeList& keys, c
} }
} }
void Converter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs, void Converter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs,
const aiVector3D& def_value, const aiVector3D& def_value,
double& maxTime, double& maxTime,
@ -3140,7 +3143,6 @@ void Converter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, con
valOut[ i ].mTime = temp[ i ].mTime; valOut[ i ].mTime = temp[ i ].mTime;
GetRotationMatrix( order, temp[ i ].mValue, m ); GetRotationMatrix( order, temp[ i ].mValue, m );
aiQuaternion quat = aiQuaternion( aiMatrix3x3( m ) ); aiQuaternion quat = aiQuaternion( aiMatrix3x3( m ) );
@ -3159,7 +3161,6 @@ void Converter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, con
} }
} }
void Converter::ConvertTransformOrder_TRStoSRT( aiQuatKey* out_quat, aiVectorKey* out_scale, void Converter::ConvertTransformOrder_TRStoSRT( aiQuatKey* out_quat, aiVectorKey* out_scale,
aiVectorKey* out_translation, aiVectorKey* out_translation,
const KeyFrameListList& scaling, const KeyFrameListList& scaling,
@ -3218,7 +3219,6 @@ void Converter::ConvertTransformOrder_TRStoSRT( aiQuatKey* out_quat, aiVectorKey
} }
} }
aiQuaternion Converter::EulerToQuaternion( const aiVector3D& rot, Model::RotOrder order ) aiQuaternion Converter::EulerToQuaternion( const aiVector3D& rot, Model::RotOrder order )
{ {
aiMatrix4x4 m; aiMatrix4x4 m;
@ -3227,7 +3227,6 @@ aiQuaternion Converter::EulerToQuaternion( const aiVector3D& rot, Model::RotOrde
return aiQuaternion( aiMatrix3x3( m ) ); return aiQuaternion( aiMatrix3x3( m ) );
} }
void Converter::ConvertScaleKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/, void Converter::ConvertScaleKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/,
int64_t start, int64_t stop, int64_t start, int64_t stop,
double& maxTime, double& maxTime,
@ -3248,7 +3247,6 @@ void Converter::ConvertScaleKeys( aiNodeAnim* na, const std::vector<const Animat
InterpolateKeys( na->mScalingKeys, keys, inputs, aiVector3D( 1.0f, 1.0f, 1.0f ), maxTime, minTime ); InterpolateKeys( na->mScalingKeys, keys, inputs, aiVector3D( 1.0f, 1.0f, 1.0f ), maxTime, minTime );
} }
void Converter::ConvertTranslationKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, void Converter::ConvertTranslationKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
const LayerMap& /*layers*/, const LayerMap& /*layers*/,
int64_t start, int64_t stop, int64_t start, int64_t stop,
@ -3267,7 +3265,6 @@ void Converter::ConvertTranslationKeys( aiNodeAnim* na, const std::vector<const
InterpolateKeys( na->mPositionKeys, keys, inputs, aiVector3D( 0.0f, 0.0f, 0.0f ), maxTime, minTime ); InterpolateKeys( na->mPositionKeys, keys, inputs, aiVector3D( 0.0f, 0.0f, 0.0f ), maxTime, minTime );
} }
void Converter::ConvertRotationKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, void Converter::ConvertRotationKeys( aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
const LayerMap& /*layers*/, const LayerMap& /*layers*/,
int64_t start, int64_t stop, int64_t start, int64_t stop,
@ -3289,7 +3286,8 @@ void Converter::ConvertRotationKeys( aiNodeAnim* na, const std::vector<const Ani
void Converter::TransferDataToScene() void Converter::TransferDataToScene()
{ {
ai_assert( !out->mMeshes && !out->mNumMeshes ); ai_assert( !out->mMeshes );
ai_assert( !out->mNumMeshes );
// note: the trailing () ensures initialization with NULL - not // note: the trailing () ensures initialization with NULL - not
// 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

View File

@ -70,13 +70,13 @@ LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc)
, id(id) , id(id)
, flags() , flags()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
LazyObject::~LazyObject() LazyObject::~LazyObject()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -232,16 +232,15 @@ Object::Object(uint64_t id, const Element& element, const std::string& name)
, name(name) , name(name)
, id(id) , id(id)
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Object::~Object() Object::~Object()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
FileGlobalSettings::FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props) FileGlobalSettings::FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props)
: props(props) : props(props)
@ -292,11 +291,10 @@ Document::~Document()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static const int LowerSupportedVersion = 7100; static const unsigned int LowerSupportedVersion = 7100;
static const int UpperSupportedVersion = 7400; static const unsigned int UpperSupportedVersion = 7400;
void Document::ReadHeader() void Document::ReadHeader() {
{
// Read ID objects from "Objects" section // Read ID objects from "Objects" section
const Scope& sc = parser.GetRootScope(); const Scope& sc = parser.GetRootScope();
const Element* const ehead = sc["FBXHeaderExtension"]; const Element* const ehead = sc["FBXHeaderExtension"];
@ -362,7 +360,6 @@ void Document::ReadGlobalSettings()
globals.reset(new FileGlobalSettings(*this, props)); globals.reset(new FileGlobalSettings(*this, props));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Document::ReadObjects() void Document::ReadObjects()
{ {
@ -388,7 +385,6 @@ void Document::ReadObjects()
} }
const char* err; const char* err;
const uint64_t id = ParseTokenAsID(*tok[0], err); const uint64_t id = ParseTokenAsID(*tok[0], err);
if(err) { if(err) {
DOMError(err,el.second); DOMError(err,el.second);
@ -470,8 +466,6 @@ void Document::ReadPropertyTemplates()
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Document::ReadConnections() void Document::ReadConnections()
{ {
@ -483,7 +477,6 @@ void Document::ReadConnections()
} }
uint64_t insertionOrder = 0l; uint64_t insertionOrder = 0l;
const Scope& sconns = *econns->Compound(); const Scope& sconns = *econns->Compound();
const ElementCollection conns = sconns.GetCollection("C"); const ElementCollection conns = sconns.GetCollection("C");
for(ElementMap::const_iterator it = conns.first; it != conns.second; ++it) { for(ElementMap::const_iterator it = conns.first; it != conns.second; ++it) {
@ -492,7 +485,9 @@ void Document::ReadConnections()
// PP = property-property connection, ignored for now // PP = property-property connection, ignored for now
// (tokens: "PP", ID1, "Property1", ID2, "Property2") // (tokens: "PP", ID1, "Property1", ID2, "Property2")
if(type == "PP") continue; if ( type == "PP" ) {
continue;
}
const uint64_t src = ParseTokenAsID(GetRequiredToken(el,1)); const uint64_t src = ParseTokenAsID(GetRequiredToken(el,1));
const uint64_t dest = ParseTokenAsID(GetRequiredToken(el,2)); const uint64_t dest = ParseTokenAsID(GetRequiredToken(el,2));
@ -519,11 +514,10 @@ void Document::ReadConnections()
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const std::vector<const AnimationStack*>& Document::AnimationStacks() const const std::vector<const AnimationStack*>& Document::AnimationStacks() const
{ {
if (!animationStacksResolved.empty() || !animationStacks.size()) { if (!animationStacksResolved.empty() || animationStacks.empty()) {
return animationStacksResolved; return animationStacksResolved;
} }
@ -541,7 +535,6 @@ const std::vector<const AnimationStack*>& Document::AnimationStacks() const
return animationStacksResolved; return animationStacksResolved;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
LazyObject* Document::GetObject(uint64_t id) const LazyObject* Document::GetObject(uint64_t id) const
{ {
@ -552,8 +545,7 @@ LazyObject* Document::GetObject(uint64_t id) const
#define MAX_CLASSNAMES 6 #define MAX_CLASSNAMES 6
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, const ConnectionMap& conns) const
const ConnectionMap& conns) const
{ {
std::vector<const Connection*> temp; std::vector<const Connection*> temp;
@ -570,7 +562,6 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id,
return temp; // NRVO should handle this return temp; // NRVO should handle this
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bool is_src, std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bool is_src,
const ConnectionMap& conns, const ConnectionMap& conns,
@ -579,17 +570,17 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
{ {
ai_assert(classnames); ai_assert(classnames);
ai_assert(count != 0 && count <= MAX_CLASSNAMES); ai_assert( count != 0 );
ai_assert( count <= MAX_CLASSNAMES);
size_t lenghts[MAX_CLASSNAMES]; size_t lenghts[MAX_CLASSNAMES];
const size_t c = count; const size_t c = count;
for (size_t i = 0; i < c; ++i) { for (size_t i = 0; i < c; ++i) {
lenghts[i] = strlen(classnames[i]); lenghts[ i ] = strlen(classnames[i]);
} }
std::vector<const Connection*> temp; std::vector<const Connection*> temp;
const std::pair<ConnectionMap::const_iterator,ConnectionMap::const_iterator> range = const std::pair<ConnectionMap::const_iterator,ConnectionMap::const_iterator> range =
conns.equal_range(id); conns.equal_range(id);
@ -621,25 +612,19 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
return temp; // NRVO should handle this return temp; // NRVO should handle this
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source) const std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source) const
{ {
return GetConnectionsSequenced(source, ConnectionsBySource()); return GetConnectionsSequenced(source, ConnectionsBySource());
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t dest, std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t dest, const char* classname) const
const char* classname) const
{ {
const char* arr[] = {classname}; const char* arr[] = {classname};
return GetConnectionsBySourceSequenced(dest, arr,1); return GetConnectionsBySourceSequenced(dest, arr,1);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source, std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source,
const char* const* classnames, size_t count) const const char* const* classnames, size_t count) const
@ -647,7 +632,6 @@ std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_
return GetConnectionsSequenced(source, true, ConnectionsBySource(),classnames, count); return GetConnectionsSequenced(source, true, ConnectionsBySource(),classnames, count);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest, std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
const char* classname) const const char* classname) const
@ -656,14 +640,12 @@ std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(ui
return GetConnectionsByDestinationSequenced(dest, arr,1); return GetConnectionsByDestinationSequenced(dest, arr,1);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest) const std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest) const
{ {
return GetConnectionsSequenced(dest, ConnectionsByDestination()); return GetConnectionsSequenced(dest, ConnectionsByDestination());
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest, std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(uint64_t dest,
const char* const* classnames, size_t count) const const char* const* classnames, size_t count) const
@ -672,7 +654,6 @@ std::vector<const Connection*> Document::GetConnectionsByDestinationSequenced(ui
return GetConnectionsSequenced(dest, false, ConnectionsByDestination(),classnames, count); return GetConnectionsSequenced(dest, false, ConnectionsByDestination(),classnames, count);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop, Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop,
const Document& doc) const Document& doc)
@ -688,14 +669,12 @@ Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, co
ai_assert(!dest || doc.Objects().find(dest) != doc.Objects().end()); ai_assert(!dest || doc.Objects().find(dest) != doc.Objects().end());
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Connection::~Connection() Connection::~Connection()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
LazyObject& Connection::LazySourceObject() const LazyObject& Connection::LazySourceObject() const
{ {
@ -704,7 +683,6 @@ LazyObject& Connection::LazySourceObject() const
return *lazy; return *lazy;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
LazyObject& Connection::LazyDestinationObject() const LazyObject& Connection::LazyDestinationObject() const
{ {
@ -713,7 +691,6 @@ LazyObject& Connection::LazyDestinationObject() const
return *lazy; return *lazy;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const Object* Connection::SourceObject() const const Object* Connection::SourceObject() const
{ {
@ -722,7 +699,6 @@ const Object* Connection::SourceObject() const
return lazy->Get(); return lazy->Get();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const Object* Connection::DestinationObject() const const Object* Connection::DestinationObject() const
{ {
@ -735,4 +711,3 @@ const Object* Connection::DestinationObject() const
} // !Assimp } // !Assimp
#endif #endif

View File

@ -338,12 +338,7 @@ public:
class Model : public Object class Model : public Object
{ {
public: public:
Model(uint64_t id, const Element& element, const Document& doc, const std::string& name); enum RotOrder {
virtual ~Model();
public:
enum RotOrder
{
RotOrder_EulerXYZ = 0, RotOrder_EulerXYZ = 0,
RotOrder_EulerXZY, RotOrder_EulerXZY,
RotOrder_EulerYZX, RotOrder_EulerYZX,
@ -357,8 +352,7 @@ public:
}; };
enum TransformInheritance enum TransformInheritance {
{
TransformInheritance_RrSs = 0, TransformInheritance_RrSs = 0,
TransformInheritance_RSrs, TransformInheritance_RSrs,
TransformInheritance_Rrs, TransformInheritance_Rrs,
@ -366,7 +360,10 @@ public:
TransformInheritance_MAX // end-of-enum sentinel TransformInheritance_MAX // end-of-enum sentinel
}; };
public: Model(uint64_t id, const Element& element, const Document& doc, const std::string& name);
virtual ~Model();
fbx_simple_property(QuaternionInterpolate, int, 0) fbx_simple_property(QuaternionInterpolate, int, 0)
fbx_simple_property(RotationOffset, aiVector3D, aiVector3D()) fbx_simple_property(RotationOffset, aiVector3D, aiVector3D())
@ -443,7 +440,6 @@ public:
fbx_simple_property(LODBox, bool, false) fbx_simple_property(LODBox, bool, false)
fbx_simple_property(Freeze, bool, false) fbx_simple_property(Freeze, bool, false)
public:
const std::string& Shading() const { const std::string& Shading() const {
return shading; return shading;
} }
@ -462,13 +458,11 @@ public:
return materials; return materials;
} }
/** Get geometry links */ /** Get geometry links */
const std::vector<const Geometry*>& GetGeometry() const { const std::vector<const Geometry*>& GetGeometry() const {
return geometry; return geometry;
} }
/** Get node attachments */ /** Get node attachments */
const std::vector<const NodeAttribute*>& GetAttributes() const { const std::vector<const NodeAttribute*>& GetAttributes() const {
return attributes; return attributes;
@ -477,7 +471,6 @@ public:
/** convenience method to check if the node has a Null node marker */ /** convenience method to check if the node has a Null node marker */
bool IsNull() const; bool IsNull() const;
private: private:
void ResolveLinks(const Element& element, const Document& doc); void ResolveLinks(const Element& element, const Document& doc);
@ -603,10 +596,10 @@ public:
return textures[index]; return textures[index];
} }
const int textureCount() const { int textureCount() const {
return static_cast<int>(textures.size()); return static_cast<int>(textures.size());
} }
const BlendMode GetBlendMode() const BlendMode GetBlendMode() const
{ {
return blendMode; return blendMode;
} }
@ -654,7 +647,7 @@ public:
return content; return content;
} }
const uint32_t ContentLength() const { uint32_t ContentLength() const {
return contentLength; return contentLength;
} }
@ -805,7 +798,6 @@ private:
typedef std::vector<const AnimationCurveNode*> AnimationCurveNodeList; typedef std::vector<const AnimationCurveNode*> AnimationCurveNodeList;
/** Represents a FBX animation layer (i.e. a list of node animations) */ /** Represents a FBX animation layer (i.e. a list of node animations) */
class AnimationLayer : public Object class AnimationLayer : public Object
{ {
@ -828,10 +820,8 @@ private:
const Document& doc; const Document& doc;
}; };
typedef std::vector<const AnimationLayer*> AnimationLayerList; typedef std::vector<const AnimationLayer*> AnimationLayerList;
/** Represents a FBX animation stack (i.e. a list of animation layers) */ /** Represents a FBX animation stack (i.e. a list of animation layers) */
class AnimationStack : public Object class AnimationStack : public Object
{ {
@ -839,7 +829,6 @@ public:
AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc); AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc);
virtual ~AnimationStack(); virtual ~AnimationStack();
public:
fbx_simple_property(LocalStart, int64_t, 0L) fbx_simple_property(LocalStart, int64_t, 0L)
fbx_simple_property(LocalStop, int64_t, 0L) fbx_simple_property(LocalStop, int64_t, 0L)
fbx_simple_property(ReferenceStart, int64_t, 0L) fbx_simple_property(ReferenceStart, int64_t, 0L)
@ -879,7 +868,6 @@ private:
typedef std::vector<float> WeightArray; typedef std::vector<float> WeightArray;
typedef std::vector<unsigned int> WeightIndexArray; typedef std::vector<unsigned int> WeightIndexArray;
/** DOM class for skin deformer clusters (aka subdeformers) */ /** DOM class for skin deformer clusters (aka subdeformers) */
class Cluster : public Deformer class Cluster : public Deformer
{ {
@ -924,8 +912,6 @@ private:
const Model* node; const Model* node;
}; };
/** DOM class for skin deformers */ /** DOM class for skin deformers */
class Skin : public Deformer class Skin : public Deformer
{ {
@ -1009,10 +995,8 @@ public:
typedef std::map<uint64_t, LazyObject*> ObjectMap; typedef std::map<uint64_t, LazyObject*> ObjectMap;
typedef std::fbx_unordered_map<std::string, std::shared_ptr<const PropertyTable> > PropertyTemplateMap; typedef std::fbx_unordered_map<std::string, std::shared_ptr<const PropertyTable> > PropertyTemplateMap;
typedef std::multimap<uint64_t, const Connection*> ConnectionMap; typedef std::multimap<uint64_t, const Connection*> ConnectionMap;
/** DOM class for global document settings, a single instance per document can /** DOM class for global document settings, a single instance per document can
* be accessed via Document.Globals(). */ * be accessed via Document.Globals(). */
class FileGlobalSettings class FileGlobalSettings
@ -1074,9 +1058,6 @@ private:
const Document& doc; const Document& doc;
}; };
/** DOM root for a FBX file */ /** DOM root for a FBX file */
class Document class Document
{ {
@ -1154,8 +1135,6 @@ private:
const ConnectionMap&, const ConnectionMap&,
const char* const* classnames, const char* const* classnames,
size_t count) const; size_t count) const;
private:
void ReadHeader(); void ReadHeader();
void ReadObjects(); void ReadObjects();
void ReadPropertyTemplates(); void ReadPropertyTemplates();

View File

@ -59,7 +59,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
namespace Assimp { namespace Assimp {
template<> const std::string LogFunctions<FBXImporter>::log_prefix = "FBX: "; template<> const char* LogFunctions<FBXImporter>::Prefix()
{
static auto prefix = "FBX: ";
return prefix;
}
} }
using namespace Assimp; using namespace Assimp;

View File

@ -243,7 +243,6 @@ const unsigned int* MeshGeometry::ToOutputVertexIndex( unsigned int in_index, un
ai_assert( m_mapping_counts.size() == m_mapping_offsets.size() ); ai_assert( m_mapping_counts.size() == m_mapping_offsets.size() );
count = m_mapping_counts[ in_index ]; count = m_mapping_counts[ in_index ];
// ai_assert( count != 0 );
ai_assert( m_mapping_offsets[ in_index ] + count <= m_mappings.size() ); ai_assert( m_mapping_offsets[ in_index ] + count <= m_mappings.size() );
return &m_mappings[ m_mapping_offsets[ in_index ] ]; return &m_mappings[ m_mapping_offsets[ in_index ] ];

View File

@ -77,14 +77,12 @@ Model::Model(uint64_t id, const Element& element, const Document& doc, const std
ResolveLinks(element,doc); ResolveLinks(element,doc);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Model::~Model() Model::~Model()
{ {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Model::ResolveLinks(const Element& element, const Document& doc) void Model::ResolveLinks(const Element& element, const Document& doc)
{ {
@ -132,7 +130,6 @@ void Model::ResolveLinks(const Element& element, const Document& doc)
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool Model::IsNull() const bool Model::IsNull() const
{ {

View File

@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
namespace FBX { namespace FBX {
using namespace Util; using namespace Util;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name) NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name)
@ -75,7 +75,7 @@ NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
NodeAttribute::~NodeAttribute() NodeAttribute::~NodeAttribute()
{ {
// empty
} }
@ -101,33 +101,30 @@ CameraSwitcher::CameraSwitcher(uint64_t id, const Element& element, const Docume
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
CameraSwitcher::~CameraSwitcher() CameraSwitcher::~CameraSwitcher()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Camera::Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name) Camera::Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name)
: NodeAttribute(id,element,doc,name) : NodeAttribute(id,element,doc,name)
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Camera::~Camera() Camera::~Camera()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Light::Light(uint64_t id, const Element& element, const Document& doc, const std::string& name) Light::Light(uint64_t id, const Element& element, const Document& doc, const std::string& name)
: NodeAttribute(id,element,doc,name) : NodeAttribute(id,element,doc,name)
{ {
// empty
} }

View File

@ -224,41 +224,36 @@ Parser::Parser (const TokenList& tokens, bool is_binary)
root.reset(new Scope(*this,true)); root.reset(new Scope(*this,true));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Parser::~Parser() Parser::~Parser()
{ {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
TokenPtr Parser::AdvanceToNextToken() TokenPtr Parser::AdvanceToNextToken()
{ {
last = current; last = current;
if (cursor == tokens.end()) { if (cursor == tokens.end()) {
current = NULL; current = NULL;
} } else {
else {
current = *cursor++; current = *cursor++;
} }
return current; return current;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
TokenPtr Parser::CurrentToken() const TokenPtr Parser::CurrentToken() const
{ {
return current; return current;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
TokenPtr Parser::LastToken() const TokenPtr Parser::LastToken() const
{ {
return last; return last;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
uint64_t ParseTokenAsID(const Token& t, const char*& err_out) uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
{ {
@ -286,7 +281,7 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
unsigned int length = static_cast<unsigned int>(t.end() - t.begin()); unsigned int length = static_cast<unsigned int>(t.end() - t.begin());
ai_assert(length > 0); ai_assert(length > 0);
const char* out; const char* out = nullptr;
const uint64_t id = strtoul10_64(t.begin(),&out,&length); const uint64_t id = strtoul10_64(t.begin(),&out,&length);
if (out > t.end()) { if (out > t.end()) {
err_out = "failed to parse ID (text)"; err_out = "failed to parse ID (text)";
@ -296,7 +291,6 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
return id; return id;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
size_t ParseTokenAsDim(const Token& t, const char*& err_out) size_t ParseTokenAsDim(const Token& t, const char*& err_out)
{ {
@ -333,7 +327,7 @@ size_t ParseTokenAsDim(const Token& t, const char*& err_out)
return 0; return 0;
} }
const char* out; const char* out = nullptr;
const size_t id = static_cast<size_t>(strtoul10_64(t.begin() + 1,&out,&length)); const size_t id = static_cast<size_t>(strtoul10_64(t.begin() + 1,&out,&length));
if (out > t.end()) { if (out > t.end()) {
err_out = "failed to parse ID"; err_out = "failed to parse ID";
@ -446,7 +440,7 @@ int64_t ParseTokenAsInt64(const Token& t, const char*& err_out)
unsigned int length = static_cast<unsigned int>(t.end() - t.begin()); unsigned int length = static_cast<unsigned int>(t.end() - t.begin());
ai_assert(length > 0); ai_assert(length > 0);
const char* out; const char* out = nullptr;
const int64_t id = strtol10_64(t.begin(), &out, &length); const int64_t id = strtol10_64(t.begin(), &out, &length);
if (out > t.end()) { if (out > t.end()) {
err_out = "failed to parse Int64 (text)"; err_out = "failed to parse Int64 (text)";

View File

@ -85,12 +85,9 @@ typedef std::pair<ElementMap::const_iterator,ElementMap::const_iterator> Element
class Element class Element
{ {
public: public:
Element(const Token& key_token, Parser& parser); Element(const Token& key_token, Parser& parser);
~Element(); ~Element();
public:
const Scope* Compound() const { const Scope* Compound() const {
return compound.get(); return compound.get();
} }
@ -104,14 +101,11 @@ public:
} }
private: private:
const Token& key_token; const Token& key_token;
TokenList tokens; TokenList tokens;
std::unique_ptr<Scope> compound; std::unique_ptr<Scope> compound;
}; };
/** FBX data entity that consists of a 'scope', a collection /** FBX data entity that consists of a 'scope', a collection
* of not necessarily unique #Element instances. * of not necessarily unique #Element instances.
* *
@ -125,14 +119,10 @@ private:
* @endverbatim */ * @endverbatim */
class Scope class Scope
{ {
public: public:
Scope(Parser& parser, bool topLevel = false); Scope(Parser& parser, bool topLevel = false);
~Scope(); ~Scope();
public:
const Element* operator[] (const std::string& index) const { const Element* operator[] (const std::string& index) const {
ElementMap::const_iterator it = elements.find(index); ElementMap::const_iterator it = elements.find(index);
return it == elements.end() ? NULL : (*it).second; return it == elements.end() ? NULL : (*it).second;
@ -158,28 +148,23 @@ public:
} }
private: private:
ElementMap elements; ElementMap elements;
}; };
/** FBX parsing class, takes a list of input tokens and generates a hierarchy /** FBX parsing class, takes a list of input tokens and generates a hierarchy
* of nested #Scope instances, representing the fbx DOM.*/ * of nested #Scope instances, representing the fbx DOM.*/
class Parser class Parser
{ {
public: public:
/** Parse given a token list. Does not take ownership of the tokens - /** Parse given a token list. Does not take ownership of the tokens -
* the objects must persist during the entire parser lifetime */ * the objects must persist during the entire parser lifetime */
Parser (const TokenList& tokens,bool is_binary); Parser (const TokenList& tokens,bool is_binary);
~Parser(); ~Parser();
public:
const Scope& GetRootScope() const { const Scope& GetRootScope() const {
return *root.get(); return *root.get();
} }
bool IsBinary() const { bool IsBinary() const {
return is_binary; return is_binary;
} }
@ -233,8 +218,6 @@ void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el);
void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& e); void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& e);
void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el); void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el);
// extract a required element from a scope, abort if the element cannot be found // extract a required element from a scope, abort if the element cannot be found
const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element = NULL); const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element = NULL);
@ -243,8 +226,6 @@ const Scope& GetRequiredScope(const Element& el);
// get token at a particular index // get token at a particular index
const Token& GetRequiredToken(const Element& el, unsigned int index); const Token& GetRequiredToken(const Element& el, unsigned int index);
// read a 4x4 matrix from an array of 16 floats // read a 4x4 matrix from an array of 16 floats
aiMatrix4x4 ReadMatrix(const Element& element); aiMatrix4x4 ReadMatrix(const Element& element);

View File

@ -55,17 +55,14 @@ namespace FBX {
// Forward declarations // Forward declarations
class Element; class Element;
/** Represents a dynamic property. Type info added by deriving classes, /** Represents a dynamic property. Type info added by deriving classes,
* see #TypedProperty. * see #TypedProperty.
Example: Example:
@verbatim @verbatim
P: "ShininessExponent", "double", "Number", "",0.5 P: "ShininessExponent", "double", "Number", "",0.5
@endvebatim @endvebatim
*/ */
class Property class Property {
{
protected: protected:
Property(); Property();
@ -79,17 +76,14 @@ public:
} }
}; };
template<typename T> template<typename T>
class TypedProperty : public Property class TypedProperty : public Property {
{
public: public:
explicit TypedProperty(const T& value) explicit TypedProperty(const T& value)
: value(value) : value(value) {
{ // empty
} }
public:
const T& Value() const { const T& Value() const {
return value; return value;
} }
@ -106,15 +100,13 @@ typedef std::fbx_unordered_map<std::string,const Element*> LazyPropertyMap;
/** /**
* Represents a property table as can be found in the newer FBX files (Properties60, Properties70) * Represents a property table as can be found in the newer FBX files (Properties60, Properties70)
*/ */
class PropertyTable class PropertyTable {
{
public: public:
// in-memory property table with no source element // in-memory property table with no source element
PropertyTable(); PropertyTable();
PropertyTable(const Element& element, std::shared_ptr<const PropertyTable> templateProps); PropertyTable(const Element& element, std::shared_ptr<const PropertyTable> templateProps);
~PropertyTable(); ~PropertyTable();
public:
const Property* Get(const std::string& name) const; const Property* Get(const std::string& name) const;
// PropertyTable's need not be coupled with FBX elements so this can be NULL // PropertyTable's need not be coupled with FBX elements so this can be NULL
@ -135,41 +127,37 @@ private:
const Element* const element; const Element* const element;
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
template <typename T> template <typename T>
inline T PropertyGet(const PropertyTable& in, const std::string& name, inline
const T& defaultValue) T PropertyGet(const PropertyTable& in, const std::string& name, const T& defaultValue) {
{
const Property* const prop = in.Get(name); const Property* const prop = in.Get(name);
if(!prop) { if( nullptr == prop) {
return defaultValue; return defaultValue;
} }
// strong typing, no need to be lenient // strong typing, no need to be lenient
const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >(); const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >();
if(!tprop) { if( nullptr == tprop) {
return defaultValue; return defaultValue;
} }
return tprop->Value(); return tprop->Value();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
template <typename T> template <typename T>
inline T PropertyGet(const PropertyTable& in, const std::string& name, inline
bool& result) T PropertyGet(const PropertyTable& in, const std::string& name, bool& result) {
{
const Property* const prop = in.Get(name); const Property* const prop = in.Get(name);
if(!prop) { if( nullptr == prop) {
result = false; result = false;
return T(); return T();
} }
// strong typing, no need to be lenient // strong typing, no need to be lenient
const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >(); const TypedProperty<T>* const tprop = prop->As< TypedProperty<T> >();
if(!tprop) { if( nullptr == tprop) {
result = false; result = false;
return T(); return T();
} }
@ -178,7 +166,6 @@ inline T PropertyGet(const PropertyTable& in, const std::string& name,
return tprop->Value(); return tprop->Value();
} }
} //! FBX } //! FBX
} //! Assimp } //! Assimp

View File

@ -101,7 +101,6 @@ public:
return std::string(begin(),end()); return std::string(begin(),end());
} }
public:
bool IsBinary() const { bool IsBinary() const {
return column == BINARY_MARKER; return column == BINARY_MARKER;
} }

View File

@ -45,6 +45,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
// Workaround for issue #1361
// https://github.com/assimp/assimp/issues/1361
#ifdef __ANDROID__
#define _GLIBCXX_USE_C99 1
#endif
#include "FIReader.hpp" #include "FIReader.hpp"
#include "Exceptional.h" #include "Exceptional.h"
#include <assimp/IOStream.hpp> #include <assimp/IOStream.hpp>
@ -162,7 +168,7 @@ struct FIBase64ValueImpl: public FIBase64Value {
if (!strValueValid) { if (!strValueValid) {
strValueValid = true; strValueValid = true;
std::ostringstream os; std::ostringstream os;
uint8_t c1, c2; uint8_t c1 = 0, c2;
int imod3 = 0; int imod3 = 0;
std::vector<uint8_t>::size_type valueSize = value.size(); std::vector<uint8_t>::size_type valueSize = value.size();
for (std::vector<uint8_t>::size_type i = 0; i < valueSize; ++i) { for (std::vector<uint8_t>::size_type i = 0; i < valueSize; ++i) {

View File

@ -111,7 +111,7 @@ inline void SetGenericPropertyPtr(std::map< unsigned int, T* >& list,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
template <class T> template <class T>
inline const bool HasGenericProperty(const std::map< unsigned int, T >& list, inline bool HasGenericProperty(const std::map< unsigned int, T >& list,
const char* szName) const char* szName)
{ {
ai_assert(NULL != szName); ai_assert(NULL != szName);

View File

@ -448,7 +448,8 @@ void HMPImporter::CreateOutputFaceList(unsigned int width,unsigned int height)
void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szCursor, void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szCursor,
const unsigned char** szCursorOut) const unsigned char** szCursorOut)
{ {
ai_assert(0 != iNumSkins && NULL != szCursor); ai_assert( 0 != iNumSkins );
ai_assert( nullptr != szCursor);
// read the type of the skin ... // read the type of the skin ...
// sometimes we need to skip 12 bytes here, I don't know why ... // sometimes we need to skip 12 bytes here, I don't know why ...

View File

@ -272,7 +272,6 @@ bool IntersectsBoundaryProfile(const IfcVector3& e0, const IfcVector3& e1, const
const IfcVector3& b0 = boundary[i]; const IfcVector3& b0 = boundary[i];
const IfcVector3& b1 = boundary[(i + 1) % bcount]; const IfcVector3& b1 = boundary[(i + 1) % bcount];
IfcVector3 b = b1 - b0; IfcVector3 b = b1 - b0;
IfcFloat b_sqlen_inv = 1.0 / b.SquareLength();
// segment-segment intersection // segment-segment intersection
// solve b0 + b*s = e0 + e*t for (s,t) // solve b0 + b*s = e0 + e*t for (s,t)
@ -281,6 +280,7 @@ bool IntersectsBoundaryProfile(const IfcVector3& e0, const IfcVector3& e1, const
// no solutions (parallel lines) // no solutions (parallel lines)
continue; continue;
} }
IfcFloat b_sqlen_inv = 1.0 / b.SquareLength();
const IfcFloat x = b0.x - e0.x; const IfcFloat x = b0.x - e0.x;
const IfcFloat y = b0.y - e0.y; const IfcFloat y = b0.y - e0.y;
@ -381,7 +381,6 @@ bool PointInPoly(const IfcVector3& p, const std::vector<IfcVector3>& boundary)
IntersectsBoundaryProfile(p, p + IfcVector3(0.6, -0.6, 0.0), boundary, true, intersected_boundary, true); IntersectsBoundaryProfile(p, p + IfcVector3(0.6, -0.6, 0.0), boundary, true, intersected_boundary, true);
votes += intersected_boundary.size() % 2; votes += intersected_boundary.size() % 2;
// ai_assert(votes == 3 || votes == 0);
return votes > 1; return votes > 1;
} }

View File

@ -548,8 +548,6 @@ bool Curve :: InRange(IfcFloat u) const
const ParamRange range = GetParametricRange(); const ParamRange range = GetParametricRange();
if (IsClosed()) { if (IsClosed()) {
return true; return true;
//ai_assert(range.first != std::numeric_limits<IfcFloat>::infinity() && range.second != std::numeric_limits<IfcFloat>::infinity());
//u = range.first + std::fmod(u-range.first,range.second-range.first);
} }
const IfcFloat epsilon = 1e-5; const IfcFloat epsilon = 1e-5;
return u - range.first > -epsilon && range.second - u > -epsilon; return u - range.first > -epsilon && range.second - u > -epsilon;

View File

@ -66,7 +66,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
template<> const std::string LogFunctions<IFCImporter>::log_prefix = "IFC: "; template<> const char* LogFunctions<IFCImporter>::Prefix()
{
static auto prefix = "IFC: ";
return prefix;
}
} }
using namespace Assimp; using namespace Assimp;

View File

@ -1492,7 +1492,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
vmax -= vmin; vmax -= vmin;
// If this happens then the projection must have been wrong. // If this happens then the projection must have been wrong.
assert(vmax.Length()); ai_assert(vmax.Length());
ClipperLib::ExPolygons clipped; ClipperLib::ExPolygons clipped;
ClipperLib::Polygons holes_union; ClipperLib::Polygons holes_union;
@ -1616,7 +1616,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
std::vector<IfcVector3> tmpvec; std::vector<IfcVector3> tmpvec;
for(ClipperLib::Polygon& opening : holes_union) { for(ClipperLib::Polygon& opening : holes_union) {
assert(ClipperLib::Orientation(opening)); ai_assert(ClipperLib::Orientation(opening));
tmpvec.clear(); tmpvec.clear();
@ -1705,7 +1705,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
static_cast<IfcFloat>( tri->GetPoint(i)->y ) static_cast<IfcFloat>( tri->GetPoint(i)->y )
); );
assert(v.x <= 1.0 && v.x >= 0.0 && v.y <= 1.0 && v.y >= 0.0); ai_assert(v.x <= 1.0 && v.x >= 0.0 && v.y <= 1.0 && v.y >= 0.0);
const IfcVector3 v3 = minv * IfcVector3(vmin.x + v.x * vmax.x, vmin.y + v.y * vmax.y,coord) ; const IfcVector3 v3 = minv * IfcVector3(vmin.x + v.x * vmax.x, vmin.y + v.y * vmax.y,coord) ;
curmesh.verts.push_back(v3); curmesh.verts.push_back(v3);

View File

@ -128,7 +128,7 @@ void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh&
meshout.verts.push_back( IfcVector3( std::cos(angle)*radius, std::sin(angle)*radius, 0.f )); meshout.verts.push_back( IfcVector3( std::cos(angle)*radius, std::sin(angle)*radius, 0.f ));
} }
meshout.vertcnt.push_back(segments); meshout.vertcnt.push_back(static_cast<unsigned int>(segments));
} }
else if( const IfcIShapeProfileDef* const ishape = def.ToPtr<IfcIShapeProfileDef>()) { else if( const IfcIShapeProfileDef* const ishape = def.ToPtr<IfcIShapeProfileDef>()) {
// construct simplified IBeam shape // construct simplified IBeam shape

View File

@ -284,11 +284,17 @@ bool IOStreamBuffer<T>::getNextDataLine( std::vector<T> &buffer, T continuationT
return true; return true;
} }
static
inline
bool isEndOfCache( size_t pos, size_t cacheSize ) {
return ( pos == cacheSize );
}
template<class T> template<class T>
inline inline
bool IOStreamBuffer<T>::getNextLine(std::vector<T> &buffer) { bool IOStreamBuffer<T>::getNextLine(std::vector<T> &buffer) {
buffer.resize(m_cacheSize); buffer.resize(m_cacheSize);
if (m_cachePos == m_cacheSize || 0 == m_filePos) { if ( isEndOfCache( m_cachePos, m_cacheSize ) || 0 == m_filePos) {
if (!readNextBlock()) { if (!readNextBlock()) {
return false; return false;
} }
@ -300,11 +306,16 @@ bool IOStreamBuffer<T>::getNextLine(std::vector<T> &buffer) {
++m_cachePos; ++m_cachePos;
} }
++m_cachePos; ++m_cachePos;
if ( isEndOfCache( m_cachePos, m_cacheSize ) ) {
if ( !readNextBlock() ) {
return false;
}
}
} }
size_t i = 0; size_t i = 0;
while (!IsLineEnd(m_cache[m_cachePos])) { while (!IsLineEnd(m_cache[ m_cachePos ])) {
buffer[i] = m_cache[m_cachePos]; buffer[i] = m_cache[ m_cachePos ];
m_cachePos++; m_cachePos++;
i++; i++;
if (m_cachePos >= m_cacheSize) { if (m_cachePos >= m_cacheSize) {

View File

@ -182,6 +182,7 @@ corresponding preprocessor flag to selectively disable formats.
#endif #endif
#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER #ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
# include "glTFImporter.h" # include "glTFImporter.h"
# include "glTF2Importer.h"
#endif #endif
#ifndef ASSIMP_BUILD_NO_C4D_IMPORTER #ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
# include "C4DImporter.h" # include "C4DImporter.h"
@ -336,6 +337,7 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
#endif #endif
#if ( !defined ASSIMP_BUILD_NO_GLTF_IMPORTER ) #if ( !defined ASSIMP_BUILD_NO_GLTF_IMPORTER )
out.push_back( new glTFImporter() ); out.push_back( new glTFImporter() );
out.push_back( new glTF2Importer() );
#endif #endif
#if ( !defined ASSIMP_BUILD_NO_C4D_IMPORTER ) #if ( !defined ASSIMP_BUILD_NO_C4D_IMPORTER )
out.push_back( new C4DImporter() ); out.push_back( new C4DImporter() );

View File

@ -60,34 +60,34 @@ public:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void ThrowException(const std::string& msg) static void ThrowException(const std::string& msg)
{ {
throw DeadlyImportError(log_prefix+msg); throw DeadlyImportError(Prefix()+msg);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void LogWarn(const Formatter::format& message) { static void LogWarn(const Formatter::format& message) {
if (!DefaultLogger::isNullLogger()) { if (!DefaultLogger::isNullLogger()) {
DefaultLogger::get()->warn(log_prefix+(std::string)message); DefaultLogger::get()->warn(Prefix()+(std::string)message);
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void LogError(const Formatter::format& message) { static void LogError(const Formatter::format& message) {
if (!DefaultLogger::isNullLogger()) { if (!DefaultLogger::isNullLogger()) {
DefaultLogger::get()->error(log_prefix+(std::string)message); DefaultLogger::get()->error(Prefix()+(std::string)message);
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void LogInfo(const Formatter::format& message) { static void LogInfo(const Formatter::format& message) {
if (!DefaultLogger::isNullLogger()) { if (!DefaultLogger::isNullLogger()) {
DefaultLogger::get()->info(log_prefix+(std::string)message); DefaultLogger::get()->info(Prefix()+(std::string)message);
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void LogDebug(const Formatter::format& message) { static void LogDebug(const Formatter::format& message) {
if (!DefaultLogger::isNullLogger()) { if (!DefaultLogger::isNullLogger()) {
DefaultLogger::get()->debug(log_prefix+(std::string)message); DefaultLogger::get()->debug(Prefix()+(std::string)message);
} }
} }
@ -125,8 +125,7 @@ public:
#endif #endif
private: private:
static const char* Prefix();
static const std::string log_prefix;
}; };

View File

@ -126,16 +126,16 @@ struct Header {
int32_t version; int32_t version;
//! scale factors for each axis //! scale factors for each axis
aiVector3D scale; ai_real scale[3];
//! translation factors for each axis //! translation factors for each axis
aiVector3D translate; ai_real translate[3];
//! bounding radius of the mesh //! bounding radius of the mesh
float boundingradius; float boundingradius;
//! Position of the viewer's exe. Ignored //! Position of the viewer's exe. Ignored
aiVector3D vEyePos; ai_real vEyePos[3];
//! Number of textures //! Number of textures
int32_t num_skins; int32_t num_skins;
@ -164,7 +164,7 @@ struct Header {
//! Could be the total size of the file (and not a float) //! Could be the total size of the file (and not a float)
float size; float size;
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
@ -223,7 +223,7 @@ struct Header_MDL7 {
//! Size of the Frame_MDL7 data structure used in the file //! Size of the Frame_MDL7 data structure used in the file
uint16_t frame_stc_size; uint16_t frame_stc_size;
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
@ -242,7 +242,7 @@ struct Bone_MDL7 {
//! Optional name of the bone //! Optional name of the bone
char name[1 /* DUMMY SIZE */]; char name[1 /* DUMMY SIZE */];
} /* PACK_STRUCT */; } PACK_STRUCT;
#if (!defined AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS) #if (!defined AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS)
# define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS (16 + 20) # define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS (16 + 20)
@ -290,7 +290,7 @@ struct Group_MDL7 {
//! Number of frames //! Number of frames
int32_t numframes; int32_t numframes;
} /* PACK_STRUCT */; } PACK_STRUCT;
#define AI_MDL7_SKINTYPE_MIPFLAG 0x08 #define AI_MDL7_SKINTYPE_MIPFLAG 0x08
#define AI_MDL7_SKINTYPE_MATERIAL 0x10 #define AI_MDL7_SKINTYPE_MATERIAL 0x10
@ -312,7 +312,7 @@ struct Deformer_MDL7 {
int32_t group_index; int32_t group_index;
int32_t elements; int32_t elements;
int32_t deformerdata_size; int32_t deformerdata_size;
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
@ -324,7 +324,7 @@ struct DeformerElement_MDL7 {
int32_t element_index; int32_t element_index;
char element_name[AI_MDL7_MAX_BONENAMESIZE]; char element_name[AI_MDL7_MAX_BONENAMESIZE];
int32_t weights; int32_t weights;
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
/** \struct DeformerWeight_MDL7 /** \struct DeformerWeight_MDL7
@ -334,7 +334,7 @@ struct DeformerWeight_MDL7 {
//! for deformer_typ==0 (==bones) index == vertex index //! for deformer_typ==0 (==bones) index == vertex index
int32_t index; int32_t index;
float weight; float weight;
} /* PACK_STRUCT */; } PACK_STRUCT;
// don't know why this was in the original headers ... // don't know why this was in the original headers ...
typedef int32_t MD7_MATERIAL_ASCDEFSIZE; typedef int32_t MD7_MATERIAL_ASCDEFSIZE;
@ -345,7 +345,7 @@ typedef int32_t MD7_MATERIAL_ASCDEFSIZE;
*/ */
struct ColorValue_MDL7 { struct ColorValue_MDL7 {
float r,g,b,a; float r,g,b,a;
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
/** \struct Material_MDL7 /** \struct Material_MDL7
@ -366,7 +366,7 @@ struct Material_MDL7 {
//! Phong power //! Phong power
float Power; float Power;
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
/** \struct Skin /** \struct Skin
@ -388,7 +388,7 @@ struct Skin {
//! Texture data //! Texture data
uint8_t *data; uint8_t *data;
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
@ -399,7 +399,7 @@ struct Skin {
struct Skin_MDL5 { struct Skin_MDL5 {
int32_t size, width, height; int32_t size, width, height;
uint8_t *data; uint8_t *data;
} /* PACK_STRUCT */; } PACK_STRUCT;
// maximum length of texture file name // maximum length of texture file name
#if (!defined AI_MDL7_MAX_TEXNAMESIZE) #if (!defined AI_MDL7_MAX_TEXNAMESIZE)
@ -416,7 +416,7 @@ struct Skin_MDL7 {
int32_t width; int32_t width;
int32_t height; int32_t height;
char texture_name[AI_MDL7_MAX_TEXNAMESIZE]; char texture_name[AI_MDL7_MAX_TEXNAMESIZE];
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
/** \struct RGB565 /** \struct RGB565
@ -426,7 +426,7 @@ struct RGB565 {
uint16_t r : 5; uint16_t r : 5;
uint16_t g : 6; uint16_t g : 6;
uint16_t b : 5; uint16_t b : 5;
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
/** \struct ARGB4 /** \struct ARGB4
@ -455,7 +455,7 @@ struct GroupSkin {
//! Data of each image //! Data of each image
uint8_t **data; uint8_t **data;
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
/** \struct TexCoord /** \struct TexCoord
@ -470,7 +470,7 @@ struct TexCoord {
//! Texture coordinate in the ty direction //! Texture coordinate in the ty direction
int32_t t; int32_t t;
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
/** \struct TexCoord_MDL3 /** \struct TexCoord_MDL3
@ -482,7 +482,7 @@ struct TexCoord_MDL3 {
//! position, vertically in range 0..skinheight-1 //! position, vertically in range 0..skinheight-1
int16_t v; int16_t v;
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
/** \struct TexCoord_MDL7 /** \struct TexCoord_MDL7
@ -494,7 +494,7 @@ struct TexCoord_MDL7 {
//! position, vertically in range 0..1 //! position, vertically in range 0..1
float v; float v;
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
/** \struct SkinSet_MDL7 /** \struct SkinSet_MDL7
@ -510,7 +510,7 @@ struct SkinSet_MDL7
//! Material index //! Material index
int32_t material; // size 4 int32_t material; // size 4
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
/** \struct Triangle /** \struct Triangle
@ -523,7 +523,7 @@ struct Triangle
//! Vertex indices //! Vertex indices
int32_t vertex[3]; int32_t vertex[3];
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
/** \struct Triangle_MDL3 /** \struct Triangle_MDL3
@ -536,7 +536,7 @@ struct Triangle_MDL3
//! Index of 3 skin vertices in range 0..numskinverts //! Index of 3 skin vertices in range 0..numskinverts
uint16_t index_uv[3]; uint16_t index_uv[3];
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
/** \struct Triangle_MDL7 /** \struct Triangle_MDL7
@ -549,7 +549,7 @@ struct Triangle_MDL7
//! Two skinsets. The second will be used for multi-texturing //! Two skinsets. The second will be used for multi-texturing
SkinSet_MDL7 skinsets[2]; SkinSet_MDL7 skinsets[2];
} /* PACK_STRUCT */; } PACK_STRUCT;
#if (!defined AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV) #if (!defined AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV)
# define AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV (6+sizeof(SkinSet_MDL7)-sizeof(uint32_t)) # define AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV (6+sizeof(SkinSet_MDL7)-sizeof(uint32_t))
@ -577,7 +577,7 @@ struct Vertex
{ {
uint8_t v[3]; uint8_t v[3];
uint8_t normalIndex; uint8_t normalIndex;
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
@ -603,7 +603,7 @@ struct Vertex_MDL7
uint8_t norm162index; uint8_t norm162index;
float norm[3]; float norm[3];
}; };
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
/** \struct BoneTransform_MDL7 /** \struct BoneTransform_MDL7
@ -620,7 +620,7 @@ struct BoneTransform_MDL7
//! I HATE 3DGS AND THE SILLY DEVELOPER WHO DESIGNED //! I HATE 3DGS AND THE SILLY DEVELOPER WHO DESIGNED
//! THIS STUPID FILE FORMAT! //! THIS STUPID FILE FORMAT!
int8_t _unused_[2]; int8_t _unused_[2];
} /* PACK_STRUCT */; } PACK_STRUCT;
#define AI_MDL7_MAX_FRAMENAMESIZE 16 #define AI_MDL7_MAX_FRAMENAMESIZE 16
@ -654,7 +654,7 @@ struct SimpleFrame
//! Vertex list of the frame //! Vertex list of the frame
Vertex *verts; Vertex *verts;
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
/** \struct Frame /** \struct Frame
@ -667,7 +667,7 @@ struct Frame
//! Frame data //! Frame data
SimpleFrame frame; SimpleFrame frame;
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
@ -684,7 +684,7 @@ struct SimpleFrame_MDLn_SP
//! Vertex list of the frame //! Vertex list of the frame
Vertex_MDL4 *verts; Vertex_MDL4 *verts;
} /* PACK_STRUCT */; } PACK_STRUCT;
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------
/** \struct GroupFrame /** \struct GroupFrame
@ -706,7 +706,7 @@ struct GroupFrame
//! List of single frames //! List of single frames
SimpleFrame *frames; SimpleFrame *frames;
} /* PACK_STRUCT */; } PACK_STRUCT;
#include "./../include/assimp/Compiler/poppack1.h" #include "./../include/assimp/Compiler/poppack1.h"

View File

@ -1132,7 +1132,9 @@ bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInf
const unsigned char* szCurrent, const unsigned char* szCurrent,
const unsigned char** szCurrentOut) const unsigned char** szCurrentOut)
{ {
ai_assert(NULL != szCurrent && NULL != szCurrentOut); ai_assert( nullptr != szCurrent );
ai_assert( nullptr != szCurrentOut);
const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)mBuffer; const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)mBuffer;
// if we have no bones we can simply skip all frames, // if we have no bones we can simply skip all frames,

View File

@ -118,7 +118,7 @@ void MMDImporter::InternReadFile(const std::string &file, aiScene *pScene,
// Get the file-size and validate it, throwing an exception when fails // Get the file-size and validate it, throwing an exception when fails
fileStream.seekg(0, fileStream.end); fileStream.seekg(0, fileStream.end);
size_t fileSize = fileStream.tellg(); size_t fileSize = static_cast<size_t>(fileStream.tellg());
fileStream.seekg(0, fileStream.beg); fileStream.seekg(0, fileStream.beg);
if (fileSize < sizeof(pmx::PmxModel)) { if (fileSize < sizeof(pmx::PmxModel)) {
@ -278,7 +278,7 @@ aiMesh *MMDImporter::CreateMesh(const pmx::PmxModel *pModel,
bone_vertex_map[vsBDEF2_ptr->bone_index1].push_back( bone_vertex_map[vsBDEF2_ptr->bone_index1].push_back(
aiVertexWeight(index, vsBDEF2_ptr->bone_weight)); aiVertexWeight(index, vsBDEF2_ptr->bone_weight));
bone_vertex_map[vsBDEF2_ptr->bone_index2].push_back( bone_vertex_map[vsBDEF2_ptr->bone_index2].push_back(
aiVertexWeight(index, 1.0 - vsBDEF2_ptr->bone_weight)); aiVertexWeight(index, 1.0f - vsBDEF2_ptr->bone_weight));
break; break;
case pmx::PmxVertexSkinningType::BDEF4: case pmx::PmxVertexSkinningType::BDEF4:
bone_vertex_map[vsBDEF4_ptr->bone_index1].push_back( bone_vertex_map[vsBDEF4_ptr->bone_index1].push_back(
@ -295,7 +295,7 @@ aiMesh *MMDImporter::CreateMesh(const pmx::PmxModel *pModel,
bone_vertex_map[vsSDEF_ptr->bone_index1].push_back( bone_vertex_map[vsSDEF_ptr->bone_index1].push_back(
aiVertexWeight(index, vsSDEF_ptr->bone_weight)); aiVertexWeight(index, vsSDEF_ptr->bone_weight));
bone_vertex_map[vsSDEF_ptr->bone_index2].push_back( bone_vertex_map[vsSDEF_ptr->bone_index2].push_back(
aiVertexWeight(index, 1.0 - vsSDEF_ptr->bone_weight)); aiVertexWeight(index, 1.0f - vsSDEF_ptr->bone_weight));
break; break;
case pmx::PmxVertexSkinningType::QDEF: case pmx::PmxVertexSkinningType::QDEF:
const auto vsQDEF_ptr = const auto vsQDEF_ptr =
@ -325,7 +325,7 @@ aiMesh *MMDImporter::CreateMesh(const pmx::PmxModel *pModel,
aiMatrix4x4::Translation(-pos, pBone->mOffsetMatrix); aiMatrix4x4::Translation(-pos, pBone->mOffsetMatrix);
auto it = bone_vertex_map.find(ii); auto it = bone_vertex_map.find(ii);
if (it != bone_vertex_map.end()) { if (it != bone_vertex_map.end()) {
pBone->mNumWeights = it->second.size(); pBone->mNumWeights = static_cast<unsigned int>(it->second.size());
pBone->mWeights = it->second.data(); pBone->mWeights = it->second.data();
it->second.swap(*(new vector<aiVertexWeight>)); it->second.swap(*(new vector<aiVertexWeight>));
} }

View File

@ -49,17 +49,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace pmd namespace pmd
{ {
/// ヘッダ
class PmdHeader class PmdHeader
{ {
public: public:
/// モデル名
std::string name; std::string name;
/// モデル名(英語)
std::string name_english; std::string name_english;
/// コメント
std::string comment; std::string comment;
/// コメント(英語)
std::string comment_english; std::string comment_english;
bool Read(std::ifstream* stream) bool Read(std::ifstream* stream)
@ -83,26 +78,19 @@ namespace pmd
} }
}; };
/// 頂点
class PmdVertex class PmdVertex
{ {
public: public:
/// 位置
float position[3]; float position[3];
/// 法線
float normal[3]; float normal[3];
/// UV座標
float uv[2]; float uv[2];
/// 関連ボーンインデックス
uint16_t bone_index[2]; uint16_t bone_index[2];
/// ボーンウェイト
uint8_t bone_weight; uint8_t bone_weight;
/// エッジ不可視
bool edge_invisible; bool edge_invisible;
bool Read(std::ifstream* stream) bool Read(std::ifstream* stream)
@ -117,27 +105,17 @@ namespace pmd
} }
}; };
/// 材質
class PmdMaterial class PmdMaterial
{ {
public: public:
/// 減衰色
float diffuse[4]; float diffuse[4];
/// 光沢度
float power; float power;
/// 光沢色
float specular[3]; float specular[3];
/// 環境色
float ambient[3]; float ambient[3];
/// トーンインデックス
uint8_t toon_index; uint8_t toon_index;
/// エッジ
uint8_t edge_flag; uint8_t edge_flag;
/// インデックス数
uint32_t index_count; uint32_t index_count;
/// テクスチャファイル名
std::string texture_filename; std::string texture_filename;
/// スフィアファイル名
std::string sphere_filename; std::string sphere_filename;
bool Read(std::ifstream* stream) bool Read(std::ifstream* stream)
@ -158,7 +136,7 @@ namespace pmd
sphere_filename.clear(); sphere_filename.clear();
} }
else { else {
*pstar = (char)NULL; *pstar = 0;
texture_filename = std::string(buffer); texture_filename = std::string(buffer);
sphere_filename = std::string(pstar+1); sphere_filename = std::string(pstar+1);
} }
@ -180,23 +158,15 @@ namespace pmd
RotationMovement RotationMovement
}; };
/// ボーン
class PmdBone class PmdBone
{ {
public: public:
/// ボーン名
std::string name; std::string name;
/// ボーン名(英語)
std::string name_english; std::string name_english;
/// 親ボーン番号
uint16_t parent_bone_index; uint16_t parent_bone_index;
/// 末端ボーン番号
uint16_t tail_pos_bone_index; uint16_t tail_pos_bone_index;
/// ボーン種類
BoneType bone_type; BoneType bone_type;
/// IKボーン番号
uint16_t ik_parent_bone_index; uint16_t ik_parent_bone_index;
/// ボーンのヘッドの位置
float bone_head_pos[3]; float bone_head_pos[3];
void Read(std::istream *stream) void Read(std::istream *stream)
@ -219,19 +189,13 @@ namespace pmd
} }
}; };
/// IK
class PmdIk class PmdIk
{ {
public: public:
/// IKボーン番号
uint16_t ik_bone_index; uint16_t ik_bone_index;
/// IKターゲットボーン番号
uint16_t target_bone_index; uint16_t target_bone_index;
/// 再帰回数
uint16_t interations; uint16_t interations;
/// 角度制限
float angle_limit; float angle_limit;
/// 影響下ボーン番号
std::vector<uint16_t> ik_child_bone_index; std::vector<uint16_t> ik_child_bone_index;
void Read(std::istream *stream) void Read(std::istream *stream)
@ -303,7 +267,6 @@ namespace pmd
} }
}; };
/// ボーン枠用の枠名
class PmdBoneDispName class PmdBoneDispName
{ {
public: public:
@ -338,59 +301,36 @@ namespace pmd
} }
}; };
/// 衝突形状
enum class RigidBodyShape : uint8_t enum class RigidBodyShape : uint8_t
{ {
/// 球
Sphere = 0, Sphere = 0,
/// 直方体
Box = 1, Box = 1,
/// カプセル
Cpusel = 2 Cpusel = 2
}; };
/// 剛体タイプ
enum class RigidBodyType : uint8_t enum class RigidBodyType : uint8_t
{ {
/// ボーン追従
BoneConnected = 0, BoneConnected = 0,
/// 物理演算
Physics = 1, Physics = 1,
/// 物理演算(Bone位置合せ)
ConnectedPhysics = 2 ConnectedPhysics = 2
}; };
/// 剛体
class PmdRigidBody class PmdRigidBody
{ {
public: public:
/// 名前
std::string name; std::string name;
/// 関連ボーン番号
uint16_t related_bone_index; uint16_t related_bone_index;
/// グループ番号
uint8_t group_index; uint8_t group_index;
/// マスク
uint16_t mask; uint16_t mask;
/// 形状
RigidBodyShape shape; RigidBodyShape shape;
/// 大きさ
float size[3]; float size[3];
/// 位置
float position[3]; float position[3];
/// 回転
float orientation[3]; float orientation[3];
/// 質量
float weight; float weight;
/// 移動ダンピング
float linear_damping; float linear_damping;
/// 回転ダンピング
float anglar_damping; float anglar_damping;
/// 反発係数
float restitution; float restitution;
/// 摩擦係数
float friction; float friction;
/// 演算方法
RigidBodyType rigid_type; RigidBodyType rigid_type;
void Read(std::istream *stream) void Read(std::istream *stream)
@ -414,31 +354,19 @@ namespace pmd
} }
}; };
/// 剛体の拘束
class PmdConstraint class PmdConstraint
{ {
public: public:
/// 名前
std::string name; std::string name;
/// 剛体Aのインデックス
uint32_t rigid_body_index_a; uint32_t rigid_body_index_a;
/// 剛体Bのインデックス
uint32_t rigid_body_index_b; uint32_t rigid_body_index_b;
/// 位置
float position[3]; float position[3];
/// 回転
float orientation[3]; float orientation[3];
/// 最小移動制限
float linear_lower_limit[3]; float linear_lower_limit[3];
/// 最大移動制限
float linear_upper_limit[3]; float linear_upper_limit[3];
/// 最小回転制限
float angular_lower_limit[3]; float angular_lower_limit[3];
/// 最大回転制限
float angular_upper_limit[3]; float angular_upper_limit[3];
/// 移動に対する復元力
float linear_stiffness[3]; float linear_stiffness[3];
/// 回転に対する復元力
float angular_stiffness[3]; float angular_stiffness[3];
void Read(std::istream *stream) void Read(std::istream *stream)
@ -459,7 +387,6 @@ namespace pmd
} }
}; };
/// PMDモデル
class PmdModel class PmdModel
{ {
public: public:
@ -491,7 +418,6 @@ namespace pmd
return result; return result;
} }
/// ファイルからPmdModelを生成する
static std::unique_ptr<PmdModel> LoadFromStream(std::ifstream *stream) static std::unique_ptr<PmdModel> LoadFromStream(std::ifstream *stream)
{ {
auto result = mmd::make_unique<PmdModel>(); auto result = mmd::make_unique<PmdModel>();

View File

@ -45,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace pmx namespace pmx
{ {
/// インデックス値を読み込む
int ReadIndex(std::istream *stream, int size) int ReadIndex(std::istream *stream, int size)
{ {
switch (size) switch (size)
@ -79,7 +78,6 @@ namespace pmx
} }
} }
/// 文字列を読み込む
std::string ReadString(std::istream *stream, uint8_t encoding) std::string ReadString(std::istream *stream, uint8_t encoding)
{ {
int size; int size;
@ -218,8 +216,8 @@ namespace pmx
void PmxMaterial::Read(std::istream *stream, PmxSetting *setting) void PmxMaterial::Read(std::istream *stream, PmxSetting *setting)
{ {
this->material_name = std::move(ReadString(stream, setting->encoding)); this->material_name = ReadString(stream, setting->encoding);
this->material_english_name = std::move(ReadString(stream, setting->encoding)); this->material_english_name = ReadString(stream, setting->encoding);
stream->read((char*) this->diffuse, sizeof(float) * 4); stream->read((char*) this->diffuse, sizeof(float) * 4);
stream->read((char*) this->specular, sizeof(float) * 3); stream->read((char*) this->specular, sizeof(float) * 3);
stream->read((char*) &this->specularlity, sizeof(float)); stream->read((char*) &this->specularlity, sizeof(float));
@ -238,7 +236,7 @@ namespace pmx
else { else {
this->toon_texture_index = ReadIndex(stream, setting->texture_index_size); this->toon_texture_index = ReadIndex(stream, setting->texture_index_size);
} }
this->memo = std::move(ReadString(stream, setting->encoding)); this->memo = ReadString(stream, setting->encoding);
stream->read((char*) &this->index_count, sizeof(int)); stream->read((char*) &this->index_count, sizeof(int));
} }
@ -255,8 +253,8 @@ namespace pmx
void PmxBone::Read(std::istream *stream, PmxSetting *setting) void PmxBone::Read(std::istream *stream, PmxSetting *setting)
{ {
this->bone_name = std::move(ReadString(stream, setting->encoding)); this->bone_name = ReadString(stream, setting->encoding);
this->bone_english_name = std::move(ReadString(stream, setting->encoding)); this->bone_english_name = ReadString(stream, setting->encoding);
stream->read((char*) this->position, sizeof(float) * 3); stream->read((char*) this->position, sizeof(float) * 3);
this->parent_index = ReadIndex(stream, setting->bone_index_size); this->parent_index = ReadIndex(stream, setting->bone_index_size);
stream->read((char*) &this->level, sizeof(int)); stream->read((char*) &this->level, sizeof(int));
@ -530,10 +528,10 @@ namespace pmx
this->setting.Read(stream); this->setting.Read(stream);
// モデル情報 // モデル情報
this->model_name = std::move(ReadString(stream, setting.encoding)); this->model_name = ReadString(stream, setting.encoding);
this->model_english_name = std::move(ReadString(stream, setting.encoding)); this->model_english_name = ReadString(stream, setting.encoding);
this->model_comment = std::move(ReadString(stream, setting.encoding)); this->model_comment = ReadString(stream, setting.encoding);
this->model_english_comment = std::move(ReadString(stream, setting.encoding)); this->model_english_comment = ReadString(stream, setting.encoding);
// 頂点 // 頂点
stream->read((char*) &vertex_count, sizeof(int)); stream->read((char*) &vertex_count, sizeof(int));
@ -607,7 +605,6 @@ namespace pmx
this->joints[i].Read(stream, &setting); this->joints[i].Read(stream, &setting);
} }
//// ソフトボディ
//if (this->version == 2.1f) //if (this->version == 2.1f)
//{ //{
// stream->read((char*) &this->soft_body_count, sizeof(int)); // stream->read((char*) &this->soft_body_count, sizeof(int));

View File

@ -49,7 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace pmx namespace pmx
{ {
/// インデックス設定
class PmxSetting class PmxSetting
{ {
public: public:
@ -64,26 +63,17 @@ namespace pmx
, rigidbody_index_size(0) , rigidbody_index_size(0)
{} {}
/// エンコード方式
uint8_t encoding; uint8_t encoding;
/// 追加UV数
uint8_t uv; uint8_t uv;
/// 頂点インデックスサイズ
uint8_t vertex_index_size; uint8_t vertex_index_size;
/// テクスチャインデックスサイズ
uint8_t texture_index_size; uint8_t texture_index_size;
/// マテリアルインデックスサイズ
uint8_t material_index_size; uint8_t material_index_size;
/// ボーンインデックスサイズ
uint8_t bone_index_size; uint8_t bone_index_size;
/// モーフインデックスサイズ
uint8_t morph_index_size; uint8_t morph_index_size;
/// 剛体インデックスサイズ
uint8_t rigidbody_index_size; uint8_t rigidbody_index_size;
void Read(std::istream *stream); void Read(std::istream *stream);
}; };
/// 頂点スキニングタイプ
enum class PmxVertexSkinningType : uint8_t enum class PmxVertexSkinningType : uint8_t
{ {
BDEF1 = 0, BDEF1 = 0,
@ -93,7 +83,6 @@ namespace pmx
QDEF = 4, QDEF = 4,
}; };
/// 頂点スキニング
class PmxVertexSkinning class PmxVertexSkinning
{ {
public: public:
@ -200,7 +189,6 @@ namespace pmx
void Read(std::istream *stresam, PmxSetting *setting); void Read(std::istream *stresam, PmxSetting *setting);
}; };
/// 頂点
class PmxVertex class PmxVertex
{ {
public: public:
@ -219,24 +207,16 @@ namespace pmx
} }
} }
/// 位置
float position[3]; float position[3];
/// 法線
float normal[3]; float normal[3];
/// テクスチャ座標
float uv[2]; float uv[2];
/// 追加テクスチャ座標
float uva[4][4]; float uva[4][4];
/// スキニングタイプ
PmxVertexSkinningType skinning_type; PmxVertexSkinningType skinning_type;
/// スキニング
std::unique_ptr<PmxVertexSkinning> skinning; std::unique_ptr<PmxVertexSkinning> skinning;
/// エッジ倍率
float edge; float edge;
void Read(std::istream *stream, PmxSetting *setting); void Read(std::istream *stream, PmxSetting *setting);
}; };
/// マテリアル
class PmxMaterial class PmxMaterial
{ {
public: public:
@ -261,42 +241,25 @@ namespace pmx
} }
} }
/// モデル名
std::string material_name; std::string material_name;
/// モデル英名
std::string material_english_name; std::string material_english_name;
/// 減衰色
float diffuse[4]; float diffuse[4];
/// 光沢色
float specular[3]; float specular[3];
/// 光沢度
float specularlity; float specularlity;
/// 環境色
float ambient[3]; float ambient[3];
/// 描画フラグ
uint8_t flag; uint8_t flag;
/// エッジ色
float edge_color[4]; float edge_color[4];
/// エッジサイズ
float edge_size; float edge_size;
/// アルベドテクスチャインデックス
int diffuse_texture_index; int diffuse_texture_index;
/// スフィアテクスチャインデックス
int sphere_texture_index; int sphere_texture_index;
/// スフィアテクスチャ演算モード
uint8_t sphere_op_mode; uint8_t sphere_op_mode;
/// 共有トゥーンフラグ
uint8_t common_toon_flag; uint8_t common_toon_flag;
/// トゥーンテクスチャインデックス
int toon_texture_index; int toon_texture_index;
/// メモ
std::string memo; std::string memo;
/// 頂点インデックス数
int index_count; int index_count;
void Read(std::istream *stream, PmxSetting *setting); void Read(std::istream *stream, PmxSetting *setting);
}; };
/// リンク
class PmxIkLink class PmxIkLink
{ {
public: public:
@ -310,18 +273,13 @@ namespace pmx
} }
} }
/// リンクボーンインデックス
int link_target; int link_target;
/// 角度制限
uint8_t angle_lock; uint8_t angle_lock;
/// 最大制限角度
float max_radian[3]; float max_radian[3];
/// 最小制限角度
float min_radian[3]; float min_radian[3];
void Read(std::istream *stream, PmxSetting *settingn); void Read(std::istream *stream, PmxSetting *settingn);
}; };
/// ボーン
class PmxBone class PmxBone
{ {
public: public:
@ -347,43 +305,24 @@ namespace pmx
} }
} }
/// ボーン名
std::string bone_name; std::string bone_name;
/// ボーン英名
std::string bone_english_name; std::string bone_english_name;
/// 位置
float position[3]; float position[3];
/// 親ボーンインデックス
int parent_index; int parent_index;
/// 階層
int level; int level;
/// ボーンフラグ
uint16_t bone_flag; uint16_t bone_flag;
/// 座標オフセット(has Target)
float offset[3]; float offset[3];
/// 接続先ボーンインデックス(not has Target)
int target_index; int target_index;
/// 付与親ボーンインデックス
int grant_parent_index; int grant_parent_index;
/// 付与率
float grant_weight; float grant_weight;
/// 固定軸の方向
float lock_axis_orientation[3]; float lock_axis_orientation[3];
/// ローカル軸のX軸方向
float local_axis_x_orientation[3]; float local_axis_x_orientation[3];
/// ローカル軸のY軸方向
float local_axis_y_orientation[3]; float local_axis_y_orientation[3];
/// 外部親変形のkey値
int key; int key;
/// IKターゲットボーン
int ik_target_bone_index; int ik_target_bone_index;
/// IKループ回数
int ik_loop; int ik_loop;
/// IKループ計算時の角度制限(ラジアン)
float ik_loop_angle_limit; float ik_loop_angle_limit;
/// IKリンク数
int ik_link_count; int ik_link_count;
/// IKリンク
std::unique_ptr<PmxIkLink []> ik_links; std::unique_ptr<PmxIkLink []> ik_links;
void Read(std::istream *stream, PmxSetting *setting); void Read(std::istream *stream, PmxSetting *setting);
}; };
@ -543,7 +482,6 @@ namespace pmx
void Read(std::istream *stream, PmxSetting *setting); //override; void Read(std::istream *stream, PmxSetting *setting); //override;
}; };
/// モーフ
class PmxMorph class PmxMorph
{ {
public: public:
@ -551,34 +489,21 @@ namespace pmx
: offset_count(0) : offset_count(0)
{ {
} }
/// モーフ名
std::string morph_name; std::string morph_name;
/// モーフ英名
std::string morph_english_name; std::string morph_english_name;
/// カテゴリ
MorphCategory category; MorphCategory category;
/// モーフタイプ
MorphType morph_type; MorphType morph_type;
/// オフセット数
int offset_count; int offset_count;
/// 頂点モーフ配列
std::unique_ptr<PmxMorphVertexOffset []> vertex_offsets; std::unique_ptr<PmxMorphVertexOffset []> vertex_offsets;
/// UVモーフ配列
std::unique_ptr<PmxMorphUVOffset []> uv_offsets; std::unique_ptr<PmxMorphUVOffset []> uv_offsets;
/// ボーンモーフ配列
std::unique_ptr<PmxMorphBoneOffset []> bone_offsets; std::unique_ptr<PmxMorphBoneOffset []> bone_offsets;
/// マテリアルモーフ配列
std::unique_ptr<PmxMorphMaterialOffset []> material_offsets; std::unique_ptr<PmxMorphMaterialOffset []> material_offsets;
/// グループモーフ配列
std::unique_ptr<PmxMorphGroupOffset []> group_offsets; std::unique_ptr<PmxMorphGroupOffset []> group_offsets;
/// フリップモーフ配列
std::unique_ptr<PmxMorphFlipOffset []> flip_offsets; std::unique_ptr<PmxMorphFlipOffset []> flip_offsets;
/// インパルスモーフ配列
std::unique_ptr<PmxMorphImplusOffset []> implus_offsets; std::unique_ptr<PmxMorphImplusOffset []> implus_offsets;
void Read(std::istream *stream, PmxSetting *setting); void Read(std::istream *stream, PmxSetting *setting);
}; };
/// 枠内要素
class PmxFrameElement class PmxFrameElement
{ {
public: public:
@ -587,14 +512,11 @@ namespace pmx
, index(0) , index(0)
{ {
} }
/// 要素対象
uint8_t element_target; uint8_t element_target;
/// 要素対象インデックス
int index; int index;
void Read(std::istream *stream, PmxSetting *setting); void Read(std::istream *stream, PmxSetting *setting);
}; };
/// 表示枠
class PmxFrame class PmxFrame
{ {
public: public:
@ -603,15 +525,10 @@ namespace pmx
, element_count(0) , element_count(0)
{ {
} }
/// 枠名
std::string frame_name; std::string frame_name;
/// 枠英名
std::string frame_english_name; std::string frame_english_name;
/// 特殊枠フラグ
uint8_t frame_flag; uint8_t frame_flag;
/// 枠内要素数
int element_count; int element_count;
/// 枠内要素配列
std::unique_ptr<PmxFrameElement []> elements; std::unique_ptr<PmxFrameElement []> elements;
void Read(std::istream *stream, PmxSetting *setting); void Read(std::istream *stream, PmxSetting *setting);
}; };
@ -637,17 +554,11 @@ namespace pmx
orientation[i] = 0.0f; orientation[i] = 0.0f;
} }
} }
/// 剛体名
std::string girid_body_name; std::string girid_body_name;
/// 剛体英名
std::string girid_body_english_name; std::string girid_body_english_name;
/// 関連ボーンインデックス
int target_bone; int target_bone;
/// グループ
uint8_t group; uint8_t group;
/// マスク
uint16_t mask; uint16_t mask;
/// 形状
uint8_t shape; uint8_t shape;
float size[3]; float size[3];
float position[3]; float position[3];
@ -818,7 +729,6 @@ namespace pmx
void Read(std::istream *stream, PmxSetting *setting); void Read(std::istream *stream, PmxSetting *setting);
}; };
/// PMXモデル
class PmxModel class PmxModel
{ {
public: public:
@ -836,65 +746,35 @@ namespace pmx
, soft_body_count(0) , soft_body_count(0)
{} {}
/// バージョン
float version; float version;
/// 設定
PmxSetting setting; PmxSetting setting;
/// モデル名
std::string model_name; std::string model_name;
/// モデル英名
std::string model_english_name; std::string model_english_name;
/// コメント
std::string model_comment; std::string model_comment;
/// 英語コメント
std::string model_english_comment; std::string model_english_comment;
/// 頂点数
int vertex_count; int vertex_count;
/// 頂点配列
std::unique_ptr<PmxVertex []> vertices; std::unique_ptr<PmxVertex []> vertices;
/// インデックス数
int index_count; int index_count;
/// インデックス配列
std::unique_ptr<int []> indices; std::unique_ptr<int []> indices;
/// テクスチャ数
int texture_count; int texture_count;
/// テクスチャ配列
std::unique_ptr< std::string []> textures; std::unique_ptr< std::string []> textures;
/// マテリアル数
int material_count; int material_count;
/// マテリアル
std::unique_ptr<PmxMaterial []> materials; std::unique_ptr<PmxMaterial []> materials;
/// ボーン数
int bone_count; int bone_count;
/// ボーン配列
std::unique_ptr<PmxBone []> bones; std::unique_ptr<PmxBone []> bones;
/// モーフ数
int morph_count; int morph_count;
/// モーフ配列
std::unique_ptr<PmxMorph []> morphs; std::unique_ptr<PmxMorph []> morphs;
/// 表示枠数
int frame_count; int frame_count;
/// 表示枠配列
std::unique_ptr<PmxFrame [] > frames; std::unique_ptr<PmxFrame [] > frames;
/// 剛体数
int rigid_body_count; int rigid_body_count;
/// 剛体配列
std::unique_ptr<PmxRigidBody []> rigid_bodies; std::unique_ptr<PmxRigidBody []> rigid_bodies;
/// ジョイント数
int joint_count; int joint_count;
/// ジョイント配列
std::unique_ptr<PmxJoint []> joints; std::unique_ptr<PmxJoint []> joints;
/// ソフトボディ数
int soft_body_count; int soft_body_count;
/// ソフトボディ配列
std::unique_ptr<PmxSoftBody []> soft_bodies; std::unique_ptr<PmxSoftBody []> soft_bodies;
/// モデル初期化
void Init(); void Init();
/// モデル読み込み
void Read(std::istream *stream); void Read(std::istream *stream);
///// ファイルからモデルの読み込み
//static std::unique_ptr<PmxModel> ReadFromFile(const char *filename); //static std::unique_ptr<PmxModel> ReadFromFile(const char *filename);
///// 入力ストリームからモデルの読み込み
//static std::unique_ptr<PmxModel> ReadFromStream(std::istream *stream); //static std::unique_ptr<PmxModel> ReadFromStream(std::istream *stream);
}; };
} }

View File

@ -50,19 +50,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace vmd namespace vmd
{ {
/// ボーンフレーム
class VmdBoneFrame class VmdBoneFrame
{ {
public: public:
/// ボーン名
std::string name; std::string name;
/// フレーム番号
int frame; int frame;
/// 位置
float position[3]; float position[3];
/// 回転
float orientation[4]; float orientation[4];
/// 補間曲線
char interpolation[4][4][4]; char interpolation[4][4][4];
void Read(std::istream* stream) void Read(std::istream* stream)
@ -86,15 +80,11 @@ namespace vmd
} }
}; };
/// 表情フレーム
class VmdFaceFrame class VmdFaceFrame
{ {
public: public:
/// 表情名
std::string face_name; std::string face_name;
/// 表情の重み
float weight; float weight;
/// フレーム番号
uint32_t frame; uint32_t frame;
void Read(std::istream* stream) void Read(std::istream* stream)
@ -114,23 +104,15 @@ namespace vmd
} }
}; };
/// カメラフレーム
class VmdCameraFrame class VmdCameraFrame
{ {
public: public:
/// フレーム番号
int frame; int frame;
/// 距離
float distance; float distance;
/// 位置
float position[3]; float position[3];
/// 回転
float orientation[3]; float orientation[3];
/// 補間曲線
char interpolation[6][4]; char interpolation[6][4];
/// 視野角
float angle; float angle;
/// 不明データ
char unknown[3]; char unknown[3];
void Read(std::istream *stream) void Read(std::istream *stream)
@ -156,15 +138,11 @@ namespace vmd
} }
}; };
/// ライトフレーム
class VmdLightFrame class VmdLightFrame
{ {
public: public:
/// フレーム番号
int frame; int frame;
/// 色
float color[3]; float color[3];
/// 位置
float position[3]; float position[3];
void Read(std::istream* stream) void Read(std::istream* stream)
@ -182,7 +160,6 @@ namespace vmd
} }
}; };
/// IKの有効無効
class VmdIkEnable class VmdIkEnable
{ {
public: public:
@ -190,7 +167,6 @@ namespace vmd
bool enable; bool enable;
}; };
/// IKフレーム
class VmdIkFrame class VmdIkFrame
{ {
public: public:
@ -229,23 +205,15 @@ namespace vmd
} }
}; };
/// VMDモーション
class VmdMotion class VmdMotion
{ {
public: public:
/// モデル名
std::string model_name; std::string model_name;
/// バージョン
int version; int version;
/// ボーンフレーム
std::vector<VmdBoneFrame> bone_frames; std::vector<VmdBoneFrame> bone_frames;
/// 表情フレーム
std::vector<VmdFaceFrame> face_frames; std::vector<VmdFaceFrame> face_frames;
/// カメラフレーム
std::vector<VmdCameraFrame> camera_frames; std::vector<VmdCameraFrame> camera_frames;
/// ライトフレーム
std::vector<VmdLightFrame> light_frames; std::vector<VmdLightFrame> light_frames;
/// IKフレーム
std::vector<VmdIkFrame> ik_frames; std::vector<VmdIkFrame> ik_frames;
static std::unique_ptr<VmdMotion> LoadFromFile(char const *filename) static std::unique_ptr<VmdMotion> LoadFromFile(char const *filename)

View File

@ -193,14 +193,14 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
p = 0; p = 0;
while (pcMesh->HasTextureCoords(p)) while (pcMesh->HasTextureCoords(p))
{ {
delete pcMesh->mTextureCoords[p]; delete[] pcMesh->mTextureCoords[p];
pcMesh->mTextureCoords[p] = apvTextureCoords[p]; pcMesh->mTextureCoords[p] = apvTextureCoords[p];
++p; ++p;
} }
p = 0; p = 0;
while (pcMesh->HasVertexColors(p)) while (pcMesh->HasVertexColors(p))
{ {
delete pcMesh->mColors[p]; delete[] pcMesh->mColors[p];
pcMesh->mColors[p] = apvColorSets[p]; pcMesh->mColors[p] = apvColorSets[p];
++p; ++p;
} }

View File

@ -94,7 +94,7 @@ bool OFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
{ {
if (!pIOHandler)return true; if (!pIOHandler)return true;
const char* tokens[] = {"off"}; const char* tokens[] = {"off"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1,3);
} }
return false; return false;
} }

View File

@ -91,11 +91,11 @@ ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene)
, vn() , vn()
, vt() , vt()
, vc() , vc()
, vpMap() , mVpMap()
, vnMap() , mVnMap()
, vtMap() , mVtMap()
, vcMap() , mVcMap()
, meshes() , mMeshes()
, endl("\n") { , endl("\n") {
// 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
const std::locale& l = std::locale("C"); const std::locale& l = std::locale("C");
@ -137,15 +137,21 @@ std::string ObjExporter::GetMaterialLibFileName() {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ObjExporter :: WriteHeader(std::ostringstream& out) { void ObjExporter::WriteHeader(std::ostringstream& out) {
out << "# File produced by Open Asset Import Library (http://www.assimp.sf.net)" << endl; out << "# File produced by Open Asset Import Library (http://www.assimp.sf.net)" << endl;
out << "# (assimp v" << aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.' << aiGetVersionRevision() << ")" << endl << endl; out << "# (assimp v" << aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.'
<< aiGetVersionRevision() << ")" << endl << endl;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::string ObjExporter :: GetMaterialName(unsigned int index) std::string ObjExporter::GetMaterialName(unsigned int index)
{ {
const aiMaterial* const mat = pScene->mMaterials[index]; const aiMaterial* const mat = pScene->mMaterials[index];
if ( nullptr == mat ) {
static const std::string EmptyStr;
return EmptyStr;
}
aiString s; aiString s;
if(AI_SUCCESS == mat->Get(AI_MATKEY_NAME,s)) { if(AI_SUCCESS == mat->Get(AI_MATKEY_NAME,s)) {
return std::string(s.data,s.length); return std::string(s.data,s.length);
@ -235,8 +241,8 @@ void ObjExporter::WriteGeometryFile() {
AddNode(pScene->mRootNode, mBase); AddNode(pScene->mRootNode, mBase);
// write vertex positions with colors, if any // write vertex positions with colors, if any
vpMap.getVectors( vp ); mVpMap.getVectors( vp );
vcMap.getColors( vc ); mVcMap.getColors( vc );
if ( vc.empty() ) { if ( vc.empty() ) {
mOutput << "# " << vp.size() << " vertex positions" << endl; mOutput << "# " << vp.size() << " vertex positions" << endl;
for ( const aiVector3D& v : vp ) { for ( const aiVector3D& v : vp ) {
@ -253,7 +259,7 @@ void ObjExporter::WriteGeometryFile() {
mOutput << endl; mOutput << endl;
// write uv coordinates // write uv coordinates
vtMap.getVectors(vt); mVtMap.getVectors(vt);
mOutput << "# " << vt.size() << " UV coordinates" << endl; mOutput << "# " << vt.size() << " UV coordinates" << endl;
for(const aiVector3D& v : vt) { for(const aiVector3D& v : vt) {
mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl; mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl;
@ -261,7 +267,7 @@ void ObjExporter::WriteGeometryFile() {
mOutput << endl; mOutput << endl;
// write vertex normals // write vertex normals
vnMap.getVectors(vn); mVnMap.getVectors(vn);
mOutput << "# " << vn.size() << " vertex normals" << endl; mOutput << "# " << vn.size() << " vertex normals" << endl;
for(const aiVector3D& v : vn) { for(const aiVector3D& v : vn) {
mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl; mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl;
@ -269,7 +275,7 @@ void ObjExporter::WriteGeometryFile() {
mOutput << endl; mOutput << endl;
// now write all mesh instances // now write all mesh instances
for(const MeshInstance& m : meshes) { for(const MeshInstance& m : mMeshes) {
mOutput << "# Mesh \'" << m.name << "\' with " << m.faces.size() << " faces" << endl; mOutput << "# Mesh \'" << m.name << "\' with " << m.faces.size() << " faces" << endl;
if (!m.name.empty()) { if (!m.name.empty()) {
mOutput << "g " << m.name << endl; mOutput << "g " << m.name << endl;
@ -345,8 +351,8 @@ void ObjExporter::colIndexMap::getColors( std::vector<aiColor4D> &colors ) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) { void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) {
meshes.push_back(MeshInstance()); mMeshes.push_back(MeshInstance());
MeshInstance& mesh = meshes.back(); MeshInstance& mesh = mMeshes.back();
mesh.name = std::string(name.data,name.length) + (m->mName.length ? "_" + std::string(m->mName.data,m->mName.length) : ""); mesh.name = std::string(name.data,name.length) + (m->mName.length ? "_" + std::string(m->mName.data,m->mName.length) : "");
mesh.matname = GetMaterialName(m->mMaterialIndex); mesh.matname = GetMaterialName(m->mMaterialIndex);
@ -373,24 +379,24 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4
const unsigned int idx = f.mIndices[a]; const unsigned int idx = f.mIndices[a];
aiVector3D vert = mat * m->mVertices[idx]; aiVector3D vert = mat * m->mVertices[idx];
face.indices[a].vp = vpMap.getIndex(vert); face.indices[a].vp = mVpMap.getIndex(vert);
if (m->mNormals) { if (m->mNormals) {
aiVector3D norm = aiMatrix3x3(mat) * m->mNormals[idx]; aiVector3D norm = aiMatrix3x3(mat) * m->mNormals[idx];
face.indices[a].vn = vnMap.getIndex(norm); face.indices[a].vn = mVnMap.getIndex(norm);
} else { } else {
face.indices[a].vn = 0; face.indices[a].vn = 0;
} }
if ( nullptr != m->mColors[ 0 ] ) { if ( nullptr != m->mColors[ 0 ] ) {
aiColor4D col4 = m->mColors[ 0 ][ idx ]; aiColor4D col4 = m->mColors[ 0 ][ idx ];
face.indices[ a ].vc = vcMap.getIndex( col4 ); face.indices[ a ].vc = mVcMap.getIndex( col4 );
} else { } else {
face.indices[ a ].vc = 0; face.indices[ a ].vc = 0;
} }
if ( m->mTextureCoords[ 0 ] ) { if ( m->mTextureCoords[ 0 ] ) {
face.indices[a].vt = vtMap.getIndex(m->mTextureCoords[0][idx]); face.indices[a].vt = mVtMap.getIndex(m->mTextureCoords[0][idx]);
} else { } else {
face.indices[a].vt = 0; face.indices[a].vt = 0;
} }

View File

@ -163,9 +163,9 @@ private:
void getColors( std::vector<aiColor4D> &colors ); void getColors( std::vector<aiColor4D> &colors );
}; };
vecIndexMap vpMap, vnMap, vtMap; vecIndexMap mVpMap, mVnMap, mVtMap;
colIndexMap vcMap; colIndexMap mVcMap;
std::vector<MeshInstance> meshes; std::vector<MeshInstance> mMeshes;
// this endl() doesn't flush() the stream // this endl() doesn't flush() the stream
const std::string endl; const std::string endl;

View File

@ -55,19 +55,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
// Material specific token // Material specific token (case insensitive compare)
static const std::string DiffuseTexture = "map_Kd"; static const std::string DiffuseTexture = "map_Kd";
static const std::string AmbientTexture = "map_Ka"; static const std::string AmbientTexture = "map_Ka";
static const std::string SpecularTexture = "map_Ks"; static const std::string SpecularTexture = "map_Ks";
static const std::string OpacityTexture = "map_d"; static const std::string OpacityTexture = "map_d";
static const std::string EmissiveTexture = "map_emissive"; static const std::string EmissiveTexture1 = "map_emissive";
static const std::string EmissiveTexture_1 = "map_Ke"; static const std::string EmissiveTexture2 = "map_Ke";
static const std::string BumpTexture1 = "map_bump"; static const std::string BumpTexture1 = "map_bump";
static const std::string BumpTexture2 = "map_Bump"; static const std::string BumpTexture2 = "bump";
static const std::string BumpTexture3 = "bump";
static const std::string NormalTexture = "map_Kn"; static const std::string NormalTexture = "map_Kn";
static const std::string ReflectionTexture = "refl"; static const std::string ReflectionTexture = "refl";
static const std::string DisplacementTexture = "disp"; static const std::string DisplacementTexture1 = "map_disp";
static const std::string DisplacementTexture2 = "disp";
static const std::string SpecularityTexture = "map_ns"; static const std::string SpecularityTexture = "map_ns";
// texture option specific token // texture option specific token
@ -304,7 +304,7 @@ void ObjFileMtlImporter::createMaterial()
m_pModel->m_pCurrentMaterial = new ObjFile::Material(); m_pModel->m_pCurrentMaterial = new ObjFile::Material();
m_pModel->m_pCurrentMaterial->MaterialName.Set( name ); m_pModel->m_pCurrentMaterial->MaterialName.Set( name );
if (m_pModel->m_pCurrentMesh) { if (m_pModel->m_pCurrentMesh) {
m_pModel->m_pCurrentMesh->m_uiMaterialIndex = m_pModel->m_MaterialLib.size() - 1; m_pModel->m_pCurrentMesh->m_uiMaterialIndex = static_cast<unsigned int>(m_pModel->m_MaterialLib.size() - 1);
} }
m_pModel->m_MaterialLib.push_back( name ); m_pModel->m_MaterialLib.push_back( name );
m_pModel->m_MaterialMap[ name ] = m_pModel->m_pCurrentMaterial; m_pModel->m_MaterialMap[ name ] = m_pModel->m_pCurrentMaterial;
@ -329,7 +329,7 @@ void ObjFileMtlImporter::getTexture() {
// Ambient texture // Ambient texture
out = & m_pModel->m_pCurrentMaterial->textureAmbient; out = & m_pModel->m_pCurrentMaterial->textureAmbient;
clampIndex = ObjFile::Material::TextureAmbientType; clampIndex = ObjFile::Material::TextureAmbientType;
} else if (!ASSIMP_strincmp( pPtr, SpecularTexture.c_str(), static_cast<unsigned int>(SpecularTexture.size()) ) ) { } else if ( !ASSIMP_strincmp( pPtr, SpecularTexture.c_str(), static_cast<unsigned int>(SpecularTexture.size()) ) ) {
// Specular texture // Specular texture
out = & m_pModel->m_pCurrentMaterial->textureSpecular; out = & m_pModel->m_pCurrentMaterial->textureSpecular;
clampIndex = ObjFile::Material::TextureSpecularType; clampIndex = ObjFile::Material::TextureSpecularType;
@ -337,33 +337,30 @@ void ObjFileMtlImporter::getTexture() {
// Opacity texture // Opacity texture
out = & m_pModel->m_pCurrentMaterial->textureOpacity; out = & m_pModel->m_pCurrentMaterial->textureOpacity;
clampIndex = ObjFile::Material::TextureOpacityType; clampIndex = ObjFile::Material::TextureOpacityType;
} else if (!ASSIMP_strincmp( pPtr, EmissiveTexture.c_str(), static_cast<unsigned int>(EmissiveTexture.size()) ) ) { } else if ( !ASSIMP_strincmp( pPtr, EmissiveTexture1.c_str(), static_cast<unsigned int>(EmissiveTexture1.size()) ) ||
!ASSIMP_strincmp( pPtr, EmissiveTexture2.c_str(), static_cast<unsigned int>(EmissiveTexture2.size()) ) ) {
// Emissive texture // Emissive texture
out = & m_pModel->m_pCurrentMaterial->textureEmissive; out = & m_pModel->m_pCurrentMaterial->textureEmissive;
clampIndex = ObjFile::Material::TextureEmissiveType; clampIndex = ObjFile::Material::TextureEmissiveType;
} else if ( !ASSIMP_strincmp( pPtr, EmissiveTexture_1.c_str(), static_cast<unsigned int>(EmissiveTexture_1.size()) ) ) {
// Emissive texture
out = &m_pModel->m_pCurrentMaterial->textureEmissive;
clampIndex = ObjFile::Material::TextureEmissiveType;
} else if ( !ASSIMP_strincmp( pPtr, BumpTexture1.c_str(), static_cast<unsigned int>(BumpTexture1.size()) ) || } else if ( !ASSIMP_strincmp( pPtr, BumpTexture1.c_str(), static_cast<unsigned int>(BumpTexture1.size()) ) ||
!ASSIMP_strincmp( pPtr, BumpTexture2.c_str(), static_cast<unsigned int>(BumpTexture2.size()) ) || !ASSIMP_strincmp( pPtr, BumpTexture2.c_str(), static_cast<unsigned int>(BumpTexture2.size()) ) ) {
!ASSIMP_strincmp( pPtr, BumpTexture3.c_str(), static_cast<unsigned int>(BumpTexture3.size()) ) ) {
// Bump texture // Bump texture
out = & m_pModel->m_pCurrentMaterial->textureBump; out = & m_pModel->m_pCurrentMaterial->textureBump;
clampIndex = ObjFile::Material::TextureBumpType; clampIndex = ObjFile::Material::TextureBumpType;
} else if (!ASSIMP_strincmp( pPtr,NormalTexture.c_str(), static_cast<unsigned int>(NormalTexture.size()) ) ) { } else if ( !ASSIMP_strincmp( pPtr,NormalTexture.c_str(), static_cast<unsigned int>(NormalTexture.size()) ) ) {
// Normal map // Normal map
out = & m_pModel->m_pCurrentMaterial->textureNormal; out = & m_pModel->m_pCurrentMaterial->textureNormal;
clampIndex = ObjFile::Material::TextureNormalType; clampIndex = ObjFile::Material::TextureNormalType;
} else if(!ASSIMP_strincmp( pPtr, ReflectionTexture.c_str(), static_cast<unsigned int>(ReflectionTexture.size()) ) ) { } else if( !ASSIMP_strincmp( pPtr, ReflectionTexture.c_str(), static_cast<unsigned int>(ReflectionTexture.size()) ) ) {
// Reflection texture(s) // Reflection texture(s)
//Do nothing here //Do nothing here
return; return;
} else if (!ASSIMP_strincmp( pPtr, DisplacementTexture.c_str(), static_cast<unsigned int>(DisplacementTexture.size()) ) ) { } else if ( !ASSIMP_strincmp( pPtr, DisplacementTexture1.c_str(), static_cast<unsigned int>(DisplacementTexture1.size()) ) ||
!ASSIMP_strincmp( pPtr, DisplacementTexture2.c_str(), static_cast<unsigned int>(DisplacementTexture2.size()) ) ) {
// Displacement texture // Displacement texture
out = &m_pModel->m_pCurrentMaterial->textureDisp; out = &m_pModel->m_pCurrentMaterial->textureDisp;
clampIndex = ObjFile::Material::TextureDispType; clampIndex = ObjFile::Material::TextureDispType;
} else if (!ASSIMP_strincmp( pPtr, SpecularityTexture.c_str(), static_cast<unsigned int>(SpecularityTexture.size()) ) ) { } else if ( !ASSIMP_strincmp( pPtr, SpecularityTexture.c_str(), static_cast<unsigned int>(SpecularityTexture.size()) ) ) {
// Specularity scaling (glossiness) // Specularity scaling (glossiness)
out = & m_pModel->m_pCurrentMaterial->textureSpecularity; out = & m_pModel->m_pCurrentMaterial->textureSpecularity;
clampIndex = ObjFile::Material::TextureSpecularityType; clampIndex = ObjFile::Material::TextureSpecularityType;

View File

@ -359,8 +359,6 @@ void ObjFileParser::getHomogeneousVector3( std::vector<aiVector3D> &point3d_arra
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
} }
// -------------------------------------------------------------------
// Get values for two 3D vectors on the same line
void ObjFileParser::getTwoVectors3( std::vector<aiVector3D> &point3d_array_a, std::vector<aiVector3D> &point3d_array_b ) { void ObjFileParser::getTwoVectors3( std::vector<aiVector3D> &point3d_array_a, std::vector<aiVector3D> &point3d_array_b ) {
ai_real x, y, z; ai_real x, y, z;
copyNextWord(m_buffer, Buffersize); copyNextWord(m_buffer, Buffersize);
@ -388,8 +386,6 @@ void ObjFileParser::getTwoVectors3( std::vector<aiVector3D> &point3d_array_a, st
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
} }
// -------------------------------------------------------------------
// Get values for a new 2D vector instance
void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) { void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) {
ai_real x, y; ai_real x, y;
copyNextWord(m_buffer, Buffersize); copyNextWord(m_buffer, Buffersize);
@ -405,8 +401,6 @@ void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) {
static const std::string DefaultObjName = "defaultobject"; static const std::string DefaultObjName = "defaultobject";
// -------------------------------------------------------------------
// Get values for a new face instance
void ObjFileParser::getFace( aiPrimitiveType type ) { void ObjFileParser::getFace( aiPrimitiveType type ) {
m_DataIt = getNextToken<DataArrayIt>( m_DataIt, m_DataItEnd ); m_DataIt = getNextToken<DataArrayIt>( m_DataIt, m_DataItEnd );
if ( m_DataIt == m_DataItEnd || *m_DataIt == '\0' ) { if ( m_DataIt == m_DataItEnd || *m_DataIt == '\0' ) {
@ -522,8 +516,6 @@ void ObjFileParser::getFace( aiPrimitiveType type ) {
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
} }
// -------------------------------------------------------------------
// Get values for a new material description
void ObjFileParser::getMaterialDesc() { void ObjFileParser::getMaterialDesc() {
// Get next data for material data // Get next data for material data
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
@ -555,10 +547,15 @@ void ObjFileParser::getMaterialDesc() {
// Search for material // Search for material
std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find(strName); std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find(strName);
if (it == m_pModel->m_MaterialMap.end()) { if (it == m_pModel->m_MaterialMap.end()) {
// Not found, use default material // Not found, so we don't know anything about the material except for its name.
m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial; // This may be the case if the material library is missing. We don't want to lose all
DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", skipping"); // materials if that happens, so create a new named material instead of discarding it
strName = m_pModel->m_pDefaultMaterial->MaterialName.C_Str(); // completely.
DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", creating new material");
m_pModel->m_pCurrentMaterial = new ObjFile::Material();
m_pModel->m_pCurrentMaterial->MaterialName.Set(strName);
m_pModel->m_MaterialLib.push_back(strName);
m_pModel->m_MaterialMap[strName] = m_pModel->m_pCurrentMaterial;
} else { } else {
// Found, using detected material // Found, using detected material
m_pModel->m_pCurrentMaterial = (*it).second; m_pModel->m_pCurrentMaterial = (*it).second;

View File

@ -261,6 +261,7 @@ OpenGEXImporter::OpenGEXImporter()
, m_nodeChildMap() , m_nodeChildMap()
, m_meshCache() , m_meshCache()
, m_mesh2refMap() , m_mesh2refMap()
, m_material2refMap()
, m_ctx( nullptr ) , m_ctx( nullptr )
, m_metrics() , m_metrics()
, m_currentNode( nullptr ) , m_currentNode( nullptr )
@ -306,6 +307,7 @@ void OpenGEXImporter::InternReadFile( const std::string &filename, aiScene *pSce
std::vector<char> buffer; std::vector<char> buffer;
TextFileToBuffer( file, buffer ); TextFileToBuffer( file, buffer );
pIOHandler->Close( file );
OpenDDLParser myParser; OpenDDLParser myParser;
myParser.setBuffer( &buffer[ 0 ], buffer.size() ); myParser.setBuffer( &buffer[ 0 ], buffer.size() );
@ -320,6 +322,7 @@ void OpenGEXImporter::InternReadFile( const std::string &filename, aiScene *pSce
copyMeshes( pScene ); copyMeshes( pScene );
copyCameras( pScene ); copyCameras( pScene );
copyLights( pScene ); copyLights( pScene );
copyMaterials( pScene );
resolveReferences(); resolveReferences();
createNodeTree( pScene ); createNodeTree( pScene );
} }
@ -482,7 +485,10 @@ void OpenGEXImporter::handleNameNode( DDLNode *node, aiScene *pScene ) {
|| m_tokenType == Grammar::CameraNodeToken ) { || m_tokenType == Grammar::CameraNodeToken ) {
m_currentNode->mName.Set( name.c_str() ); m_currentNode->mName.Set( name.c_str() );
} else if( m_tokenType == Grammar::MaterialToken ) { } else if( m_tokenType == Grammar::MaterialToken ) {
aiString aiName;
aiName.Set( name );
m_currentMaterial->AddProperty( &aiName, AI_MATKEY_NAME );
m_material2refMap[ name ] = m_materialCache.size() - 1;
} }
} }
} }
@ -520,7 +526,7 @@ void OpenGEXImporter::handleObjectRefNode( DDLNode *node, aiScene *pScene ) {
m_currentNode->mNumMeshes = static_cast<unsigned int>(objRefNames.size()); m_currentNode->mNumMeshes = static_cast<unsigned int>(objRefNames.size());
m_currentNode->mMeshes = new unsigned int[ objRefNames.size() ]; m_currentNode->mMeshes = new unsigned int[ objRefNames.size() ];
if ( !objRefNames.empty() ) { if ( !objRefNames.empty() ) {
m_unresolvedRefStack.push_back( new RefInfo( m_currentNode, RefInfo::MeshRef, objRefNames ) ); m_unresolvedRefStack.push_back( std::unique_ptr<RefInfo>( new RefInfo( m_currentNode, RefInfo::MeshRef, objRefNames ) ) );
} }
} else if ( m_tokenType == Grammar::LightNodeToken ) { } else if ( m_tokenType == Grammar::LightNodeToken ) {
// TODO! // TODO!
@ -539,7 +545,7 @@ void OpenGEXImporter::handleMaterialRefNode( ODDLParser::DDLNode *node, aiScene
std::vector<std::string> matRefNames; std::vector<std::string> matRefNames;
getRefNames( node, matRefNames ); getRefNames( node, matRefNames );
if( !matRefNames.empty() ) { if( !matRefNames.empty() ) {
m_unresolvedRefStack.push_back( new RefInfo( m_currentNode, RefInfo::MaterialRef, matRefNames ) ); m_unresolvedRefStack.push_back( std::unique_ptr<RefInfo>( new RefInfo( m_currentNode, RefInfo::MaterialRef, matRefNames ) ) );
} }
} }
@ -1050,7 +1056,6 @@ void OpenGEXImporter::handleTextureNode( ODDLParser::DDLNode *node, aiScene *pSc
m_currentMaterial->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) ); m_currentMaterial->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) );
} else if( prop->m_value->getString() == Grammar::SpecularPowerTextureToken ) { } else if( prop->m_value->getString() == Grammar::SpecularPowerTextureToken ) {
m_currentMaterial->AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR( 0 ) ); m_currentMaterial->AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR( 0 ) );
} else if( prop->m_value->getString() == Grammar::EmissionTextureToken ) { } else if( prop->m_value->getString() == Grammar::EmissionTextureToken ) {
m_currentMaterial->AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE( 0 ) ); m_currentMaterial->AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE( 0 ) );
} else if( prop->m_value->getString() == Grammar::OpacyTextureToken ) { } else if( prop->m_value->getString() == Grammar::OpacyTextureToken ) {
@ -1154,6 +1159,19 @@ void OpenGEXImporter::copyLights( aiScene *pScene ) {
std::copy( m_lightCache.begin(), m_lightCache.end(), pScene->mLights ); std::copy( m_lightCache.begin(), m_lightCache.end(), pScene->mLights );
} }
//------------------------------------------------------------------------------------------------
void OpenGEXImporter::copyMaterials( aiScene *pScene ) {
ai_assert( nullptr != pScene );
if ( m_materialCache.empty() ) {
return;
}
pScene->mNumMaterials = static_cast<unsigned int>(m_materialCache.size());
pScene->mMaterials = new aiMaterial*[ pScene->mNumMaterials ];
std::copy( m_materialCache.begin(), m_materialCache.end(), pScene->mMaterials );
}
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
void OpenGEXImporter::resolveReferences() { void OpenGEXImporter::resolveReferences() {
if( m_unresolvedRefStack.empty() ) { if( m_unresolvedRefStack.empty() ) {
@ -1161,12 +1179,12 @@ void OpenGEXImporter::resolveReferences() {
} }
RefInfo *currentRefInfo( nullptr ); RefInfo *currentRefInfo( nullptr );
for( std::vector<RefInfo*>::iterator it = m_unresolvedRefStack.begin(); it != m_unresolvedRefStack.end(); ++it ) { for( auto it = m_unresolvedRefStack.begin(); it != m_unresolvedRefStack.end(); ++it ) {
currentRefInfo = *it; currentRefInfo = it->get();
if( nullptr != currentRefInfo ) { if( nullptr != currentRefInfo ) {
aiNode *node( currentRefInfo->m_node ); aiNode *node( currentRefInfo->m_node );
if( RefInfo::MeshRef == currentRefInfo->m_type ) { if( RefInfo::MeshRef == currentRefInfo->m_type ) {
for( size_t i = 0; i < currentRefInfo->m_Names.size(); i++ ) { for( size_t i = 0; i < currentRefInfo->m_Names.size(); ++i ) {
const std::string &name( currentRefInfo->m_Names[ i ] ); const std::string &name( currentRefInfo->m_Names[ i ] );
ReferenceMap::const_iterator it( m_mesh2refMap.find( name ) ); ReferenceMap::const_iterator it( m_mesh2refMap.find( name ) );
if( m_mesh2refMap.end() != it ) { if( m_mesh2refMap.end() != it ) {
@ -1175,7 +1193,22 @@ void OpenGEXImporter::resolveReferences() {
} }
} }
} else if( RefInfo::MaterialRef == currentRefInfo->m_type ) { } else if( RefInfo::MaterialRef == currentRefInfo->m_type ) {
// ToDo! for ( size_t i = 0; i < currentRefInfo->m_Names.size(); ++i ) {
const std::string name( currentRefInfo->m_Names[ i ] );
ReferenceMap::const_iterator it( m_material2refMap.find( name ) );
if ( m_material2refMap.end() != it ) {
if ( nullptr != m_currentMesh ) {
unsigned int matIdx = static_cast< unsigned int >( m_material2refMap[ name ] );
if ( m_currentMesh->mMaterialIndex != 0 ) {
DefaultLogger::get()->warn( "Override of material reference in current mesh by material reference." );
}
m_currentMesh->mMaterialIndex = matIdx;
} else {
DefaultLogger::get()->warn( "Cannot resolve material reference, because no current mesh is there." );
}
}
}
} else { } else {
throw DeadlyImportError( "Unknown reference info to resolve." ); throw DeadlyImportError( "Unknown reference info to resolve." );
} }
@ -1213,9 +1246,9 @@ void OpenGEXImporter::pushNode( aiNode *node, aiScene *pScene ) {
if( m_nodeChildMap.end() == it ) { if( m_nodeChildMap.end() == it ) {
info = new ChildInfo; info = new ChildInfo;
m_root = info; m_root = info;
m_nodeChildMap[ node->mParent ] = info; m_nodeChildMap[ node->mParent ] = std::unique_ptr<ChildInfo>(info);
} else { } else {
info = it->second; info = it->second.get();
} }
info->m_children.push_back( node ); info->m_children.push_back( node );
} else { } else {
@ -1225,9 +1258,9 @@ void OpenGEXImporter::pushNode( aiNode *node, aiScene *pScene ) {
NodeChildMap::iterator it( m_nodeChildMap.find( node->mParent ) ); NodeChildMap::iterator it( m_nodeChildMap.find( node->mParent ) );
if( m_nodeChildMap.end() == it ) { if( m_nodeChildMap.end() == it ) {
info = new ChildInfo; info = new ChildInfo;
m_nodeChildMap[ node->mParent ] = info; m_nodeChildMap[ node->mParent ] = std::unique_ptr<ChildInfo>(info);
} else { } else {
info = it->second; info = it->second.get();
} }
info->m_children.push_back( node ); info->m_children.push_back( node );
} }

View File

@ -49,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector> #include <vector>
#include <list> #include <list>
#include <map> #include <map>
#include <memory>
namespace ODDLParser { namespace ODDLParser {
class DDLNode; class DDLNode;
@ -132,6 +133,7 @@ protected:
void copyMeshes( aiScene *pScene ); void copyMeshes( aiScene *pScene );
void copyCameras( aiScene *pScene ); void copyCameras( aiScene *pScene );
void copyLights( aiScene *pScene ); void copyLights( aiScene *pScene );
void copyMaterials( aiScene *pScene );
void resolveReferences(); void resolveReferences();
void pushNode( aiNode *node, aiScene *pScene ); void pushNode( aiNode *node, aiScene *pScene );
aiNode *popNode(); aiNode *popNode();
@ -179,12 +181,13 @@ private:
std::list<aiNode*> m_children; std::list<aiNode*> m_children;
}; };
ChildInfo *m_root; ChildInfo *m_root;
typedef std::map<aiNode*, ChildInfo*> NodeChildMap; typedef std::map<aiNode*, std::unique_ptr<ChildInfo> > NodeChildMap;
NodeChildMap m_nodeChildMap; NodeChildMap m_nodeChildMap;
std::vector<aiMesh*> m_meshCache; std::vector<aiMesh*> m_meshCache;
typedef std::map<std::string, size_t> ReferenceMap; typedef std::map<std::string, size_t> ReferenceMap;
std::map<std::string, size_t> m_mesh2refMap; std::map<std::string, size_t> m_mesh2refMap;
std::map<std::string, size_t> m_material2refMap;
ODDLParser::Context *m_ctx; ODDLParser::Context *m_ctx;
MetricInfo m_metrics[ MetricInfo::Max ]; MetricInfo m_metrics[ MetricInfo::Max ];
@ -199,7 +202,7 @@ private:
std::vector<aiCamera*> m_cameraCache; std::vector<aiCamera*> m_cameraCache;
std::vector<aiLight*> m_lightCache; std::vector<aiLight*> m_lightCache;
std::vector<aiNode*> m_nodeStack; std::vector<aiNode*> m_nodeStack;
std::vector<RefInfo*> m_unresolvedRefStack; std::vector<std::unique_ptr<RefInfo> > m_unresolvedRefStack;
}; };
} // Namespace OpenGEX } // Namespace OpenGEX

View File

@ -181,11 +181,8 @@ void OptimizeMeshesProcess::ProcessNode( aiNode* pNode)
verts += mScene->mMeshes[am]->mNumVertices; verts += mScene->mMeshes[am]->mNumVertices;
faces += mScene->mMeshes[am]->mNumFaces; faces += mScene->mMeshes[am]->mNumFaces;
pNode->mMeshes[a] = pNode->mMeshes[pNode->mNumMeshes - 1];
--pNode->mNumMeshes; --pNode->mNumMeshes;
for( unsigned int n = a; n < pNode->mNumMeshes; ++n ) {
pNode->mMeshes[ n ] = pNode->mMeshes[ n + 1 ];
}
--a; --a;
} }
} }

View File

@ -170,9 +170,10 @@ void PLYImporter::InternReadFile(const std::string& pFile,
std::vector<char> headerCheck; std::vector<char> headerCheck;
streamedBuffer.getNextLine(headerCheck); streamedBuffer.getNextLine(headerCheck);
if ((headerCheck.size() >= 3) && (headerCheck[0] != 'P' && headerCheck[0] != 'p') || if ((headerCheck.size() < 3) ||
(headerCheck[0] != 'P' && headerCheck[0] != 'p') ||
(headerCheck[1] != 'L' && headerCheck[1] != 'l') || (headerCheck[1] != 'L' && headerCheck[1] != 'l') ||
(headerCheck[2] != 'Y' && headerCheck[2] != 'y')) (headerCheck[2] != 'Y' && headerCheck[2] != 'y') )
{ {
streamedBuffer.close(); streamedBuffer.close();
throw DeadlyImportError("Invalid .ply file: Magic number \'ply\' is no there"); throw DeadlyImportError("Invalid .ply file: Magic number \'ply\' is no there");
@ -299,8 +300,7 @@ void PLYImporter::InternReadFile(const std::string& pFile,
} }
} }
void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos) void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos) {
{
ai_assert(NULL != pcElement); ai_assert(NULL != pcElement);
ai_assert(NULL != instElement); ai_assert(NULL != instElement);
@ -316,113 +316,84 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn
unsigned int aiTexcoord[2] = { 0xFFFFFFFF, 0xFFFFFFFF }; unsigned int aiTexcoord[2] = { 0xFFFFFFFF, 0xFFFFFFFF };
PLY::EDataType aiTexcoordTypes[2] = { EDT_Char, EDT_Char }; PLY::EDataType aiTexcoordTypes[2] = { EDT_Char, EDT_Char };
unsigned int cnt = 0;
// now check whether which normal components are available // now check whether which normal components are available
unsigned int _a = 0; unsigned int _a( 0 ), cnt( 0 );
for (std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin(); for ( std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin();
a != pcElement->alProperties.end(); ++a, ++_a) a != pcElement->alProperties.end(); ++a, ++_a) {
{ if ((*a).bIsList) {
if ((*a).bIsList)continue; continue;
}
// Positions // Positions
if (PLY::EST_XCoord == (*a).Semantic) if (PLY::EST_XCoord == (*a).Semantic) {
{ ++cnt;
cnt++;
aiPositions[0] = _a; aiPositions[0] = _a;
aiTypes[0] = (*a).eType; aiTypes[0] = (*a).eType;
} } else if (PLY::EST_YCoord == (*a).Semantic) {
else if (PLY::EST_YCoord == (*a).Semantic) ++cnt;
{
cnt++;
aiPositions[1] = _a; aiPositions[1] = _a;
aiTypes[1] = (*a).eType; aiTypes[1] = (*a).eType;
} } else if (PLY::EST_ZCoord == (*a).Semantic) {
else if (PLY::EST_ZCoord == (*a).Semantic) ++cnt;
{
cnt++;
aiPositions[2] = _a; aiPositions[2] = _a;
aiTypes[2] = (*a).eType; aiTypes[2] = (*a).eType;
} } else if (PLY::EST_XNormal == (*a).Semantic) {
// Normals // Normals
else if (PLY::EST_XNormal == (*a).Semantic) ++cnt;
{
cnt++;
aiNormal[0] = _a; aiNormal[0] = _a;
aiNormalTypes[0] = (*a).eType; aiNormalTypes[0] = (*a).eType;
} } else if (PLY::EST_YNormal == (*a).Semantic) {
else if (PLY::EST_YNormal == (*a).Semantic) ++cnt;
{
cnt++;
aiNormal[1] = _a; aiNormal[1] = _a;
aiNormalTypes[1] = (*a).eType; aiNormalTypes[1] = (*a).eType;
} } else if (PLY::EST_ZNormal == (*a).Semantic) {
else if (PLY::EST_ZNormal == (*a).Semantic) ++cnt;
{
cnt++;
aiNormal[2] = _a; aiNormal[2] = _a;
aiNormalTypes[2] = (*a).eType; aiNormalTypes[2] = (*a).eType;
} } else if (PLY::EST_Red == (*a).Semantic) {
// Colors // Colors
else if (PLY::EST_Red == (*a).Semantic) ++cnt;
{
cnt++;
aiColors[0] = _a; aiColors[0] = _a;
aiColorsTypes[0] = (*a).eType; aiColorsTypes[0] = (*a).eType;
} } else if (PLY::EST_Green == (*a).Semantic) {
else if (PLY::EST_Green == (*a).Semantic) ++cnt;
{
cnt++;
aiColors[1] = _a; aiColors[1] = _a;
aiColorsTypes[1] = (*a).eType; aiColorsTypes[1] = (*a).eType;
} } else if (PLY::EST_Blue == (*a).Semantic) {
else if (PLY::EST_Blue == (*a).Semantic) ++cnt;
{
cnt++;
aiColors[2] = _a; aiColors[2] = _a;
aiColorsTypes[2] = (*a).eType; aiColorsTypes[2] = (*a).eType;
} } else if (PLY::EST_Alpha == (*a).Semantic) {
else if (PLY::EST_Alpha == (*a).Semantic) ++cnt;
{
cnt++;
aiColors[3] = _a; aiColors[3] = _a;
aiColorsTypes[3] = (*a).eType; aiColorsTypes[3] = (*a).eType;
} } else if (PLY::EST_UTextureCoord == (*a).Semantic) {
// Texture coordinates // Texture coordinates
else if (PLY::EST_UTextureCoord == (*a).Semantic) ++cnt;
{
cnt++;
aiTexcoord[0] = _a; aiTexcoord[0] = _a;
aiTexcoordTypes[0] = (*a).eType; aiTexcoordTypes[0] = (*a).eType;
} } else if (PLY::EST_VTextureCoord == (*a).Semantic) {
else if (PLY::EST_VTextureCoord == (*a).Semantic) ++cnt;
{
cnt++;
aiTexcoord[1] = _a; aiTexcoord[1] = _a;
aiTexcoordTypes[1] = (*a).eType; aiTexcoordTypes[1] = (*a).eType;
} }
} }
// check whether we have a valid source for the vertex data // check whether we have a valid source for the vertex data
if (0 != cnt) if (0 != cnt) {
{
// Position // Position
aiVector3D vOut; aiVector3D vOut;
if (0xFFFFFFFF != aiPositions[0]) if (0xFFFFFFFF != aiPositions[0]) {
{
vOut.x = PLY::PropertyInstance::ConvertTo<ai_real>( vOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiPositions[0]).avList.front(), aiTypes[0]); GetProperty(instElement->alProperties, aiPositions[0]).avList.front(), aiTypes[0]);
} }
if (0xFFFFFFFF != aiPositions[1]) if (0xFFFFFFFF != aiPositions[1]) {
{
vOut.y = PLY::PropertyInstance::ConvertTo<ai_real>( vOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiPositions[1]).avList.front(), aiTypes[1]); GetProperty(instElement->alProperties, aiPositions[1]).avList.front(), aiTypes[1]);
} }
if (0xFFFFFFFF != aiPositions[2]) if (0xFFFFFFFF != aiPositions[2]) {
{
vOut.z = PLY::PropertyInstance::ConvertTo<ai_real>( vOut.z = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiPositions[2]).avList.front(), aiTypes[2]); GetProperty(instElement->alProperties, aiPositions[2]).avList.front(), aiTypes[2]);
} }
@ -430,22 +401,19 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn
// Normals // Normals
aiVector3D nOut; aiVector3D nOut;
bool haveNormal = false; bool haveNormal = false;
if (0xFFFFFFFF != aiNormal[0]) if (0xFFFFFFFF != aiNormal[0]) {
{
nOut.x = PLY::PropertyInstance::ConvertTo<ai_real>( nOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiNormal[0]).avList.front(), aiNormalTypes[0]); GetProperty(instElement->alProperties, aiNormal[0]).avList.front(), aiNormalTypes[0]);
haveNormal = true; haveNormal = true;
} }
if (0xFFFFFFFF != aiNormal[1]) if (0xFFFFFFFF != aiNormal[1]) {
{
nOut.y = PLY::PropertyInstance::ConvertTo<ai_real>( nOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiNormal[1]).avList.front(), aiNormalTypes[1]); GetProperty(instElement->alProperties, aiNormal[1]).avList.front(), aiNormalTypes[1]);
haveNormal = true; haveNormal = true;
} }
if (0xFFFFFFFF != aiNormal[2]) if (0xFFFFFFFF != aiNormal[2]) {
{
nOut.z = PLY::PropertyInstance::ConvertTo<ai_real>( nOut.z = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiNormal[2]).avList.front(), aiNormalTypes[2]); GetProperty(instElement->alProperties, aiNormal[2]).avList.front(), aiNormalTypes[2]);
haveNormal = true; haveNormal = true;
@ -454,34 +422,28 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn
//Colors //Colors
aiColor4D cOut; aiColor4D cOut;
bool haveColor = false; bool haveColor = false;
if (0xFFFFFFFF != aiColors[0]) if (0xFFFFFFFF != aiColors[0]) {
{
cOut.r = NormalizeColorValue(GetProperty(instElement->alProperties, cOut.r = NormalizeColorValue(GetProperty(instElement->alProperties,
aiColors[0]).avList.front(), aiColorsTypes[0]); aiColors[0]).avList.front(), aiColorsTypes[0]);
haveColor = true; haveColor = true;
} }
if (0xFFFFFFFF != aiColors[1]) if (0xFFFFFFFF != aiColors[1]) {
{
cOut.g = NormalizeColorValue(GetProperty(instElement->alProperties, cOut.g = NormalizeColorValue(GetProperty(instElement->alProperties,
aiColors[1]).avList.front(), aiColorsTypes[1]); aiColors[1]).avList.front(), aiColorsTypes[1]);
haveColor = true; haveColor = true;
} }
if (0xFFFFFFFF != aiColors[2]) if (0xFFFFFFFF != aiColors[2]) {
{
cOut.b = NormalizeColorValue(GetProperty(instElement->alProperties, cOut.b = NormalizeColorValue(GetProperty(instElement->alProperties,
aiColors[2]).avList.front(), aiColorsTypes[2]); aiColors[2]).avList.front(), aiColorsTypes[2]);
haveColor = true; haveColor = true;
} }
// assume 1.0 for the alpha channel ifit is not set // assume 1.0 for the alpha channel ifit is not set
if (0xFFFFFFFF == aiColors[3]) if (0xFFFFFFFF == aiColors[3]) {
{
cOut.a = 1.0; cOut.a = 1.0;
} } else {
else
{
cOut.a = NormalizeColorValue(GetProperty(instElement->alProperties, cOut.a = NormalizeColorValue(GetProperty(instElement->alProperties,
aiColors[3]).avList.front(), aiColorsTypes[3]); aiColors[3]).avList.front(), aiColorsTypes[3]);
@ -492,53 +454,45 @@ void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementIn
aiVector3D tOut; aiVector3D tOut;
tOut.z = 0; tOut.z = 0;
bool haveTextureCoords = false; bool haveTextureCoords = false;
if (0xFFFFFFFF != aiTexcoord[0]) if (0xFFFFFFFF != aiTexcoord[0]) {
{
tOut.x = PLY::PropertyInstance::ConvertTo<ai_real>( tOut.x = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiTexcoord[0]).avList.front(), aiTexcoordTypes[0]); GetProperty(instElement->alProperties, aiTexcoord[0]).avList.front(), aiTexcoordTypes[0]);
haveTextureCoords = true; haveTextureCoords = true;
} }
if (0xFFFFFFFF != aiTexcoord[1]) if (0xFFFFFFFF != aiTexcoord[1]) {
{
tOut.y = PLY::PropertyInstance::ConvertTo<ai_real>( tOut.y = PLY::PropertyInstance::ConvertTo<ai_real>(
GetProperty(instElement->alProperties, aiTexcoord[1]).avList.front(), aiTexcoordTypes[1]); GetProperty(instElement->alProperties, aiTexcoord[1]).avList.front(), aiTexcoordTypes[1]);
haveTextureCoords = true; haveTextureCoords = true;
} }
//create aiMesh if needed //create aiMesh if needed
if (mGeneratedMesh == NULL) if ( nullptr == mGeneratedMesh ) {
{
mGeneratedMesh = new aiMesh(); mGeneratedMesh = new aiMesh();
mGeneratedMesh->mMaterialIndex = 0; mGeneratedMesh->mMaterialIndex = 0;
} }
if (mGeneratedMesh->mVertices == NULL) if (nullptr == mGeneratedMesh->mVertices) {
{
mGeneratedMesh->mNumVertices = pcElement->NumOccur; mGeneratedMesh->mNumVertices = pcElement->NumOccur;
mGeneratedMesh->mVertices = new aiVector3D[mGeneratedMesh->mNumVertices]; mGeneratedMesh->mVertices = new aiVector3D[mGeneratedMesh->mNumVertices];
} }
mGeneratedMesh->mVertices[pos] = vOut; mGeneratedMesh->mVertices[pos] = vOut;
if (haveNormal) if (haveNormal) {
{ if (nullptr == mGeneratedMesh->mNormals)
if (mGeneratedMesh->mNormals == NULL)
mGeneratedMesh->mNormals = new aiVector3D[mGeneratedMesh->mNumVertices]; mGeneratedMesh->mNormals = new aiVector3D[mGeneratedMesh->mNumVertices];
mGeneratedMesh->mNormals[pos] = nOut; mGeneratedMesh->mNormals[pos] = nOut;
} }
if (haveColor) if (haveColor) {
{ if (nullptr == mGeneratedMesh->mColors[0])
if (mGeneratedMesh->mColors[0] == NULL)
mGeneratedMesh->mColors[0] = new aiColor4D[mGeneratedMesh->mNumVertices]; mGeneratedMesh->mColors[0] = new aiColor4D[mGeneratedMesh->mNumVertices];
mGeneratedMesh->mColors[0][pos] = cOut; mGeneratedMesh->mColors[0][pos] = cOut;
} }
if (haveTextureCoords) if (haveTextureCoords) {
{ if (nullptr == mGeneratedMesh->mTextureCoords[0]) {
if (mGeneratedMesh->mTextureCoords[0] == NULL)
{
mGeneratedMesh->mNumUVComponents[0] = 2; mGeneratedMesh->mNumUVComponents[0] = 2;
mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices]; mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices];
} }
@ -585,7 +539,7 @@ void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInst
ai_assert(NULL != instElement); ai_assert(NULL != instElement);
if (mGeneratedMesh == NULL) if (mGeneratedMesh == NULL)
throw DeadlyImportError("Invalid .ply file: Vertices shoud be declared before faces"); throw DeadlyImportError("Invalid .ply file: Vertices should be declared before faces");
bool bOne = false; bool bOne = false;

View File

@ -618,7 +618,7 @@ bool PLY::DOM::ParseInstanceBinary(IOStreamBuffer<char> &streamBuffer, DOM* p_pc
} }
streamBuffer.getNextBlock(buffer); streamBuffer.getNextBlock(buffer);
unsigned int bufferSize = buffer.size(); unsigned int bufferSize = static_cast<unsigned int>(buffer.size());
const char* pCur = (char*)&buffer[0]; const char* pCur = (char*)&buffer[0];
if (!p_pcOut->ParseElementInstanceListsBinary(streamBuffer, buffer, pCur, bufferSize, loader, p_bBE)) if (!p_pcOut->ParseElementInstanceListsBinary(streamBuffer, buffer, pCur, bufferSize, loader, p_bBE))
{ {
@ -1025,7 +1025,7 @@ bool PLY::PropertyInstance::ParseValueBinary(IOStreamBuffer<char> &streamBuffer,
buffer = std::vector<char>(buffer.end() - bufferSize, buffer.end()); buffer = std::vector<char>(buffer.end() - bufferSize, buffer.end());
buffer.insert(buffer.end(), nbuffer.begin(), nbuffer.end()); buffer.insert(buffer.end(), nbuffer.begin(), nbuffer.end());
nbuffer.clear(); nbuffer.clear();
bufferSize = buffer.size(); bufferSize = static_cast<unsigned int>(buffer.size());
pCur = (char*)&buffer[0]; pCur = (char*)&buffer[0];
} }
else else

View File

@ -104,7 +104,7 @@ unsigned int PretransformVertices::CountNodes( aiNode* pcNode )
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Get a bitwise combination identifying the vertex format of a mesh // Get a bitwise combination identifying the vertex format of a mesh
unsigned int PretransformVertices::GetMeshVFormat(aiMesh* pcMesh) unsigned int PretransformVertices::GetMeshVFormat( aiMesh* pcMesh )
{ {
// the vertex format is stored in aiMesh::mBones for later retrieval. // the vertex format is stored in aiMesh::mBones for later retrieval.
// there isn't a good reason to compute it a few hundred times // there isn't a good reason to compute it a few hundred times
@ -160,6 +160,11 @@ void PretransformVertices::CollectData( aiScene* pcScene, aiNode* pcNode, unsign
unsigned int& num_ref = num_refs[pcNode->mMeshes[i]]; unsigned int& num_ref = num_refs[pcNode->mMeshes[i]];
ai_assert(0 != num_ref); ai_assert(0 != num_ref);
--num_ref; --num_ref;
// Save the name of the last mesh
if (num_ref==0)
{
pcMeshOut->mName = pcMesh->mName;
}
if (identity) { if (identity) {
// copy positions without modifying them // copy positions without modifying them
@ -626,9 +631,10 @@ void PretransformVertices::Execute( aiScene* pScene)
// now delete all nodes in the scene and build a new // now delete all nodes in the scene and build a new
// flat node graph with a root node and some level 1 children // flat node graph with a root node and some level 1 children
aiNode* newRoot = new aiNode();
newRoot->mName = pScene->mRootNode->mName;
delete pScene->mRootNode; delete pScene->mRootNode;
pScene->mRootNode = new aiNode(); pScene->mRootNode = newRoot;
pScene->mRootNode->mName.Set("<dummy_root>");
if (1 == pScene->mNumMeshes && !pScene->mNumLights && !pScene->mNumCameras) if (1 == pScene->mNumMeshes && !pScene->mNumLights && !pScene->mNumCameras)
{ {
@ -646,7 +652,7 @@ void PretransformVertices::Execute( aiScene* pScene)
{ {
aiNode* pcNode = *nodes = new aiNode(); aiNode* pcNode = *nodes = new aiNode();
pcNode->mParent = pScene->mRootNode; pcNode->mParent = pScene->mRootNode;
pcNode->mName.length = ::ai_snprintf(pcNode->mName.data,MAXLEN,"mesh_%u",i); pcNode->mName = pScene->mMeshes[i]->mName;
// setup mesh indices // setup mesh indices
pcNode->mNumMeshes = 1; pcNode->mNumMeshes = 1;

View File

@ -52,21 +52,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <map> #include <map>
namespace Assimp { namespace Assimp {
namespace Profiling { namespace Profiling {
using namespace Formatter;
using namespace Formatter;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
/** Simple wrapper around boost::timer to simplify reporting. Timings are automatically /** Simple wrapper around boost::timer to simplify reporting. Timings are automatically
* dumped to the log file. * dumped to the log file.
*/ */
class Profiler class Profiler {
{
public: public:
Profiler() {
Profiler() {} // empty
}
public: public:
@ -84,17 +82,17 @@ public:
return; return;
} }
auto elapsedSeconds = std::chrono::system_clock::now() - regions[region]; std::chrono::duration<double> elapsedSeconds = std::chrono::system_clock::now() - regions[region];
DefaultLogger::get()->debug((format("END `"),region,"`, dt= ", elapsedSeconds.count()," s")); DefaultLogger::get()->debug((format("END `"),region,"`, dt= ", elapsedSeconds.count()," s"));
} }
private: private:
typedef std::map<std::string,std::chrono::time_point<std::chrono::system_clock>> RegionMap; typedef std::map<std::string,std::chrono::time_point<std::chrono::system_clock>> RegionMap;
RegionMap regions; RegionMap regions;
}; };
} }
} }
#endif #endif

View File

@ -39,14 +39,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER #ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
#include "Q3BSPZipArchive.h" #include "Q3BSPZipArchive.h"
#include <algorithm>
#include <cassert> #include <cassert>
#include <cstdlib>
#include <assimp/ai_assert.h> #include <assimp/ai_assert.h>
namespace Assimp { namespace Assimp {
@ -137,7 +133,6 @@ zlib_filefunc_def IOSystem2Unzip::get(IOSystem* pIOHandler) {
return mapping; return mapping;
} }
// ------------------------------------------------------------------------------------------------
ZipFile::ZipFile(size_t size) : m_Size(size) { ZipFile::ZipFile(size_t size) : m_Size(size) {
ai_assert(m_Size != 0); ai_assert(m_Size != 0);

View File

@ -44,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <contrib/unzip/unzip.h> #include <contrib/unzip/unzip.h>
#include <assimp/IOStream.hpp> #include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <string>
#include <vector> #include <vector>
#include <map> #include <map>
#include <cassert> #include <cassert>

View File

@ -176,36 +176,29 @@ static void UnknownChunk(StreamReaderLE* stream, const SIBChunk& chunk)
} }
// Reads a UTF-16LE string and returns it at UTF-8. // Reads a UTF-16LE string and returns it at UTF-8.
static aiString ReadString(StreamReaderLE* stream, uint32_t numWChars) static aiString ReadString(StreamReaderLE *stream, uint32_t numWChars) {
{ if ( nullptr == stream || 0 == numWChars ) {
if ( 0 == numWChars ) {
static const aiString empty; static const aiString empty;
return empty; return empty;
} }
// Allocate buffers (max expansion is 1 byte -> 4 bytes for UTF-8) // Allocate buffers (max expansion is 1 byte -> 4 bytes for UTF-8)
//UTF16* temp = new UTF16[numWChars];
std::vector<unsigned char> str; std::vector<unsigned char> str;
str.reserve(numWChars * 4 + 1); str.reserve( numWChars * 4 + 1 );
//unsigned char* str = new unsigned char[numWChars * 4 + 1]; uint16_t *temp = new uint16_t[ numWChars ];
uint16_t *temp = new uint16_t[numWChars]; for ( uint32_t n = 0; n < numWChars; ++n ) {
for (uint32_t n=0;n<numWChars;n++) temp[ n ] = stream->GetU2();
temp[n] = stream->GetU2(); }
// Convert it and NUL-terminate. // Convert it and NUL-terminate.
//const UTF16 *start = temp, *end = temp + numWChars; const uint16_t *start( temp ), *end( temp + numWChars );
utf8::utf16to8( start, end, back_inserter( str ) );
str[ str.size() - 1 ] = '\0';
const uint16_t *start = temp, *end = temp + numWChars;
utf8::utf16to8(start, end, back_inserter(str));
//UTF8 *dest = str, *limit = str + numWChars*4;
//ConvertUTF16toUTF8(&start, end, &dest, limit, lenientConversion);
//*dest = '\0';
str[str.size()-1] = '\0';
// Return the final string. // Return the final string.
aiString result = aiString((const char *)&str[0]); aiString result = aiString((const char *)&str[0]);
//delete[] str;
delete[] temp; delete[] temp;
return result; return result;
} }
@ -223,26 +216,26 @@ SIBImporter::~SIBImporter() {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool SIBImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const bool SIBImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const {
{
return SimpleExtensionCheck(pFile, "sib"); return SimpleExtensionCheck(pFile, "sib");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const aiImporterDesc* SIBImporter::GetInfo () const const aiImporterDesc* SIBImporter::GetInfo () const {
{
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
static void ReadVerts(SIBMesh* mesh, StreamReaderLE* stream, uint32_t count) static void ReadVerts(SIBMesh* mesh, StreamReaderLE* stream, uint32_t count) {
{ if ( nullptr == mesh || nullptr == stream ) {
mesh->pos.resize(count); return;
}
for (uint32_t n=0;n<count;n++) { mesh->pos.resize(count);
mesh->pos[n].x = stream->GetF4(); for ( uint32_t n=0; n<count; ++n ) {
mesh->pos[n].y = stream->GetF4(); mesh->pos[ n ].x = stream->GetF4();
mesh->pos[n].z = stream->GetF4(); mesh->pos[ n ].y = stream->GetF4();
mesh->pos[ n ].z = stream->GetF4();
} }
} }
@ -827,7 +820,7 @@ static void ReadInstance(SIB* sib, StreamReaderLE* stream)
static void CheckVersion(StreamReaderLE* stream) static void CheckVersion(StreamReaderLE* stream)
{ {
uint32_t version = stream->GetU4(); uint32_t version = stream->GetU4();
if ( version != 1 ) { if ( version < 1 || version > 2 ) {
throw DeadlyImportError( "SIB: Unsupported file version." ); throw DeadlyImportError( "SIB: Unsupported file version." );
} }
} }

View File

@ -450,7 +450,9 @@ void SMDImporter::CreateOutputMeshes()
// add bone child nodes // add bone child nodes
void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent) void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent)
{ {
ai_assert(NULL != pcNode && 0 == pcNode->mNumChildren && NULL == pcNode->mChildren); ai_assert( NULL != pcNode );
ai_assert( 0 == pcNode->mNumChildren );
ai_assert( NULL == pcNode->mChildren);
// first count ... // first count ...
for (unsigned int i = 0; i < asBones.size();++i) for (unsigned int i = 0; i < asBones.size();++i)
@ -648,12 +650,14 @@ void SMDImporter::ComputeAbsoluteBoneTransformations()
// create output materials // create output materials
void SMDImporter::CreateOutputMaterials() void SMDImporter::CreateOutputMaterials()
{ {
ai_assert( nullptr != pScene );
pScene->mNumMaterials = (unsigned int)aszTextures.size(); pScene->mNumMaterials = (unsigned int)aszTextures.size();
pScene->mMaterials = new aiMaterial*[std::max(1u, pScene->mNumMaterials)]; pScene->mMaterials = new aiMaterial*[std::max(1u, pScene->mNumMaterials)];
for (unsigned int iMat = 0; iMat < pScene->mNumMaterials;++iMat) for (unsigned int iMat = 0; iMat < pScene->mNumMaterials; ++iMat) {
{
aiMaterial* pcMat = new aiMaterial(); aiMaterial* pcMat = new aiMaterial();
ai_assert( nullptr != pcMat );
pScene->mMaterials[iMat] = pcMat; pScene->mMaterials[iMat] = pcMat;
aiString szName; aiString szName;

View File

@ -58,6 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "time.h" #include "time.h"
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/mesh.h>
#include <stdio.h> #include <stdio.h>
#include "ScenePrivate.h" #include "ScenePrivate.h"
@ -757,7 +758,7 @@ void SceneCombiner::MergeBones(aiMesh* out,std::vector<aiMesh*>::const_iterator
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Merge a list of meshes // Merge a list of meshes
void SceneCombiner::MergeMeshes(aiMesh** _out,unsigned int /*flags*/, void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/,
std::vector<aiMesh*>::const_iterator begin, std::vector<aiMesh*>::const_iterator begin,
std::vector<aiMesh*>::const_iterator end) std::vector<aiMesh*>::const_iterator end)
{ {
@ -772,8 +773,14 @@ void SceneCombiner::MergeMeshes(aiMesh** _out,unsigned int /*flags*/,
aiMesh* out = *_out = new aiMesh(); aiMesh* out = *_out = new aiMesh();
out->mMaterialIndex = (*begin)->mMaterialIndex; out->mMaterialIndex = (*begin)->mMaterialIndex;
std::string name;
// Find out how much output storage we'll need // Find out how much output storage we'll need
for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { for (std::vector<aiMesh*>::const_iterator it = begin; it != end; ++it) {
const char *meshName( (*it)->mName.C_Str() );
name += std::string( meshName );
if ( it != end - 1 ) {
name += ".";
}
out->mNumVertices += (*it)->mNumVertices; out->mNumVertices += (*it)->mNumVertices;
out->mNumFaces += (*it)->mNumFaces; out->mNumFaces += (*it)->mNumFaces;
out->mNumBones += (*it)->mNumBones; out->mNumBones += (*it)->mNumBones;
@ -781,6 +788,7 @@ void SceneCombiner::MergeMeshes(aiMesh** _out,unsigned int /*flags*/,
// combine primitive type flags // combine primitive type flags
out->mPrimitiveTypes |= (*it)->mPrimitiveTypes; out->mPrimitiveTypes |= (*it)->mPrimitiveTypes;
} }
out->mName.Set( name.c_str() );
if (out->mNumVertices) { if (out->mNumVertices) {
aiVector3D* pv2; aiVector3D* pv2;
@ -789,7 +797,7 @@ void SceneCombiner::MergeMeshes(aiMesh** _out,unsigned int /*flags*/,
if ((**begin).HasPositions()) { if ((**begin).HasPositions()) {
pv2 = out->mVertices = new aiVector3D[out->mNumVertices]; pv2 = out->mVertices = new aiVector3D[out->mNumVertices];
for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { for (std::vector<aiMesh*>::const_iterator it = begin; it != end; ++it) {
if ((*it)->mVertices) { if ((*it)->mVertices) {
::memcpy(pv2,(*it)->mVertices,(*it)->mNumVertices*sizeof(aiVector3D)); ::memcpy(pv2,(*it)->mVertices,(*it)->mNumVertices*sizeof(aiVector3D));
} }
@ -809,7 +817,7 @@ void SceneCombiner::MergeMeshes(aiMesh** _out,unsigned int /*flags*/,
pv2 += (*it)->mNumVertices; pv2 += (*it)->mNumVertices;
} }
} }
// copy tangents and bitangents // copy tangents and bi-tangents
if ((**begin).HasTangentsAndBitangents()) { if ((**begin).HasTangentsAndBitangents()) {
pv2 = out->mTangents = new aiVector3D[out->mNumVertices]; pv2 = out->mTangents = new aiVector3D[out->mNumVertices];

View File

@ -291,15 +291,11 @@ private:
throw DeadlyImportError("End of file or stream limit was reached"); throw DeadlyImportError("End of file or stream limit was reached");
} }
///*#ifdef __arm__
T f; T f;
::memcpy (&f, current, sizeof(T)); ::memcpy (&f, current, sizeof(T));
//#else*/ Intern::Getter<SwapEndianess,T,RuntimeSwitch>() (&f,le);
// T f = *((const T*)current);
//#endif
Intern :: Getter<SwapEndianess,T,RuntimeSwitch>() (&f,le);
current += sizeof(T); current += sizeof(T);
return f; return f;
} }

View File

@ -157,7 +157,7 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
DefaultLogger::get()->debug("UNREAL: uc file is " + uc_path); DefaultLogger::get()->debug("UNREAL: uc file is " + uc_path);
// and open the files ... we can't live without them // and open the files ... we can't live without them
IOStream* p = pIOHandler->Open(d_path); std::unique_ptr<IOStream> p(pIOHandler->Open(d_path));
if (!p) if (!p)
throw DeadlyImportError("UNREAL: Unable to open _d file"); throw DeadlyImportError("UNREAL: Unable to open _d file");
StreamReaderLE d_reader(pIOHandler->Open(d_path)); StreamReaderLE d_reader(pIOHandler->Open(d_path));
@ -203,7 +203,7 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
d_reader.IncPtr(1); d_reader.IncPtr(1);
} }
p = pIOHandler->Open(a_path); p.reset(pIOHandler->Open(a_path));
if (!p) if (!p)
throw DeadlyImportError("UNREAL: Unable to open _a file"); throw DeadlyImportError("UNREAL: Unable to open _a file");
StreamReaderLE a_reader(pIOHandler->Open(a_path)); StreamReaderLE a_reader(pIOHandler->Open(a_path));

View File

@ -89,9 +89,7 @@ AI_WONT_RETURN void ValidateDSProcess::ReportError(const char* msg,...)
ai_assert(iLen > 0); ai_assert(iLen > 0);
va_end(args); va_end(args);
#ifdef ASSIMP_BUILD_DEBUG
ai_assert( false );
#endif
throw DeadlyImportError("Validation failed: " + std::string(szBuffer,iLen)); throw DeadlyImportError("Validation failed: " + std::string(szBuffer,iLen));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -409,12 +407,12 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
// the MSB flag is temporarily used by the extra verbose // the MSB flag is temporarily used by the extra verbose
// mode to tell us that the JoinVerticesProcess might have // mode to tell us that the JoinVerticesProcess might have
// been executed already. // been executed already.
if ( !(this->mScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT ) && !(this->mScene->mFlags & AI_SCENE_FLAGS_ALLOW_SHARED) && /*if ( !(this->mScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT ) && !(this->mScene->mFlags & AI_SCENE_FLAGS_ALLOW_SHARED) &&
abRefList[face.mIndices[a]]) abRefList[face.mIndices[a]])
{ {
ReportError("aiMesh::mVertices[%i] is referenced twice - second " ReportError("aiMesh::mVertices[%i] is referenced twice - second "
"time by aiMesh::mFaces[%i]::mIndices[%i]",face.mIndices[a],i,a); "time by aiMesh::mFaces[%i]::mIndices[%i]",face.mIndices[a],i,a);
} }*/
abRefList[face.mIndices[a]] = true; abRefList[face.mIndices[a]] = true;
} }
} }

View File

@ -107,8 +107,7 @@ ASSIMP_API unsigned int aiGetCompileFlags () {
#include "revision.h" #include "revision.h"
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API unsigned int aiGetVersionRevision () ASSIMP_API unsigned int aiGetVersionRevision() {
{
return GitVersion; return GitVersion;
} }
@ -133,8 +132,7 @@ ASSIMP_API aiScene::aiScene()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API aiScene::~aiScene() ASSIMP_API aiScene::~aiScene() {
{
// delete all sub-objects recursively // delete all sub-objects recursively
delete mRootNode; delete mRootNode;
@ -173,3 +171,4 @@ ASSIMP_API aiScene::~aiScene()
delete static_cast<Assimp::ScenePrivateData*>( mPrivate ); delete static_cast<Assimp::ScenePrivateData*>( mPrivate );
} }

View File

@ -95,8 +95,8 @@ struct WordIterator: public std::iterator<std::input_iterator_tag, const char*>
end_ = other.end_; end_ = other.end_;
return *this; return *this;
} }
bool operator==(WordIterator &other) const { return start_ == other.start_; } bool operator==(const WordIterator &other) const { return start_ == other.start_; }
bool operator!=(WordIterator &other) const { return start_ != other.start_; } bool operator!=(const WordIterator &other) const { return start_ != other.start_; }
WordIterator &operator++() { WordIterator &operator++() {
start_ += strcspn(start_, whitespace); start_ += strcspn(start_, whitespace);
start_ += strspn(start_, whitespace); start_ += strspn(start_, whitespace);
@ -558,7 +558,7 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsArrF(const int pAttrIdx, std::vector
WordIterator wordItBegin(val, val + strlen(val)); WordIterator wordItBegin(val, val + strlen(val));
WordIterator wordItEnd; WordIterator wordItEnd;
std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const char *match) { return atof(match); }); std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const char *match) { return static_cast<float>(atof(match)); });
} }
} }

View File

@ -93,7 +93,10 @@ protected:
void PushTag() { startstr.append( " "); } void PushTag() { startstr.append( " "); }
/// Leaves an element, decreasing the indentation /// Leaves an element, decreasing the indentation
void PopTag() { ai_assert( startstr.length() > 1); startstr.erase( startstr.length() - 2); } void PopTag() {
ai_assert( startstr.length() > 1);
startstr.erase( startstr.length() - 2);
}
public: public:
/// Stringstream to write all output into /// Stringstream to write all output into

View File

@ -83,8 +83,11 @@ struct free_it
}; };
namespace Assimp { // this has to be in here because LogFunctions is in ::Assimp namespace Assimp { // this has to be in here because LogFunctions is in ::Assimp
template<> const std::string LogFunctions<XGLImporter>::log_prefix = "XGL: "; template<> const char* LogFunctions<XGLImporter>::Prefix()
{
static auto prefix = "XGL: ";
return prefix;
}
} }
static const aiImporterDesc desc = { static const aiImporterDesc desc = {

1108
code/glTF2Asset.h 100644

File diff suppressed because it is too large Load Diff

1319
code/glTF2Asset.inl 100644

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,93 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2017, 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 glTFWriter.h
* Declares a class to write gltf/glb files
*
* glTF Extensions Support:
* KHR_materials_pbrSpecularGlossiness: full
*/
#ifndef GLTF2ASSETWRITER_H_INC
#define GLTF2ASSETWRITER_H_INC
#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
#include "glTF2Asset.h"
namespace glTF2
{
using rapidjson::MemoryPoolAllocator;
class AssetWriter
{
template<class T>
friend void WriteLazyDict(LazyDict<T>& d, AssetWriter& w);
private:
void WriteBinaryData(IOStream* outfile, size_t sceneLength);
void WriteMetadata();
void WriteExtensionsUsed();
template<class T>
void WriteObjects(LazyDict<T>& d);
public:
Document mDoc;
Asset& mAsset;
MemoryPoolAllocator<>& mAl;
AssetWriter(Asset& asset);
void WriteFile(const char* path);
};
}
// Include the implementation of the methods
#include "glTF2AssetWriter.inl"
#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
#endif // GLTF2ASSETWRITER_H_INC

View File

@ -0,0 +1,639 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2017, 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 <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <rapidjson/prettywriter.h>
namespace glTF2 {
using rapidjson::StringBuffer;
using rapidjson::PrettyWriter;
using rapidjson::Writer;
using rapidjson::StringRef;
using rapidjson::StringRef;
namespace {
template<size_t N>
inline Value& MakeValue(Value& val, float(&r)[N], MemoryPoolAllocator<>& al) {
val.SetArray();
val.Reserve(N, al);
for (decltype(N) i = 0; i < N; ++i) {
val.PushBack(r[i], al);
}
return val;
}
inline Value& MakeValue(Value& val, const std::vector<float> & r, MemoryPoolAllocator<>& al) {
val.SetArray();
val.Reserve(static_cast<rapidjson::SizeType>(r.size()), al);
for (unsigned int i = 0; i < r.size(); ++i) {
val.PushBack(r[i], al);
}
return val;
}
inline Value& MakeValue(Value& val, float r, MemoryPoolAllocator<>& al) {
val.SetDouble(r);
return val;
}
template<class T>
inline void AddRefsVector(Value& obj, const char* fieldId, std::vector< Ref<T> >& v, MemoryPoolAllocator<>& al) {
if (v.empty()) return;
Value lst;
lst.SetArray();
lst.Reserve(unsigned(v.size()), al);
for (size_t i = 0; i < v.size(); ++i) {
lst.PushBack(v[i]->index, al);
}
obj.AddMember(StringRef(fieldId), lst, al);
}
}
inline void Write(Value& obj, Accessor& a, AssetWriter& w)
{
obj.AddMember("bufferView", a.bufferView->index, w.mAl);
obj.AddMember("byteOffset", a.byteOffset, w.mAl);
if (a.byteStride != 0) {
obj.AddMember("byteStride", a.byteStride, w.mAl);
}
obj.AddMember("componentType", int(a.componentType), w.mAl);
obj.AddMember("count", a.count, w.mAl);
obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl);
Value vTmpMax, vTmpMin;
obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl);
obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl);
}
inline void Write(Value& obj, Animation& a, AssetWriter& w)
{
/****************** Channels *******************/
Value channels;
channels.SetArray();
channels.Reserve(unsigned(a.Channels.size()), w.mAl);
for (size_t i = 0; i < unsigned(a.Channels.size()); ++i) {
Animation::AnimChannel& c = a.Channels[i];
Value valChannel;
valChannel.SetObject();
{
valChannel.AddMember("sampler", c.sampler, w.mAl);
Value valTarget;
valTarget.SetObject();
{
valTarget.AddMember("node", c.target.node->index, w.mAl);
valTarget.AddMember("path", c.target.path, w.mAl);
}
valChannel.AddMember("target", valTarget, w.mAl);
}
channels.PushBack(valChannel, w.mAl);
}
obj.AddMember("channels", channels, w.mAl);
/****************** Samplers *******************/
Value valSamplers;
valSamplers.SetArray();
for (size_t i = 0; i < unsigned(a.Samplers.size()); ++i) {
Animation::AnimSampler& s = a.Samplers[i];
Value valSampler;
valSampler.SetObject();
{
Ref<Accessor> inputAccessor = a.GetAccessor(s.input);
Ref<Accessor> outputAccessor = a.GetAccessor(s.output);
valSampler.AddMember("input", inputAccessor->index, w.mAl);
valSampler.AddMember("interpolation", s.interpolation, w.mAl);
valSampler.AddMember("output", outputAccessor->index, w.mAl);
}
valSamplers.PushBack(valSampler, w.mAl);
}
obj.AddMember("samplers", valSamplers, w.mAl);
}
inline void Write(Value& obj, Buffer& b, AssetWriter& w)
{
obj.AddMember("byteLength", static_cast<uint64_t>(b.byteLength), w.mAl);
obj.AddMember("uri", Value(b.GetURI(), w.mAl).Move(), w.mAl);
}
inline void Write(Value& obj, BufferView& bv, AssetWriter& w)
{
obj.AddMember("buffer", bv.buffer->index, w.mAl);
obj.AddMember("byteOffset", static_cast<uint64_t>(bv.byteOffset), w.mAl);
obj.AddMember("byteLength", static_cast<uint64_t>(bv.byteLength), w.mAl);
obj.AddMember("target", int(bv.target), w.mAl);
}
inline void Write(Value& obj, Camera& c, AssetWriter& w)
{
}
inline void Write(Value& obj, Image& img, AssetWriter& w)
{
std::string uri;
if (img.HasData()) {
uri = "data:" + (img.mimeType.empty() ? "application/octet-stream" : img.mimeType);
uri += ";base64,";
Util::EncodeBase64(img.GetData(), img.GetDataLength(), uri);
}
else {
uri = img.uri;
}
obj.AddMember("uri", Value(uri, w.mAl).Move(), w.mAl);
}
namespace {
inline void SetTexBasic(TextureInfo t, Value& tex, MemoryPoolAllocator<>& al)
{
tex.SetObject();
tex.AddMember("index", t.texture->index, al);
if (t.texCoord != 0) {
tex.AddMember("texCoord", t.texCoord, al);
}
}
inline void WriteTex(Value& obj, TextureInfo t, const char* propName, MemoryPoolAllocator<>& al)
{
if (t.texture) {
Value tex;
SetTexBasic(t, tex, al);
obj.AddMember(StringRef(propName), tex, al);
}
}
inline void WriteTex(Value& obj, NormalTextureInfo t, const char* propName, MemoryPoolAllocator<>& al)
{
if (t.texture) {
Value tex;
SetTexBasic(t, tex, al);
if (t.scale != 1) {
tex.AddMember("scale", t.scale, al);
}
obj.AddMember(StringRef(propName), tex, al);
}
}
inline void WriteTex(Value& obj, OcclusionTextureInfo t, const char* propName, MemoryPoolAllocator<>& al)
{
if (t.texture) {
Value tex;
SetTexBasic(t, tex, al);
if (t.strength != 1) {
tex.AddMember("strength", t.strength, al);
}
obj.AddMember(StringRef(propName), tex, al);
}
}
template<size_t N>
inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, MemoryPoolAllocator<>& al)
{
Value arr;
obj.AddMember(StringRef(propName), MakeValue(arr, prop, al), al);
}
template<size_t N>
inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, const float(&defaultVal)[N], MemoryPoolAllocator<>& al)
{
if (!std::equal(std::begin(prop), std::end(prop), std::begin(defaultVal))) {
WriteVec(obj, prop, propName, al);
}
}
inline void WriteFloat(Value& obj, float prop, const char* propName, MemoryPoolAllocator<>& al)
{
Value num;
obj.AddMember(StringRef(propName), MakeValue(num, prop, al), al);
}
}
inline void Write(Value& obj, Material& m, AssetWriter& w)
{
Value pbrMetallicRoughness;
pbrMetallicRoughness.SetObject();
{
WriteTex(pbrMetallicRoughness, m.pbrMetallicRoughness.baseColorTexture, "baseColorTexture", w.mAl);
WriteTex(pbrMetallicRoughness, m.pbrMetallicRoughness.metallicRoughnessTexture, "metallicRoughnessTexture", w.mAl);
WriteVec(pbrMetallicRoughness, m.pbrMetallicRoughness.baseColorFactor, "baseColorFactor", defaultBaseColor, w.mAl);
if (m.pbrMetallicRoughness.metallicFactor != 1) {
WriteFloat(pbrMetallicRoughness, m.pbrMetallicRoughness.metallicFactor, "metallicFactor", w.mAl);
}
if (m.pbrMetallicRoughness.roughnessFactor != 1) {
WriteFloat(pbrMetallicRoughness, m.pbrMetallicRoughness.roughnessFactor, "roughnessFactor", w.mAl);
}
}
if (!pbrMetallicRoughness.ObjectEmpty()) {
obj.AddMember("pbrMetallicRoughness", pbrMetallicRoughness, w.mAl);
}
WriteTex(obj, m.normalTexture, "normalTexture", w.mAl);
WriteTex(obj, m.emissiveTexture, "emissiveTexture", w.mAl);
WriteTex(obj, m.occlusionTexture, "occlusionTexture", w.mAl);
WriteVec(obj, m.emissiveFactor, "emissiveFactor", defaultEmissiveFactor, w.mAl);
if (m.alphaCutoff != 0.5) {
WriteFloat(obj, m.alphaCutoff, "alphaCutoff", w.mAl);
}
if (m.alphaMode != "OPAQUE") {
obj.AddMember("alphaMode", Value(m.alphaMode, w.mAl).Move(), w.mAl);
}
if (m.doubleSided) {
obj.AddMember("doubleSided", m.doubleSided, w.mAl);
}
Value exts;
exts.SetObject();
if (m.pbrSpecularGlossiness.isPresent) {
Value pbrSpecularGlossiness;
pbrSpecularGlossiness.SetObject();
PbrSpecularGlossiness &pbrSG = m.pbrSpecularGlossiness.value;
//pbrSpecularGlossiness
WriteVec(pbrSpecularGlossiness, pbrSG.diffuseFactor, "diffuseFactor", defaultDiffuseFactor, w.mAl);
WriteVec(pbrSpecularGlossiness, pbrSG.specularFactor, "specularFactor", defaultSpecularFactor, w.mAl);
if (pbrSG.glossinessFactor != 1) {
WriteFloat(obj, pbrSG.glossinessFactor, "glossinessFactor", w.mAl);
}
WriteTex(pbrSpecularGlossiness, pbrSG.diffuseTexture, "diffuseTexture", w.mAl);
WriteTex(pbrSpecularGlossiness, pbrSG.specularGlossinessTexture, "specularGlossinessTexture", w.mAl);
if (!pbrSpecularGlossiness.ObjectEmpty()) {
exts.AddMember("KHR_materials_pbrSpecularGlossiness", pbrSpecularGlossiness, w.mAl);
}
}
if (!exts.ObjectEmpty()) {
obj.AddMember("extensions", exts, w.mAl);
}
}
namespace {
inline void WriteAttrs(AssetWriter& w, Value& attrs, Mesh::AccessorList& lst,
const char* semantic, bool forceNumber = false)
{
if (lst.empty()) return;
if (lst.size() == 1 && !forceNumber) {
attrs.AddMember(StringRef(semantic), lst[0]->index, w.mAl);
}
else {
for (size_t i = 0; i < lst.size(); ++i) {
char buffer[32];
ai_snprintf(buffer, 32, "%s_%d", semantic, int(i));
attrs.AddMember(Value(buffer, w.mAl).Move(), lst[i]->index, w.mAl);
}
}
}
}
inline void Write(Value& obj, Mesh& m, AssetWriter& w)
{
/****************** Primitives *******************/
Value primitives;
primitives.SetArray();
primitives.Reserve(unsigned(m.primitives.size()), w.mAl);
for (size_t i = 0; i < m.primitives.size(); ++i) {
Mesh::Primitive& p = m.primitives[i];
Value prim;
prim.SetObject();
{
prim.AddMember("mode", Value(int(p.mode)).Move(), w.mAl);
if (p.material)
prim.AddMember("material", p.material->index, w.mAl);
if (p.indices)
prim.AddMember("indices", p.indices->index, w.mAl);
Value attrs;
attrs.SetObject();
{
WriteAttrs(w, attrs, p.attributes.position, "POSITION");
WriteAttrs(w, attrs, p.attributes.normal, "NORMAL");
WriteAttrs(w, attrs, p.attributes.texcoord, "TEXCOORD", true);
WriteAttrs(w, attrs, p.attributes.color, "COLOR", true);
WriteAttrs(w, attrs, p.attributes.joint, "JOINTS", true);
WriteAttrs(w, attrs, p.attributes.weight, "WEIGHTS", true);
}
prim.AddMember("attributes", attrs, w.mAl);
}
primitives.PushBack(prim, w.mAl);
}
obj.AddMember("primitives", primitives, w.mAl);
}
inline void Write(Value& obj, Node& n, AssetWriter& w)
{
if (n.matrix.isPresent) {
Value val;
obj.AddMember("matrix", MakeValue(val, n.matrix.value, w.mAl).Move(), w.mAl);
}
if (n.translation.isPresent) {
Value val;
obj.AddMember("translation", MakeValue(val, n.translation.value, w.mAl).Move(), w.mAl);
}
if (n.scale.isPresent) {
Value val;
obj.AddMember("scale", MakeValue(val, n.scale.value, w.mAl).Move(), w.mAl);
}
if (n.rotation.isPresent) {
Value val;
obj.AddMember("rotation", MakeValue(val, n.rotation.value, w.mAl).Move(), w.mAl);
}
AddRefsVector(obj, "children", n.children, w.mAl);
if (!n.meshes.empty()) {
obj.AddMember("mesh", n.meshes[0]->index, w.mAl);
}
AddRefsVector(obj, "skeletons", n.skeletons, w.mAl);
if (n.skin) {
obj.AddMember("skin", n.skin->index, w.mAl);
}
if (!n.jointName.empty()) {
obj.AddMember("jointName", n.jointName, w.mAl);
}
}
inline void Write(Value& obj, Program& b, AssetWriter& w)
{
}
inline void Write(Value& obj, Sampler& b, AssetWriter& w)
{
if (!b.name.empty()) {
obj.AddMember("name", b.name, w.mAl);
}
if (b.wrapS != SamplerWrap::UNSET && b.wrapS != SamplerWrap::Repeat) {
obj.AddMember("wrapS", static_cast<unsigned int>(b.wrapS), w.mAl);
}
if (b.wrapT != SamplerWrap::UNSET && b.wrapT != SamplerWrap::Repeat) {
obj.AddMember("wrapT", static_cast<unsigned int>(b.wrapT), w.mAl);
}
if (b.magFilter != SamplerMagFilter::UNSET) {
obj.AddMember("magFilter", static_cast<unsigned int>(b.magFilter), w.mAl);
}
if (b.minFilter != SamplerMinFilter::UNSET) {
obj.AddMember("minFilter", static_cast<unsigned int>(b.minFilter), w.mAl);
}
}
inline void Write(Value& scene, Scene& s, AssetWriter& w)
{
AddRefsVector(scene, "nodes", s.nodes, w.mAl);
}
inline void Write(Value& obj, Shader& b, AssetWriter& w)
{
}
inline void Write(Value& obj, Skin& b, AssetWriter& w)
{
/****************** jointNames *******************/
Value vJointNames;
vJointNames.SetArray();
vJointNames.Reserve(unsigned(b.jointNames.size()), w.mAl);
for (size_t i = 0; i < unsigned(b.jointNames.size()); ++i) {
vJointNames.PushBack(b.jointNames[i]->index, w.mAl);
}
obj.AddMember("joints", vJointNames, w.mAl);
if (b.bindShapeMatrix.isPresent) {
Value val;
obj.AddMember("bindShapeMatrix", MakeValue(val, b.bindShapeMatrix.value, w.mAl).Move(), w.mAl);
}
if (b.inverseBindMatrices) {
obj.AddMember("inverseBindMatrices", b.inverseBindMatrices->index, w.mAl);
}
}
inline void Write(Value& obj, Texture& tex, AssetWriter& w)
{
if (tex.source) {
obj.AddMember("source", tex.source->index, w.mAl);
}
if (tex.sampler) {
obj.AddMember("sampler", tex.sampler->index, w.mAl);
}
}
inline AssetWriter::AssetWriter(Asset& a)
: mDoc()
, mAsset(a)
, mAl(mDoc.GetAllocator())
{
mDoc.SetObject();
WriteMetadata();
WriteExtensionsUsed();
// Dump the contents of the dictionaries
for (size_t i = 0; i < a.mDicts.size(); ++i) {
a.mDicts[i]->WriteObjects(*this);
}
// Add the target scene field
if (mAsset.scene) {
mDoc.AddMember("scene", mAsset.scene->index, mAl);
}
}
inline void AssetWriter::WriteFile(const char* path)
{
std::unique_ptr<IOStream> jsonOutFile(mAsset.OpenFile(path, "wt", true));
if (jsonOutFile == 0) {
throw DeadlyExportError("Could not open output file: " + std::string(path));
}
StringBuffer docBuffer;
PrettyWriter<StringBuffer> writer(docBuffer);
mDoc.Accept(writer);
if (jsonOutFile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) {
throw DeadlyExportError("Failed to write scene data!");
}
// Write buffer data to separate .bin files
for (unsigned int i = 0; i < mAsset.buffers.Size(); ++i) {
Ref<Buffer> b = mAsset.buffers.Get(i);
std::string binPath = b->GetURI();
std::unique_ptr<IOStream> binOutFile(mAsset.OpenFile(binPath, "wb", true));
if (binOutFile == 0) {
throw DeadlyExportError("Could not open output file: " + binPath);
}
if (b->byteLength > 0) {
if (binOutFile->Write(b->GetPointer(), b->byteLength, 1) != 1) {
throw DeadlyExportError("Failed to write binary file: " + binPath);
}
}
}
}
inline void AssetWriter::WriteMetadata()
{
Value asset;
asset.SetObject();
asset.AddMember("version", Value(mAsset.asset.version, mAl).Move(), mAl);
asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl);
mDoc.AddMember("asset", asset, mAl);
}
inline void AssetWriter::WriteExtensionsUsed()
{
Value exts;
exts.SetArray();
{
// This is used to export pbrSpecularGlossiness materials with GLTF 2.
if (this->mAsset.extensionsUsed.KHR_materials_pbrSpecularGlossiness) {
exts.PushBack(StringRef("KHR_materials_pbrSpecularGlossiness"), mAl);
}
}
if (!exts.Empty())
mDoc.AddMember("extensionsUsed", exts, mAl);
}
template<class T>
void AssetWriter::WriteObjects(LazyDict<T>& d)
{
if (d.mObjs.empty()) return;
Value* container = &mDoc;
if (d.mExtId) {
Value* exts = FindObject(mDoc, "extensions");
if (!exts) {
mDoc.AddMember("extensions", Value().SetObject().Move(), mDoc.GetAllocator());
exts = FindObject(mDoc, "extensions");
}
if (!(container = FindObject(*exts, d.mExtId))) {
exts->AddMember(StringRef(d.mExtId), Value().SetObject().Move(), mDoc.GetAllocator());
container = FindObject(*exts, d.mExtId);
}
}
Value* dict;
if (!(dict = FindArray(*container, d.mDictId))) {
container->AddMember(StringRef(d.mDictId), Value().SetArray().Move(), mDoc.GetAllocator());
dict = FindArray(*container, d.mDictId);
}
for (size_t i = 0; i < d.mObjs.size(); ++i) {
if (d.mObjs[i]->IsSpecial()) continue;
Value obj;
obj.SetObject();
if (!d.mObjs[i]->name.empty()) {
obj.AddMember("name", StringRef(d.mObjs[i]->name.c_str()), mAl);
}
Write(obj, *d.mObjs[i], *this);
dict->PushBack(obj, mAl);
}
}
template<class T>
void WriteLazyDict(LazyDict<T>& d, AssetWriter& w)
{
w.WriteObjects(d);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,134 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2017, 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 GltfExporter.h
* Declares the exporter class to write a scene to a gltf/glb file
*/
#ifndef AI_GLTF2EXPORTER_H_INC
#define AI_GLTF2EXPORTER_H_INC
#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
#include <assimp/types.h>
#include <assimp/material.h>
#include <sstream>
#include <vector>
#include <map>
#include <memory>
struct aiScene;
struct aiNode;
struct aiMaterial;
namespace glTF2
{
template<class T>
class Ref;
class Asset;
struct TexProperty;
struct TextureInfo;
struct NormalTextureInfo;
struct OcclusionTextureInfo;
struct Node;
struct Texture;
// Vec/matrix types, as raw float arrays
typedef float (vec3)[3];
typedef float (vec4)[4];
}
namespace Assimp
{
class IOSystem;
class IOStream;
class ExportProperties;
// ------------------------------------------------------------------------------------------------
/** Helper class to export a given scene to an glTF file. */
// ------------------------------------------------------------------------------------------------
class glTF2Exporter
{
public:
/// Constructor for a specific scene to export
glTF2Exporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene,
const ExportProperties* pProperties, bool binary);
private:
const char* mFilename;
IOSystem* mIOSystem;
const aiScene* mScene;
const ExportProperties* mProperties;
std::map<std::string, unsigned int> mTexturesByPath;
std::shared_ptr<glTF2::Asset> mAsset;
std::vector<unsigned char> mBodyData;
void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
void GetTexSampler(const aiMaterial* mat, glTF2::Ref<glTF2::Texture> texture, aiTextureType tt, unsigned int slot);
void GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int idx);
void GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int idx);
void GetMatTex(const aiMaterial* mat, glTF2::Ref<glTF2::Texture>& texture, aiTextureType tt, unsigned int slot);
void GetMatTex(const aiMaterial* mat, glTF2::TextureInfo& prop, aiTextureType tt, unsigned int slot);
void GetMatTex(const aiMaterial* mat, glTF2::NormalTextureInfo& prop, aiTextureType tt, unsigned int slot);
void GetMatTex(const aiMaterial* mat, glTF2::OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot);
void GetMatColor(const aiMaterial* mat, glTF2::vec4& prop, const char* propName, int type, int idx);
void GetMatColor(const aiMaterial* mat, glTF2::vec3& prop, const char* propName, int type, int idx);
void ExportMetadata();
void ExportMaterials();
void ExportMeshes();
void MergeMeshes();
unsigned int ExportNodeHierarchy(const aiNode* n);
unsigned int ExportNode(const aiNode* node, glTF2::Ref<glTF2::Node>& parent);
void ExportScene();
void ExportAnimations();
};
}
#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
#endif // AI_GLTF2EXPORTER_H_INC

View File

@ -0,0 +1,654 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2017, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
#include "glTF2Importer.h"
#include "StringComparison.h"
#include "StringUtils.h"
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/ai_assert.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/importerdesc.h>
#include <memory>
#include "MakeVerboseFormat.h"
#include "glTF2Asset.h"
// This is included here so WriteLazyDict<T>'s definition is found.
#include "glTF2AssetWriter.h"
#include <rapidjson/document.h>
#include <rapidjson/rapidjson.h>
using namespace Assimp;
using namespace glTF2;
//
// glTF2Importer
//
static const aiImporterDesc desc = {
"glTF2 Importer",
"",
"",
"",
aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental,
0,
0,
0,
0,
"gltf glb"
};
glTF2Importer::glTF2Importer()
: BaseImporter()
, meshOffsets()
, embeddedTexIdxs()
, mScene( NULL ) {
// empty
}
glTF2Importer::~glTF2Importer() {
// empty
}
const aiImporterDesc* glTF2Importer::GetInfo() const
{
return &desc;
}
bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
const std::string &extension = GetExtension(pFile);
if (extension != "gltf") // We currently can't read glTF2 binary files (.glb), yet
return false;
if (checkSig && pIOHandler) {
glTF2::Asset asset(pIOHandler);
try {
asset.Load(pFile);
std::string version = asset.asset.version;
return !version.empty() && version[0] == '2';
} catch (...) {
return false;
}
}
return false;
}
//static void CopyValue(const glTF2::vec3& v, aiColor3D& out)
//{
// out.r = v[0]; out.g = v[1]; out.b = v[2];
//}
static void CopyValue(const glTF2::vec4& v, aiColor4D& out)
{
out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = v[3];
}
/*static void CopyValue(const glTF2::vec4& v, aiColor3D& out)
{
out.r = v[0]; out.g = v[1]; out.b = v[2];
}*/
static void CopyValue(const glTF2::vec3& v, aiColor4D& out)
{
out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = 1.0;
}
static void CopyValue(const glTF2::vec3& v, aiVector3D& out)
{
out.x = v[0]; out.y = v[1]; out.z = v[2];
}
static void CopyValue(const glTF2::vec4& v, aiQuaternion& out)
{
out.x = v[0]; out.y = v[1]; out.z = v[2]; out.w = v[3];
}
static void CopyValue(const glTF2::mat4& v, aiMatrix4x4& o)
{
o.a1 = v[ 0]; o.b1 = v[ 1]; o.c1 = v[ 2]; o.d1 = v[ 3];
o.a2 = v[ 4]; o.b2 = v[ 5]; o.c2 = v[ 6]; o.d2 = v[ 7];
o.a3 = v[ 8]; o.b3 = v[ 9]; o.c3 = v[10]; o.d3 = v[11];
o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15];
}
inline void SetMaterialColorProperty(Asset& r, vec4& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx)
{
aiColor4D col;
CopyValue(prop, col);
mat->AddProperty(&col, 1, pKey, type, idx);
}
inline void SetMaterialColorProperty(Asset& r, vec3& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx)
{
aiColor4D col;
CopyValue(prop, col);
mat->AddProperty(&col, 1, pKey, type, idx);
}
inline void SetMaterialTextureProperty(std::vector<int>& embeddedTexIdxs, Asset& r, glTF2::TextureInfo prop, aiMaterial* mat, aiTextureType texType, unsigned int texSlot = 0)
{
if (prop.texture && prop.texture->source) {
aiString uri(prop.texture->source->uri);
int texIdx = embeddedTexIdxs[prop.texture->source.GetIndex()];
if (texIdx != -1) { // embedded
// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
uri.data[0] = '*';
uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx);
}
mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot));
mat->AddProperty(&prop.texCoord, 1, _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, texType, texSlot);
if (prop.texture->sampler) {
Ref<Sampler> sampler = prop.texture->sampler;
aiString name(sampler->name);
aiString id(sampler->id);
mat->AddProperty(&name, AI_MATKEY_GLTF_MAPPINGNAME(texType, texSlot));
mat->AddProperty(&id, AI_MATKEY_GLTF_MAPPINGID(texType, texSlot));
mat->AddProperty(&sampler->wrapS, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot));
mat->AddProperty(&sampler->wrapT, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot));
if (sampler->magFilter != SamplerMagFilter::UNSET) {
mat->AddProperty(&sampler->magFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(texType, texSlot));
}
if (sampler->minFilter != SamplerMinFilter::UNSET) {
mat->AddProperty(&sampler->minFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(texType, texSlot));
}
}
}
}
void glTF2Importer::ImportMaterials(glTF2::Asset& r)
{
mScene->mNumMaterials = unsigned(r.materials.Size());
mScene->mMaterials = new aiMaterial*[mScene->mNumMaterials];
for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) {
aiMaterial* aimat = mScene->mMaterials[i] = new aiMaterial();
Material& mat = r.materials[i];
if (!mat.name.empty()) {
aiString str(mat.name);
aimat->AddProperty(&str, AI_MATKEY_NAME);
}
SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_COLOR_DIFFUSE);
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_DIFFUSE);
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE);
aimat->AddProperty(&mat.pbrMetallicRoughness.metallicFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR);
aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR);
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.normalTexture, aimat, aiTextureType_NORMALS);
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.occlusionTexture, aimat, aiTextureType_LIGHTMAP);
SetMaterialTextureProperty(embeddedTexIdxs, r, mat.emissiveTexture, aimat, aiTextureType_EMISSIVE);
SetMaterialColorProperty(r, mat.emissiveFactor, aimat, AI_MATKEY_COLOR_EMISSIVE);
aimat->AddProperty(&mat.doubleSided, 1, AI_MATKEY_TWOSIDED);
aiString alphaMode(mat.alphaMode);
aimat->AddProperty(&alphaMode, AI_MATKEY_GLTF_ALPHAMODE);
aimat->AddProperty(&mat.alphaCutoff, 1, AI_MATKEY_GLTF_ALPHACUTOFF);
//pbrSpecularGlossiness
if (mat.pbrSpecularGlossiness.isPresent) {
PbrSpecularGlossiness &pbrSG = mat.pbrSpecularGlossiness.value;
aimat->AddProperty(&mat.pbrSpecularGlossiness.isPresent, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS);
SetMaterialColorProperty(r, pbrSG.diffuseFactor, aimat, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_DIFFUSE_FACTOR);
SetMaterialColorProperty(r, pbrSG.specularFactor, aimat, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_SPECULAR_FACTOR);
aimat->AddProperty(&pbrSG.glossinessFactor, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR);
SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.diffuseTexture, aimat, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_DIFFUSE_TEXTURE);
SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.specularGlossinessTexture, aimat, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_SPECULARGLOSSINESS_TEXTURE);
}
}
}
static inline void SetFace(aiFace& face, int a)
{
face.mNumIndices = 1;
face.mIndices = new unsigned int[1];
face.mIndices[0] = a;
}
static inline void SetFace(aiFace& face, int a, int b)
{
face.mNumIndices = 2;
face.mIndices = new unsigned int[2];
face.mIndices[0] = a;
face.mIndices[1] = b;
}
static inline void SetFace(aiFace& face, int a, int b, int c)
{
face.mNumIndices = 3;
face.mIndices = new unsigned int[3];
face.mIndices[0] = a;
face.mIndices[1] = b;
face.mIndices[2] = c;
}
static inline bool CheckValidFacesIndices(aiFace* faces, unsigned nFaces, unsigned nVerts)
{
for (unsigned i = 0; i < nFaces; ++i) {
for (unsigned j = 0; j < faces[i].mNumIndices; ++j) {
unsigned idx = faces[i].mIndices[j];
if (idx >= nVerts)
return false;
}
}
return true;
}
void glTF2Importer::ImportMeshes(glTF2::Asset& r)
{
std::vector<aiMesh*> meshes;
unsigned int k = 0;
for (unsigned int m = 0; m < r.meshes.Size(); ++m) {
Mesh& mesh = r.meshes[m];
meshOffsets.push_back(k);
k += unsigned(mesh.primitives.size());
for (unsigned int p = 0; p < mesh.primitives.size(); ++p) {
Mesh::Primitive& prim = mesh.primitives[p];
aiMesh* aim = new aiMesh();
meshes.push_back(aim);
aim->mName = mesh.name.empty() ? mesh.id : mesh.name;
if (mesh.primitives.size() > 1) {
size_t& len = aim->mName.length;
aim->mName.data[len] = '-';
len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p);
}
switch (prim.mode) {
case PrimitiveMode_POINTS:
aim->mPrimitiveTypes |= aiPrimitiveType_POINT;
break;
case PrimitiveMode_LINES:
case PrimitiveMode_LINE_LOOP:
case PrimitiveMode_LINE_STRIP:
aim->mPrimitiveTypes |= aiPrimitiveType_LINE;
break;
case PrimitiveMode_TRIANGLES:
case PrimitiveMode_TRIANGLE_STRIP:
case PrimitiveMode_TRIANGLE_FAN:
aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
break;
}
Mesh::Primitive::Attributes& attr = prim.attributes;
if (attr.position.size() > 0 && attr.position[0]) {
aim->mNumVertices = attr.position[0]->count;
attr.position[0]->ExtractData(aim->mVertices);
}
if (attr.normal.size() > 0 && attr.normal[0]) attr.normal[0]->ExtractData(aim->mNormals);
for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) {
attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]);
aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents();
aiVector3D* values = aim->mTextureCoords[tc];
for (unsigned int i = 0; i < aim->mNumVertices; ++i) {
values[i].y = 1 - values[i].y; // Flip Y coords
}
}
if (prim.indices) {
aiFace* faces = 0;
unsigned int nFaces = 0;
unsigned int count = prim.indices->count;
Accessor::Indexer data = prim.indices->GetIndexer();
ai_assert(data.IsValid());
switch (prim.mode) {
case PrimitiveMode_POINTS: {
nFaces = count;
faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; ++i) {
SetFace(faces[i], data.GetUInt(i));
}
break;
}
case PrimitiveMode_LINES: {
nFaces = count / 2;
faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 2) {
SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1));
}
break;
}
case PrimitiveMode_LINE_LOOP:
case PrimitiveMode_LINE_STRIP: {
nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
faces = new aiFace[nFaces];
SetFace(faces[0], data.GetUInt(0), data.GetUInt(1));
for (unsigned int i = 2; i < count; ++i) {
SetFace(faces[i - 1], faces[i - 2].mIndices[1], data.GetUInt(i));
}
if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop
SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]);
}
break;
}
case PrimitiveMode_TRIANGLES: {
nFaces = count / 3;
faces = new aiFace[nFaces];
for (unsigned int i = 0; i < count; i += 3) {
SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2));
}
break;
}
case PrimitiveMode_TRIANGLE_STRIP: {
nFaces = count - 2;
faces = new aiFace[nFaces];
SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2));
for (unsigned int i = 3; i < count; ++i) {
SetFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], data.GetUInt(i));
}
break;
}
case PrimitiveMode_TRIANGLE_FAN:
nFaces = count - 2;
faces = new aiFace[nFaces];
SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2));
for (unsigned int i = 3; i < count; ++i) {
SetFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i));
}
break;
}
if (faces) {
aim->mFaces = faces;
aim->mNumFaces = nFaces;
ai_assert(CheckValidFacesIndices(faces, nFaces, aim->mNumVertices));
}
}
if (prim.material) {
aim->mMaterialIndex = prim.material.GetIndex();
}
}
}
meshOffsets.push_back(k);
CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes);
}
void glTF2Importer::ImportCameras(glTF2::Asset& r)
{
if (!r.cameras.Size()) return;
mScene->mNumCameras = r.cameras.Size();
mScene->mCameras = new aiCamera*[r.cameras.Size()];
for (size_t i = 0; i < r.cameras.Size(); ++i) {
Camera& cam = r.cameras[i];
aiCamera* aicam = mScene->mCameras[i] = new aiCamera();
if (cam.type == Camera::Perspective) {
aicam->mAspect = cam.cameraProperties.perspective.aspectRatio;
aicam->mHorizontalFOV = cam.cameraProperties.perspective.yfov * aicam->mAspect;
aicam->mClipPlaneFar = cam.cameraProperties.perspective.zfar;
aicam->mClipPlaneNear = cam.cameraProperties.perspective.znear;
}
else {
// assimp does not support orthographic cameras
}
}
}
aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector<unsigned int>& meshOffsets, glTF2::Ref<glTF2::Node>& ptr)
{
Node& node = *ptr;
aiNode* ainode = new aiNode(node.id);
if (!node.children.empty()) {
ainode->mNumChildren = unsigned(node.children.size());
ainode->mChildren = new aiNode*[ainode->mNumChildren];
for (unsigned int i = 0; i < ainode->mNumChildren; ++i) {
aiNode* child = ImportNode(pScene, r, meshOffsets, node.children[i]);
child->mParent = ainode;
ainode->mChildren[i] = child;
}
}
aiMatrix4x4& matrix = ainode->mTransformation;
if (node.matrix.isPresent) {
CopyValue(node.matrix.value, matrix);
}
else {
if (node.translation.isPresent) {
aiVector3D trans;
CopyValue(node.translation.value, trans);
aiMatrix4x4 t;
aiMatrix4x4::Translation(trans, t);
matrix = t * matrix;
}
if (node.scale.isPresent) {
aiVector3D scal(1.f);
CopyValue(node.scale.value, scal);
aiMatrix4x4 s;
aiMatrix4x4::Scaling(scal, s);
matrix = s * matrix;
}
if (node.rotation.isPresent) {
aiQuaternion rot;
CopyValue(node.rotation.value, rot);
matrix = aiMatrix4x4(rot.GetMatrix()) * matrix;
}
}
if (!node.meshes.empty()) {
int count = 0;
for (size_t i = 0; i < node.meshes.size(); ++i) {
int idx = node.meshes[i].GetIndex();
count += meshOffsets[idx + 1] - meshOffsets[idx];
}
ainode->mNumMeshes = count;
ainode->mMeshes = new unsigned int[count];
int k = 0;
for (size_t i = 0; i < node.meshes.size(); ++i) {
int idx = node.meshes[i].GetIndex();
for (unsigned int j = meshOffsets[idx]; j < meshOffsets[idx + 1]; ++j, ++k) {
ainode->mMeshes[k] = j;
}
}
}
if (node.camera) {
pScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName;
}
return ainode;
}
void glTF2Importer::ImportNodes(glTF2::Asset& r)
{
if (!r.scene) return;
std::vector< Ref<Node> > rootNodes = r.scene->nodes;
// The root nodes
unsigned int numRootNodes = unsigned(rootNodes.size());
if (numRootNodes == 1) { // a single root node: use it
mScene->mRootNode = ImportNode(mScene, r, meshOffsets, rootNodes[0]);
}
else if (numRootNodes > 1) { // more than one root node: create a fake root
aiNode* root = new aiNode("ROOT");
root->mChildren = new aiNode*[numRootNodes];
for (unsigned int i = 0; i < numRootNodes; ++i) {
aiNode* node = ImportNode(mScene, r, meshOffsets, rootNodes[i]);
node->mParent = root;
root->mChildren[root->mNumChildren++] = node;
}
mScene->mRootNode = root;
}
//if (!mScene->mRootNode) {
// mScene->mRootNode = new aiNode("EMPTY");
//}
}
void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset& r)
{
embeddedTexIdxs.resize(r.images.Size(), -1);
int numEmbeddedTexs = 0;
for (size_t i = 0; i < r.images.Size(); ++i) {
if (r.images[i].HasData())
numEmbeddedTexs += 1;
}
if (numEmbeddedTexs == 0)
return;
mScene->mTextures = new aiTexture*[numEmbeddedTexs];
// Add the embedded textures
for (size_t i = 0; i < r.images.Size(); ++i) {
Image img = r.images[i];
if (!img.HasData()) continue;
int idx = mScene->mNumTextures++;
embeddedTexIdxs[i] = idx;
aiTexture* tex = mScene->mTextures[idx] = new aiTexture();
size_t length = img.GetDataLength();
void* data = img.StealData();
tex->mWidth = static_cast<unsigned int>(length);
tex->mHeight = 0;
tex->pcData = reinterpret_cast<aiTexel*>(data);
if (!img.mimeType.empty()) {
const char* ext = strchr(img.mimeType.c_str(), '/') + 1;
if (ext) {
if (strcmp(ext, "jpeg") == 0) ext = "jpg";
size_t len = strlen(ext);
if (len <= 3) {
strcpy(tex->achFormatHint, ext);
}
}
}
}
}
void glTF2Importer::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) {
this->mScene = pScene;
// read the asset file
glTF2::Asset asset(pIOHandler);
asset.Load(pFile);
//
// Copy the data out
//
ImportEmbeddedTextures(asset);
ImportMaterials(asset);
ImportMeshes(asset);
ImportCameras(asset);
ImportNodes(asset);
// TODO: it does not split the loaded vertices, should it?
//pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
MakeVerboseFormatProcess process;
process.Execute(pScene);
if (pScene->mNumMeshes == 0) {
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
}
}
#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER

View File

@ -0,0 +1,91 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2017, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#ifndef AI_GLTF2IMPORTER_H_INC
#define AI_GLTF2IMPORTER_H_INC
#include "BaseImporter.h"
#include <assimp/DefaultIOSystem.h>
struct aiNode;
namespace glTF2
{
class Asset;
}
namespace Assimp {
/**
* Load the glTF2 format.
* https://github.com/KhronosGroup/glTF/tree/master/specification
*/
class glTF2Importer : public BaseImporter{
public:
glTF2Importer();
virtual ~glTF2Importer();
virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const;
protected:
virtual const aiImporterDesc* GetInfo() const;
virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler );
private:
std::vector<unsigned int> meshOffsets;
std::vector<int> embeddedTexIdxs;
aiScene* mScene;
void ImportEmbeddedTextures(glTF2::Asset& a);
void ImportMaterials(glTF2::Asset& a);
void ImportMeshes(glTF2::Asset& a);
void ImportCameras(glTF2::Asset& a);
void ImportLights(glTF2::Asset& a);
void ImportNodes(glTF2::Asset& a);
};
} // Namespace assimp
#endif // AI_GLTF2IMPORTER_H_INC

View File

@ -232,7 +232,9 @@ namespace glTF
case ComponentType_UNSIGNED_BYTE: case ComponentType_UNSIGNED_BYTE:
return 1; return 1;
default: default:
throw DeadlyImportError("GLTF: Unsupported Component Type "+t); std::string err = "GLTF: Unsupported Component Type ";
err += t;
throw DeadlyImportError(err);
} }
} }
@ -1058,13 +1060,13 @@ namespace glTF
std::string version; //!< Specifies the target rendering API (default: "1.0.3") std::string version; //!< Specifies the target rendering API (default: "1.0.3")
} profile; //!< Specifies the target rendering API and version, e.g., WebGL 1.0.3. (default: {}) } profile; //!< Specifies the target rendering API and version, e.g., WebGL 1.0.3. (default: {})
int version; //!< The glTF format version (should be 1) std::string version; //!< The glTF format version (should be 1.0)
void Read(Document& doc); void Read(Document& doc);
AssetMetadata() AssetMetadata()
: premultipliedAlpha(false) : premultipliedAlpha(false)
, version(0) , version("")
{ {
} }
}; };

View File

@ -40,6 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "StringUtils.h" #include "StringUtils.h"
#include <iomanip>
// Header files, Assimp // Header files, Assimp
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
@ -128,6 +129,12 @@ namespace {
return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0; return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0;
} }
inline Value* FindNumber(Value& val, const char* id)
{
Value::MemberIterator it = val.FindMember(id);
return (it != val.MemberEnd() && it->value.IsNumber()) ? &it->value : 0;
}
inline Value* FindArray(Value& val, const char* id) inline Value* FindArray(Value& val, const char* id)
{ {
Value::MemberIterator it = val.FindMember(id); Value::MemberIterator it = val.FindMember(id);
@ -309,7 +316,9 @@ inline void Buffer::Read(Value& obj, Asset& r)
} }
else { // Local file else { // Local file
if (byteLength > 0) { if (byteLength > 0) {
IOStream* file = r.OpenFile(uri, "rb"); std::string dir = !r.mCurrentAssetDir.empty() ? (r.mCurrentAssetDir + "/") : "";
IOStream* file = r.OpenFile(dir + uri, "rb");
if (file) { if (file) {
bool ok = LoadFromStream(*file, byteLength); bool ok = LoadFromStream(*file, byteLength);
delete file; delete file;
@ -332,7 +341,7 @@ inline bool Buffer::LoadFromStream(IOStream& stream, size_t length, size_t baseO
stream.Seek(baseOffset, aiOrigin_SET); stream.Seek(baseOffset, aiOrigin_SET);
} }
mData.reset(new uint8_t[byteLength]); mData.reset(new uint8_t[byteLength], std::default_delete<uint8_t[]>());
if (stream.Read(mData.get(), byteLength, 1) != 1) { if (stream.Read(mData.get(), byteLength, 1) != 1) {
return false; return false;
@ -1228,13 +1237,21 @@ inline void Scene::Read(Value& obj, Asset& r)
inline void AssetMetadata::Read(Document& doc) inline void AssetMetadata::Read(Document& doc)
{ {
// read the version, etc. // read the version, etc.
int statedVersion = 0;
if (Value* obj = FindObject(doc, "asset")) { if (Value* obj = FindObject(doc, "asset")) {
ReadMember(*obj, "copyright", copyright); ReadMember(*obj, "copyright", copyright);
ReadMember(*obj, "generator", generator); ReadMember(*obj, "generator", generator);
premultipliedAlpha = MemberOrDefault(*obj, "premultipliedAlpha", false); premultipliedAlpha = MemberOrDefault(*obj, "premultipliedAlpha", false);
statedVersion = MemberOrDefault(*obj, "version", 0);
if (Value* versionString = FindString(*obj, "version")) {
version = versionString->GetString();
} else if (Value* versionNumber = FindNumber (*obj, "version")) {
char buf[4];
ai_snprintf(buf, 4, "%.1f", versionNumber->GetDouble());
version = buf;
}
if (Value* profile = FindObject(*obj, "profile")) { if (Value* profile = FindObject(*obj, "profile")) {
ReadMember(*profile, "api", this->profile.api); ReadMember(*profile, "api", this->profile.api);
@ -1242,16 +1259,8 @@ inline void AssetMetadata::Read(Document& doc)
} }
} }
version = std::max(statedVersion, version); if (version.empty() || version[0] != '1') {
if (version == 0) { throw DeadlyImportError("GLTF: Unsupported glTF version: " + version);
// if missing version, we'll assume version 1...
version = 1;
}
if (version != 1) {
char msg[128];
ai_snprintf(msg, 128, "GLTF: Unsupported glTF version: %d", version);
throw DeadlyImportError(msg);
} }
} }
@ -1273,7 +1282,7 @@ inline void Asset::ReadBinaryHeader(IOStream& stream)
} }
AI_SWAP4(header.version); AI_SWAP4(header.version);
asset.version = header.version; asset.version = std::to_string(header.version);
if (header.version != 1) { if (header.version != 1) {
throw DeadlyImportError("GLTF: Unsupported binary glTF version"); throw DeadlyImportError("GLTF: Unsupported binary glTF version");
} }

View File

@ -606,13 +606,8 @@ namespace glTF {
{ {
Value asset; Value asset;
asset.SetObject(); asset.SetObject();
{ asset.AddMember("version", Value(mAsset.asset.version, mAl).Move(), mAl);
char versionChar[10];
ai_snprintf(versionChar, sizeof(versionChar), "%d", mAsset.asset.version);
asset.AddMember("version", Value(versionChar, mAl).Move(), mAl);
asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl); asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl);
}
mDoc.AddMember("asset", asset, mAl); mDoc.AddMember("asset", asset, mAl);
} }

View File

@ -444,7 +444,7 @@ void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref<Mesh>& meshRef, Ref<Buf
Ref<Node> nodeRef = mAsset.nodes.Get(aib->mName.C_Str()); Ref<Node> nodeRef = mAsset.nodes.Get(aib->mName.C_Str());
nodeRef->jointName = nodeRef->id; nodeRef->jointName = nodeRef->id;
unsigned int jointNamesIndex; unsigned int jointNamesIndex = 0;
bool addJointToJointNames = true; bool addJointToJointNames = true;
for ( unsigned int idx_joint = 0; idx_joint < skinRef->jointNames.size(); ++idx_joint) { for ( unsigned int idx_joint = 0; idx_joint < skinRef->jointNames.size(); ++idx_joint) {
if (skinRef->jointNames[idx_joint]->jointName.compare(nodeRef->jointName) == 0) { if (skinRef->jointNames[idx_joint]->jointName.compare(nodeRef->jointName) == 0) {
@ -473,7 +473,7 @@ void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref<Mesh>& meshRef, Ref<Buf
continue; continue;
} }
vertexJointData[vertexId][jointsPerVertex[vertexId]] = jointNamesIndex; vertexJointData[vertexId][jointsPerVertex[vertexId]] = static_cast<float>(jointNamesIndex);
vertexWeightData[vertexId][jointsPerVertex[vertexId]] = vertWeight; vertexWeightData[vertexId][jointsPerVertex[vertexId]] = vertWeight;
jointsPerVertex[vertexId] += 1; jointsPerVertex[vertexId] += 1;
@ -507,7 +507,7 @@ void glTFExporter::ExportMeshes()
// Variables needed for compression. BEGIN. // Variables needed for compression. BEGIN.
// Indices, not pointers - because pointer to buffer is changing while writing to it. // Indices, not pointers - because pointer to buffer is changing while writing to it.
size_t idx_srcdata_begin;// Index of buffer before writing mesh data. Also, index of begin of coordinates array in buffer. size_t idx_srcdata_begin = 0; // Index of buffer before writing mesh data. Also, index of begin of coordinates array in buffer.
size_t idx_srcdata_normal = SIZE_MAX;// Index of begin of normals array in buffer. SIZE_MAX - mean that mesh has no normals. size_t idx_srcdata_normal = SIZE_MAX;// Index of begin of normals array in buffer. SIZE_MAX - mean that mesh has no normals.
std::vector<size_t> idx_srcdata_tc;// Array of indices. Every index point to begin of texture coordinates array in buffer. std::vector<size_t> idx_srcdata_tc;// Array of indices. Every index point to begin of texture coordinates array in buffer.
size_t idx_srcdata_ind;// Index of begin of coordinates indices array in buffer. size_t idx_srcdata_ind;// Index of begin of coordinates indices array in buffer.
@ -872,10 +872,10 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
size_t frameIndex = i * nodeChannel->mNumPositionKeys / numKeyframes; size_t frameIndex = i * nodeChannel->mNumPositionKeys / numKeyframes;
// mTime is measured in ticks, but GLTF time is measured in seconds, so convert. // mTime is measured in ticks, but GLTF time is measured in seconds, so convert.
// Check if we have to cast type here. e.g. uint16_t() // Check if we have to cast type here. e.g. uint16_t()
timeData[i] = nodeChannel->mPositionKeys[frameIndex].mTime / ticksPerSecond; timeData[i] = static_cast<float>(nodeChannel->mPositionKeys[frameIndex].mTime / ticksPerSecond);
} }
Ref<Accessor> timeAccessor = ExportData(mAsset, animId, buffer, numKeyframes, &timeData[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_FLOAT); Ref<Accessor> timeAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), &timeData[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_FLOAT);
if (timeAccessor) animRef->Parameters.TIME = timeAccessor; if (timeAccessor) animRef->Parameters.TIME = timeAccessor;
} }
@ -888,7 +888,7 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
translationData[i] = nodeChannel->mPositionKeys[frameIndex].mValue; translationData[i] = nodeChannel->mPositionKeys[frameIndex].mValue;
} }
Ref<Accessor> tranAccessor = ExportData(mAsset, animId, buffer, numKeyframes, translationData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); Ref<Accessor> tranAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), translationData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
if ( tranAccessor ) { if ( tranAccessor ) {
animRef->Parameters.translation = tranAccessor; animRef->Parameters.translation = tranAccessor;
} }
@ -904,7 +904,7 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
scaleData[i] = nodeChannel->mScalingKeys[frameIndex].mValue; scaleData[i] = nodeChannel->mScalingKeys[frameIndex].mValue;
} }
Ref<Accessor> scaleAccessor = ExportData(mAsset, animId, buffer, numKeyframes, scaleData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); Ref<Accessor> scaleAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), scaleData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
if ( scaleAccessor ) { if ( scaleAccessor ) {
animRef->Parameters.scale = scaleAccessor; animRef->Parameters.scale = scaleAccessor;
} }
@ -923,7 +923,7 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref<Animati
rotationData[i][3] = nodeChannel->mRotationKeys[frameIndex].mValue.w; rotationData[i][3] = nodeChannel->mRotationKeys[frameIndex].mValue.w;
} }
Ref<Accessor> rotAccessor = ExportData(mAsset, animId, buffer, numKeyframes, rotationData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); Ref<Accessor> rotAccessor = ExportData(mAsset, animId, buffer, static_cast<unsigned int>(numKeyframes), rotationData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
if ( rotAccessor ) { if ( rotAccessor ) {
animRef->Parameters.rotation = rotAccessor; animRef->Parameters.rotation = rotAccessor;
} }
@ -953,7 +953,7 @@ void glTFExporter::ExportAnimations()
Ref<Animation> animRef = mAsset->animations.Create(name); Ref<Animation> animRef = mAsset->animations.Create(name);
/******************* Parameters ********************/ /******************* Parameters ********************/
ExtractAnimationData(*mAsset, name, animRef, bufferRef, nodeChannel, anim->mTicksPerSecond); ExtractAnimationData(*mAsset, name, animRef, bufferRef, nodeChannel, static_cast<float>(anim->mTicksPerSecond));
for (unsigned int j = 0; j < 3; ++j) { for (unsigned int j = 0; j < 3; ++j) {
std::string channelType; std::string channelType;

View File

@ -100,24 +100,19 @@ const aiImporterDesc* glTFImporter::GetInfo() const
bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{ {
const std::string& extension = GetExtension(pFile); const std::string &extension = GetExtension(pFile);
if (extension == "gltf" || extension == "glb") if (extension != "gltf" && extension != "glb")
return true; return false;
if ((checkSig || !extension.length()) && pIOHandler) { if (checkSig && pIOHandler) {
char buffer[4]; glTF::Asset asset(pIOHandler);
try {
std::unique_ptr<IOStream> pStream(pIOHandler->Open(pFile)); asset.Load(pFile, extension == "glb");
if (pStream && pStream->Read(buffer, sizeof(buffer), 1) == 1) { std::string version = asset.asset.version;
if (memcmp(buffer, AI_GLB_MAGIC_NUMBER, sizeof(buffer)) == 0) { return !version.empty() && version[0] == '1';
return true; // Has GLB header } catch (...) {
} return false;
else if (memcmp(buffer, "{\r\n ", sizeof(buffer)) == 0
|| memcmp(buffer, "{\n ", sizeof(buffer)) == 0) {
// seems a JSON file, and we're the only format that can read them
return true;
}
} }
} }
@ -179,10 +174,8 @@ inline void SetMaterialColorProperty(std::vector<int>& embeddedTexIdxs, Asset& r
else { else {
aiColor4D col; aiColor4D col;
CopyValue(prop.color, col); CopyValue(prop.color, col);
if (col.r != 1.f || col.g != 1.f || col.b != 1.f || col.a != 1.f) {
mat->AddProperty(&col, 1, pKey, type, idx); mat->AddProperty(&col, 1, pKey, type, idx);
} }
}
} }
void glTFImporter::ImportMaterials(glTF::Asset& r) void glTFImporter::ImportMaterials(glTF::Asset& r)

View File

@ -140,8 +140,8 @@ namespace o3dgc
{ {
return End(element) - Begin(element); return End(element) - Begin(element);
} }
long * const GetNumNeighborsBuffer() { return m_numNeighbors;} long * GetNumNeighborsBuffer() { return m_numNeighbors;}
long * const GetNeighborsBuffer() { return m_neighbors;} long * GetNeighborsBuffer() { return m_neighbors;}
private: private:
long m_neighborsSize; // actual allocated size for m_neighbors long m_neighborsSize; // actual allocated size for m_neighbors

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