Merge pull request #15 from assimp/master

Update Fork
pull/4057/head
Madrich 2019-07-13 06:49:58 +02:00 committed by GitHub
commit 5fb77f8523
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
462 changed files with 8599 additions and 2170 deletions

7
.gitignore vendored
View File

@ -7,6 +7,12 @@ build
*.sln *.sln
*.ncb *.ncb
*.vcproj *.vcproj
*.vcxproj.user
*.VC.db
*.VC.db-shm
*.VC.db-wal
*.VC.opendb
*.ipch
# Output # Output
bin/ bin/
@ -32,6 +38,7 @@ cmake_uninstall.cmake
*.dir/ *.dir/
assimp-config.cmake assimp-config.cmake
assimp-config-version.cmake assimp-config-version.cmake
assimpTargets*.cmake
# MakeFile # MakeFile
Makefile Makefile

View File

@ -1,7 +1,7 @@
# Open Asset Import Library (assimp) # Open Asset Import Library (assimp)
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# Copyright (c) 2006-2019, assimp team # Copyright (c) 2006-2019, assimp team
#
# All rights reserved. # All rights reserved.
# #
# Redistribution and use of this software in source and binary forms, # Redistribution and use of this software in source and binary forms,
@ -34,9 +34,24 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# 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_POLICY_DEFAULT_CMP0074 NEW)
CMAKE_MINIMUM_REQUIRED( VERSION 2.8 )
PROJECT( Assimp ) CMAKE_MINIMUM_REQUIRED( VERSION 3.0 )
# Toggles the use of the hunter package manager
option(HUNTER_ENABLED "Enable Hunter package manager support" OFF)
include("cmake/HunterGate.cmake")
HunterGate(
URL "https://github.com/ruslo/hunter/archive/v0.23.176.tar.gz"
SHA1 "2e9ae973d028660b735ac4c6142725ca36a0048a"
)
IF(HUNTER_ENABLED)
add_definitions(-DASSIMP_USE_HUNTER)
ENDIF(HUNTER_ENABLED)
PROJECT( Assimp VERSION 5.0.0 )
# All supported options ############################################### # All supported options ###############################################
@ -67,7 +82,7 @@ OPTION( ASSIMP_NO_EXPORT
) )
OPTION( ASSIMP_BUILD_ZLIB 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."
@ -115,12 +130,12 @@ OPTION ( IGNORE_GIT_HASH
OFF OFF
) )
IF (IOS) IF (IOS AND NOT HUNTER_ENABLED)
IF (NOT CMAKE_BUILD_TYPE) IF (NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE "Release") SET(CMAKE_BUILD_TYPE "Release")
ENDIF (NOT CMAKE_BUILD_TYPE) ENDIF (NOT CMAKE_BUILD_TYPE)
ADD_DEFINITIONS(-DENABLE_BITCODE) ADD_DEFINITIONS(-DENABLE_BITCODE)
ENDIF (IOS) ENDIF (IOS AND NOT HUNTER_ENABLED)
# Use subset of Windows.h # Use subset of Windows.h
if (WIN32) if (WIN32)
@ -151,17 +166,18 @@ ELSE()
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 ${PROJECT_VERSION_MAJOR})
SET (ASSIMP_VERSION_MINOR 1) SET (ASSIMP_VERSION_MINOR ${PROJECT_VERSION_MINOR})
SET (ASSIMP_VERSION_PATCH 0) SET (ASSIMP_VERSION_PATCH ${PROJECT_VERSION_PATCH})
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 5)
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" )
# Enable C++11 support globally if(NOT HUNTER_ENABLED)
set_property( GLOBAL PROPERTY CXX_STANDARD 11 ) # Enable C++11 support globally
set_property( GLOBAL PROPERTY CXX_STANDARD 11 )
endif()
IF(NOT IGNORE_GIT_HASH) IF(NOT IGNORE_GIT_HASH)
# Get the current working branch # Get the current working branch
@ -203,6 +219,7 @@ CONFIGURE_FILE(
INCLUDE_DIRECTORIES( BEFORE INCLUDE_DIRECTORIES( BEFORE
./ ./
code/
include include
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}/include ${CMAKE_CURRENT_BINARY_DIR}/include
@ -221,9 +238,13 @@ ENDIF( UNIX )
# Grouped compiler settings # Grouped compiler settings
IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW) IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW)
IF(NOT HUNTER_ENABLED)
SET(CMAKE_CXX_FLAGS "-fPIC -std=c++0x ${CMAKE_CXX_FLAGS}")
SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
ENDIF()
# hide all not-exported symbols # hide all not-exported symbols
SET(CMAKE_CXX_FLAGS "-g -fvisibility=hidden -fPIC -fno-strict-aliasing -Wall -std=c++0x ${CMAKE_CXX_FLAGS}") SET(CMAKE_CXX_FLAGS "-g -fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
SET(CMAKE_C_FLAGS "-fPIC -fno-strict-aliasing ${CMAKE_C_FLAGS}") SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
SET(LIBSTDC++_LIBRARIES -lstdc++) SET(LIBSTDC++_LIBRARIES -lstdc++)
ELSEIF(MSVC) ELSEIF(MSVC)
# enable multi-core compilation with MSVC # enable multi-core compilation with MSVC
@ -234,20 +255,28 @@ ELSEIF(MSVC)
ADD_COMPILE_OPTIONS(/wd4351) ADD_COMPILE_OPTIONS(/wd4351)
ENDIF() ENDIF()
ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
SET(CMAKE_CXX_FLAGS "-g -fvisibility=hidden -fPIC -fno-strict-aliasing -Wall -Wno-long-long -std=c++11 ${CMAKE_CXX_FLAGS}" ) IF(NOT HUNTER_ENABLED)
SET(CMAKE_C_FLAGS "-fPIC -fno-strict-aliasing ${CMAKE_C_FLAGS}") SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 ${CMAKE_CXX_FLAGS}")
SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
ENDIF()
SET(CMAKE_CXX_FLAGS "-g -fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" )
SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
ELSEIF( CMAKE_COMPILER_IS_MINGW ) ELSEIF( CMAKE_COMPILER_IS_MINGW )
IF (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0) IF (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0)
message(FATAL_ERROR "MinGW is too old to be supported. Please update MinGW and try again.") message(FATAL_ERROR "MinGW is too old to be supported. Please update MinGW and try again.")
ELSEIF(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.3) ELSEIF(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.3)
message(WARNING "MinGW is old, if you experience errors, update MinGW.") message(WARNING "MinGW is old, if you experience errors, update MinGW.")
ENDIF() ENDIF()
SET( CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long -std=c++11 -Wa,-mbig-obj ${CMAKE_CXX_FLAGS}" ) IF(NOT HUNTER_ENABLED)
SET(CMAKE_C_FLAGS "-fPIC -fno-strict-aliasing ${CMAKE_C_FLAGS} ") SET(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
ENDIF()
SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long -Wa,-mbig-obj ${CMAKE_CXX_FLAGS}")
SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
ADD_DEFINITIONS( -U__STRICT_ANSI__ ) ADD_DEFINITIONS( -U__STRICT_ANSI__ )
ENDIF() ENDIF()
IF ( IOS ) IF ( IOS AND NOT HUNTER_ENABLED)
IF (CMAKE_BUILD_TYPE STREQUAL "Debug") IF (CMAKE_BUILD_TYPE STREQUAL "Debug")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -Og") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -Og")
@ -255,9 +284,10 @@ IF (CMAKE_BUILD_TYPE STREQUAL "Debug")
ELSE() ELSE()
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3")
# Experimental for pdb generation
ENDIF() ENDIF()
ENDIF( IOS ) ENDIF( IOS AND NOT HUNTER_ENABLED)
IF (ASSIMP_COVERALLS) IF (ASSIMP_COVERALLS)
MESSAGE(STATUS "Coveralls enabled") MESSAGE(STATUS "Coveralls enabled")
@ -324,20 +354,67 @@ IF (NOT TARGET uninstall)
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 IF(HUNTER_ENABLED)
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE) set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}")
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimpTargets.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets.cmake" @ONLY IMMEDIATE) set(INCLUDE_INSTALL_DIR "include")
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimpTargets-debug.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-debug.cmake" @ONLY IMMEDIATE)
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimpTargets-release.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-release.cmake" @ONLY IMMEDIATE) set(GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE)
#we should generated these scripts after CMake VERSION 3.0.2 using export(EXPORT ...) and write_basic_package_version_file(...) # Configuration
INSTALL(FILES set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
"${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake")
"${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
"${CMAKE_CURRENT_BINARY_DIR}/assimpTargets.cmake" set(NAMESPACE "${PROJECT_NAME}::")
"${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-debug.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-release.cmake" # Include module with fuction 'write_basic_package_version_file'
DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT}) include(CMakePackageConfigHelpers)
# Note: PROJECT_VERSION is used as a VERSION
write_basic_package_version_file("${VERSION_CONFIG}" COMPATIBILITY SameMajorVersion)
# Use variables:
# * TARGETS_EXPORT_NAME
# * PROJECT_NAME
configure_package_config_file(
"cmake/assimp-hunter-config.cmake.in"
"${PROJECT_CONFIG}"
INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}"
)
install(
FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}"
DESTINATION "${CONFIG_INSTALL_DIR}"
)
install(
EXPORT "${TARGETS_EXPORT_NAME}"
NAMESPACE "${NAMESPACE}"
DESTINATION "${CONFIG_INSTALL_DIR}"
)
ELSE(HUNTER_ENABLED)
# 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}/assimpTargets.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets.cmake" @ONLY IMMEDIATE)
IF (is_multi_config)
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimpTargets-debug.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-debug.cmake" @ONLY IMMEDIATE)
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimpTargets-release.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-release.cmake" @ONLY IMMEDIATE)
SET(PACKAGE_TARGETS_FILE "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-debug.cmake" "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-release.cmake")
ELSEIF (CMAKE_BUILD_TYPE STREQUAL Debug)
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimpTargets-debug.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-debug.cmake" @ONLY IMMEDIATE)
SET(PACKAGE_TARGETS_FILE "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-debug.cmake")
ELSE()
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimpTargets-release.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-release.cmake" @ONLY IMMEDIATE)
SET(PACKAGE_TARGETS_FILE "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets-release.cmake")
ENDIF()
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE)
#we should generated these scripts after CMake VERSION 3.0.2 using export(EXPORT ...) and write_basic_package_version_file(...)
INSTALL(FILES
"${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/assimpTargets.cmake"
${PACKAGE_TARGETS_FILE}
DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT})
ENDIF(HUNTER_ENABLED)
FIND_PACKAGE( DirectX ) FIND_PACKAGE( DirectX )
@ -352,48 +429,57 @@ ENDIF( SYSTEM_IRRXML )
# Search for external dependencies, and build them from source if not found # Search for external dependencies, and build them from source if not found
# Search for zlib # Search for zlib
IF ( NOT ASSIMP_BUILD_ZLIB ) IF(HUNTER_ENABLED)
FIND_PACKAGE(ZLIB) hunter_add_package(ZLIB)
ENDIF( NOT ASSIMP_BUILD_ZLIB ) find_package(ZLIB CONFIG REQUIRED)
IF( NOT ZLIB_FOUND ) add_definitions(-DASSIMP_BUILD_NO_OWN_ZLIB)
MESSAGE(STATUS "compiling zlib from sources") set(ZLIB_FOUND TRUE)
INCLUDE(CheckIncludeFile) set(ZLIB_LIBRARIES ZLIB::zlib)
INCLUDE(CheckTypeSize) set(ASSIMP_BUILD_MINIZIP TRUE)
INCLUDE(CheckFunctionExists) ELSE(HUNTER_ENABLED)
IF ( NOT ASSIMP_BUILD_ZLIB )
FIND_PACKAGE(ZLIB)
ENDIF( NOT ASSIMP_BUILD_ZLIB )
# Explicitly turn off ASM686 and AMD64 cmake options. IF( NOT ZLIB_FOUND )
# The AMD64 option causes a build failure on MSVC and the ASM builds seem to have problems: MESSAGE(STATUS "compiling zlib from sources")
# https://github.com/madler/zlib/issues/41#issuecomment-125848075 INCLUDE(CheckIncludeFile)
# Also prevents these options from "polluting" the cmake options if assimp is being INCLUDE(CheckTypeSize)
# included as a submodule. INCLUDE(CheckFunctionExists)
set( ASM686 FALSE CACHE INTERNAL "Override ZLIB flag to turn off assembly" FORCE )
set( AMD64 FALSE CACHE INTERNAL "Override ZLIB flag to turn off assembly" FORCE )
# compile from sources # Explicitly turn off ASM686 and AMD64 cmake options.
ADD_SUBDIRECTORY(contrib/zlib) # The AMD64 option causes a build failure on MSVC and the ASM builds seem to have problems:
SET(ZLIB_FOUND 1) # https://github.com/madler/zlib/issues/41#issuecomment-125848075
SET(ZLIB_LIBRARIES zlibstatic) # Also prevents these options from "polluting" the cmake options if assimp is being
SET(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib) # included as a submodule.
# need to ensure we don't link with system zlib or minizip as well. set( ASM686 FALSE CACHE INTERNAL "Override ZLIB flag to turn off assembly" FORCE )
SET(ASSIMP_BUILD_MINIZIP 1) set( AMD64 FALSE CACHE INTERNAL "Override ZLIB flag to turn off assembly" FORCE )
ELSE(NOT ZLIB_FOUND)
ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB)
SET(ZLIB_LIBRARIES_LINKED -lz)
ENDIF(NOT ZLIB_FOUND)
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
# Search for unzip # compile from sources
IF ( NOT IOS ) ADD_SUBDIRECTORY(contrib/zlib)
SET(ZLIB_FOUND 1)
SET(ZLIB_LIBRARIES zlibstatic)
SET(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib)
# need to ensure we don't link with system zlib or minizip as well.
SET(ASSIMP_BUILD_MINIZIP 1)
ELSE(NOT ZLIB_FOUND)
ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB)
SET(ZLIB_LIBRARIES_LINKED -lz)
ENDIF(NOT ZLIB_FOUND)
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
ENDIF(HUNTER_ENABLED)
IF( NOT IOS )
IF( NOT ASSIMP_BUILD_MINIZIP ) IF( NOT ASSIMP_BUILD_MINIZIP )
use_pkgconfig(UNZIP minizip) use_pkgconfig(UNZIP minizip)
ENDIF( NOT ASSIMP_BUILD_MINIZIP ) ENDIF( NOT ASSIMP_BUILD_MINIZIP )
ELSE ( NOT IOS ) ELSE ( NOT IOS )
IF(NOT BUILD_SHARED_LIBS) IF( NOT BUILD_SHARED_LIBS )
IF( NOT ASSIMP_BUILD_MINIZIP ) IF( NOT ASSIMP_BUILD_MINIZIP )
use_pkgconfig(UNZIP minizip) use_pkgconfig(UNZIP minizip)
ENDIF( NOT ASSIMP_BUILD_MINIZIP ) ENDIF( NOT ASSIMP_BUILD_MINIZIP )
ENDIF (NOT BUILD_SHARED_LIBS) ENDIF ( NOT BUILD_SHARED_LIBS )
ENDIF ( NOT IOS ) ENDIF ( NOT IOS )
IF ( ASSIMP_NO_EXPORT ) IF ( ASSIMP_NO_EXPORT )
@ -467,7 +553,9 @@ ELSE (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER ) ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER )
ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
ADD_SUBDIRECTORY(contrib) IF(NOT HUNTER_ENABLED)
ADD_SUBDIRECTORY(contrib)
ENDIF(NOT HUNTER_ENABLED)
ADD_SUBDIRECTORY( code/ ) ADD_SUBDIRECTORY( code/ )
IF ( ASSIMP_BUILD_ASSIMP_TOOLS ) IF ( ASSIMP_BUILD_ASSIMP_TOOLS )

View File

@ -125,7 +125,7 @@ Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file.
### Ports ### ### Ports ###
* [Android](port/AndroidJNI/README.md) * [Android](port/AndroidJNI/README.md)
* [Python](port/PyAssimp/README.md) * [Python](port/PyAssimp/README.md)
* [.NET](port/AssimpNET/Readme.md) * [.NET](https://github.com/kebby/assimp-net)
* [Pascal](port/AssimpPascal/Readme.md) * [Pascal](port/AssimpPascal/Readme.md)
* [Javascript (Alpha)](https://github.com/makc/assimp2json) * [Javascript (Alpha)](https://github.com/makc/assimp2json)
* [Unity 3d Plugin](https://www.assetstore.unity3d.com/en/#!/content/91777) * [Unity 3d Plugin](https://www.assetstore.unity3d.com/en/#!/content/91777)
@ -136,7 +136,7 @@ Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file.
[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.
#### Repository structure #### #### Repository structure ####
Open Asset Import Library is implemented in C++. The directory structure is: Open Asset Import Library is implemented in C++. The directory structure looks like:
/code Source code /code Source code
/contrib Third-party libraries /contrib Third-party libraries
@ -149,6 +149,11 @@ Open Asset Import Library is implemented in C++. The directory structure is:
/samples A small number of samples to illustrate possible /samples A small number of samples to illustrate possible
use cases for Assimp use cases for Assimp
The source code is organized in the following way:
code/Common The base implementation for importers and the infrastructure
code/PostProcessing The post-processing steps
code/<FormatName> Implementation for import and export for the format
### Where to get help ### ### Where to get help ###
For more information, visit [our website](http://assimp.org/). Or check out the `./doc`- folder, which contains the official documentation in HTML format. For more information, visit [our website](http://assimp.org/). Or check out the `./doc`- folder, which contains the official documentation in HTML format.

View File

@ -5,48 +5,79 @@
# Commands may need to know the format version. # Commands may need to know the format version.
set(CMAKE_IMPORT_FILE_VERSION 1) set(CMAKE_IMPORT_FILE_VERSION 1)
set(ASSIMP_BUILD_SHARED_LIBS @BUILD_SHARED_LIBS@)
if(MSVC) if(MSVC)
if( MSVC70 OR MSVC71 ) if(MSVC_TOOLSET_VERSION)
set(MSVC_PREFIX "vc70") set(MSVC_PREFIX "vc${MSVC_TOOLSET_VERSION}")
elseif( MSVC80 )
set(MSVC_PREFIX "vc80")
elseif( MSVC90 )
set(MSVC_PREFIX "vc90")
elseif( MSVC10 )
set(MSVC_PREFIX "vc100")
elseif( MSVC11 )
set(MSVC_PREFIX "vc110")
elseif( MSVC12 )
set(MSVC_PREFIX "vc120")
elseif( MSVC14 )
set(MSVC_PREFIX "vc140")
else() else()
set(MSVC_PREFIX "vc150") if( MSVC70 OR MSVC71 )
set(MSVC_PREFIX "vc70")
elseif( MSVC80 )
set(MSVC_PREFIX "vc80")
elseif( MSVC90 )
set(MSVC_PREFIX "vc90")
elseif( MSVC10 )
set(MSVC_PREFIX "vc100")
elseif( MSVC11 )
set(MSVC_PREFIX "vc110")
elseif( MSVC12 )
set(MSVC_PREFIX "vc120")
elseif( MSVC_VERSION LESS 1910)
set(MSVC_PREFIX "vc140")
elseif( MSVC_VERSION LESS 1920)
set(MSVC_PREFIX "vc141")
elseif( MSVC_VERSION LESS 1930)
set(MSVC_PREFIX "vc142")
else()
set(MSVC_PREFIX "vc150")
endif()
endif() endif()
set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" ) set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" )
set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") if(ASSIMP_BUILD_SHARED_LIBS)
set(importLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_IMPORT_LIBRARY_SUFFIX@") set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@")
set(importLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_IMPORT_LIBRARY_SUFFIX@")
# Import target "assimp::assimp" for configuration "Debug" # Import target "assimp::assimp" for configuration "Debug"
set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(assimp::assimp PROPERTIES set_target_properties(assimp::assimp PROPERTIES
IMPORTED_IMPLIB_DEBUG "${_IMPORT_PREFIX}/lib/${importLibraryName}" IMPORTED_IMPLIB_DEBUG "${_IMPORT_PREFIX}/lib/${importLibraryName}"
IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/bin/${sharedLibraryName}" IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/bin/${sharedLibraryName}"
) )
list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp ) list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${importLibraryName}") list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${importLibraryName}")
list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/bin/${sharedLibraryName}" ) list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/bin/${sharedLibraryName}" )
else()
set(staticLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_STATIC_LIBRARY_SUFFIX@")
# Import target "assimp::assimp" for configuration "Debug"
set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(assimp::assimp PROPERTIES
IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/${staticLibraryName}"
)
list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${staticLibraryName}")
endif()
else() else()
set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the openrave libraries" ) set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the assimp libraries" )
set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@") if(ASSIMP_BUILD_SHARED_LIBS)
set_target_properties(assimp::assimp PROPERTIES set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@")
IMPORTED_SONAME_DEBUG "${sharedLibraryName}" set_target_properties(assimp::assimp PROPERTIES
IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/${sharedLibraryName}" IMPORTED_SONAME_DEBUG "${sharedLibraryName}"
IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/${sharedLibraryName}"
) )
list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp ) list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${sharedLibraryName}" ) list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${sharedLibraryName}" )
else()
set(staticLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_STATIC_LIBRARY_SUFFIX@")
set_target_properties(assimp::assimp PROPERTIES
IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/${staticLibraryName}"
)
list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${staticLibraryName}" )
endif()
endif() endif()
@ -60,7 +91,11 @@ set( ASSIMP_CXX_FLAGS ) # dynamically linked library
set( ASSIMP_LINK_FLAGS "" ) set( ASSIMP_LINK_FLAGS "" )
set( ASSIMP_LIBRARY_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_LIB_INSTALL_DIR@") set( ASSIMP_LIBRARY_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_LIB_INSTALL_DIR@")
set( ASSIMP_INCLUDE_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_INCLUDE_INSTALL_DIR@") set( ASSIMP_INCLUDE_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_INCLUDE_INSTALL_DIR@")
set( ASSIMP_LIBRARIES ${sharedLibraryName}) if(ASSIMP_BUILD_SHARED_LIBS)
set( ASSIMP_LIBRARIES ${sharedLibraryName})
else()
set( ASSIMP_LIBRARIES ${staticLibraryName})
endif()
# for compatibility with pkg-config # for compatibility with pkg-config
set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}") set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}")
@ -75,4 +110,5 @@ MARK_AS_ADVANCED(
ASSIMP_CFLAGS_OTHER ASSIMP_CFLAGS_OTHER
ASSIMP_LDFLAGS_OTHER ASSIMP_LDFLAGS_OTHER
ASSIMP_LIBRARY_SUFFIX ASSIMP_LIBRARY_SUFFIX
ASSIMP_BUILD_SHARED_LIBS
) )

View File

@ -5,59 +5,95 @@
# Commands may need to know the format version. # Commands may need to know the format version.
set(CMAKE_IMPORT_FILE_VERSION 1) set(CMAKE_IMPORT_FILE_VERSION 1)
set(ASSIMP_BUILD_SHARED_LIBS @BUILD_SHARED_LIBS@)
if(MSVC) if(MSVC)
if( MSVC70 OR MSVC71 ) if(MSVC_TOOLSET_VERSION)
set(MSVC_PREFIX "vc70") set(MSVC_PREFIX "vc${MSVC_TOOLSET_VERSION}")
elseif( MSVC80 )
set(MSVC_PREFIX "vc80")
elseif( MSVC90 )
set(MSVC_PREFIX "vc90")
elseif( MSVC10 )
set(MSVC_PREFIX "vc100")
elseif( MSVC11 )
set(MSVC_PREFIX "vc110")
elseif( MSVC12 )
set(MSVC_PREFIX "vc120")
elseif( MSVC14 )
set(MSVC_PREFIX "vc140")
else() else()
set(MSVC_PREFIX "vc150") if( MSVC70 OR MSVC71 )
set(MSVC_PREFIX "vc70")
elseif( MSVC80 )
set(MSVC_PREFIX "vc80")
elseif( MSVC90 )
set(MSVC_PREFIX "vc90")
elseif( MSVC10 )
set(MSVC_PREFIX "vc100")
elseif( MSVC11 )
set(MSVC_PREFIX "vc110")
elseif( MSVC12 )
set(MSVC_PREFIX "vc120")
elseif( MSVC_VERSION LESS 1910)
set(MSVC_PREFIX "vc140")
elseif( MSVC_VERSION LESS 1920)
set(MSVC_PREFIX "vc141")
elseif( MSVC_VERSION LESS 1930)
set(MSVC_PREFIX "vc142")
else()
set(MSVC_PREFIX "vc150")
endif()
endif() endif()
set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" ) set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" )
set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@") if(ASSIMP_BUILD_SHARED_LIBS)
set(importLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_IMPORT_LIBRARY_SUFFIX@") set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@")
set(importLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_IMPORT_LIBRARY_SUFFIX@")
# Import target "assimp::assimp" for configuration "Release" # Import target "assimp::assimp" for configuration "Release"
set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(assimp::assimp PROPERTIES set_target_properties(assimp::assimp PROPERTIES
IMPORTED_IMPLIB_RELEASE "${_IMPORT_PREFIX}/lib/${importLibraryName}" IMPORTED_IMPLIB_RELEASE "${_IMPORT_PREFIX}/lib/${importLibraryName}"
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/bin/${sharedLibraryName}" IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/bin/${sharedLibraryName}"
) )
list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp ) list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${importLibraryName}") list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${importLibraryName}")
list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/bin/${sharedLibraryName}" ) list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/bin/${sharedLibraryName}" )
else()
set(staticLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_STATIC_LIBRARY_SUFFIX@")
# Import target "assimp::assimp" for configuration "Release"
set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(assimp::assimp PROPERTIES
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/${staticLibraryName}"
)
list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${staticLibraryName}")
endif()
else() else()
set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the openrave libraries" ) set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the assimp libraries" )
set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@") if(ASSIMP_BUILD_SHARED_LIBS)
set_target_properties(assimp::assimp PROPERTIES set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@")
IMPORTED_SONAME_RELEASE "${sharedLibraryName}" set_target_properties(assimp::assimp PROPERTIES
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/${sharedLibraryName}" IMPORTED_SONAME_RELEASE "${sharedLibraryName}"
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/${sharedLibraryName}"
) )
list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp ) list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${sharedLibraryName}" ) list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${sharedLibraryName}" )
else()
set(staticLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_STATIC_LIBRARY_SUFFIX@")
set_target_properties(assimp::assimp PROPERTIES
IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/${staticLibraryName}"
)
list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${staticLibraryName}" )
endif()
endif() endif()
# Commands beyond this point should not need to know the version. # Commands beyond this point should not need to know the version.
set(CMAKE_IMPORT_FILE_VERSION) set(CMAKE_IMPORT_FILE_VERSION)
get_filename_component(ASSIMP_ROOT_DIR "@CMAKE_INSTALL_PREFIX@" REALPATH) get_filename_component(ASSIMP_ROOT_DIR "@CMAKE_INSTALL_PREFIX@" REALPATH)
set( ASSIMP_CXX_FLAGS ) # dynamically linked library set( ASSIMP_CXX_FLAGS ) # dynamically linked library
set( ASSIMP_LINK_FLAGS "" ) set( ASSIMP_LINK_FLAGS "" )
set( ASSIMP_LIBRARY_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_LIB_INSTALL_DIR@") set( ASSIMP_LIBRARY_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_LIB_INSTALL_DIR@")
set( ASSIMP_INCLUDE_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_INCLUDE_INSTALL_DIR@") set( ASSIMP_INCLUDE_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_INCLUDE_INSTALL_DIR@")
set( ASSIMP_LIBRARIES ${sharedLibraryName}) if(ASSIMP_BUILD_SHARED_LIBS)
set( ASSIMP_LIBRARIES ${sharedLibraryName})
else()
set( ASSIMP_LIBRARIES ${staticLibraryName})
endif()
# for compatibility with pkg-config # for compatibility with pkg-config
set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}") set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}")
@ -72,4 +108,5 @@ MARK_AS_ADVANCED(
ASSIMP_CFLAGS_OTHER ASSIMP_CFLAGS_OTHER
ASSIMP_LDFLAGS_OTHER ASSIMP_LDFLAGS_OTHER
ASSIMP_LIBRARY_SUFFIX ASSIMP_LIBRARY_SUFFIX
ASSIMP_BUILD_SHARED_LIBS
) )

View File

@ -51,7 +51,11 @@ if(_IMPORT_PREFIX STREQUAL "/")
endif() endif()
# Create imported target assimp::assimp # Create imported target assimp::assimp
add_library(assimp::assimp SHARED IMPORTED) if(@BUILD_SHARED_LIBS@)
add_library(assimp::assimp SHARED IMPORTED)
else()
add_library(assimp::assimp STATIC IMPORTED)
endif()
set_target_properties(assimp::assimp PROPERTIES set_target_properties(assimp::assimp PROPERTIES
COMPATIBLE_INTERFACE_STRING "assimp_MAJOR_VERSION" COMPATIBLE_INTERFACE_STRING "assimp_MAJOR_VERSION"

View File

@ -0,0 +1,540 @@
# Copyright (c) 2013-2018, Ruslan Baratov
# All rights reserved.
#
# Redistribution and use 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.
#
# 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 HOLDER 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.
# This is a gate file to Hunter package manager.
# Include this file using `include` command and add package you need, example:
#
# cmake_minimum_required(VERSION 3.2)
#
# include("cmake/HunterGate.cmake")
# HunterGate(
# URL "https://github.com/path/to/hunter/archive.tar.gz"
# SHA1 "798501e983f14b28b10cda16afa4de69eee1da1d"
# )
#
# project(MyProject)
#
# hunter_add_package(Foo)
# hunter_add_package(Boo COMPONENTS Bar Baz)
#
# Projects:
# * https://github.com/hunter-packages/gate/
# * https://github.com/ruslo/hunter
option(HUNTER_ENABLED "Enable Hunter package manager support" ON)
if(HUNTER_ENABLED)
if(CMAKE_VERSION VERSION_LESS "3.2")
message(
FATAL_ERROR
"At least CMake version 3.2 required for Hunter dependency management."
" Update CMake or set HUNTER_ENABLED to OFF."
)
endif()
endif()
include(CMakeParseArguments) # cmake_parse_arguments
option(HUNTER_STATUS_PRINT "Print working status" ON)
option(HUNTER_STATUS_DEBUG "Print a lot info" OFF)
option(HUNTER_TLS_VERIFY "Enable/disable TLS certificate checking on downloads" ON)
set(HUNTER_WIKI "https://github.com/ruslo/hunter/wiki")
function(hunter_gate_status_print)
if(HUNTER_STATUS_PRINT OR HUNTER_STATUS_DEBUG)
foreach(print_message ${ARGV})
message(STATUS "[hunter] ${print_message}")
endforeach()
endif()
endfunction()
function(hunter_gate_status_debug)
if(HUNTER_STATUS_DEBUG)
foreach(print_message ${ARGV})
string(TIMESTAMP timestamp)
message(STATUS "[hunter *** DEBUG *** ${timestamp}] ${print_message}")
endforeach()
endif()
endfunction()
function(hunter_gate_wiki wiki_page)
message("------------------------------ WIKI -------------------------------")
message(" ${HUNTER_WIKI}/${wiki_page}")
message("-------------------------------------------------------------------")
message("")
message(FATAL_ERROR "")
endfunction()
function(hunter_gate_internal_error)
message("")
foreach(print_message ${ARGV})
message("[hunter ** INTERNAL **] ${print_message}")
endforeach()
message("[hunter ** INTERNAL **] [Directory:${CMAKE_CURRENT_LIST_DIR}]")
message("")
hunter_gate_wiki("error.internal")
endfunction()
function(hunter_gate_fatal_error)
cmake_parse_arguments(hunter "" "WIKI" "" "${ARGV}")
string(COMPARE EQUAL "${hunter_WIKI}" "" have_no_wiki)
if(have_no_wiki)
hunter_gate_internal_error("Expected wiki")
endif()
message("")
foreach(x ${hunter_UNPARSED_ARGUMENTS})
message("[hunter ** FATAL ERROR **] ${x}")
endforeach()
message("[hunter ** FATAL ERROR **] [Directory:${CMAKE_CURRENT_LIST_DIR}]")
message("")
hunter_gate_wiki("${hunter_WIKI}")
endfunction()
function(hunter_gate_user_error)
hunter_gate_fatal_error(${ARGV} WIKI "error.incorrect.input.data")
endfunction()
function(hunter_gate_self root version sha1 result)
string(COMPARE EQUAL "${root}" "" is_bad)
if(is_bad)
hunter_gate_internal_error("root is empty")
endif()
string(COMPARE EQUAL "${version}" "" is_bad)
if(is_bad)
hunter_gate_internal_error("version is empty")
endif()
string(COMPARE EQUAL "${sha1}" "" is_bad)
if(is_bad)
hunter_gate_internal_error("sha1 is empty")
endif()
string(SUBSTRING "${sha1}" 0 7 archive_id)
if(EXISTS "${root}/cmake/Hunter")
set(hunter_self "${root}")
else()
set(
hunter_self
"${root}/_Base/Download/Hunter/${version}/${archive_id}/Unpacked"
)
endif()
set("${result}" "${hunter_self}" PARENT_SCOPE)
endfunction()
# Set HUNTER_GATE_ROOT cmake variable to suitable value.
function(hunter_gate_detect_root)
# Check CMake variable
string(COMPARE NOTEQUAL "${HUNTER_ROOT}" "" not_empty)
if(not_empty)
set(HUNTER_GATE_ROOT "${HUNTER_ROOT}" PARENT_SCOPE)
hunter_gate_status_debug("HUNTER_ROOT detected by cmake variable")
return()
endif()
# Check environment variable
string(COMPARE NOTEQUAL "$ENV{HUNTER_ROOT}" "" not_empty)
if(not_empty)
set(HUNTER_GATE_ROOT "$ENV{HUNTER_ROOT}" PARENT_SCOPE)
hunter_gate_status_debug("HUNTER_ROOT detected by environment variable")
return()
endif()
# Check HOME environment variable
string(COMPARE NOTEQUAL "$ENV{HOME}" "" result)
if(result)
set(HUNTER_GATE_ROOT "$ENV{HOME}/.hunter" PARENT_SCOPE)
hunter_gate_status_debug("HUNTER_ROOT set using HOME environment variable")
return()
endif()
# Check SYSTEMDRIVE and USERPROFILE environment variable (windows only)
if(WIN32)
string(COMPARE NOTEQUAL "$ENV{SYSTEMDRIVE}" "" result)
if(result)
set(HUNTER_GATE_ROOT "$ENV{SYSTEMDRIVE}/.hunter" PARENT_SCOPE)
hunter_gate_status_debug(
"HUNTER_ROOT set using SYSTEMDRIVE environment variable"
)
return()
endif()
string(COMPARE NOTEQUAL "$ENV{USERPROFILE}" "" result)
if(result)
set(HUNTER_GATE_ROOT "$ENV{USERPROFILE}/.hunter" PARENT_SCOPE)
hunter_gate_status_debug(
"HUNTER_ROOT set using USERPROFILE environment variable"
)
return()
endif()
endif()
hunter_gate_fatal_error(
"Can't detect HUNTER_ROOT"
WIKI "error.detect.hunter.root"
)
endfunction()
function(hunter_gate_download dir)
string(
COMPARE
NOTEQUAL
"$ENV{HUNTER_DISABLE_AUTOINSTALL}"
""
disable_autoinstall
)
if(disable_autoinstall AND NOT HUNTER_RUN_INSTALL)
hunter_gate_fatal_error(
"Hunter not found in '${dir}'"
"Set HUNTER_RUN_INSTALL=ON to auto-install it from '${HUNTER_GATE_URL}'"
"Settings:"
" HUNTER_ROOT: ${HUNTER_GATE_ROOT}"
" HUNTER_SHA1: ${HUNTER_GATE_SHA1}"
WIKI "error.run.install"
)
endif()
string(COMPARE EQUAL "${dir}" "" is_bad)
if(is_bad)
hunter_gate_internal_error("Empty 'dir' argument")
endif()
string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" is_bad)
if(is_bad)
hunter_gate_internal_error("HUNTER_GATE_SHA1 empty")
endif()
string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" is_bad)
if(is_bad)
hunter_gate_internal_error("HUNTER_GATE_URL empty")
endif()
set(done_location "${dir}/DONE")
set(sha1_location "${dir}/SHA1")
set(build_dir "${dir}/Build")
set(cmakelists "${dir}/CMakeLists.txt")
hunter_gate_status_debug("Locking directory: ${dir}")
file(LOCK "${dir}" DIRECTORY GUARD FUNCTION)
hunter_gate_status_debug("Lock done")
if(EXISTS "${done_location}")
# while waiting for lock other instance can do all the job
hunter_gate_status_debug("File '${done_location}' found, skip install")
return()
endif()
file(REMOVE_RECURSE "${build_dir}")
file(REMOVE_RECURSE "${cmakelists}")
file(MAKE_DIRECTORY "${build_dir}") # check directory permissions
# Disabling languages speeds up a little bit, reduces noise in the output
# and avoids path too long windows error
file(
WRITE
"${cmakelists}"
"cmake_minimum_required(VERSION 3.2)\n"
"project(HunterDownload LANGUAGES NONE)\n"
"include(ExternalProject)\n"
"ExternalProject_Add(\n"
" Hunter\n"
" URL\n"
" \"${HUNTER_GATE_URL}\"\n"
" URL_HASH\n"
" SHA1=${HUNTER_GATE_SHA1}\n"
" DOWNLOAD_DIR\n"
" \"${dir}\"\n"
" TLS_VERIFY\n"
" ${HUNTER_TLS_VERIFY}\n"
" SOURCE_DIR\n"
" \"${dir}/Unpacked\"\n"
" CONFIGURE_COMMAND\n"
" \"\"\n"
" BUILD_COMMAND\n"
" \"\"\n"
" INSTALL_COMMAND\n"
" \"\"\n"
")\n"
)
if(HUNTER_STATUS_DEBUG)
set(logging_params "")
else()
set(logging_params OUTPUT_QUIET)
endif()
hunter_gate_status_debug("Run generate")
# Need to add toolchain file too.
# Otherwise on Visual Studio + MDD this will fail with error:
# "Could not find an appropriate version of the Windows 10 SDK installed on this machine"
if(EXISTS "${CMAKE_TOOLCHAIN_FILE}")
get_filename_component(absolute_CMAKE_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}" ABSOLUTE)
set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=${absolute_CMAKE_TOOLCHAIN_FILE}")
else()
# 'toolchain_arg' can't be empty
set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=")
endif()
string(COMPARE EQUAL "${CMAKE_MAKE_PROGRAM}" "" no_make)
if(no_make)
set(make_arg "")
else()
# Test case: remove Ninja from PATH but set it via CMAKE_MAKE_PROGRAM
set(make_arg "-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}")
endif()
execute_process(
COMMAND
"${CMAKE_COMMAND}"
"-H${dir}"
"-B${build_dir}"
"-G${CMAKE_GENERATOR}"
"${toolchain_arg}"
${make_arg}
WORKING_DIRECTORY "${dir}"
RESULT_VARIABLE download_result
${logging_params}
)
if(NOT download_result EQUAL 0)
hunter_gate_internal_error(
"Configure project failed."
"To reproduce the error run: ${CMAKE_COMMAND} -H${dir} -B${build_dir} -G${CMAKE_GENERATOR} ${toolchain_arg} ${make_arg}"
"In directory ${dir}"
)
endif()
hunter_gate_status_print(
"Initializing Hunter workspace (${HUNTER_GATE_SHA1})"
" ${HUNTER_GATE_URL}"
" -> ${dir}"
)
execute_process(
COMMAND "${CMAKE_COMMAND}" --build "${build_dir}"
WORKING_DIRECTORY "${dir}"
RESULT_VARIABLE download_result
${logging_params}
)
if(NOT download_result EQUAL 0)
hunter_gate_internal_error("Build project failed")
endif()
file(REMOVE_RECURSE "${build_dir}")
file(REMOVE_RECURSE "${cmakelists}")
file(WRITE "${sha1_location}" "${HUNTER_GATE_SHA1}")
file(WRITE "${done_location}" "DONE")
hunter_gate_status_debug("Finished")
endfunction()
# Must be a macro so master file 'cmake/Hunter' can
# apply all variables easily just by 'include' command
# (otherwise PARENT_SCOPE magic needed)
macro(HunterGate)
if(HUNTER_GATE_DONE)
# variable HUNTER_GATE_DONE set explicitly for external project
# (see `hunter_download`)
set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES)
endif()
# First HunterGate command will init Hunter, others will be ignored
get_property(_hunter_gate_done GLOBAL PROPERTY HUNTER_GATE_DONE SET)
if(NOT HUNTER_ENABLED)
# Empty function to avoid error "unknown function"
function(hunter_add_package)
endfunction()
set(
_hunter_gate_disabled_mode_dir
"${CMAKE_CURRENT_LIST_DIR}/cmake/Hunter/disabled-mode"
)
if(EXISTS "${_hunter_gate_disabled_mode_dir}")
hunter_gate_status_debug(
"Adding \"disabled-mode\" modules: ${_hunter_gate_disabled_mode_dir}"
)
list(APPEND CMAKE_PREFIX_PATH "${_hunter_gate_disabled_mode_dir}")
endif()
elseif(_hunter_gate_done)
hunter_gate_status_debug("Secondary HunterGate (use old settings)")
hunter_gate_self(
"${HUNTER_CACHED_ROOT}"
"${HUNTER_VERSION}"
"${HUNTER_SHA1}"
_hunter_self
)
include("${_hunter_self}/cmake/Hunter")
else()
set(HUNTER_GATE_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}")
string(COMPARE NOTEQUAL "${PROJECT_NAME}" "" _have_project_name)
if(_have_project_name)
hunter_gate_fatal_error(
"Please set HunterGate *before* 'project' command. "
"Detected project: ${PROJECT_NAME}"
WIKI "error.huntergate.before.project"
)
endif()
cmake_parse_arguments(
HUNTER_GATE "LOCAL" "URL;SHA1;GLOBAL;FILEPATH" "" ${ARGV}
)
string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" _empty_sha1)
string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" _empty_url)
string(
COMPARE
NOTEQUAL
"${HUNTER_GATE_UNPARSED_ARGUMENTS}"
""
_have_unparsed
)
string(COMPARE NOTEQUAL "${HUNTER_GATE_GLOBAL}" "" _have_global)
string(COMPARE NOTEQUAL "${HUNTER_GATE_FILEPATH}" "" _have_filepath)
if(_have_unparsed)
hunter_gate_user_error(
"HunterGate unparsed arguments: ${HUNTER_GATE_UNPARSED_ARGUMENTS}"
)
endif()
if(_empty_sha1)
hunter_gate_user_error("SHA1 suboption of HunterGate is mandatory")
endif()
if(_empty_url)
hunter_gate_user_error("URL suboption of HunterGate is mandatory")
endif()
if(_have_global)
if(HUNTER_GATE_LOCAL)
hunter_gate_user_error("Unexpected LOCAL (already has GLOBAL)")
endif()
if(_have_filepath)
hunter_gate_user_error("Unexpected FILEPATH (already has GLOBAL)")
endif()
endif()
if(HUNTER_GATE_LOCAL)
if(_have_global)
hunter_gate_user_error("Unexpected GLOBAL (already has LOCAL)")
endif()
if(_have_filepath)
hunter_gate_user_error("Unexpected FILEPATH (already has LOCAL)")
endif()
endif()
if(_have_filepath)
if(_have_global)
hunter_gate_user_error("Unexpected GLOBAL (already has FILEPATH)")
endif()
if(HUNTER_GATE_LOCAL)
hunter_gate_user_error("Unexpected LOCAL (already has FILEPATH)")
endif()
endif()
hunter_gate_detect_root() # set HUNTER_GATE_ROOT
# Beautify path, fix probable problems with windows path slashes
get_filename_component(
HUNTER_GATE_ROOT "${HUNTER_GATE_ROOT}" ABSOLUTE
)
hunter_gate_status_debug("HUNTER_ROOT: ${HUNTER_GATE_ROOT}")
if(NOT HUNTER_ALLOW_SPACES_IN_PATH)
string(FIND "${HUNTER_GATE_ROOT}" " " _contain_spaces)
if(NOT _contain_spaces EQUAL -1)
hunter_gate_fatal_error(
"HUNTER_ROOT (${HUNTER_GATE_ROOT}) contains spaces."
"Set HUNTER_ALLOW_SPACES_IN_PATH=ON to skip this error"
"(Use at your own risk!)"
WIKI "error.spaces.in.hunter.root"
)
endif()
endif()
string(
REGEX
MATCH
"[0-9]+\\.[0-9]+\\.[0-9]+[-_a-z0-9]*"
HUNTER_GATE_VERSION
"${HUNTER_GATE_URL}"
)
string(COMPARE EQUAL "${HUNTER_GATE_VERSION}" "" _is_empty)
if(_is_empty)
set(HUNTER_GATE_VERSION "unknown")
endif()
hunter_gate_self(
"${HUNTER_GATE_ROOT}"
"${HUNTER_GATE_VERSION}"
"${HUNTER_GATE_SHA1}"
_hunter_self
)
set(_master_location "${_hunter_self}/cmake/Hunter")
if(EXISTS "${HUNTER_GATE_ROOT}/cmake/Hunter")
# Hunter downloaded manually (e.g. by 'git clone')
set(_unused "xxxxxxxxxx")
set(HUNTER_GATE_SHA1 "${_unused}")
set(HUNTER_GATE_VERSION "${_unused}")
else()
get_filename_component(_archive_id_location "${_hunter_self}/.." ABSOLUTE)
set(_done_location "${_archive_id_location}/DONE")
set(_sha1_location "${_archive_id_location}/SHA1")
# Check Hunter already downloaded by HunterGate
if(NOT EXISTS "${_done_location}")
hunter_gate_download("${_archive_id_location}")
endif()
if(NOT EXISTS "${_done_location}")
hunter_gate_internal_error("hunter_gate_download failed")
endif()
if(NOT EXISTS "${_sha1_location}")
hunter_gate_internal_error("${_sha1_location} not found")
endif()
file(READ "${_sha1_location}" _sha1_value)
string(COMPARE EQUAL "${_sha1_value}" "${HUNTER_GATE_SHA1}" _is_equal)
if(NOT _is_equal)
hunter_gate_internal_error(
"Short SHA1 collision:"
" ${_sha1_value} (from ${_sha1_location})"
" ${HUNTER_GATE_SHA1} (HunterGate)"
)
endif()
if(NOT EXISTS "${_master_location}")
hunter_gate_user_error(
"Master file not found:"
" ${_master_location}"
"try to update Hunter/HunterGate"
)
endif()
endif()
include("${_master_location}")
set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES)
endif()
endmacro()

View File

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

View File

@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// internal headers // internal headers
#include "3DSLoader.h" #include "3DSLoader.h"
#include "TargetAnimation.h" #include "Common/TargetAnimation.h"
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/StringComparison.h> #include <assimp/StringComparison.h>

View File

@ -43,15 +43,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER #ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
#include "3DSExporter.h" #include "3DS/3DSExporter.h"
#include "3DSLoader.h" #include "3DS/3DSLoader.h"
#include "3DSHelper.h" #include "3DS/3DSHelper.h"
#include "PostProcessing/SplitLargeMeshes.h"
#include <assimp/SceneCombiner.h> #include <assimp/SceneCombiner.h>
#include "SplitLargeMeshes.h"
#include <assimp/StringComparison.h> #include <assimp/StringComparison.h>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/Exporter.hpp> #include <assimp/Exporter.hpp>
#include <memory> #include <memory>
using namespace Assimp; using namespace Assimp;

View File

@ -55,7 +55,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "3MFXmlTags.h" #include "3MFXmlTags.h"
#include "D3MFOpcPackage.h" #include "D3MFOpcPackage.h"
#include <contrib/zip/src/zip.h> #ifdef ASSIMP_USE_HUNTER
# include <zip/zip.h>
#else
# include <contrib/zip/src/zip.h>
#endif
namespace Assimp { namespace Assimp {

View File

@ -58,7 +58,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory> #include <memory>
#include "D3MFOpcPackage.h" #include "D3MFOpcPackage.h"
#include <unzip.h> #ifdef ASSIMP_USE_HUNTER
# include <minizip/unzip.h>
#else
# include <unzip.h>
#endif
#include <assimp/irrXMLWrapper.h> #include <assimp/irrXMLWrapper.h>
#include "3MFXmlTags.h" #include "3MFXmlTags.h"
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>

View File

@ -56,7 +56,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <map> #include <map>
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <unzip.h> #ifdef ASSIMP_USE_HUNTER
# include <minizip/unzip.h>
#else
# include <unzip.h>
#endif
#include "3MFXmlTags.h" #include "3MFXmlTags.h"
namespace Assimp { namespace Assimp {
@ -148,6 +152,15 @@ int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) {
zlib_filefunc_def IOSystem2Unzip::get(IOSystem* pIOHandler) { zlib_filefunc_def IOSystem2Unzip::get(IOSystem* pIOHandler) {
zlib_filefunc_def mapping; zlib_filefunc_def mapping;
#ifdef ASSIMP_USE_HUNTER
mapping.zopen_file = (open_file_func)open;
mapping.zread_file = (read_file_func)read;
mapping.zwrite_file = (write_file_func)write;
mapping.ztell_file = (tell_file_func)tell;
mapping.zseek_file = (seek_file_func)seek;
mapping.zclose_file = (close_file_func)close;
mapping.zerror_file = (error_file_func)testerror;
#else
mapping.zopen_file = open; mapping.zopen_file = open;
mapping.zread_file = read; mapping.zread_file = read;
mapping.zwrite_file = write; mapping.zwrite_file = write;
@ -155,6 +168,7 @@ zlib_filefunc_def IOSystem2Unzip::get(IOSystem* pIOHandler) {
mapping.zseek_file = seek; mapping.zseek_file = seek;
mapping.zclose_file = close; mapping.zclose_file = close;
mapping.zerror_file = testerror; mapping.zerror_file = testerror;
#endif
mapping.opaque = reinterpret_cast<voidpf>(pIOHandler); mapping.opaque = reinterpret_cast<voidpf>(pIOHandler);
return mapping; return mapping;

View File

@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/ParsingUtils.h> #include <assimp/ParsingUtils.h>
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
#include <assimp/Subdivision.h> #include <assimp/Subdivision.h>
#include "Importer.h" #include "Common/Importer.h"
#include <assimp/BaseImporter.h> #include <assimp/BaseImporter.h>
#include <assimp/Importer.hpp> #include <assimp/Importer.hpp>
#include <assimp/light.h> #include <assimp/light.h>

View File

@ -53,7 +53,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ASELoader.h" #include "ASELoader.h"
#include <assimp/StringComparison.h> #include <assimp/StringComparison.h>
#include <assimp/SkeletonMeshBuilder.h> #include <assimp/SkeletonMeshBuilder.h>
#include "TargetAnimation.h" #include "Common/TargetAnimation.h"
#include <assimp/Importer.hpp> #include <assimp/Importer.hpp>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
@ -88,23 +89,25 @@ ASEImporter::ASEImporter()
, mBuffer() , mBuffer()
, pcScene() , pcScene()
, configRecomputeNormals() , configRecomputeNormals()
, noSkeletonMesh() , noSkeletonMesh() {
{} // empty
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
ASEImporter::~ASEImporter() ASEImporter::~ASEImporter() {
{} // empty
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool ASEImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const bool ASEImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const {
{
// check file extension // check file extension
const std::string extension = GetExtension(pFile); const std::string extension = GetExtension(pFile);
if( extension == "ase" || extension == "ask") if (extension == "ase" || extension == "ask") {
return true; return true;
}
if ((!extension.length() || cs) && pIOHandler) { if ((!extension.length() || cs) && pIOHandler) {
const char* tokens[] = {"*3dsmax_asciiexport"}; const char* tokens[] = {"*3dsmax_asciiexport"};
@ -115,15 +118,13 @@ bool ASEImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Loader meta information // Loader meta information
const aiImporterDesc* ASEImporter::GetInfo () const const aiImporterDesc* ASEImporter::GetInfo () const {
{
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Setup configuration options // Setup configuration options
void ASEImporter::SetupProperties(const Importer* pImp) void ASEImporter::SetupProperties(const Importer* pImp) {
{
configRecomputeNormals = (pImp->GetPropertyInteger( configRecomputeNormals = (pImp->GetPropertyInteger(
AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS,1) ? true : false); AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS,1) ? true : false);
@ -133,12 +134,11 @@ void ASEImporter::SetupProperties(const Importer* pImp)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void ASEImporter::InternReadFile( const std::string& pFile, void ASEImporter::InternReadFile( const std::string& pFile,
aiScene* pScene, IOSystem* pIOHandler) aiScene* pScene, IOSystem* pIOHandler) {
{
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
// Check whether we can read from the file // Check whether we can read from the file
if( file.get() == NULL) { if( file.get() == nullptr) {
throw DeadlyImportError( "Failed to open ASE file " + pFile + "."); throw DeadlyImportError( "Failed to open ASE file " + pFile + ".");
} }

View File

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

View File

@ -49,15 +49,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
// internal headers // internal headers
#include "TextureTransform.h" #include "PostProcessing/TextureTransform.h"
#include "ASELoader.h" #include "ASELoader.h"
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
using namespace Assimp; using namespace Assimp;
using namespace Assimp::ASE; using namespace Assimp::ASE;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Begin an ASE parsing function // Begin an ASE parsing function

View File

@ -57,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/qnan.h> #include <assimp/qnan.h>
// ASE is quite similar to 3ds. We can reuse some structures // ASE is quite similar to 3ds. We can reuse some structures
#include "3DSLoader.h" #include "3DS/3DSLoader.h"
namespace Assimp { namespace Assimp {
namespace ASE { namespace ASE {

View File

@ -46,12 +46,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER #ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
#include "assbin_chunks.h" #include "Common/assbin_chunks.h"
#include "PostProcessing/ProcessHelper.h"
#include <assimp/version.h> #include <assimp/version.h>
#include <assimp/IOStream.hpp> #include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/Exporter.hpp> #include <assimp/Exporter.hpp>
#include "ProcessHelper.h"
#include <assimp/Exceptional.h> #include <assimp/Exceptional.h>
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB #ifdef ASSIMP_BUILD_NO_OWN_ZLIB

View File

@ -50,8 +50,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER #ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
// internal headers // internal headers
#include "AssbinLoader.h" #include "Assbin/AssbinLoader.h"
#include "assbin_chunks.h" #include "Common/assbin_chunks.h"
#include <assimp/MemoryIOWrapper.h> #include <assimp/MemoryIOWrapper.h>
#include <assimp/mesh.h> #include <assimp/mesh.h>
#include <assimp/anim.h> #include <assimp/anim.h>

View File

@ -0,0 +1,109 @@
/*
cencoder.c - c source to a base64 encoding algorithm implementation
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#include "cencode.h" // changed from <B64/cencode.h>
const int CHARS_PER_LINE = 72;
void base64_init_encodestate(base64_encodestate* state_in)
{
state_in->step = step_A;
state_in->result = 0;
state_in->stepcount = 0;
}
char base64_encode_value(char value_in)
{
static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (value_in > 63) return '=';
return encoding[(int)value_in];
}
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in)
{
const char* plainchar = plaintext_in;
const char* const plaintextend = plaintext_in + length_in;
char* codechar = code_out;
char result;
char fragment;
result = state_in->result;
switch (state_in->step)
{
while (1)
{
case step_A:
if (plainchar == plaintextend)
{
state_in->result = result;
state_in->step = step_A;
return codechar - code_out;
}
fragment = *plainchar++;
result = (fragment & 0x0fc) >> 2;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x003) << 4;
case step_B:
if (plainchar == plaintextend)
{
state_in->result = result;
state_in->step = step_B;
return codechar - code_out;
}
fragment = *plainchar++;
result |= (fragment & 0x0f0) >> 4;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x00f) << 2;
case step_C:
if (plainchar == plaintextend)
{
state_in->result = result;
state_in->step = step_C;
return codechar - code_out;
}
fragment = *plainchar++;
result |= (fragment & 0x0c0) >> 6;
*codechar++ = base64_encode_value(result);
result = (fragment & 0x03f) >> 0;
*codechar++ = base64_encode_value(result);
++(state_in->stepcount);
if (state_in->stepcount == CHARS_PER_LINE/4)
{
*codechar++ = '\n';
state_in->stepcount = 0;
}
}
}
/* control should not reach here */
return codechar - code_out;
}
int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
{
char* codechar = code_out;
switch (state_in->step)
{
case step_B:
*codechar++ = base64_encode_value(state_in->result);
*codechar++ = '=';
*codechar++ = '=';
break;
case step_C:
*codechar++ = base64_encode_value(state_in->result);
*codechar++ = '=';
break;
case step_A:
break;
}
*codechar++ = '\n';
return codechar - code_out;
}

View File

@ -0,0 +1,31 @@
/*
cencode.h - c header for a base64 encoding algorithm
This is part of the libb64 project, and has been placed in the public domain.
For details, see http://sourceforge.net/projects/libb64
*/
#ifndef BASE64_CENCODE_H
#define BASE64_CENCODE_H
typedef enum
{
step_A, step_B, step_C
} base64_encodestep;
typedef struct
{
base64_encodestep step;
char result;
int stepcount;
} base64_encodestate;
void base64_init_encodestate(base64_encodestate* state_in);
char base64_encode_value(char value_in);
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in);
int base64_encode_blockend(char* code_out, base64_encodestate* state_in);
#endif /* BASE64_CENCODE_H */

View File

@ -0,0 +1,818 @@
/*
Assimp2Json
Copyright (c) 2011, Alexander C. Gessler
Licensed under a 3-clause BSD license. See the LICENSE file for more information.
*/
#ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER
#include <assimp/Importer.hpp>
#include <assimp/Exporter.hpp>
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
#include <sstream>
#include <limits>
#include <cassert>
#include <memory>
#define CURRENT_FORMAT_VERSION 100
// grab scoped_ptr from assimp to avoid a dependency on boost.
//#include <assimp/../../code/BoostWorkaround/boost/scoped_ptr.hpp>
#include "mesh_splitter.h"
extern "C" {
#include "cencode.h"
}
namespace Assimp {
void ExportAssimp2Json(const char*, Assimp::IOSystem*, const aiScene*, const Assimp::ExportProperties*);
Exporter::ExportFormatEntry Assimp2Json_desc = Assimp::Exporter::ExportFormatEntry(
"json",
"Plain JSON representation of the Assimp scene data structure",
"json",
&ExportAssimp2Json,
0u
);
// small utility class to simplify serializing the aiScene to Json
class JSONWriter {
public:
enum {
Flag_DoNotIndent = 0x1,
Flag_WriteSpecialFloats = 0x2,
};
JSONWriter(Assimp::IOStream& out, unsigned int flags = 0u)
: out(out)
, first()
, flags(flags) {
// make sure that all formatting happens using the standard, C locale and not the user's current locale
buff.imbue(std::locale("C"));
}
~JSONWriter() {
Flush();
}
void Flush() {
const std::string s = buff.str();
out.Write(s.c_str(), s.length(), 1);
buff.clear();
}
void PushIndent() {
indent += '\t';
}
void PopIndent() {
indent.erase(indent.end() - 1);
}
void Key(const std::string& name) {
AddIndentation();
Delimit();
buff << '\"' + name + "\": ";
}
template<typename Literal>
void Element(const Literal& name) {
AddIndentation();
Delimit();
LiteralToString(buff, name) << '\n';
}
template<typename Literal>
void SimpleValue(const Literal& s) {
LiteralToString(buff, s) << '\n';
}
void SimpleValue(const void* buffer, size_t len) {
base64_encodestate s;
base64_init_encodestate(&s);
char* const out = new char[std::max(len * 2, static_cast<size_t>(16u))];
const int n = base64_encode_block(reinterpret_cast<const char*>(buffer), static_cast<int>(len), out, &s);
out[n + base64_encode_blockend(out + n, &s)] = '\0';
// base64 encoding may add newlines, but JSON strings may not contain 'real' newlines
// (only escaped ones). Remove any newlines in out.
for (char* cur = out; *cur; ++cur) {
if (*cur == '\n') {
*cur = ' ';
}
}
buff << '\"' << out << "\"\n";
delete[] out;
}
void StartObj(bool is_element = false) {
// if this appears as a plain array element, we need to insert a delimiter and we should also indent it
if (is_element) {
AddIndentation();
if (!first) {
buff << ',';
}
}
first = true;
buff << "{\n";
PushIndent();
}
void EndObj() {
PopIndent();
AddIndentation();
first = false;
buff << "}\n";
}
void StartArray(bool is_element = false) {
// if this appears as a plain array element, we need to insert a delimiter and we should also indent it
if (is_element) {
AddIndentation();
if (!first) {
buff << ',';
}
}
first = true;
buff << "[\n";
PushIndent();
}
void EndArray() {
PopIndent();
AddIndentation();
buff << "]\n";
first = false;
}
void AddIndentation() {
if (!(flags & Flag_DoNotIndent)) {
buff << indent;
}
}
void Delimit() {
if (!first) {
buff << ',';
}
else {
buff << ' ';
first = false;
}
}
private:
template<typename Literal>
std::stringstream& LiteralToString(std::stringstream& stream, const Literal& s) {
stream << s;
return stream;
}
std::stringstream& LiteralToString(std::stringstream& stream, const aiString& s) {
std::string t;
// escape backslashes and single quotes, both would render the JSON invalid if left as is
t.reserve(s.length);
for (size_t i = 0; i < s.length; ++i) {
if (s.data[i] == '\\' || s.data[i] == '\'' || s.data[i] == '\"') {
t.push_back('\\');
}
t.push_back(s.data[i]);
}
stream << "\"";
stream << t;
stream << "\"";
return stream;
}
std::stringstream& LiteralToString(std::stringstream& stream, float f) {
if (!std::numeric_limits<float>::is_iec559) {
// on a non IEEE-754 platform, we make no assumptions about the representation or existence
// of special floating-point numbers.
stream << f;
return stream;
}
// JSON does not support writing Inf/Nan
// [RFC 4672: "Numeric values that cannot be represented as sequences of digits
// (such as Infinity and NaN) are not permitted."]
// Nevertheless, many parsers will accept the special keywords Infinity, -Infinity and NaN
if (std::numeric_limits<float>::infinity() == fabs(f)) {
if (flags & Flag_WriteSpecialFloats) {
stream << (f < 0 ? "\"-" : "\"") + std::string("Infinity\"");
return stream;
}
// we should print this warning, but we can't - this is called from within a generic assimp exporter, we cannot use cerr
// std::cerr << "warning: cannot represent infinite number literal, substituting 0 instead (use -i flag to enforce Infinity/NaN)" << std::endl;
stream << "0.0";
return stream;
}
// f!=f is the most reliable test for NaNs that I know of
else if (f != f) {
if (flags & Flag_WriteSpecialFloats) {
stream << "\"NaN\"";
return stream;
}
// we should print this warning, but we can't - this is called from within a generic assimp exporter, we cannot use cerr
// std::cerr << "warning: cannot represent infinite number literal, substituting 0 instead (use -i flag to enforce Infinity/NaN)" << std::endl;
stream << "0.0";
return stream;
}
stream << f;
return stream;
}
private:
Assimp::IOStream& out;
std::string indent, newline;
std::stringstream buff;
bool first;
unsigned int flags;
};
void Write(JSONWriter& out, const aiVector3D& ai, bool is_elem = true) {
out.StartArray(is_elem);
out.Element(ai.x);
out.Element(ai.y);
out.Element(ai.z);
out.EndArray();
}
void Write(JSONWriter& out, const aiQuaternion& ai, bool is_elem = true) {
out.StartArray(is_elem);
out.Element(ai.w);
out.Element(ai.x);
out.Element(ai.y);
out.Element(ai.z);
out.EndArray();
}
void Write(JSONWriter& out, const aiColor3D& ai, bool is_elem = true) {
out.StartArray(is_elem);
out.Element(ai.r);
out.Element(ai.g);
out.Element(ai.b);
out.EndArray();
}
void Write(JSONWriter& out, const aiMatrix4x4& ai, bool is_elem = true) {
out.StartArray(is_elem);
for (unsigned int x = 0; x < 4; ++x) {
for (unsigned int y = 0; y < 4; ++y) {
out.Element(ai[x][y]);
}
}
out.EndArray();
}
void Write(JSONWriter& out, const aiBone& ai, bool is_elem = true) {
out.StartObj(is_elem);
out.Key("name");
out.SimpleValue(ai.mName);
out.Key("offsetmatrix");
Write(out, ai.mOffsetMatrix, false);
out.Key("weights");
out.StartArray();
for (unsigned int i = 0; i < ai.mNumWeights; ++i) {
out.StartArray(true);
out.Element(ai.mWeights[i].mVertexId);
out.Element(ai.mWeights[i].mWeight);
out.EndArray();
}
out.EndArray();
out.EndObj();
}
void Write(JSONWriter& out, const aiFace& ai, bool is_elem = true) {
out.StartArray(is_elem);
for (unsigned int i = 0; i < ai.mNumIndices; ++i) {
out.Element(ai.mIndices[i]);
}
out.EndArray();
}
void Write(JSONWriter& out, const aiMesh& ai, bool is_elem = true) {
out.StartObj(is_elem);
out.Key("name");
out.SimpleValue(ai.mName);
out.Key("materialindex");
out.SimpleValue(ai.mMaterialIndex);
out.Key("primitivetypes");
out.SimpleValue(ai.mPrimitiveTypes);
out.Key("vertices");
out.StartArray();
for (unsigned int i = 0; i < ai.mNumVertices; ++i) {
out.Element(ai.mVertices[i].x);
out.Element(ai.mVertices[i].y);
out.Element(ai.mVertices[i].z);
}
out.EndArray();
if (ai.HasNormals()) {
out.Key("normals");
out.StartArray();
for (unsigned int i = 0; i < ai.mNumVertices; ++i) {
out.Element(ai.mNormals[i].x);
out.Element(ai.mNormals[i].y);
out.Element(ai.mNormals[i].z);
}
out.EndArray();
}
if (ai.HasTangentsAndBitangents()) {
out.Key("tangents");
out.StartArray();
for (unsigned int i = 0; i < ai.mNumVertices; ++i) {
out.Element(ai.mTangents[i].x);
out.Element(ai.mTangents[i].y);
out.Element(ai.mTangents[i].z);
}
out.EndArray();
out.Key("bitangents");
out.StartArray();
for (unsigned int i = 0; i < ai.mNumVertices; ++i) {
out.Element(ai.mBitangents[i].x);
out.Element(ai.mBitangents[i].y);
out.Element(ai.mBitangents[i].z);
}
out.EndArray();
}
if (ai.GetNumUVChannels()) {
out.Key("numuvcomponents");
out.StartArray();
for (unsigned int n = 0; n < ai.GetNumUVChannels(); ++n) {
out.Element(ai.mNumUVComponents[n]);
}
out.EndArray();
out.Key("texturecoords");
out.StartArray();
for (unsigned int n = 0; n < ai.GetNumUVChannels(); ++n) {
const unsigned int numc = ai.mNumUVComponents[n] ? ai.mNumUVComponents[n] : 2;
out.StartArray(true);
for (unsigned int i = 0; i < ai.mNumVertices; ++i) {
for (unsigned int c = 0; c < numc; ++c) {
out.Element(ai.mTextureCoords[n][i][c]);
}
}
out.EndArray();
}
out.EndArray();
}
if (ai.GetNumColorChannels()) {
out.Key("colors");
out.StartArray();
for (unsigned int n = 0; n < ai.GetNumColorChannels(); ++n) {
out.StartArray(true);
for (unsigned int i = 0; i < ai.mNumVertices; ++i) {
out.Element(ai.mColors[n][i].r);
out.Element(ai.mColors[n][i].g);
out.Element(ai.mColors[n][i].b);
out.Element(ai.mColors[n][i].a);
}
out.EndArray();
}
out.EndArray();
}
if (ai.mNumBones) {
out.Key("bones");
out.StartArray();
for (unsigned int n = 0; n < ai.mNumBones; ++n) {
Write(out, *ai.mBones[n]);
}
out.EndArray();
}
out.Key("faces");
out.StartArray();
for (unsigned int n = 0; n < ai.mNumFaces; ++n) {
Write(out, ai.mFaces[n]);
}
out.EndArray();
out.EndObj();
}
void Write(JSONWriter& out, const aiNode& ai, bool is_elem = true) {
out.StartObj(is_elem);
out.Key("name");
out.SimpleValue(ai.mName);
out.Key("transformation");
Write(out, ai.mTransformation, false);
if (ai.mNumMeshes) {
out.Key("meshes");
out.StartArray();
for (unsigned int n = 0; n < ai.mNumMeshes; ++n) {
out.Element(ai.mMeshes[n]);
}
out.EndArray();
}
if (ai.mNumChildren) {
out.Key("children");
out.StartArray();
for (unsigned int n = 0; n < ai.mNumChildren; ++n) {
Write(out, *ai.mChildren[n]);
}
out.EndArray();
}
out.EndObj();
}
void Write(JSONWriter& out, const aiMaterial& ai, bool is_elem = true) {
out.StartObj(is_elem);
out.Key("properties");
out.StartArray();
for (unsigned int i = 0; i < ai.mNumProperties; ++i) {
const aiMaterialProperty* const prop = ai.mProperties[i];
out.StartObj(true);
out.Key("key");
out.SimpleValue(prop->mKey);
out.Key("semantic");
out.SimpleValue(prop->mSemantic);
out.Key("index");
out.SimpleValue(prop->mIndex);
out.Key("type");
out.SimpleValue(prop->mType);
out.Key("value");
switch (prop->mType) {
case aiPTI_Float:
if (prop->mDataLength / sizeof(float) > 1) {
out.StartArray();
for (unsigned int i = 0; i < prop->mDataLength / sizeof(float); ++i) {
out.Element(reinterpret_cast<float*>(prop->mData)[i]);
}
out.EndArray();
}
else {
out.SimpleValue(*reinterpret_cast<float*>(prop->mData));
}
break;
case aiPTI_Integer:
if (prop->mDataLength / sizeof(int) > 1) {
out.StartArray();
for (unsigned int i = 0; i < prop->mDataLength / sizeof(int); ++i) {
out.Element(reinterpret_cast<int*>(prop->mData)[i]);
}
out.EndArray();
} else {
out.SimpleValue(*reinterpret_cast<int*>(prop->mData));
}
break;
case aiPTI_String:
{
aiString s;
aiGetMaterialString(&ai, prop->mKey.data, prop->mSemantic, prop->mIndex, &s);
out.SimpleValue(s);
}
break;
case aiPTI_Buffer:
{
// binary data is written as series of hex-encoded octets
out.SimpleValue(prop->mData, prop->mDataLength);
}
break;
default:
assert(false);
}
out.EndObj();
}
out.EndArray();
out.EndObj();
}
void Write(JSONWriter& out, const aiTexture& ai, bool is_elem = true) {
out.StartObj(is_elem);
out.Key("width");
out.SimpleValue(ai.mWidth);
out.Key("height");
out.SimpleValue(ai.mHeight);
out.Key("formathint");
out.SimpleValue(aiString(ai.achFormatHint));
out.Key("data");
if (!ai.mHeight) {
out.SimpleValue(ai.pcData, ai.mWidth);
}
else {
out.StartArray();
for (unsigned int y = 0; y < ai.mHeight; ++y) {
out.StartArray(true);
for (unsigned int x = 0; x < ai.mWidth; ++x) {
const aiTexel& tx = ai.pcData[y*ai.mWidth + x];
out.StartArray(true);
out.Element(static_cast<unsigned int>(tx.r));
out.Element(static_cast<unsigned int>(tx.g));
out.Element(static_cast<unsigned int>(tx.b));
out.Element(static_cast<unsigned int>(tx.a));
out.EndArray();
}
out.EndArray();
}
out.EndArray();
}
out.EndObj();
}
void Write(JSONWriter& out, const aiLight& ai, bool is_elem = true) {
out.StartObj(is_elem);
out.Key("name");
out.SimpleValue(ai.mName);
out.Key("type");
out.SimpleValue(ai.mType);
if (ai.mType == aiLightSource_SPOT || ai.mType == aiLightSource_UNDEFINED) {
out.Key("angleinnercone");
out.SimpleValue(ai.mAngleInnerCone);
out.Key("angleoutercone");
out.SimpleValue(ai.mAngleOuterCone);
}
out.Key("attenuationconstant");
out.SimpleValue(ai.mAttenuationConstant);
out.Key("attenuationlinear");
out.SimpleValue(ai.mAttenuationLinear);
out.Key("attenuationquadratic");
out.SimpleValue(ai.mAttenuationQuadratic);
out.Key("diffusecolor");
Write(out, ai.mColorDiffuse, false);
out.Key("specularcolor");
Write(out, ai.mColorSpecular, false);
out.Key("ambientcolor");
Write(out, ai.mColorAmbient, false);
if (ai.mType != aiLightSource_POINT) {
out.Key("direction");
Write(out, ai.mDirection, false);
}
if (ai.mType != aiLightSource_DIRECTIONAL) {
out.Key("position");
Write(out, ai.mPosition, false);
}
out.EndObj();
}
void Write(JSONWriter& out, const aiNodeAnim& ai, bool is_elem = true) {
out.StartObj(is_elem);
out.Key("name");
out.SimpleValue(ai.mNodeName);
out.Key("prestate");
out.SimpleValue(ai.mPreState);
out.Key("poststate");
out.SimpleValue(ai.mPostState);
if (ai.mNumPositionKeys) {
out.Key("positionkeys");
out.StartArray();
for (unsigned int n = 0; n < ai.mNumPositionKeys; ++n) {
const aiVectorKey& pos = ai.mPositionKeys[n];
out.StartArray(true);
out.Element(pos.mTime);
Write(out, pos.mValue);
out.EndArray();
}
out.EndArray();
}
if (ai.mNumRotationKeys) {
out.Key("rotationkeys");
out.StartArray();
for (unsigned int n = 0; n < ai.mNumRotationKeys; ++n) {
const aiQuatKey& rot = ai.mRotationKeys[n];
out.StartArray(true);
out.Element(rot.mTime);
Write(out, rot.mValue);
out.EndArray();
}
out.EndArray();
}
if (ai.mNumScalingKeys) {
out.Key("scalingkeys");
out.StartArray();
for (unsigned int n = 0; n < ai.mNumScalingKeys; ++n) {
const aiVectorKey& scl = ai.mScalingKeys[n];
out.StartArray(true);
out.Element(scl.mTime);
Write(out, scl.mValue);
out.EndArray();
}
out.EndArray();
}
out.EndObj();
}
void Write(JSONWriter& out, const aiAnimation& ai, bool is_elem = true) {
out.StartObj(is_elem);
out.Key("name");
out.SimpleValue(ai.mName);
out.Key("tickspersecond");
out.SimpleValue(ai.mTicksPerSecond);
out.Key("duration");
out.SimpleValue(ai.mDuration);
out.Key("channels");
out.StartArray();
for (unsigned int n = 0; n < ai.mNumChannels; ++n) {
Write(out, *ai.mChannels[n]);
}
out.EndArray();
out.EndObj();
}
void Write(JSONWriter& out, const aiCamera& ai, bool is_elem = true) {
out.StartObj(is_elem);
out.Key("name");
out.SimpleValue(ai.mName);
out.Key("aspect");
out.SimpleValue(ai.mAspect);
out.Key("clipplanefar");
out.SimpleValue(ai.mClipPlaneFar);
out.Key("clipplanenear");
out.SimpleValue(ai.mClipPlaneNear);
out.Key("horizontalfov");
out.SimpleValue(ai.mHorizontalFOV);
out.Key("up");
Write(out, ai.mUp, false);
out.Key("lookat");
Write(out, ai.mLookAt, false);
out.EndObj();
}
void WriteFormatInfo(JSONWriter& out) {
out.StartObj();
out.Key("format");
out.SimpleValue("\"assimp2json\"");
out.Key("version");
out.SimpleValue(CURRENT_FORMAT_VERSION);
out.EndObj();
}
void Write(JSONWriter& out, const aiScene& ai) {
out.StartObj();
out.Key("__metadata__");
WriteFormatInfo(out);
out.Key("rootnode");
Write(out, *ai.mRootNode, false);
out.Key("flags");
out.SimpleValue(ai.mFlags);
if (ai.HasMeshes()) {
out.Key("meshes");
out.StartArray();
for (unsigned int n = 0; n < ai.mNumMeshes; ++n) {
Write(out, *ai.mMeshes[n]);
}
out.EndArray();
}
if (ai.HasMaterials()) {
out.Key("materials");
out.StartArray();
for (unsigned int n = 0; n < ai.mNumMaterials; ++n) {
Write(out, *ai.mMaterials[n]);
}
out.EndArray();
}
if (ai.HasAnimations()) {
out.Key("animations");
out.StartArray();
for (unsigned int n = 0; n < ai.mNumAnimations; ++n) {
Write(out, *ai.mAnimations[n]);
}
out.EndArray();
}
if (ai.HasLights()) {
out.Key("lights");
out.StartArray();
for (unsigned int n = 0; n < ai.mNumLights; ++n) {
Write(out, *ai.mLights[n]);
}
out.EndArray();
}
if (ai.HasCameras()) {
out.Key("cameras");
out.StartArray();
for (unsigned int n = 0; n < ai.mNumCameras; ++n) {
Write(out, *ai.mCameras[n]);
}
out.EndArray();
}
if (ai.HasTextures()) {
out.Key("textures");
out.StartArray();
for (unsigned int n = 0; n < ai.mNumTextures; ++n) {
Write(out, *ai.mTextures[n]);
}
out.EndArray();
}
out.EndObj();
}
void ExportAssimp2Json(const char* file, Assimp::IOSystem* io, const aiScene* scene, const Assimp::ExportProperties*) {
std::unique_ptr<Assimp::IOStream> str(io->Open(file, "wt"));
if (!str) {
//throw Assimp::DeadlyExportError("could not open output file");
}
// get a copy of the scene so we can modify it
aiScene* scenecopy_tmp;
aiCopyScene(scene, &scenecopy_tmp);
try {
// split meshes so they fit into a 16 bit index buffer
MeshSplitter splitter;
splitter.SetLimit(1 << 16);
splitter.Execute(scenecopy_tmp);
// XXX Flag_WriteSpecialFloats is turned on by default, right now we don't have a configuration interface for exporters
JSONWriter s(*str, JSONWriter::Flag_WriteSpecialFloats);
Write(s, *scenecopy_tmp);
}
catch (...) {
aiFreeScene(scenecopy_tmp);
throw;
}
aiFreeScene(scenecopy_tmp);
}
}
#endif // ASSIMP_BUILD_NO_ASSJSON_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT

View File

@ -0,0 +1,320 @@
/*
Assimp2Json
Copyright (c) 2011, Alexander C. Gessler
Licensed under a 3-clause BSD license. See the LICENSE file for more information.
*/
#include "mesh_splitter.h"
#include <assimp/scene.h>
// ----------------------------------------------------------------------------
// Note: this is largely based on assimp's SplitLargeMeshes_Vertex process.
// it is refactored and the coding style is slightly improved, though.
// ----------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data.
void MeshSplitter::Execute( aiScene* pScene) {
std::vector<std::pair<aiMesh*, unsigned int> > source_mesh_map;
for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
SplitMesh(a, pScene->mMeshes[a],source_mesh_map);
}
const unsigned int size = static_cast<unsigned int>(source_mesh_map.size());
if (size != pScene->mNumMeshes) {
// it seems something has been split. rebuild the mesh list
delete[] pScene->mMeshes;
pScene->mNumMeshes = size;
pScene->mMeshes = new aiMesh*[size]();
for (unsigned int i = 0; i < size;++i) {
pScene->mMeshes[i] = source_mesh_map[i].first;
}
// now we need to update all nodes
UpdateNode(pScene->mRootNode,source_mesh_map);
}
}
// ------------------------------------------------------------------------------------------------
void MeshSplitter::UpdateNode(aiNode* pcNode, const std::vector<std::pair<aiMesh*, unsigned int> >& source_mesh_map) {
// TODO: should better use std::(multi)set for source_mesh_map.
// for every index in out list build a new entry
std::vector<unsigned int> aiEntries;
aiEntries.reserve(pcNode->mNumMeshes + 1);
for (unsigned int i = 0; i < pcNode->mNumMeshes;++i) {
for (unsigned int a = 0, end = static_cast<unsigned int>(source_mesh_map.size()); a < end;++a) {
if (source_mesh_map[a].second == pcNode->mMeshes[i]) {
aiEntries.push_back(a);
}
}
}
// now build the new list
delete pcNode->mMeshes;
pcNode->mNumMeshes = static_cast<unsigned int>(aiEntries.size());
pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
for (unsigned int b = 0; b < pcNode->mNumMeshes;++b) {
pcNode->mMeshes[b] = aiEntries[b];
}
// recursively update children
for (unsigned int i = 0, end = pcNode->mNumChildren; i < end;++i) {
UpdateNode ( pcNode->mChildren[i], source_mesh_map );
}
return;
}
#define WAS_NOT_COPIED 0xffffffff
typedef std::pair <unsigned int,float> PerVertexWeight;
typedef std::vector <PerVertexWeight> VertexWeightTable;
// ------------------------------------------------------------------------------------------------
VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh) {
if (!pMesh || !pMesh->mNumVertices || !pMesh->mNumBones) {
return nullptr;
}
VertexWeightTable* const avPerVertexWeights = new VertexWeightTable[pMesh->mNumVertices];
for (unsigned int i = 0; i < pMesh->mNumBones;++i) {
aiBone* bone = pMesh->mBones[i];
for (unsigned int a = 0; a < bone->mNumWeights;++a) {
const aiVertexWeight& weight = bone->mWeights[a];
avPerVertexWeights[weight.mVertexId].push_back( std::make_pair(i,weight.mWeight) );
}
}
return avPerVertexWeights;
}
// ------------------------------------------------------------------------------------------------
void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, std::vector<std::pair<aiMesh*, unsigned int> >& source_mesh_map) {
// TODO: should better use std::(multi)set for source_mesh_map.
if (in_mesh->mNumVertices <= LIMIT) {
source_mesh_map.push_back(std::make_pair(in_mesh,a));
return;
}
// build a per-vertex weight list if necessary
VertexWeightTable* avPerVertexWeights = ComputeVertexBoneWeightTable(in_mesh);
// we need to split this mesh into sub meshes. Estimate submesh size
const unsigned int sub_meshes = (in_mesh->mNumVertices / LIMIT) + 1;
// create a std::vector<unsigned int> to remember which vertices have already
// been copied and to which position (i.e. output index)
std::vector<unsigned int> was_copied_to;
was_copied_to.resize(in_mesh->mNumVertices,WAS_NOT_COPIED);
// Try to find a good estimate for the number of output faces
// per mesh. Add 12.5% as buffer
unsigned int size_estimated = in_mesh->mNumFaces / sub_meshes;
size_estimated += size_estimated / 8;
// now generate all submeshes
unsigned int base = 0;
while (true) {
const unsigned int out_vertex_index = LIMIT;
aiMesh* out_mesh = new aiMesh();
out_mesh->mNumVertices = 0;
out_mesh->mMaterialIndex = in_mesh->mMaterialIndex;
// the name carries the adjacency information between the meshes
out_mesh->mName = in_mesh->mName;
typedef std::vector<aiVertexWeight> BoneWeightList;
if (in_mesh->HasBones()) {
out_mesh->mBones = new aiBone*[in_mesh->mNumBones]();
}
// clear the temporary helper array
if (base) {
std::fill(was_copied_to.begin(), was_copied_to.end(), WAS_NOT_COPIED);
}
std::vector<aiFace> vFaces;
// reserve enough storage for most cases
if (in_mesh->HasPositions()) {
out_mesh->mVertices = new aiVector3D[out_vertex_index];
}
if (in_mesh->HasNormals()) {
out_mesh->mNormals = new aiVector3D[out_vertex_index];
}
if (in_mesh->HasTangentsAndBitangents()) {
out_mesh->mTangents = new aiVector3D[out_vertex_index];
out_mesh->mBitangents = new aiVector3D[out_vertex_index];
}
for (unsigned int c = 0; in_mesh->HasVertexColors(c);++c) {
out_mesh->mColors[c] = new aiColor4D[out_vertex_index];
}
for (unsigned int c = 0; in_mesh->HasTextureCoords(c);++c) {
out_mesh->mNumUVComponents[c] = in_mesh->mNumUVComponents[c];
out_mesh->mTextureCoords[c] = new aiVector3D[out_vertex_index];
}
vFaces.reserve(size_estimated);
// (we will also need to copy the array of indices)
while (base < in_mesh->mNumFaces) {
const unsigned int iNumIndices = in_mesh->mFaces[base].mNumIndices;
// doesn't catch degenerates but is quite fast
unsigned int iNeed = 0;
for (unsigned int v = 0; v < iNumIndices;++v) {
unsigned int index = in_mesh->mFaces[base].mIndices[v];
// check whether we do already have this vertex
if (WAS_NOT_COPIED == was_copied_to[index]) {
iNeed++;
}
}
if (out_mesh->mNumVertices + iNeed > out_vertex_index) {
// don't use this face
break;
}
vFaces.push_back(aiFace());
aiFace& rFace = vFaces.back();
// setup face type and number of indices
rFace.mNumIndices = iNumIndices;
rFace.mIndices = new unsigned int[iNumIndices];
// need to update the output primitive types
switch (rFace.mNumIndices)
{
case 1:
out_mesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
break;
case 2:
out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
break;
case 3:
out_mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
break;
default:
out_mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
}
// and copy the contents of the old array, offset them by current base
for (unsigned int v = 0; v < iNumIndices;++v) {
const unsigned int index = in_mesh->mFaces[base].mIndices[v];
// check whether we do already have this vertex
if (WAS_NOT_COPIED != was_copied_to[index]) {
rFace.mIndices[v] = was_copied_to[index];
continue;
}
// copy positions
out_mesh->mVertices[out_mesh->mNumVertices] = (in_mesh->mVertices[index]);
// copy normals
if (in_mesh->HasNormals()) {
out_mesh->mNormals[out_mesh->mNumVertices] = (in_mesh->mNormals[index]);
}
// copy tangents/bi-tangents
if (in_mesh->HasTangentsAndBitangents()) {
out_mesh->mTangents[out_mesh->mNumVertices] = (in_mesh->mTangents[index]);
out_mesh->mBitangents[out_mesh->mNumVertices] = (in_mesh->mBitangents[index]);
}
// texture coordinates
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
if (in_mesh->HasTextureCoords( c)) {
out_mesh->mTextureCoords[c][out_mesh->mNumVertices] = in_mesh->mTextureCoords[c][index];
}
}
// vertex colors
for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) {
if (in_mesh->HasVertexColors( c)) {
out_mesh->mColors[c][out_mesh->mNumVertices] = in_mesh->mColors[c][index];
}
}
// check whether we have bone weights assigned to this vertex
rFace.mIndices[v] = out_mesh->mNumVertices;
if (avPerVertexWeights) {
VertexWeightTable& table = avPerVertexWeights[ out_mesh->mNumVertices ];
for (VertexWeightTable::const_iterator iter = table.begin(), end = table.end(); iter != end;++iter) {
// allocate the bone weight array if necessary and store it in the mBones field (HACK!)
BoneWeightList* weight_list = reinterpret_cast<BoneWeightList*>(out_mesh->mBones[(*iter).first]);
if (!weight_list) {
weight_list = new BoneWeightList();
out_mesh->mBones[(*iter).first] = reinterpret_cast<aiBone*>(weight_list);
}
weight_list->push_back(aiVertexWeight(out_mesh->mNumVertices,(*iter).second));
}
}
was_copied_to[index] = out_mesh->mNumVertices;
out_mesh->mNumVertices++;
}
base++;
if(out_mesh->mNumVertices == out_vertex_index) {
// break here. The face is only added if it was complete
break;
}
}
// check which bones we'll need to create for this submesh
if (in_mesh->HasBones()) {
aiBone** ppCurrent = out_mesh->mBones;
for (unsigned int k = 0; k < in_mesh->mNumBones;++k) {
// check whether the bone exists
BoneWeightList* const weight_list = reinterpret_cast<BoneWeightList*>(out_mesh->mBones[k]);
if (weight_list) {
const aiBone* const bone_in = in_mesh->mBones[k];
aiBone* const bone_out = new aiBone();
*ppCurrent++ = bone_out;
bone_out->mName = aiString(bone_in->mName);
bone_out->mOffsetMatrix =bone_in->mOffsetMatrix;
bone_out->mNumWeights = (unsigned int)weight_list->size();
bone_out->mWeights = new aiVertexWeight[bone_out->mNumWeights];
// copy the vertex weights
::memcpy(bone_out->mWeights, &(*weight_list)[0],bone_out->mNumWeights * sizeof(aiVertexWeight));
delete weight_list;
out_mesh->mNumBones++;
}
}
}
// copy the face list to the mesh
out_mesh->mFaces = new aiFace[vFaces.size()];
out_mesh->mNumFaces = (unsigned int)vFaces.size();
for (unsigned int p = 0; p < out_mesh->mNumFaces;++p) {
out_mesh->mFaces[p] = vFaces[p];
}
// add the newly created mesh to the list
source_mesh_map.push_back(std::make_pair(out_mesh,a));
if (base == in_mesh->mNumFaces) {
break;
}
}
// delete the per-vertex weight list again
delete[] avPerVertexWeights;
// now delete the old mesh data
delete in_mesh;
}

View File

@ -0,0 +1,61 @@
/*
Assimp2Json
Copyright (c) 2011, Alexander C. Gessler
Licensed under a 3-clause BSD license. See the LICENSE file for more information.
*/
#ifndef INCLUDED_MESH_SPLITTER
#define INCLUDED_MESH_SPLITTER
// ----------------------------------------------------------------------------
// Note: this is largely based on assimp's SplitLargeMeshes_Vertex process.
// it is refactored and the coding style is slightly improved, though.
// ----------------------------------------------------------------------------
#include <vector>
struct aiScene;
struct aiMesh;
struct aiNode;
// ---------------------------------------------------------------------------
/** Splits meshes of unique vertices into meshes with no more vertices than
* a given, configurable threshold value.
*/
class MeshSplitter
{
public:
void SetLimit(unsigned int l) {
LIMIT = l;
}
unsigned int GetLimit() const {
return LIMIT;
}
public:
// -------------------------------------------------------------------
/** Executes the post processing step on the given imported data.
* At the moment a process is not supposed to fail.
* @param pScene The imported data to work at.
*/
void Execute( aiScene* pScene);
private:
void UpdateNode(aiNode* pcNode, const std::vector<std::pair<aiMesh*, unsigned int> >& source_mesh_map);
void SplitMesh (unsigned int index, aiMesh* mesh, std::vector<std::pair<aiMesh*, unsigned int> >& source_mesh_map);
public:
unsigned int LIMIT;
};
#endif // INCLUDED_MESH_SPLITTER

View File

@ -46,13 +46,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER #ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
#include <stdarg.h> #include "PostProcessing/ProcessHelper.h"
#include <assimp/version.h> #include <assimp/version.h>
#include "ProcessHelper.h"
#include <assimp/IOStream.hpp> #include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/Exporter.hpp> #include <assimp/Exporter.hpp>
#include <stdarg.h>
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB #ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h> # include <zlib.h>
#else #else

View File

@ -49,17 +49,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_B3D_IMPORTER #ifndef ASSIMP_BUILD_NO_B3D_IMPORTER
// internal headers // internal headers
#include "B3DImporter.h" #include "B3D/B3DImporter.h"
#include "TextureTransform.h" #include "PostProcessing/TextureTransform.h"
#include "ConvertToLHProcess.h" #include "PostProcessing/ConvertToLHProcess.h"
#include <assimp/StringUtils.h> #include <assimp/StringUtils.h>
#include <memory>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/anim.h> #include <assimp/anim.h>
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
#include <memory>
using namespace Assimp; using namespace Assimp;
using namespace std; using namespace std;

View File

@ -1225,6 +1225,16 @@ aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, c
case Lamp::Type_Local: case Lamp::Type_Local:
out->mType = aiLightSource_POINT; out->mType = aiLightSource_POINT;
break; break;
case Lamp::Type_Spot:
out->mType = aiLightSource_SPOT;
// blender orients directional lights as facing toward -z
out->mDirection = aiVector3D(0.f, 0.f, -1.f);
out->mUp = aiVector3D(0.f, 1.f, 0.f);
out->mAngleInnerCone = lamp->spotsize * (1.0f - lamp->spotblend);
out->mAngleOuterCone = lamp->spotsize;
break;
case Lamp::Type_Sun: case Lamp::Type_Sun:
out->mType = aiLightSource_DIRECTIONAL; out->mType = aiLightSource_DIRECTIONAL;
@ -1255,6 +1265,23 @@ aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, c
out->mColorAmbient = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy; out->mColorAmbient = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
out->mColorSpecular = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy; out->mColorSpecular = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
out->mColorDiffuse = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy; out->mColorDiffuse = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
// If default values are supplied, compute the coefficients from light's max distance
// Read this: https://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/
//
if (lamp->constant_coefficient == 1.0f && lamp->linear_coefficient == 0.0f && lamp->quadratic_coefficient == 0.0f && lamp->dist > 0.0f)
{
out->mAttenuationConstant = 1.0f;
out->mAttenuationLinear = 2.0f / lamp->dist;
out->mAttenuationQuadratic = 1.0f / (lamp->dist * lamp->dist);
}
else
{
out->mAttenuationConstant = lamp->constant_coefficient;
out->mAttenuationLinear = lamp->linear_coefficient;
out->mAttenuationQuadratic = lamp->quadratic_coefficient;
}
return out.release(); return out.release();
} }

View File

@ -211,9 +211,12 @@ template <> void Structure :: Convert<Lamp> (
ReadField<ErrorPolicy_Warn>(dest.b,"b",db); ReadField<ErrorPolicy_Warn>(dest.b,"b",db);
ReadField<ErrorPolicy_Warn>(dest.k,"k",db); ReadField<ErrorPolicy_Warn>(dest.k,"k",db);
ReadField<ErrorPolicy_Igno>(dest.energy,"energy",db); ReadField<ErrorPolicy_Igno>(dest.energy,"energy",db);
ReadField<ErrorPolicy_Igno>(dest.dist,"dist",db); ReadField<ErrorPolicy_Warn>(dest.dist,"dist",db);
ReadField<ErrorPolicy_Igno>(dest.spotsize,"spotsize",db); ReadField<ErrorPolicy_Igno>(dest.spotsize,"spotsize",db);
ReadField<ErrorPolicy_Igno>(dest.spotblend,"spotblend",db); ReadField<ErrorPolicy_Igno>(dest.spotblend,"spotblend",db);
ReadField<ErrorPolicy_Warn>(dest.constant_coefficient, "coeff_const", db);
ReadField<ErrorPolicy_Warn>(dest.linear_coefficient, "coeff_lin", db);
ReadField<ErrorPolicy_Warn>(dest.quadratic_coefficient, "coeff_quad", db);
ReadField<ErrorPolicy_Igno>(dest.att1,"att1",db); ReadField<ErrorPolicy_Igno>(dest.att1,"att1",db);
ReadField<ErrorPolicy_Igno>(dest.att2,"att2",db); ReadField<ErrorPolicy_Igno>(dest.att2,"att2",db);
ReadField<ErrorPolicy_Igno>(temp,"falloff_type",db); ReadField<ErrorPolicy_Igno>(temp,"falloff_type",db);

View File

@ -538,6 +538,10 @@ struct Lamp : ElemBase {
float energy, dist, spotsize, spotblend; float energy, dist, spotsize, spotblend;
//float haint; //float haint;
float constant_coefficient;
float linear_coefficient;
float quadratic_coefficient;
float att1, att2; float att1, att2;
//struct CurveMapping *curfalloff; //struct CurveMapping *curfalloff;
FalloffType falloff_type; FalloffType falloff_type;

View File

@ -144,7 +144,11 @@ namespace Assimp
#if ASSIMP_BLEND_WITH_POLY_2_TRI #if ASSIMP_BLEND_WITH_POLY_2_TRI
#include "../contrib/poly2tri/poly2tri/poly2tri.h" #ifdef ASSIMP_USE_HUNTER
# include <poly2tri/poly2tri.h>
#else
# include "../contrib/poly2tri/poly2tri/poly2tri.h"
#endif
namespace Assimp namespace Assimp
{ {

View File

@ -49,7 +49,7 @@ Assimp C export interface. See Exporter.cpp for some notes.
#include "CInterfaceIOWrapper.h" #include "CInterfaceIOWrapper.h"
#include <assimp/SceneCombiner.h> #include <assimp/SceneCombiner.h>
#include "ScenePrivate.h" #include "Common/ScenePrivate.h"
#include <assimp/Exporter.hpp> #include <assimp/Exporter.hpp>
using namespace Assimp; using namespace Assimp;

File diff suppressed because it is too large Load Diff

View File

@ -45,20 +45,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_COB_IMPORTER #ifndef ASSIMP_BUILD_NO_COB_IMPORTER
#include "COBLoader.h" #include "COB/COBLoader.h"
#include "COBScene.h" #include "COB/COBScene.h"
#include "ConvertToLHProcess.h" #include "PostProcessing/ConvertToLHProcess.h"
#include <assimp/StreamReader.h> #include <assimp/StreamReader.h>
#include <assimp/ParsingUtils.h> #include <assimp/ParsingUtils.h>
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
#include <assimp/LineSplitter.h> #include <assimp/LineSplitter.h>
#include <assimp/TinyFormatter.h> #include <assimp/TinyFormatter.h>
#include <memory>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
#include <memory>
using namespace Assimp; using namespace Assimp;
using namespace Assimp::COB; using namespace Assimp::COB;
using namespace Assimp::Formatter; using namespace Assimp::Formatter;
@ -896,6 +898,7 @@ public:
: nfo(nfo) : nfo(nfo)
, reader(reader) , reader(reader)
, cur(reader.GetCurrentPos()) { , cur(reader.GetCurrentPos()) {
// empty
} }
~chunk_guard() { ~chunk_guard() {
@ -903,7 +906,7 @@ public:
if(nfo.size != static_cast<unsigned int>(-1)) { if(nfo.size != static_cast<unsigned int>(-1)) {
try { try {
reader.IncPtr( static_cast< int >( nfo.size ) - reader.GetCurrentPos() + cur ); reader.IncPtr( static_cast< int >( nfo.size ) - reader.GetCurrentPos() + cur );
} catch (const DeadlyImportError& e ) { } catch (const DeadlyImportError& ) {
// out of limit so correct the value // out of limit so correct the value
reader.IncPtr( reader.GetReadLimit() ); reader.IncPtr( reader.GetReadLimit() );
} }
@ -911,15 +914,17 @@ public:
} }
private: private:
const COB::ChunkInfo& nfo; const COB::ChunkInfo& nfo;
StreamReaderLE& reader; StreamReaderLE& reader;
long cur; long cur;
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void COBImporter::ReadBinaryFile(Scene& out, StreamReaderLE* reader) void COBImporter::ReadBinaryFile(Scene& out, StreamReaderLE* reader) {
{ if (nullptr == reader) {
return;
}
while(1) { while(1) {
std::string type; std::string type;
type += reader -> GetI1() type += reader -> GetI1()

View File

@ -64,13 +64,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
namespace Assimp namespace Assimp {
{
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp // Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) {
{
std::string path = DefaultIOSystem::absolutePath(std::string(pFile)); std::string path = DefaultIOSystem::absolutePath(std::string(pFile));
std::string file = DefaultIOSystem::completeBaseName(std::string(pFile)); std::string file = DefaultIOSystem::completeBaseName(std::string(pFile));
@ -93,15 +91,15 @@ void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* p
} // end of namespace Assimp } // end of namespace Assimp
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor for a specific scene to export // Constructor for a specific scene to export
ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) : mIOSystem(pIOSystem), mPath(path), mFile(file) ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file)
{ : mIOSystem(pIOSystem)
, mPath(path)
, mFile(file) {
// 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
mOutput.imbue( std::locale("C") ); mOutput.imbue( std::locale("C") );
mOutput.precision(16); mOutput.precision(ASSIMP_AI_REAL_TEXT_PRECISION);
mScene = pScene; mScene = pScene;
mSceneOwned = false; mSceneOwned = false;
@ -115,17 +113,15 @@ ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, co
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor // Destructor
ColladaExporter::~ColladaExporter() ColladaExporter::~ColladaExporter() {
{ if ( mSceneOwned ) {
if(mSceneOwned) {
delete mScene; delete mScene;
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Starts writing the contents // Starts writing the contents
void ColladaExporter::WriteFile() void ColladaExporter::WriteFile() {
{
// write the DTD // write the DTD
mOutput << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>" << endstr; mOutput << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>" << endstr;
// COLLADA element start // COLLADA element start
@ -158,8 +154,7 @@ void ColladaExporter::WriteFile()
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Writes the asset header // Writes the asset header
void ColladaExporter::WriteHeader() void ColladaExporter::WriteHeader() {
{
static const ai_real epsilon = ai_real( 0.00001 ); static const ai_real epsilon = ai_real( 0.00001 );
static const aiQuaternion x_rot(aiMatrix3x3( static const aiQuaternion x_rot(aiMatrix3x3(
0, -1, 0, 0, -1, 0,
@ -240,51 +235,60 @@ void ColladaExporter::WriteHeader()
// If no Scene metadata, use root node metadata // If no Scene metadata, use root node metadata
aiMetadata* meta = mScene->mMetaData; aiMetadata* meta = mScene->mMetaData;
if (!meta) if (nullptr == meta) {
meta = mScene->mRootNode->mMetaData; meta = mScene->mRootNode->mMetaData;
}
aiString value; aiString value;
if (!meta || !meta->Get("Author", value)) if (!meta || !meta->Get("Author", value)) {
mOutput << startstr << "<author>" << "Assimp" << "</author>" << endstr; mOutput << startstr << "<author>" << "Assimp" << "</author>" << endstr;
else } else {
mOutput << startstr << "<author>" << XMLEscape(value.C_Str()) << "</author>" << endstr; mOutput << startstr << "<author>" << XMLEscape(value.C_Str()) << "</author>" << endstr;
}
if (!meta || !meta->Get("AuthoringTool", value)) if (nullptr == meta || !meta->Get("AuthoringTool", value)) {
mOutput << startstr << "<authoring_tool>" << "Assimp Exporter" << "</authoring_tool>" << endstr; mOutput << startstr << "<authoring_tool>" << "Assimp Exporter" << "</authoring_tool>" << endstr;
else } else {
mOutput << startstr << "<authoring_tool>" << XMLEscape(value.C_Str()) << "</authoring_tool>" << endstr; mOutput << startstr << "<authoring_tool>" << XMLEscape(value.C_Str()) << "</authoring_tool>" << endstr;
}
if (meta) if (meta) {
{ if (meta->Get("Comments", value)) {
if (meta->Get("Comments", value))
mOutput << startstr << "<comments>" << XMLEscape(value.C_Str()) << "</comments>" << endstr; mOutput << startstr << "<comments>" << XMLEscape(value.C_Str()) << "</comments>" << endstr;
if (meta->Get("Copyright", value)) }
if (meta->Get("Copyright", value)) {
mOutput << startstr << "<copyright>" << XMLEscape(value.C_Str()) << "</copyright>" << endstr; mOutput << startstr << "<copyright>" << XMLEscape(value.C_Str()) << "</copyright>" << endstr;
if (meta->Get("SourceData", value)) }
if (meta->Get("SourceData", value)) {
mOutput << startstr << "<source_data>" << XMLEscape(value.C_Str()) << "</source_data>" << endstr; mOutput << startstr << "<source_data>" << XMLEscape(value.C_Str()) << "</source_data>" << endstr;
}
} }
PopTag(); PopTag();
mOutput << startstr << "</contributor>" << endstr; mOutput << startstr << "</contributor>" << endstr;
if (!meta || !meta->Get("Created", value)) if (nullptr == meta || !meta->Get("Created", value)) {
mOutput << startstr << "<created>" << date_str << "</created>" << endstr; mOutput << startstr << "<created>" << date_str << "</created>" << endstr;
else } else {
mOutput << startstr << "<created>" << XMLEscape(value.C_Str()) << "</created>" << endstr; mOutput << startstr << "<created>" << XMLEscape(value.C_Str()) << "</created>" << endstr;
}
// Modified date is always the date saved // Modified date is always the date saved
mOutput << startstr << "<modified>" << date_str << "</modified>" << endstr; mOutput << startstr << "<modified>" << date_str << "</modified>" << endstr;
if (meta) if (meta) {
{ if (meta->Get("Keywords", value)) {
if (meta->Get("Keywords", value))
mOutput << startstr << "<keywords>" << XMLEscape(value.C_Str()) << "</keywords>" << endstr; mOutput << startstr << "<keywords>" << XMLEscape(value.C_Str()) << "</keywords>" << endstr;
if (meta->Get("Revision", value)) }
if (meta->Get("Revision", value)) {
mOutput << startstr << "<revision>" << XMLEscape(value.C_Str()) << "</revision>" << endstr; mOutput << startstr << "<revision>" << XMLEscape(value.C_Str()) << "</revision>" << endstr;
if (meta->Get("Subject", value)) }
if (meta->Get("Subject", value)) {
mOutput << startstr << "<subject>" << XMLEscape(value.C_Str()) << "</subject>" << endstr; mOutput << startstr << "<subject>" << XMLEscape(value.C_Str()) << "</subject>" << endstr;
if (meta->Get("Title", value)) }
if (meta->Get("Title", value)) {
mOutput << startstr << "<title>" << XMLEscape(value.C_Str()) << "</title>" << endstr; mOutput << startstr << "<title>" << XMLEscape(value.C_Str()) << "</title>" << endstr;
}
} }
mOutput << startstr << "<unit name=\"meter\" meter=\"" << scale << "\" />" << endstr; mOutput << startstr << "<unit name=\"meter\" meter=\"" << scale << "\" />" << endstr;
@ -299,12 +303,15 @@ void ColladaExporter::WriteTextures() {
static const unsigned int buffer_size = 1024; static const unsigned int buffer_size = 1024;
char str[buffer_size]; char str[buffer_size];
if(mScene->HasTextures()) { if (mScene->HasTextures()) {
for(unsigned int i = 0; i < mScene->mNumTextures; i++) { for(unsigned int i = 0; i < mScene->mNumTextures; i++) {
// It would be great to be able to create a directory in portable standard C++, but it's not the case, // It would be great to be able to create a directory in portable standard C++, but it's not the case,
// so we just write the textures in the current directory. // so we just write the textures in the current directory.
aiTexture* texture = mScene->mTextures[i]; aiTexture* texture = mScene->mTextures[i];
if ( nullptr == texture ) {
continue;
}
ASSIMP_itoa10(str, buffer_size, i + 1); ASSIMP_itoa10(str, buffer_size, i + 1);
@ -458,6 +465,7 @@ void ColladaExporter::WritePointLight(const aiLight *const light){
mOutput << startstr << "</point>" << endstr; mOutput << startstr << "</point>" << endstr;
} }
void ColladaExporter::WriteDirectionalLight(const aiLight *const light){ void ColladaExporter::WriteDirectionalLight(const aiLight *const light){
const aiColor3D &color= light->mColorDiffuse; const aiColor3D &color= light->mColorDiffuse;
mOutput << startstr << "<directional>" << endstr; mOutput << startstr << "<directional>" << endstr;
@ -470,6 +478,7 @@ void ColladaExporter::WriteDirectionalLight(const aiLight *const light){
mOutput << startstr << "</directional>" << endstr; mOutput << startstr << "</directional>" << endstr;
} }
void ColladaExporter::WriteSpotLight(const aiLight *const light){ void ColladaExporter::WriteSpotLight(const aiLight *const light){
const aiColor3D &color= light->mColorDiffuse; const aiColor3D &color= light->mColorDiffuse;
@ -526,18 +535,16 @@ void ColladaExporter::WriteAmbienttLight(const aiLight *const light){
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads a single surface entry from the given material keys // Reads a single surface entry from the given material keys
void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex) void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat,
{ aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex) {
if( pSrcMat->GetTextureCount( pTexture) > 0 ) if( pSrcMat->GetTextureCount( pTexture) > 0 ) {
{
aiString texfile; aiString texfile;
unsigned int uvChannel = 0; unsigned int uvChannel = 0;
pSrcMat->GetTexture( pTexture, 0, &texfile, NULL, &uvChannel); pSrcMat->GetTexture( pTexture, 0, &texfile, NULL, &uvChannel);
std::string index_str(texfile.C_Str()); std::string index_str(texfile.C_Str());
if(index_str.size() != 0 && index_str[0] == '*') if(index_str.size() != 0 && index_str[0] == '*') {
{
unsigned int index; unsigned int index;
index_str = index_str.substr(1, std::string::npos); index_str = index_str.substr(1, std::string::npos);
@ -555,15 +562,13 @@ void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial*
} else { } else {
throw DeadlyExportError("could not find embedded texture at index " + index_str); throw DeadlyExportError("could not find embedded texture at index " + index_str);
} }
} else } else {
{
poSurface.texture = texfile.C_Str(); poSurface.texture = texfile.C_Str();
} }
poSurface.channel = uvChannel; poSurface.channel = uvChannel;
poSurface.exist = true; poSurface.exist = true;
} else } else {
{
if( pKey ) if( pKey )
poSurface.exist = pSrcMat->Get( pKey, static_cast<unsigned int>(pType), static_cast<unsigned int>(pIndex), poSurface.color) == aiReturn_SUCCESS; poSurface.exist = pSrcMat->Get( pKey, static_cast<unsigned int>(pType), static_cast<unsigned int>(pIndex), poSurface.color) == aiReturn_SUCCESS;
} }
@ -571,15 +576,13 @@ void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial*
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reimplementation of isalnum(,C locale), because AppVeyor does not see standard version. // Reimplementation of isalnum(,C locale), because AppVeyor does not see standard version.
static bool isalnum_C(char c) static bool isalnum_C(char c) {
{
return ( nullptr != strchr("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",c) ); return ( nullptr != strchr("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",c) );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Writes an image entry for the given surface // Writes an image entry for the given surface
void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd) void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd) {
{
if( !pSurface.texture.empty() ) if( !pSurface.texture.empty() )
{ {
mOutput << startstr << "<image id=\"" << XMLEscape(pNameAdd) << "\">" << endstr; mOutput << startstr << "<image id=\"" << XMLEscape(pNameAdd) << "\">" << endstr;
@ -833,8 +836,9 @@ void ColladaExporter::WriteControllerLibrary()
mOutput << startstr << "<library_controllers>" << endstr; mOutput << startstr << "<library_controllers>" << endstr;
PushTag(); PushTag();
for( size_t a = 0; a < mScene->mNumMeshes; ++a) for( size_t a = 0; a < mScene->mNumMeshes; ++a) {
WriteController( a); WriteController( a);
}
PopTag(); PopTag();
mOutput << startstr << "</library_controllers>" << endstr; mOutput << startstr << "</library_controllers>" << endstr;
@ -1667,4 +1671,4 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode)
} }
#endif #endif
#endif #endif

View File

@ -150,7 +150,6 @@ public:
/// Stringstream to write all output into /// Stringstream to write all output into
std::stringstream mOutput; std::stringstream mOutput;
protected:
/// The IOSystem for output /// The IOSystem for output
IOSystem* mIOSystem; IOSystem* mIOSystem;
@ -204,7 +203,7 @@ protected:
std::map<unsigned int, std::string> textures; std::map<unsigned int, std::string> textures;
protected: public:
/// Dammit C++ - y u no compile two-pass? No I have to add all methods below the struct definitions /// Dammit C++ - y u no compile two-pass? No I have to add all methods below the struct definitions
/// Reads a single surface entry from the given material keys /// Reads a single surface entry from the given material keys
void ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex); void ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex);

View File

@ -65,6 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "math.h" #include "math.h"
#include <algorithm> #include <algorithm>
#include <numeric> #include <numeric>
#include <memory>
using namespace Assimp; using namespace Assimp;
using namespace Assimp::Formatter; using namespace Assimp::Formatter;
@ -126,7 +127,7 @@ bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, boo
if (!pIOHandler) { if (!pIOHandler) {
return true; return true;
} }
const char* tokens[] = {"<collada"}; static const char* tokens[] = {"<collada"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
} }
@ -134,8 +135,7 @@ bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, boo
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ColladaLoader::SetupProperties(const Importer* pImp) void ColladaLoader::SetupProperties(const Importer* pImp) {
{
noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0; noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0; ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0;
useColladaName = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES,0) != 0; useColladaName = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES,0) != 0;
@ -143,8 +143,7 @@ void ColladaLoader::SetupProperties(const Importer* pImp)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Get file extension list // Get file extension list
const aiImporterDesc* ColladaLoader::GetInfo () const const aiImporterDesc* ColladaLoader::GetInfo () const {
{
return &desc; return &desc;
} }
@ -246,8 +245,7 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Recursively constructs a scene node for the given parser node and returns it. // Recursively constructs a scene node for the given parser node and returns it.
aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode) aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode) {
{
// create a node for it // create a node for it
aiNode* node = new aiNode(); aiNode* node = new aiNode();
@ -265,15 +263,13 @@ aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Colla
node->mNumChildren = static_cast<unsigned int>(pNode->mChildren.size()+instances.size()); node->mNumChildren = static_cast<unsigned int>(pNode->mChildren.size()+instances.size());
node->mChildren = new aiNode*[node->mNumChildren]; node->mChildren = new aiNode*[node->mNumChildren];
for( size_t a = 0; a < pNode->mChildren.size(); a++) for( size_t a = 0; a < pNode->mChildren.size(); ++a) {
{
node->mChildren[a] = BuildHierarchy( pParser, pNode->mChildren[a]); node->mChildren[a] = BuildHierarchy( pParser, pNode->mChildren[a]);
node->mChildren[a]->mParent = node; node->mChildren[a]->mParent = node;
} }
// ... and finally the resolved node instances // ... and finally the resolved node instances
for( size_t a = 0; a < instances.size(); a++) for( size_t a = 0; a < instances.size(); ++a) {
{
node->mChildren[pNode->mChildren.size() + a] = BuildHierarchy( pParser, instances[a]); node->mChildren[pNode->mChildren.size() + a] = BuildHierarchy( pParser, instances[a]);
node->mChildren[pNode->mChildren.size() + a]->mParent = node; node->mChildren[pNode->mChildren.size() + a]->mParent = node;
} }
@ -286,20 +282,19 @@ aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Colla
// construct lights // construct lights
BuildLightsForNode(pParser, pNode, node); BuildLightsForNode(pParser, pNode, node);
return node; return node;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Resolve node instances // Resolve node instances
void ColladaLoader::ResolveNodeInstances( const ColladaParser& pParser, const Collada::Node* pNode, void ColladaLoader::ResolveNodeInstances( const ColladaParser& pParser, const Collada::Node* pNode,
std::vector<const Collada::Node*>& resolved) std::vector<const Collada::Node*>& resolved) {
{
// reserve enough storage // reserve enough storage
resolved.reserve(pNode->mNodeInstances.size()); resolved.reserve(pNode->mNodeInstances.size());
// ... and iterate through all nodes to be instanced as children of pNode // ... and iterate through all nodes to be instanced as children of pNode
for (const auto &nodeInst: pNode->mNodeInstances) for (const auto &nodeInst: pNode->mNodeInstances) {
{
// find the corresponding node in the library // find the corresponding node in the library
const ColladaParser::NodeLibrary::const_iterator itt = pParser.mNodeLibrary.find(nodeInst.mNode); const ColladaParser::NodeLibrary::const_iterator itt = pParser.mNodeLibrary.find(nodeInst.mNode);
const Collada::Node* nd = itt == pParser.mNodeLibrary.end() ? NULL : (*itt).second; const Collada::Node* nd = itt == pParser.mNodeLibrary.end() ? NULL : (*itt).second;
@ -323,12 +318,12 @@ void ColladaLoader::ResolveNodeInstances( const ColladaParser& pParser, const Co
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Resolve UV channels // Resolve UV channels
void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler, void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler,
const Collada::SemanticMappingTable& table) const Collada::SemanticMappingTable& table) {
{
std::map<std::string, Collada::InputSemanticMapEntry>::const_iterator it = table.mMap.find(sampler.mUVChannel); std::map<std::string, Collada::InputSemanticMapEntry>::const_iterator it = table.mMap.find(sampler.mUVChannel);
if (it != table.mMap.end()) { if (it != table.mMap.end()) {
if (it->second.mType != Collada::IT_Texcoord) if (it->second.mType != Collada::IT_Texcoord) {
ASSIMP_LOG_ERROR("Collada: Unexpected effect input mapping"); ASSIMP_LOG_ERROR("Collada: Unexpected effect input mapping");
}
sampler.mUVId = it->second.mSet; sampler.mUVId = it->second.mSet;
} }
@ -336,14 +331,11 @@ void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Builds lights for the given node and references them // Builds lights for the given node and references them
void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) {
{ for( const Collada::LightInstance& lid : pNode->mLights) {
for( const Collada::LightInstance& lid : pNode->mLights)
{
// find the referred light // find the referred light
ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find( lid.mLight); ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find( lid.mLight);
if( srcLightIt == pParser.mLightLibrary.end()) if( srcLightIt == pParser.mLightLibrary.end()) {
{
ASSIMP_LOG_WARN_F("Collada: Unable to find light for ID \"" , lid.mLight , "\". Skipping."); ASSIMP_LOG_WARN_F("Collada: Unable to find light for ID \"" , lid.mLight , "\". Skipping.");
continue; continue;
} }
@ -365,8 +357,7 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
if (out->mType == aiLightSource_AMBIENT) { if (out->mType == aiLightSource_AMBIENT) {
out->mColorDiffuse = out->mColorSpecular = aiColor3D(0, 0, 0); out->mColorDiffuse = out->mColorSpecular = aiColor3D(0, 0, 0);
out->mColorAmbient = srcLight->mColor*srcLight->mIntensity; out->mColorAmbient = srcLight->mColor*srcLight->mIntensity;
} } else {
else {
// collada doesn't differentiate between these color types // collada doesn't differentiate between these color types
out->mColorDiffuse = out->mColorSpecular = srcLight->mColor*srcLight->mIntensity; out->mColorDiffuse = out->mColorSpecular = srcLight->mColor*srcLight->mIntensity;
out->mColorAmbient = aiColor3D(0, 0, 0); out->mColorAmbient = aiColor3D(0, 0, 0);
@ -374,27 +365,24 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
// convert falloff angle and falloff exponent in our representation, if given // convert falloff angle and falloff exponent in our representation, if given
if (out->mType == aiLightSource_SPOT) { if (out->mType == aiLightSource_SPOT) {
out->mAngleInnerCone = AI_DEG_TO_RAD( srcLight->mFalloffAngle ); out->mAngleInnerCone = AI_DEG_TO_RAD( srcLight->mFalloffAngle );
// ... some extension magic. // ... some extension magic.
if (srcLight->mOuterAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET*(1-1e-6f)) if (srcLight->mOuterAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET*(1-1e-6f)) {
{
// ... some deprecation magic. // ... some deprecation magic.
if (srcLight->mPenumbraAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET*(1-1e-6f)) if (srcLight->mPenumbraAngle >= ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET*(1-1e-6f)) {
{
// Need to rely on falloff_exponent. I don't know how to interpret it, so I need to guess .... // Need to rely on falloff_exponent. I don't know how to interpret it, so I need to guess ....
// epsilon chosen to be 0.1 // epsilon chosen to be 0.1
out->mAngleOuterCone = std::acos(std::pow(0.1f,1.f/srcLight->mFalloffExponent))+ out->mAngleOuterCone = std::acos(std::pow(0.1f,1.f/srcLight->mFalloffExponent))+
out->mAngleInnerCone; out->mAngleInnerCone;
} } else {
else {
out->mAngleOuterCone = out->mAngleInnerCone + AI_DEG_TO_RAD( srcLight->mPenumbraAngle ); out->mAngleOuterCone = out->mAngleInnerCone + AI_DEG_TO_RAD( srcLight->mPenumbraAngle );
if (out->mAngleOuterCone < out->mAngleInnerCone) if (out->mAngleOuterCone < out->mAngleInnerCone)
std::swap(out->mAngleInnerCone,out->mAngleOuterCone); std::swap(out->mAngleInnerCone,out->mAngleOuterCone);
} }
} else {
out->mAngleOuterCone = AI_DEG_TO_RAD( srcLight->mOuterAngle );
} }
else out->mAngleOuterCone = AI_DEG_TO_RAD( srcLight->mOuterAngle );
} }
// add to light list // add to light list
@ -404,14 +392,11 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Builds cameras for the given node and references them // Builds cameras for the given node and references them
void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) {
{ for( const Collada::CameraInstance& cid : pNode->mCameras) {
for( const Collada::CameraInstance& cid : pNode->mCameras)
{
// find the referred light // find the referred light
ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find( cid.mCamera); ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find( cid.mCamera);
if( srcCameraIt == pParser.mCameraLibrary.end()) if( srcCameraIt == pParser.mCameraLibrary.end()) {
{
ASSIMP_LOG_WARN_F("Collada: Unable to find camera for ID \"" , cid.mCamera , "\". Skipping."); ASSIMP_LOG_WARN_F("Collada: Unable to find camera for ID \"" , cid.mCamera , "\". Skipping.");
continue; continue;
} }
@ -435,8 +420,9 @@ void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Col
// ... but for the rest some values are optional // ... but for the rest some values are optional
// and we need to compute the others in any combination. // and we need to compute the others in any combination.
if (srcCamera->mAspect != 10e10f) if (srcCamera->mAspect != 10e10f) {
out->mAspect = srcCamera->mAspect; out->mAspect = srcCamera->mAspect;
}
if (srcCamera->mHorFov != 10e10f) { if (srcCamera->mHorFov != 10e10f) {
out->mHorizontalFOV = srcCamera->mHorFov; out->mHorizontalFOV = srcCamera->mHorFov;
@ -461,77 +447,69 @@ void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Col
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Builds meshes for the given node and references them // Builds meshes for the given node and references them
void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) {
{
// accumulated mesh references by this node // accumulated mesh references by this node
std::vector<size_t> newMeshRefs; std::vector<size_t> newMeshRefs;
newMeshRefs.reserve(pNode->mMeshes.size()); newMeshRefs.reserve(pNode->mMeshes.size());
// add a mesh for each subgroup in each collada mesh // add a mesh for each subgroup in each collada mesh
for( const Collada::MeshInstance& mid : pNode->mMeshes) for( const Collada::MeshInstance& mid : pNode->mMeshes) {
{ const Collada::Mesh* srcMesh = nullptr;
const Collada::Mesh* srcMesh = NULL; const Collada::Controller* srcController = nullptr;
const Collada::Controller* srcController = NULL;
// find the referred mesh // find the referred mesh
ColladaParser::MeshLibrary::const_iterator srcMeshIt = pParser.mMeshLibrary.find( mid.mMeshOrController); ColladaParser::MeshLibrary::const_iterator srcMeshIt = pParser.mMeshLibrary.find( mid.mMeshOrController);
if( srcMeshIt == pParser.mMeshLibrary.end()) if( srcMeshIt == pParser.mMeshLibrary.end()) {
{
// if not found in the mesh-library, it might also be a controller referring to a mesh // if not found in the mesh-library, it might also be a controller referring to a mesh
ColladaParser::ControllerLibrary::const_iterator srcContrIt = pParser.mControllerLibrary.find( mid.mMeshOrController); ColladaParser::ControllerLibrary::const_iterator srcContrIt = pParser.mControllerLibrary.find( mid.mMeshOrController);
if( srcContrIt != pParser.mControllerLibrary.end()) if( srcContrIt != pParser.mControllerLibrary.end()) {
{
srcController = &srcContrIt->second; srcController = &srcContrIt->second;
srcMeshIt = pParser.mMeshLibrary.find( srcController->mMeshId); srcMeshIt = pParser.mMeshLibrary.find( srcController->mMeshId);
if( srcMeshIt != pParser.mMeshLibrary.end()) if( srcMeshIt != pParser.mMeshLibrary.end()) {
srcMesh = srcMeshIt->second; srcMesh = srcMeshIt->second;
}
} }
if( !srcMesh) if( !srcMesh) {
{
ASSIMP_LOG_WARN_F( "Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping." ); ASSIMP_LOG_WARN_F( "Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping." );
continue; continue;
} }
} else } else {
{
// ID found in the mesh library -> direct reference to an unskinned mesh // ID found in the mesh library -> direct reference to an unskinned mesh
srcMesh = srcMeshIt->second; srcMesh = srcMeshIt->second;
} }
// build a mesh for each of its subgroups // build a mesh for each of its subgroups
size_t vertexStart = 0, faceStart = 0; size_t vertexStart = 0, faceStart = 0;
for( size_t sm = 0; sm < srcMesh->mSubMeshes.size(); ++sm) for( size_t sm = 0; sm < srcMesh->mSubMeshes.size(); ++sm) {
{
const Collada::SubMesh& submesh = srcMesh->mSubMeshes[sm]; const Collada::SubMesh& submesh = srcMesh->mSubMeshes[sm];
if( submesh.mNumFaces == 0) if( submesh.mNumFaces == 0) {
continue; continue;
}
// find material assigned to this submesh // find material assigned to this submesh
std::string meshMaterial; std::string meshMaterial;
std::map<std::string, Collada::SemanticMappingTable >::const_iterator meshMatIt = mid.mMaterials.find( submesh.mMaterial); std::map<std::string, Collada::SemanticMappingTable >::const_iterator meshMatIt = mid.mMaterials.find( submesh.mMaterial);
const Collada::SemanticMappingTable* table = NULL; const Collada::SemanticMappingTable* table = nullptr;
if( meshMatIt != mid.mMaterials.end()) if( meshMatIt != mid.mMaterials.end()) {
{
table = &meshMatIt->second; table = &meshMatIt->second;
meshMaterial = table->mMatName; meshMaterial = table->mMatName;
} } else {
else
{
ASSIMP_LOG_WARN_F( "Collada: No material specified for subgroup <", submesh.mMaterial, "> in geometry <", ASSIMP_LOG_WARN_F( "Collada: No material specified for subgroup <", submesh.mMaterial, "> in geometry <",
mid.mMeshOrController, ">." ); mid.mMeshOrController, ">." );
if( !mid.mMaterials.empty() ) if( !mid.mMaterials.empty() ) {
meshMaterial = mid.mMaterials.begin()->second.mMatName; meshMaterial = mid.mMaterials.begin()->second.mMatName;
}
} }
// OK ... here the *real* fun starts ... we have the vertex-input-to-effect-semantic-table // OK ... here the *real* fun starts ... we have the vertex-input-to-effect-semantic-table
// given. The only mapping stuff which we do actually support is the UV channel. // given. The only mapping stuff which we do actually support is the UV channel.
std::map<std::string, size_t>::const_iterator matIt = mMaterialIndexByName.find( meshMaterial); std::map<std::string, size_t>::const_iterator matIt = mMaterialIndexByName.find( meshMaterial);
unsigned int matIdx; unsigned int matIdx = 0;
if( matIt != mMaterialIndexByName.end()) if( matIt != mMaterialIndexByName.end()) {
matIdx = static_cast<unsigned int>(matIt->second); matIdx = static_cast<unsigned int>(matIt->second);
else }
matIdx = 0;
if (table && !table->mMap.empty() ) { if (table && !table->mMap.empty() ) {
std::pair<Collada::Effect*, aiMaterial*>& mat = newMats[matIdx]; std::pair<Collada::Effect*, aiMaterial*>& mat = newMats[matIdx];
@ -553,9 +531,7 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
std::map<ColladaMeshIndex, size_t>::const_iterator dstMeshIt = mMeshIndexByID.find( index); std::map<ColladaMeshIndex, size_t>::const_iterator dstMeshIt = mMeshIndexByID.find( index);
if( dstMeshIt != mMeshIndexByID.end()) { if( dstMeshIt != mMeshIndexByID.end()) {
newMeshRefs.push_back( dstMeshIt->second); newMeshRefs.push_back( dstMeshIt->second);
} } else {
else
{
// else we have to add the mesh to the collection and store its newly assigned index at the node // else we have to add the mesh to the collection and store its newly assigned index at the node
aiMesh* dstMesh = CreateMesh( pParser, srcMesh, submesh, srcController, vertexStart, faceStart); aiMesh* dstMesh = CreateMesh( pParser, srcMesh, submesh, srcController, vertexStart, faceStart);
@ -567,22 +543,18 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
// assign the material index // assign the material index
dstMesh->mMaterialIndex = matIdx; dstMesh->mMaterialIndex = matIdx;
if(dstMesh->mName.length == 0) if(dstMesh->mName.length == 0) {
{
dstMesh->mName = mid.mMeshOrController; dstMesh->mName = mid.mMeshOrController;
} }
} }
} }
} }
// now place all mesh references we gathered in the target node // now place all mesh references we gathered in the target node
pTarget->mNumMeshes = static_cast<unsigned int>(newMeshRefs.size()); pTarget->mNumMeshes = static_cast<unsigned int>(newMeshRefs.size());
if( newMeshRefs.size()) if( newMeshRefs.size()) {
{ struct UIntTypeConverter {
struct UIntTypeConverter unsigned int operator()(const size_t& v) const {
{
unsigned int operator()(const size_t& v) const
{
return static_cast<unsigned int>(v); return static_cast<unsigned int>(v);
} }
}; };
@ -594,25 +566,27 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Find mesh from either meshes or morph target meshes // Find mesh from either meshes or morph target meshes
aiMesh *ColladaLoader::findMesh(std::string meshid) aiMesh *ColladaLoader::findMesh(std::string meshid) {
{ for (unsigned int i = 0; i < mMeshes.size(); ++i ) {
for (unsigned int i = 0; i < mMeshes.size(); i++) if (std::string(mMeshes[i]->mName.data) == meshid) {
if (std::string(mMeshes[i]->mName.data) == meshid)
return mMeshes[i]; return mMeshes[i];
}
}
for (unsigned int i = 0; i < mTargetMeshes.size(); i++) for (unsigned int i = 0; i < mTargetMeshes.size(); ++i ) {
if (std::string(mTargetMeshes[i]->mName.data) == meshid) if (std::string(mTargetMeshes[i]->mName.data) == meshid) {
return mTargetMeshes[i]; return mTargetMeshes[i];
}
return NULL; }
return nullptr;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh // Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh
aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh, aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh,
const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace) const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace) {
{ std::unique_ptr<aiMesh> dstMesh(new aiMesh);
aiMesh* dstMesh = new aiMesh;
dstMesh->mName = pSrcMesh->mName; dstMesh->mName = pSrcMesh->mName;
@ -629,24 +603,21 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
// normals, if given. HACK: (thom) Due to the glorious Collada spec we never // normals, if given. HACK: (thom) Due to the glorious Collada spec we never
// know if we have the same number of normals as there are positions. So we // know if we have the same number of normals as there are positions. So we
// also ignore any vertex attribute if it has a different count // also ignore any vertex attribute if it has a different count
if( pSrcMesh->mNormals.size() >= pStartVertex + numVertices) if( pSrcMesh->mNormals.size() >= pStartVertex + numVertices) {
{
dstMesh->mNormals = new aiVector3D[numVertices]; dstMesh->mNormals = new aiVector3D[numVertices];
std::copy( pSrcMesh->mNormals.begin() + pStartVertex, pSrcMesh->mNormals.begin() + std::copy( pSrcMesh->mNormals.begin() + pStartVertex, pSrcMesh->mNormals.begin() +
pStartVertex + numVertices, dstMesh->mNormals); pStartVertex + numVertices, dstMesh->mNormals);
} }
// tangents, if given. // tangents, if given.
if( pSrcMesh->mTangents.size() >= pStartVertex + numVertices) if( pSrcMesh->mTangents.size() >= pStartVertex + numVertices) {
{
dstMesh->mTangents = new aiVector3D[numVertices]; dstMesh->mTangents = new aiVector3D[numVertices];
std::copy( pSrcMesh->mTangents.begin() + pStartVertex, pSrcMesh->mTangents.begin() + std::copy( pSrcMesh->mTangents.begin() + pStartVertex, pSrcMesh->mTangents.begin() +
pStartVertex + numVertices, dstMesh->mTangents); pStartVertex + numVertices, dstMesh->mTangents);
} }
// bitangents, if given. // bitangents, if given.
if( pSrcMesh->mBitangents.size() >= pStartVertex + numVertices) if( pSrcMesh->mBitangents.size() >= pStartVertex + numVertices) {
{
dstMesh->mBitangents = new aiVector3D[numVertices]; dstMesh->mBitangents = new aiVector3D[numVertices];
std::copy( pSrcMesh->mBitangents.begin() + pStartVertex, pSrcMesh->mBitangents.begin() + std::copy( pSrcMesh->mBitangents.begin() + pStartVertex, pSrcMesh->mBitangents.begin() +
pStartVertex + numVertices, dstMesh->mBitangents); pStartVertex + numVertices, dstMesh->mBitangents);
@ -654,13 +625,12 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
// same for texturecoords, as many as we have // same for texturecoords, as many as we have
// empty slots are not allowed, need to pack and adjust UV indexes accordingly // empty slots are not allowed, need to pack and adjust UV indexes accordingly
for( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) for( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) {
{ if( pSrcMesh->mTexCoords[a].size() >= pStartVertex + numVertices) {
if( pSrcMesh->mTexCoords[a].size() >= pStartVertex + numVertices)
{
dstMesh->mTextureCoords[real] = new aiVector3D[numVertices]; dstMesh->mTextureCoords[real] = new aiVector3D[numVertices];
for( size_t b = 0; b < numVertices; ++b) for( size_t b = 0; b < numVertices; ++b) {
dstMesh->mTextureCoords[real][b] = pSrcMesh->mTexCoords[a][pStartVertex+b]; dstMesh->mTextureCoords[real][b] = pSrcMesh->mTexCoords[a][pStartVertex+b];
}
dstMesh->mNumUVComponents[real] = pSrcMesh->mNumUVComponents[a]; dstMesh->mNumUVComponents[real] = pSrcMesh->mNumUVComponents[a];
++real; ++real;
@ -668,10 +638,8 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
} }
// same for vertex colors, as many as we have. again the same packing to avoid empty slots // same for vertex colors, as many as we have. again the same packing to avoid empty slots
for( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) for( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) {
{ if( pSrcMesh->mColors[a].size() >= pStartVertex + numVertices) {
if( pSrcMesh->mColors[a].size() >= pStartVertex + numVertices)
{
dstMesh->mColors[real] = new aiColor4D[numVertices]; dstMesh->mColors[real] = new aiColor4D[numVertices];
std::copy( pSrcMesh->mColors[a].begin() + pStartVertex, pSrcMesh->mColors[a].begin() + pStartVertex + numVertices,dstMesh->mColors[real]); std::copy( pSrcMesh->mColors[a].begin() + pStartVertex, pSrcMesh->mColors[a].begin() + pStartVertex + numVertices,dstMesh->mColors[real]);
++real; ++real;
@ -682,14 +650,14 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
size_t vertex = 0; size_t vertex = 0;
dstMesh->mNumFaces = static_cast<unsigned int>(pSubMesh.mNumFaces); dstMesh->mNumFaces = static_cast<unsigned int>(pSubMesh.mNumFaces);
dstMesh->mFaces = new aiFace[dstMesh->mNumFaces]; dstMesh->mFaces = new aiFace[dstMesh->mNumFaces];
for( size_t a = 0; a < dstMesh->mNumFaces; ++a) for( size_t a = 0; a < dstMesh->mNumFaces; ++a) {
{
size_t s = pSrcMesh->mFaceSize[ pStartFace + a]; size_t s = pSrcMesh->mFaceSize[ pStartFace + a];
aiFace& face = dstMesh->mFaces[a]; aiFace& face = dstMesh->mFaces[a];
face.mNumIndices = static_cast<unsigned int>(s); face.mNumIndices = static_cast<unsigned int>(s);
face.mIndices = new unsigned int[s]; face.mIndices = new unsigned int[s];
for( size_t b = 0; b < s; ++b) for( size_t b = 0; b < s; ++b) {
face.mIndices[b] = static_cast<unsigned int>(vertex++); face.mIndices[b] = static_cast<unsigned int>(vertex++);
}
} }
// create morph target meshes if any // create morph target meshes if any
@ -697,14 +665,12 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
std::vector<float> targetWeights; std::vector<float> targetWeights;
Collada::MorphMethod method = Collada::Normalized; 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++) {
{
const Collada::Controller &c = it->second; const Collada::Controller &c = it->second;
const Collada::Mesh* baseMesh = pParser.ResolveLibraryReference( pParser.mMeshLibrary, c.mMeshId); const Collada::Mesh* baseMesh = pParser.ResolveLibraryReference( pParser.mMeshLibrary, c.mMeshId);
if (c.mType == Collada::Morph && baseMesh->mName == pSrcMesh->mName) if (c.mType == Collada::Morph && baseMesh->mName == pSrcMesh->mName) {
{
const Collada::Accessor& targetAccessor = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, c.mMorphTarget); const Collada::Accessor& targetAccessor = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, c.mMorphTarget);
const Collada::Accessor& weightAccessor = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, c.mMorphWeight); const Collada::Accessor& weightAccessor = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, c.mMorphWeight);
const Collada::Data& targetData = pParser.ResolveLibraryReference( pParser.mDataLibrary, targetAccessor.mSource); const Collada::Data& targetData = pParser.ResolveLibraryReference( pParser.mDataLibrary, targetAccessor.mSource);
@ -713,34 +679,34 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
// take method // take method
method = c.mMethod; method = c.mMethod;
if (!targetData.mIsStringArray) if (!targetData.mIsStringArray) {
throw DeadlyImportError( "target data must contain id. "); throw DeadlyImportError( "target data must contain id. ");
if (weightData.mIsStringArray) }
if (weightData.mIsStringArray) {
throw DeadlyImportError( "target weight data must not be textual "); throw DeadlyImportError( "target weight data must not be textual ");
}
for (unsigned int i = 0; i < targetData.mStrings.size(); ++i) for (unsigned int i = 0; i < targetData.mStrings.size(); ++i) {
{
const Collada::Mesh* targetMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, targetData.mStrings.at(i)); const Collada::Mesh* targetMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, targetData.mStrings.at(i));
aiMesh *aimesh = findMesh(targetMesh->mName); aiMesh *aimesh = findMesh(targetMesh->mName);
if (!aimesh) if (!aimesh) {
{ if (targetMesh->mSubMeshes.size() > 1) {
if (targetMesh->mSubMeshes.size() > 1)
throw DeadlyImportError( "Morhing target mesh must be a single"); throw DeadlyImportError( "Morhing target mesh must be a single");
}
aimesh = CreateMesh(pParser, targetMesh, targetMesh->mSubMeshes.at(0), NULL, 0, 0); aimesh = CreateMesh(pParser, targetMesh, targetMesh->mSubMeshes.at(0), NULL, 0, 0);
mTargetMeshes.push_back(aimesh); mTargetMeshes.push_back(aimesh);
} }
targetMeshes.push_back(aimesh); targetMeshes.push_back(aimesh);
} }
for (unsigned int i = 0; i < weightData.mValues.size(); ++i) for (unsigned int i = 0; i < weightData.mValues.size(); ++i) {
targetWeights.push_back(weightData.mValues.at(i)); targetWeights.push_back(weightData.mValues.at(i));
}
} }
} }
if (targetMeshes.size() > 0 && targetWeights.size() == targetMeshes.size()) if (targetMeshes.size() > 0 && targetWeights.size() == targetMeshes.size()) {
{
std::vector<aiAnimMesh*> animMeshes; std::vector<aiAnimMesh*> animMeshes;
for (unsigned int i = 0; i < targetMeshes.size(); i++) for (unsigned int i = 0; i < targetMeshes.size(); ++i ) {
{
aiMesh* targetMesh = targetMeshes.at(i); aiMesh* targetMesh = targetMeshes.at(i);
aiAnimMesh *animMesh = aiCreateAnimMesh(targetMesh); aiAnimMesh *animMesh = aiCreateAnimMesh(targetMesh);
float weight = targetWeights[i]; float weight = targetWeights[i];
@ -753,13 +719,13 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
: aiMorphingMethod_MORPH_NORMALIZED; : aiMorphingMethod_MORPH_NORMALIZED;
dstMesh->mAnimMeshes = new aiAnimMesh*[animMeshes.size()]; dstMesh->mAnimMeshes = new aiAnimMesh*[animMeshes.size()];
dstMesh->mNumAnimMeshes = static_cast<unsigned int>(animMeshes.size()); dstMesh->mNumAnimMeshes = static_cast<unsigned int>(animMeshes.size());
for (unsigned int i = 0; i < animMeshes.size(); i++) for (unsigned int i = 0; i < animMeshes.size(); ++i ) {
dstMesh->mAnimMeshes[i] = animMeshes.at(i); dstMesh->mAnimMeshes[i] = animMeshes.at(i);
}
} }
// create bones if given // create bones if given
if( pSrcController && pSrcController->mType == Collada::Skin) if( pSrcController && pSrcController->mType == Collada::Skin) {
{
// resolve references - joint names // resolve references - joint names
const Collada::Accessor& jointNamesAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mJointNameSource); const Collada::Accessor& jointNamesAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mJointNameSource);
const Collada::Data& jointNames = pParser.ResolveLibraryReference( pParser.mDataLibrary, jointNamesAcc.mSource); const Collada::Data& jointNames = pParser.ResolveLibraryReference( pParser.mDataLibrary, jointNamesAcc.mSource);
@ -790,15 +756,13 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
weightStartPerVertex.resize(pSrcController->mWeightCounts.size(),pSrcController->mWeights.end()); weightStartPerVertex.resize(pSrcController->mWeightCounts.size(),pSrcController->mWeights.end());
IndexPairVector::const_iterator pit = pSrcController->mWeights.begin(); IndexPairVector::const_iterator pit = pSrcController->mWeights.begin();
for( size_t a = 0; a < pSrcController->mWeightCounts.size(); ++a) for( size_t a = 0; a < pSrcController->mWeightCounts.size(); ++a) {
{
weightStartPerVertex[a] = pit; weightStartPerVertex[a] = pit;
pit += pSrcController->mWeightCounts[a]; pit += pSrcController->mWeightCounts[a];
} }
// now for each vertex put the corresponding vertex weights into each bone's weight collection // now for each vertex put the corresponding vertex weights into each bone's weight collection
for( size_t a = pStartVertex; a < pStartVertex + numVertices; ++a) for( size_t a = pStartVertex; a < pStartVertex + numVertices; ++a) {
{
// which position index was responsible for this vertex? that's also the index by which // which position index was responsible for this vertex? that's also the index by which
// the controller assigns the vertex weights // the controller assigns the vertex weights
size_t orgIndex = pSrcMesh->mFacePosIndices[a]; size_t orgIndex = pSrcMesh->mFacePosIndices[a];
@ -898,7 +862,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
} }
} }
return dstMesh; return dstMesh.release();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -323,10 +323,8 @@ void ColladaParser::ReadMetaDataItem(StringMetaData &metadata)
aiString aistr; aiString aistr;
aistr.Set(value_char); aistr.Set(value_char);
metadata.emplace(camel_key_str, aistr); metadata.emplace(camel_key_str, aistr);
TestClosing(key_str.c_str());
} }
else TestClosing(key_str.c_str());
SkipElement();
} }
else else
SkipElement(); SkipElement();

View File

@ -54,7 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/Exceptional.h> #include <assimp/Exceptional.h>
#include <assimp/BaseImporter.h> #include <assimp/BaseImporter.h>
#include "CInterfaceIOWrapper.h" #include "CApi/CInterfaceIOWrapper.h"
#include "Importer.h" #include "Importer.h"
#include "ScenePrivate.h" #include "ScenePrivate.h"

View File

@ -320,7 +320,11 @@ std::string BaseImporter::GetExtension( const std::string& file ) {
return false; return false;
} }
#include "../contrib/utf8cpp/source/utf8.h" #ifdef ASSIMP_USE_HUNTER
# include <utf8/utf8.h>
#else
# include "../contrib/utf8cpp/source/utf8.h"
#endif
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Convert to UTF8 data // Convert to UTF8 data

View File

@ -89,7 +89,7 @@ void BaseProcess::ExecuteOnScene( Importer* pImp)
// and kill the partially imported data // and kill the partially imported data
delete pImp->Pimpl()->mScene; delete pImp->Pimpl()->mScene;
pImp->Pimpl()->mScene = NULL; pImp->Pimpl()->mScene = nullptr;
} }
} }

View File

@ -47,10 +47,6 @@ namespace Assimp {
aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh) aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh)
{ {
aiAnimMesh *animesh = new aiAnimMesh; aiAnimMesh *animesh = new aiAnimMesh;
animesh->mVertices = NULL;
animesh->mNormals = NULL;
animesh->mTangents = NULL;
animesh->mBitangents = NULL;
animesh->mNumVertices = mesh->mNumVertices; animesh->mNumVertices = mesh->mNumVertices;
if (mesh->mVertices) { if (mesh->mVertices) {
animesh->mVertices = new aiVector3D[animesh->mNumVertices]; animesh->mVertices = new aiVector3D[animesh->mNumVertices];

View File

@ -61,15 +61,16 @@ Here we implement only the C++ interface (Assimp::Exporter).
#include <assimp/mesh.h> #include <assimp/mesh.h>
#include <assimp/postprocess.h> #include <assimp/postprocess.h>
#include <assimp/scene.h> #include <assimp/scene.h>
#include "DefaultProgressHandler.h"
#include "BaseProcess.h"
#include "JoinVerticesProcess.h"
#include "MakeVerboseFormat.h"
#include "ConvertToLHProcess.h"
#include "PretransformVertices.h"
#include <assimp/Exceptional.h> #include <assimp/Exceptional.h>
#include "ScenePrivate.h"
#include "Common/DefaultProgressHandler.h"
#include "Common/BaseProcess.h"
#include "Common/ScenePrivate.h"
#include "PostProcessing/CalcTangentsProcess.h"
#include "PostProcessing/MakeVerboseFormat.h"
#include "PostProcessing/JoinVerticesProcess.h"
#include "PostProcessing/ConvertToLHProcess.h"
#include "PostProcessing/PretransformVertices.h"
#include <memory> #include <memory>
@ -101,6 +102,7 @@ void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperti
void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*);
void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* ); void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* );
void ExportAssimp2Json(const char* , IOSystem*, const aiScene* , const Assimp::ExportProperties*);
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// global array of all export formats which Assimp supports in its current build // global array of all export formats which Assimp supports in its current build
@ -178,7 +180,11 @@ Exporter::ExportFormatEntry gExporters[] =
#endif #endif
#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER #ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 ) Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 ),
#endif
#ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER
Exporter::ExportFormatEntry("json", "Plain JSON representation of the Assimp scene data structure", "json", &ExportAssimp2Json, 0)
#endif #endif
}; };

View File

@ -64,15 +64,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Internal headers // Internal headers
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
#include "Importer.h" #include "Common/Importer.h"
#include <assimp/BaseImporter.h> #include "Common/BaseProcess.h"
#include "BaseProcess.h" #include "Common/DefaultProgressHandler.h"
#include "PostProcessing/ProcessHelper.h"
#include "Common/ScenePreprocessor.h"
#include "Common/ScenePrivate.h"
#include "DefaultProgressHandler.h" #include <assimp/BaseImporter.h>
#include <assimp/GenericProperty.h> #include <assimp/GenericProperty.h>
#include "ProcessHelper.h"
#include "ScenePreprocessor.h"
#include "ScenePrivate.h"
#include <assimp/MemoryIOWrapper.h> #include <assimp/MemoryIOWrapper.h>
#include <assimp/Profiler.h> #include <assimp/Profiler.h>
#include <assimp/TinyFormatter.h> #include <assimp/TinyFormatter.h>
@ -86,7 +86,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/DefaultIOSystem.h> #include <assimp/DefaultIOSystem.h>
#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
# include "ValidateDataStructure.h" # include "PostProcessing/ValidateDataStructure.h"
#endif #endif
using namespace Assimp::Profiling; using namespace Assimp::Profiling;
@ -590,10 +590,12 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
// Find an worker class which can handle the file // Find an worker class which can handle the file
BaseImporter* imp = NULL; BaseImporter* imp = NULL;
SetPropertyInteger("importerIndex", -1);
for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) { for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, false)) { if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, false)) {
imp = pimpl->mImporter[a]; imp = pimpl->mImporter[a];
SetPropertyInteger("importerIndex", a);
break; break;
} }
} }
@ -606,6 +608,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) { for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) { if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) {
imp = pimpl->mImporter[a]; imp = pimpl->mImporter[a];
SetPropertyInteger("importerIndex", a);
break; break;
} }
} }

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