Merge branch 'master' into umw_dev
commit
f096843c45
119
CMakeLists.txt
119
CMakeLists.txt
|
@ -138,8 +138,7 @@ SET (PROJECT_VERSION "${ASSIMP_VERSION}")
|
||||||
|
|
||||||
SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" )
|
SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" )
|
||||||
|
|
||||||
# Needed for openddl_parser config, no use of c++11 at this moment
|
# Enable C++1 globally
|
||||||
ADD_DEFINITIONS( -DOPENDDL_NO_USE_CPP11 )
|
|
||||||
set_property( GLOBAL PROPERTY CXX_STANDARD 11 )
|
set_property( GLOBAL PROPERTY CXX_STANDARD 11 )
|
||||||
|
|
||||||
# Get the current working branch
|
# Get the current working branch
|
||||||
|
@ -161,7 +160,7 @@ EXECUTE_PROCESS(
|
||||||
)
|
)
|
||||||
|
|
||||||
IF(NOT GIT_COMMIT_HASH)
|
IF(NOT GIT_COMMIT_HASH)
|
||||||
SET(GIT_COMMIT_HASH 0)
|
SET(GIT_COMMIT_HASH 0)
|
||||||
ENDIF(NOT GIT_COMMIT_HASH)
|
ENDIF(NOT GIT_COMMIT_HASH)
|
||||||
|
|
||||||
IF(ASSIMP_DOUBLE_PRECISION)
|
IF(ASSIMP_DOUBLE_PRECISION)
|
||||||
|
@ -179,10 +178,10 @@ CONFIGURE_FILE(
|
||||||
)
|
)
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(
|
INCLUDE_DIRECTORIES(
|
||||||
./
|
./
|
||||||
include
|
include
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/include
|
${CMAKE_CURRENT_BINARY_DIR}/include
|
||||||
)
|
)
|
||||||
|
|
||||||
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" )
|
LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" )
|
||||||
|
@ -192,14 +191,6 @@ SET(CPACK_COMPONENTS_ALL assimp-bin ${LIBASSIMP_COMPONENT} ${LIBASSIMP-DEV_COMPO
|
||||||
SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names")
|
SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names")
|
||||||
|
|
||||||
IF( UNIX )
|
IF( UNIX )
|
||||||
# Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit linux
|
|
||||||
IF( ${OPERATING_SYSTEM} MATCHES "Android")
|
|
||||||
ELSE()
|
|
||||||
IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux
|
|
||||||
#ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 )
|
|
||||||
ENDIF()
|
|
||||||
ENDIF()
|
|
||||||
|
|
||||||
# Use GNUInstallDirs for Unix predefined directories
|
# Use GNUInstallDirs for Unix predefined directories
|
||||||
INCLUDE(GNUInstallDirs)
|
INCLUDE(GNUInstallDirs)
|
||||||
ENDIF( UNIX )
|
ENDIF( UNIX )
|
||||||
|
@ -212,13 +203,13 @@ IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW)
|
||||||
SET(LIBSTDC++_LIBRARIES -lstdc++)
|
SET(LIBSTDC++_LIBRARIES -lstdc++)
|
||||||
ELSEIF(MSVC)
|
ELSEIF(MSVC)
|
||||||
# enable multi-core compilation with MSVC
|
# enable multi-core compilation with MSVC
|
||||||
add_compile_options(/MP)
|
ADD_COMPILE_OPTIONS(/MP)
|
||||||
if("${CMAKE_GENERATOR}" MATCHES "(Win64|IA64)")
|
IF("${CMAKE_GENERATOR}" MATCHES "(Win64|IA64)")
|
||||||
add_compile_options( /bigobj )
|
ADD_COMPILE_OPTIONS( /bigobj )
|
||||||
endif()
|
ENDIF()
|
||||||
# disable "elements of array '' will be default initialized" warning on MSVC2013
|
# disable "elements of array '' will be default initialized" warning on MSVC2013
|
||||||
IF(MSVC12)
|
IF(MSVC12)
|
||||||
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 "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -fPIC -Wall -Wno-long-long -std=c++11" )
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -fPIC -Wall -Wno-long-long -std=c++11" )
|
||||||
|
@ -229,39 +220,39 @@ ELSEIF( CMAKE_COMPILER_IS_MINGW )
|
||||||
ADD_DEFINITIONS( -U__STRICT_ANSI__ )
|
ADD_DEFINITIONS( -U__STRICT_ANSI__ )
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
if (IOS)
|
IF (IOS)
|
||||||
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")
|
||||||
endif()
|
ENDIF()
|
||||||
|
|
||||||
if (ASSIMP_COVERALLS)
|
IF (ASSIMP_COVERALLS)
|
||||||
MESSAGE(STATUS "Coveralls enabled")
|
MESSAGE(STATUS "Coveralls enabled")
|
||||||
INCLUDE(Coveralls)
|
INCLUDE(Coveralls)
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
|
||||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
|
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
|
||||||
endif()
|
ENDIF()
|
||||||
|
|
||||||
if (ASSIMP_WERROR)
|
IF (ASSIMP_WERROR)
|
||||||
MESSAGE(STATUS "Treating warnings as errors")
|
MESSAGE(STATUS "Treating warnings as errors")
|
||||||
IF (MSVC)
|
IF (MSVC)
|
||||||
add_compile_options(/WX)
|
ADD_COMPILE_OPTIONS(/WX)
|
||||||
ELSE()
|
ELSE()
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
||||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
|
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
endif()
|
ENDIF()
|
||||||
|
|
||||||
if (ASSIMP_ASAN)
|
IF (ASSIMP_ASAN)
|
||||||
MESSAGE(STATUS "AddressSanitizer enabled")
|
MESSAGE(STATUS "AddressSanitizer enabled")
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
|
||||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
|
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
|
||||||
endif()
|
ENDIF()
|
||||||
|
|
||||||
if (ASSIMP_UBSAN)
|
IF (ASSIMP_UBSAN)
|
||||||
MESSAGE(STATUS "Undefined Behavior sanitizer enabled")
|
MESSAGE(STATUS "Undefined Behavior sanitizer enabled")
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all")
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all")
|
||||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all")
|
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all")
|
||||||
endif()
|
ENDIF()
|
||||||
|
|
||||||
INCLUDE (FindPkgMacros)
|
INCLUDE (FindPkgMacros)
|
||||||
INCLUDE (PrecompiledHeader)
|
INCLUDE (PrecompiledHeader)
|
||||||
|
@ -294,42 +285,42 @@ ENDIF()
|
||||||
IF (NOT TARGET uninstall)
|
IF (NOT TARGET uninstall)
|
||||||
# add make uninstall capability
|
# add make uninstall capability
|
||||||
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
|
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
|
||||||
add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
# cmake configuration files
|
# cmake configuration files
|
||||||
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE)
|
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE)
|
||||||
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE)
|
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE)
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT})
|
INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT})
|
||||||
|
|
||||||
FIND_PACKAGE( DirectX )
|
FIND_PACKAGE( DirectX )
|
||||||
|
|
||||||
IF( BUILD_DOCS )
|
IF( BUILD_DOCS )
|
||||||
add_subdirectory(doc)
|
ADD_SUBDIRECTORY(doc)
|
||||||
ENDIF( BUILD_DOCS )
|
ENDIF( BUILD_DOCS )
|
||||||
|
|
||||||
# Look for system installed irrXML
|
# Look for system installed irrXML
|
||||||
IF ( SYSTEM_IRRXML )
|
IF ( SYSTEM_IRRXML )
|
||||||
find_package( IrrXML REQUIRED )
|
FIND_PACKAGE( IrrXML REQUIRED )
|
||||||
ENDIF( SYSTEM_IRRXML )
|
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 ( NOT ASSIMP_BUILD_ZLIB )
|
||||||
find_package(ZLIB)
|
FIND_PACKAGE(ZLIB)
|
||||||
ENDIF( NOT ASSIMP_BUILD_ZLIB )
|
ENDIF( NOT ASSIMP_BUILD_ZLIB )
|
||||||
|
|
||||||
IF( NOT ZLIB_FOUND )
|
IF( NOT ZLIB_FOUND )
|
||||||
message(STATUS "compiling zlib from souces")
|
MESSAGE(STATUS "compiling zlib from souces")
|
||||||
INCLUDE(CheckIncludeFile)
|
INCLUDE(CheckIncludeFile)
|
||||||
INCLUDE(CheckTypeSize)
|
INCLUDE(CheckTypeSize)
|
||||||
INCLUDE(CheckFunctionExists)
|
INCLUDE(CheckFunctionExists)
|
||||||
# compile from sources
|
# compile from sources
|
||||||
add_subdirectory(contrib/zlib)
|
ADD_SUBDIRECTORY(contrib/zlib)
|
||||||
SET(ZLIB_FOUND 1)
|
SET(ZLIB_FOUND 1)
|
||||||
SET(ZLIB_LIBRARIES zlibstatic)
|
SET(ZLIB_LIBRARIES zlibstatic)
|
||||||
SET(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib)
|
SET(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib)
|
||||||
else(NOT ZLIB_FOUND)
|
ELSE(NOT ZLIB_FOUND)
|
||||||
ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB)
|
ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB)
|
||||||
SET(ZLIB_LIBRARIES_LINKED -lz)
|
SET(ZLIB_LIBRARIES_LINKED -lz)
|
||||||
ENDIF(NOT ZLIB_FOUND)
|
ENDIF(NOT ZLIB_FOUND)
|
||||||
|
@ -371,7 +362,9 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
|
||||||
SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/includes")
|
SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/includes")
|
||||||
|
|
||||||
# pick the correct prebuilt library
|
# pick the correct prebuilt library
|
||||||
IF(MSVC14)
|
IF(MSVC15)
|
||||||
|
SET(C4D_LIB_POSTFIX "_2017")
|
||||||
|
ELSEIF(MSVC14)
|
||||||
SET(C4D_LIB_POSTFIX "_2015")
|
SET(C4D_LIB_POSTFIX "_2015")
|
||||||
ELSEIF(MSVC12)
|
ELSEIF(MSVC12)
|
||||||
SET(C4D_LIB_POSTFIX "_2013")
|
SET(C4D_LIB_POSTFIX "_2013")
|
||||||
|
@ -412,7 +405,7 @@ ADD_SUBDIRECTORY(contrib)
|
||||||
ADD_SUBDIRECTORY( code/ )
|
ADD_SUBDIRECTORY( code/ )
|
||||||
IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
|
IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
|
||||||
IF ( WIN32 AND DirectX_D3DX9_LIBRARY )
|
IF ( WIN32 AND DirectX_D3DX9_LIBRARY )
|
||||||
option ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} )
|
OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} )
|
||||||
IF ( ASSIMP_BUILD_ASSIMP_VIEW )
|
IF ( ASSIMP_BUILD_ASSIMP_VIEW )
|
||||||
ADD_SUBDIRECTORY( tools/assimp_view/ )
|
ADD_SUBDIRECTORY( tools/assimp_view/ )
|
||||||
ENDIF ( ASSIMP_BUILD_ASSIMP_VIEW )
|
ENDIF ( ASSIMP_BUILD_ASSIMP_VIEW )
|
||||||
|
@ -476,8 +469,8 @@ IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
|
||||||
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "assimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}")
|
SET(CPACK_PACKAGE_INSTALL_DIRECTORY "assimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}")
|
||||||
SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
|
SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
|
||||||
|
|
||||||
string(TOUPPER ${LIBASSIMP_COMPONENT} "LIBASSIMP_COMPONENT_UPPER")
|
STRING(TOUPPER ${LIBASSIMP_COMPONENT} "LIBASSIMP_COMPONENT_UPPER")
|
||||||
string(TOUPPER ${LIBASSIMP-DEV_COMPONENT} "LIBASSIMP-DEV_COMPONENT_UPPER")
|
STRING(TOUPPER ${LIBASSIMP-DEV_COMPONENT} "LIBASSIMP-DEV_COMPONENT_UPPER")
|
||||||
|
|
||||||
SET(CPACK_COMPONENT_ASSIMP-BIN_DISPLAY_NAME "tools")
|
SET(CPACK_COMPONENT_ASSIMP-BIN_DISPLAY_NAME "tools")
|
||||||
SET(CPACK_COMPONENT_ASSIMP-BIN_DEPENDS "${LIBASSIMP_COMPONENT}" )
|
SET(CPACK_COMPONENT_ASSIMP-BIN_DEPENDS "${LIBASSIMP_COMPONENT}" )
|
||||||
|
@ -507,8 +500,8 @@ IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
|
||||||
SET(CPACK_DEBIAN_DISTRIBUTION_RELEASES lucid maverick natty oneiric precise CACHE STRING "Release code-names of the distrubiton release")
|
SET(CPACK_DEBIAN_DISTRIBUTION_RELEASES lucid maverick natty oneiric precise CACHE STRING "Release code-names of the distrubiton release")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
SET(DPUT_HOST "" CACHE STRING "PPA repository to upload the debian sources")
|
SET(DPUT_HOST "" CACHE STRING "PPA repository to upload the debian sources")
|
||||||
include(CPack)
|
INCLUDE(CPack)
|
||||||
include(DebSourcePPA)
|
INCLUDE(DebSourcePPA)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
|
@ -520,14 +513,16 @@ if(WIN32)
|
||||||
SET(LIB_DIR "${PROJECT_SOURCE_DIR}/lib32/")
|
SET(LIB_DIR "${PROJECT_SOURCE_DIR}/lib32/")
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
if(MSVC12)
|
IF(MSVC12)
|
||||||
SET(ASSIMP_MSVC_VERSION "vc120")
|
SET(ASSIMP_MSVC_VERSION "vc120")
|
||||||
elseif(MSVC14)
|
ELSEIF(MSVC14)
|
||||||
SET(ASSIMP_MSVC_VERSION "vc140")
|
SET(ASSIMP_MSVC_VERSION "vc140")
|
||||||
|
ELSEIF(MSVC15)
|
||||||
|
SET(ASSIMP_MSVC_VERSION "vc141")
|
||||||
ENDIF(MSVC12)
|
ENDIF(MSVC12)
|
||||||
|
|
||||||
if(MSVC12 OR MSVC14)
|
IF(MSVC12 OR MSVC14 OR MSVC15 )
|
||||||
add_custom_target(UpdateAssimpLibsDebugSymbolsAndDLLs COMMENT "Copying Assimp Libraries ..." VERBATIM)
|
ADD_CUSTOM_TARGET(UpdateAssimpLibsDebugSymbolsAndDLLs COMMENT "Copying Assimp Libraries ..." VERBATIM)
|
||||||
IF(CMAKE_GENERATOR MATCHES "^Visual Studio")
|
IF(CMAKE_GENERATOR MATCHES "^Visual Studio")
|
||||||
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.dll VERBATIM)
|
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.dll VERBATIM)
|
||||||
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.exp VERBATIM)
|
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.exp VERBATIM)
|
||||||
|
@ -548,5 +543,5 @@ if(WIN32)
|
||||||
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
|
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
|
||||||
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
|
ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
ENDIF(MSVC12 OR MSVC14)
|
ENDIF(MSVC12 OR MSVC14 OR MSVC15 )
|
||||||
ENDIF (WIN32)
|
ENDIF (WIN32)
|
||||||
|
|
40
Readme.md
40
Readme.md
|
@ -35,29 +35,29 @@ Please check our Wiki as well: https://github.com/assimp/assimp/wiki
|
||||||
__Importers__:
|
__Importers__:
|
||||||
|
|
||||||
- 3D
|
- 3D
|
||||||
- 3DS
|
- [3DS](https://en.wikipedia.org/wiki/.3ds)
|
||||||
- 3MF
|
- [3MF](https://en.wikipedia.org/wiki/3D_Manufacturing_Format)
|
||||||
- AC
|
- AC
|
||||||
- AC3D
|
- [AC3D](https://en.wikipedia.org/wiki/AC3D)
|
||||||
- ACC
|
- ACC
|
||||||
- AMJ
|
- AMJ
|
||||||
- ASE
|
- ASE
|
||||||
- ASK
|
- ASK
|
||||||
- B3D
|
- B3D
|
||||||
- BLEND (Blender)
|
- [BLEND](https://en.wikipedia.org/wiki/.blend_(file_format))
|
||||||
- BVH
|
- [BVH](https://en.wikipedia.org/wiki/Biovision_Hierarchy)
|
||||||
- COB
|
|
||||||
- CMS
|
- CMS
|
||||||
- DAE/Collada
|
- COB
|
||||||
- DXF
|
- [DAE/Collada](https://en.wikipedia.org/wiki/COLLADA)
|
||||||
|
- [DXF](https://en.wikipedia.org/wiki/AutoCAD_DXF)
|
||||||
- ENFF
|
- ENFF
|
||||||
- FBX
|
- [FBX](https://en.wikipedia.org/wiki/FBX)
|
||||||
- glTF 1.0 + GLB
|
- [glTF 1.0](https://en.wikipedia.org/wiki/GlTF#glTF_1.0) + GLB
|
||||||
- glTF 2.0
|
- [glTF 2.0](https://en.wikipedia.org/wiki/GlTF#glTF_2.0)
|
||||||
- HMB
|
- HMB
|
||||||
- IFC-STEP
|
- IFC-STEP
|
||||||
- IRR / IRRMESH
|
- IRR / IRRMESH
|
||||||
- LWO
|
- [LWO](https://en.wikipedia.org/wiki/LightWave_3D)
|
||||||
- LWS
|
- LWS
|
||||||
- LXO
|
- LXO
|
||||||
- MD2
|
- MD2
|
||||||
|
@ -70,10 +70,10 @@ __Importers__:
|
||||||
- MS3D
|
- MS3D
|
||||||
- NDO
|
- NDO
|
||||||
- NFF
|
- NFF
|
||||||
- OBJ
|
- [OBJ](https://en.wikipedia.org/wiki/Wavefront_.obj_file)
|
||||||
- OFF
|
- [OFF](https://en.wikipedia.org/wiki/OFF_(file_format))
|
||||||
- OGEX
|
- [OGEX](https://en.wikipedia.org/wiki/Open_Game_Engine_Exchange)
|
||||||
- PLY
|
- [PLY](https://en.wikipedia.org/wiki/PLY_(file_format))
|
||||||
- PMX
|
- PMX
|
||||||
- PRJ
|
- PRJ
|
||||||
- Q3O
|
- Q3O
|
||||||
|
@ -82,19 +82,19 @@ __Importers__:
|
||||||
- SCN
|
- SCN
|
||||||
- SIB
|
- SIB
|
||||||
- SMD
|
- SMD
|
||||||
- STL
|
- [STP](https://en.wikipedia.org/wiki/ISO_10303-21)
|
||||||
- STP
|
- [STL](https://en.wikipedia.org/wiki/STL_(file_format))
|
||||||
- TER
|
- TER
|
||||||
- UC
|
- UC
|
||||||
- VTA
|
- VTA
|
||||||
- X
|
- X
|
||||||
- X3D
|
- [X3D](https://en.wikipedia.org/wiki/X3D)
|
||||||
- XGL
|
- XGL
|
||||||
- ZGL
|
- ZGL
|
||||||
|
|
||||||
Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default):
|
Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default):
|
||||||
|
|
||||||
- C4D (https://github.com/assimp/assimp/wiki/Cinema4D-&-Melange)
|
- [C4D](https://en.wikipedia.org/wiki/Cinema_4D) (https://github.com/assimp/assimp/wiki/Cinema4D-&-Melange)
|
||||||
|
|
||||||
__Exporters__:
|
__Exporters__:
|
||||||
|
|
||||||
|
|
|
@ -34,36 +34,18 @@ if( MSVC )
|
||||||
else()
|
else()
|
||||||
set(MSVC_PREFIX "vc150")
|
set(MSVC_PREFIX "vc150")
|
||||||
endif()
|
endif()
|
||||||
set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" FORCE)
|
set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" )
|
||||||
else()
|
else()
|
||||||
set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the openrave libraries" FORCE)
|
set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the openrave libraries" )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set( ASSIMP_CXX_FLAGS ) # dynamically linked library
|
set( ASSIMP_CXX_FLAGS ) # dynamically linked library
|
||||||
if( WIN32 )
|
|
||||||
# for visual studio linking, most of the time boost dlls will be used
|
|
||||||
set( ASSIMP_CXX_FLAGS " -DBOOST_ALL_DYN_LINK -DBOOST_ALL_NO_LIB")
|
|
||||||
endif()
|
|
||||||
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 assimp${ASSIMP_LIBRARY_SUFFIX})
|
set( ASSIMP_LIBRARIES assimp${ASSIMP_LIBRARY_SUFFIX})
|
||||||
set( ASSIMP_LIBRARIES ${ASSIMP_LIBRARIES}@CMAKE_DEBUG_POSTFIX@)
|
set( ASSIMP_LIBRARIES ${ASSIMP_LIBRARIES}@CMAKE_DEBUG_POSTFIX@)
|
||||||
|
|
||||||
# search for the boost version assimp was compiled with
|
|
||||||
#set(Boost_USE_MULTITHREAD ON)
|
|
||||||
#set(Boost_USE_STATIC_LIBS OFF)
|
|
||||||
#set(Boost_USE_STATIC_RUNTIME OFF)
|
|
||||||
#find_package(Boost ${ASSIMP_Boost_VERSION} EXACT COMPONENTS thread date_time)
|
|
||||||
#if(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
|
|
||||||
# set( ASSIMP_INCLUDE_DIRS "${ASSIMP_INCLUDE_DIRS}" ${Boost_INCLUDE_DIRS})
|
|
||||||
#else(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
|
|
||||||
# message(WARNING "Failed to find Boost ${ASSIMP_Boost_VERSION} necessary for assimp")
|
|
||||||
#endif(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
|
|
||||||
|
|
||||||
# the boost version assimp was compiled with
|
|
||||||
set( ASSIMP_Boost_VERSION "@Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@")
|
|
||||||
|
|
||||||
# for compatibility with pkg-config
|
# for compatibility with pkg-config
|
||||||
set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}")
|
set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}")
|
||||||
set(ASSIMP_LDFLAGS_OTHER "${ASSIMP_LINK_FLAGS}")
|
set(ASSIMP_LDFLAGS_OTHER "${ASSIMP_LINK_FLAGS}")
|
||||||
|
@ -74,7 +56,6 @@ MARK_AS_ADVANCED(
|
||||||
ASSIMP_LINK_FLAGS
|
ASSIMP_LINK_FLAGS
|
||||||
ASSIMP_INCLUDE_DIRS
|
ASSIMP_INCLUDE_DIRS
|
||||||
ASSIMP_LIBRARIES
|
ASSIMP_LIBRARIES
|
||||||
ASSIMP_Boost_VERSION
|
|
||||||
ASSIMP_CFLAGS_OTHER
|
ASSIMP_CFLAGS_OTHER
|
||||||
ASSIMP_LDFLAGS_OTHER
|
ASSIMP_LDFLAGS_OTHER
|
||||||
ASSIMP_LIBRARY_SUFFIX
|
ASSIMP_LIBRARY_SUFFIX
|
||||||
|
|
|
@ -71,7 +71,7 @@ static const aiImporterDesc desc = {
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
"3ds prj"
|
"3ds prj 3DS PRJ"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ Discreet3DSImporter::~Discreet3DSImporter() {
|
||||||
// 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 Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
|
bool Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
|
||||||
std::string extension = GetExtension(pFile);
|
std::string extension = GetExtension(pFile);
|
||||||
if(extension == "3ds" || extension == "prj" ) {
|
if(extension == "3ds" || extension == "3DS" || extension == "prj"|| extension == "PRJ" ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,6 +186,8 @@ SET( Common_SRCS
|
||||||
Bitmap.cpp
|
Bitmap.cpp
|
||||||
Version.cpp
|
Version.cpp
|
||||||
CreateAnimMesh.cpp
|
CreateAnimMesh.cpp
|
||||||
|
simd.h
|
||||||
|
simd.cpp
|
||||||
)
|
)
|
||||||
SOURCE_GROUP(Common FILES ${Common_SRCS})
|
SOURCE_GROUP(Common FILES ${Common_SRCS})
|
||||||
|
|
||||||
|
|
|
@ -47,11 +47,10 @@ 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 "COBLoader.h"
|
||||||
#include "COBScene.h"
|
#include "COBScene.h"
|
||||||
|
#include "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 <memory>
|
||||||
|
@ -105,7 +104,7 @@ COBImporter::~COBImporter()
|
||||||
bool COBImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
|
bool COBImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
|
||||||
{
|
{
|
||||||
const std::string& extension = GetExtension(pFile);
|
const std::string& extension = GetExtension(pFile);
|
||||||
if (extension == "cob" || extension == "scn") {
|
if (extension == "cob" || extension == "scn" || extension == "COB" || extension == "SCN") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,6 +224,9 @@ void COBImporter::InternReadFile( const std::string& pFile,
|
||||||
}
|
}
|
||||||
|
|
||||||
pScene->mRootNode = BuildNodes(*root.get(),scene,pScene);
|
pScene->mRootNode = BuildNodes(*root.get(),scene,pScene);
|
||||||
|
//flip normals after import
|
||||||
|
FlipWindingOrderProcess flip;
|
||||||
|
flip.Execute( pScene );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -1299,3 +1301,4 @@ void COBImporter::ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -190,7 +190,7 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
|
||||||
float tx = meshTex[p2].x - meshTex[p0].x, ty = meshTex[p2].y - meshTex[p0].y;
|
float tx = meshTex[p2].x - meshTex[p0].x, ty = meshTex[p2].y - meshTex[p0].y;
|
||||||
float dirCorrection = (tx * sy - ty * sx) < 0.0f ? -1.0f : 1.0f;
|
float dirCorrection = (tx * sy - ty * sx) < 0.0f ? -1.0f : 1.0f;
|
||||||
// when t1, t2, t3 in same position in UV space, just use default UV direction.
|
// when t1, t2, t3 in same position in UV space, just use default UV direction.
|
||||||
if ( 0 == sx && 0 ==sy && 0 == tx && 0 == ty ) {
|
if ( sx * ty == sy * tx ) {
|
||||||
sx = 0.0; sy = 1.0;
|
sx = 0.0; sy = 1.0;
|
||||||
tx = 1.0; ty = 0.0;
|
tx = 1.0; ty = 0.0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,7 +98,7 @@ void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportPrope
|
||||||
void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||||
void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
|
||||||
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* );
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
@ -173,7 +173,7 @@ Exporter::ExportFormatEntry gExporters[] =
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
Exporter::ExportFormatEntry( "fbx", "Autodesk FBX (binary)", "fbx", &ExportSceneFBX, 0 ),
|
Exporter::ExportFormatEntry( "fbx", "Autodesk FBX (binary)", "fbx", &ExportSceneFBX, 0 ),
|
||||||
//Exporter::ExportFormatEntry( "fbxa", "Autodesk FBX (ascii)", "fbx", &ExportSceneFBXA, 0 ),
|
Exporter::ExportFormatEntry( "fbxa", "Autodesk FBX (ascii)", "fbx", &ExportSceneFBXA, 0 ),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
|
#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
|
||||||
|
|
|
@ -61,6 +61,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
namespace FBX {
|
namespace FBX {
|
||||||
|
@ -133,9 +135,7 @@ void Converter::ConvertRootNode() {
|
||||||
ConvertNodes( 0L, *out->mRootNode );
|
ConvertNodes( 0L, *out->mRootNode );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform ) {
|
||||||
void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform )
|
|
||||||
{
|
|
||||||
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced( id, "Model" );
|
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced( id, "Model" );
|
||||||
|
|
||||||
std::vector<aiNode*> nodes;
|
std::vector<aiNode*> nodes;
|
||||||
|
@ -153,14 +153,14 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
|
||||||
}
|
}
|
||||||
|
|
||||||
const Object* const object = con->SourceObject();
|
const Object* const object = con->SourceObject();
|
||||||
if ( !object ) {
|
if ( nullptr == object ) {
|
||||||
FBXImporter::LogWarn( "failed to convert source object for Model link" );
|
FBXImporter::LogWarn( "failed to convert source object for Model link" );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Model* const model = dynamic_cast<const Model*>( object );
|
const Model* const model = dynamic_cast<const Model*>( object );
|
||||||
|
|
||||||
if ( model ) {
|
if ( nullptr != model ) {
|
||||||
nodes_chain.clear();
|
nodes_chain.clear();
|
||||||
post_nodes_chain.clear();
|
post_nodes_chain.clear();
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
|
||||||
|
|
||||||
ai_assert( nodes_chain.size() );
|
ai_assert( nodes_chain.size() );
|
||||||
|
|
||||||
const std::string& original_name = FixNodeName( model->Name() );
|
std::string original_name = FixNodeName( model->Name() );
|
||||||
|
|
||||||
// check if any of the nodes in the chain has the name the fbx node
|
// check if any of the nodes in the chain has the name the fbx node
|
||||||
// is supposed to have. If there is none, add another node to
|
// is supposed to have. If there is none, add another node to
|
||||||
|
@ -189,7 +189,15 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !name_carrier ) {
|
if ( !name_carrier ) {
|
||||||
|
NodeNameCache::const_iterator it( std::find( mNodeNames.begin(), mNodeNames.end(), original_name ) );
|
||||||
|
if ( it != mNodeNames.end() ) {
|
||||||
|
original_name = original_name + std::string( "001" );
|
||||||
|
}
|
||||||
|
|
||||||
|
mNodeNames.push_back( original_name );
|
||||||
nodes_chain.push_back( new aiNode( original_name ) );
|
nodes_chain.push_back( new aiNode( original_name ) );
|
||||||
|
} else {
|
||||||
|
original_name = nodes_chain.back()->mName.C_Str();
|
||||||
}
|
}
|
||||||
|
|
||||||
//setup metadata on newest node
|
//setup metadata on newest node
|
||||||
|
@ -250,11 +258,11 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
|
||||||
ConvertNodes( model->ID(), *last_parent, new_abs_transform );
|
ConvertNodes( model->ID(), *last_parent, new_abs_transform );
|
||||||
|
|
||||||
if ( doc.Settings().readLights ) {
|
if ( doc.Settings().readLights ) {
|
||||||
ConvertLights( *model );
|
ConvertLights( *model, original_name );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( doc.Settings().readCameras ) {
|
if ( doc.Settings().readCameras ) {
|
||||||
ConvertCameras( *model );
|
ConvertCameras( *model, original_name );
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes.push_back( nodes_chain.front() );
|
nodes.push_back( nodes_chain.front() );
|
||||||
|
@ -278,34 +286,31 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Converter::ConvertLights( const Model& model )
|
void Converter::ConvertLights( const Model& model, const std::string &orig_name ) {
|
||||||
{
|
|
||||||
const std::vector<const NodeAttribute*>& node_attrs = model.GetAttributes();
|
const std::vector<const NodeAttribute*>& node_attrs = model.GetAttributes();
|
||||||
for( const NodeAttribute* attr : node_attrs ) {
|
for( const NodeAttribute* attr : node_attrs ) {
|
||||||
const Light* const light = dynamic_cast<const Light*>( attr );
|
const Light* const light = dynamic_cast<const Light*>( attr );
|
||||||
if ( light ) {
|
if ( light ) {
|
||||||
ConvertLight( model, *light );
|
ConvertLight( *light, orig_name );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Converter::ConvertCameras( const Model& model )
|
void Converter::ConvertCameras( const Model& model, const std::string &orig_name ) {
|
||||||
{
|
|
||||||
const std::vector<const NodeAttribute*>& node_attrs = model.GetAttributes();
|
const std::vector<const NodeAttribute*>& node_attrs = model.GetAttributes();
|
||||||
for( const NodeAttribute* attr : node_attrs ) {
|
for( const NodeAttribute* attr : node_attrs ) {
|
||||||
const Camera* const cam = dynamic_cast<const Camera*>( attr );
|
const Camera* const cam = dynamic_cast<const Camera*>( attr );
|
||||||
if ( cam ) {
|
if ( cam ) {
|
||||||
ConvertCamera( model, *cam );
|
ConvertCamera( *cam, orig_name );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Converter::ConvertLight( const Model& model, const Light& light )
|
void Converter::ConvertLight( const Light& light, const std::string &orig_name ) {
|
||||||
{
|
|
||||||
lights.push_back( new aiLight() );
|
lights.push_back( new aiLight() );
|
||||||
aiLight* const out_light = lights.back();
|
aiLight* const out_light = lights.back();
|
||||||
|
|
||||||
out_light->mName.Set( FixNodeName( model.Name() ) );
|
out_light->mName.Set( orig_name );
|
||||||
|
|
||||||
const float intensity = light.Intensity() / 100.0f;
|
const float intensity = light.Intensity() / 100.0f;
|
||||||
const aiVector3D& col = light.Color();
|
const aiVector3D& col = light.Color();
|
||||||
|
@ -378,12 +383,12 @@ void Converter::ConvertLight( const Model& model, const Light& light )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Converter::ConvertCamera( const Model& model, const Camera& cam )
|
void Converter::ConvertCamera( const Camera& cam, const std::string &orig_name )
|
||||||
{
|
{
|
||||||
cameras.push_back( new aiCamera() );
|
cameras.push_back( new aiCamera() );
|
||||||
aiCamera* const out_camera = cameras.back();
|
aiCamera* const out_camera = cameras.back();
|
||||||
|
|
||||||
out_camera->mName.Set( FixNodeName( model.Name() ) );
|
out_camera->mName.Set( orig_name );
|
||||||
|
|
||||||
out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight();
|
out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight();
|
||||||
|
|
||||||
|
@ -397,6 +402,31 @@ void Converter::ConvertCamera( const Model& model, const Camera& cam )
|
||||||
out_camera->mClipPlaneFar = cam.FarPlane();
|
out_camera->mClipPlaneFar = cam.FarPlane();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool HasName( NodeNameCache &cache, const std::string &name ) {
|
||||||
|
NodeNameCache::const_iterator it( std::find( cache.begin(), cache.end(), name ) );
|
||||||
|
return it != cache.end();
|
||||||
|
|
||||||
|
}
|
||||||
|
void Converter::GetUniqueName( const std::string &name, std::string uniqueName ) {
|
||||||
|
if ( !HasName( mNodeNames, name ) ) {
|
||||||
|
uniqueName = name;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i( 0 );
|
||||||
|
std::string newName;
|
||||||
|
while ( HasName( mNodeNames, newName ) ) {
|
||||||
|
++i;
|
||||||
|
newName.clear();
|
||||||
|
newName += name;
|
||||||
|
std::stringstream ext;
|
||||||
|
ext << std::setfill( '0' ) << std::setw( 3 ) << i;
|
||||||
|
newName += ext.str();
|
||||||
|
}
|
||||||
|
uniqueName = newName;
|
||||||
|
mNodeNames.push_back( uniqueName );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* Converter::NameTransformationComp( TransformationComp comp )
|
const char* Converter::NameTransformationComp( TransformationComp comp )
|
||||||
{
|
{
|
||||||
|
@ -738,7 +768,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector
|
||||||
// not be guaranteed.
|
// not be guaranteed.
|
||||||
ai_assert( NeedsComplexTransformationChain( model ) == is_complex );
|
ai_assert( NeedsComplexTransformationChain( model ) == is_complex );
|
||||||
|
|
||||||
const std::string& name = FixNodeName( model.Name() );
|
std::string name = FixNodeName( model.Name() );
|
||||||
|
|
||||||
// now, if we have more than just Translation, Scaling and Rotation,
|
// now, if we have more than just Translation, Scaling and Rotation,
|
||||||
// we need to generate a full node chain to accommodate for assimp's
|
// we need to generate a full node chain to accommodate for assimp's
|
||||||
|
@ -786,8 +816,10 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector
|
||||||
// else, we can just multiply the matrices together
|
// else, we can just multiply the matrices together
|
||||||
aiNode* nd = new aiNode();
|
aiNode* nd = new aiNode();
|
||||||
output_nodes.push_back( nd );
|
output_nodes.push_back( nd );
|
||||||
|
std::string uniqueName;
|
||||||
|
GetUniqueName( name, uniqueName );
|
||||||
|
|
||||||
nd->mName.Set( name );
|
nd->mName.Set( uniqueName );
|
||||||
|
|
||||||
for (const auto &transform : chain) {
|
for (const auto &transform : chain) {
|
||||||
nd->mTransformation = nd->mTransformation * transform;
|
nd->mTransformation = nd->mTransformation * transform;
|
||||||
|
@ -2005,81 +2037,17 @@ void Converter::ConvertAnimations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Converter::RenameNode( const std::string& fixed_name, const std::string& new_name ) {
|
std::string Converter::FixNodeName( const std::string& name ) {
|
||||||
if ( node_names.find( fixed_name ) == node_names.end() ) {
|
|
||||||
FBXImporter::LogError( "Cannot rename node " + fixed_name + ", not existing.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( node_names.find( new_name ) != node_names.end() ) {
|
|
||||||
FBXImporter::LogError( "Cannot rename node " + fixed_name + " to " + new_name +", name already existing." );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ai_assert( node_names.find( fixed_name ) != node_names.end() );
|
|
||||||
ai_assert( node_names.find( new_name ) == node_names.end() );
|
|
||||||
|
|
||||||
renamed_nodes[ fixed_name ] = new_name;
|
|
||||||
|
|
||||||
const aiString fn( fixed_name );
|
|
||||||
|
|
||||||
for( aiCamera* cam : cameras ) {
|
|
||||||
if ( cam->mName == fn ) {
|
|
||||||
cam->mName.Set( new_name );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for( aiLight* light : lights ) {
|
|
||||||
if ( light->mName == fn ) {
|
|
||||||
light->mName.Set( new_name );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for( aiAnimation* anim : animations ) {
|
|
||||||
for ( unsigned int i = 0; i < anim->mNumChannels; ++i ) {
|
|
||||||
aiNodeAnim* const na = anim->mChannels[ i ];
|
|
||||||
if ( na->mNodeName == fn ) {
|
|
||||||
na->mNodeName.Set( new_name );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string Converter::FixNodeName( const std::string& name )
|
|
||||||
{
|
|
||||||
// strip Model:: prefix, avoiding ambiguities (i.e. don't strip if
|
// strip Model:: prefix, avoiding ambiguities (i.e. don't strip if
|
||||||
// this causes ambiguities, well possible between empty identifiers,
|
// this causes ambiguities, well possible between empty identifiers,
|
||||||
// such as "Model::" and ""). Make sure the behaviour is consistent
|
// such as "Model::" and ""). Make sure the behaviour is consistent
|
||||||
// across multiple calls to FixNodeName().
|
// across multiple calls to FixNodeName().
|
||||||
if ( name.substr( 0, 7 ) == "Model::" ) {
|
if ( name.substr( 0, 7 ) == "Model::" ) {
|
||||||
std::string temp = name.substr( 7 );
|
std::string temp = name.substr( 7 );
|
||||||
|
return temp;
|
||||||
const NodeNameMap::const_iterator it = node_names.find( temp );
|
|
||||||
if ( it != node_names.end() ) {
|
|
||||||
if ( !( *it ).second ) {
|
|
||||||
return FixNodeName( name + "_" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
node_names[ temp ] = true;
|
|
||||||
|
|
||||||
const NameNameMap::const_iterator rit = renamed_nodes.find( temp );
|
|
||||||
return rit == renamed_nodes.end() ? temp : ( *rit ).second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const NodeNameMap::const_iterator it = node_names.find( name );
|
return name;
|
||||||
if ( it != node_names.end() ) {
|
|
||||||
if ( ( *it ).second ) {
|
|
||||||
return FixNodeName( name + "_" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
node_names[ name ] = false;
|
|
||||||
|
|
||||||
const NameNameMap::const_iterator rit = renamed_nodes.find( name );
|
|
||||||
return rit == renamed_nodes.end() ? name : ( *rit ).second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Converter::ConvertAnimationStack( const AnimationStack& st )
|
void Converter::ConvertAnimationStack( const AnimationStack& st )
|
||||||
|
|
|
@ -68,6 +68,8 @@ namespace FBX {
|
||||||
|
|
||||||
class Document;
|
class Document;
|
||||||
|
|
||||||
|
using NodeNameCache = std::vector<std::string>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a FBX #Document to #aiScene
|
* Convert a FBX #Document to #aiScene
|
||||||
* @param out Empty scene to be populated
|
* @param out Empty scene to be populated
|
||||||
|
@ -117,16 +119,19 @@ private:
|
||||||
void ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform = aiMatrix4x4());
|
void ConvertNodes(uint64_t id, aiNode& parent, const aiMatrix4x4& parent_transform = aiMatrix4x4());
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertLights(const Model& model);
|
void ConvertLights(const Model& model, const std::string &orig_name );
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertCameras(const Model& model);
|
void ConvertCameras(const Model& model, const std::string &orig_name );
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertLight(const Model& model, const Light& light);
|
void ConvertLight( const Light& light, const std::string &orig_name );
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertCamera(const Model& model, const Camera& cam);
|
void ConvertCamera( const Camera& cam, const std::string &orig_name );
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void GetUniqueName( const std::string &name, std::string uniqueName );
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// this returns unified names usable within assimp identifiers (i.e. no space characters -
|
// this returns unified names usable within assimp identifiers (i.e. no space characters -
|
||||||
|
@ -258,18 +263,6 @@ private:
|
||||||
// convert animation data to aiAnimation et al
|
// convert animation data to aiAnimation et al
|
||||||
void ConvertAnimations();
|
void ConvertAnimations();
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
|
||||||
// rename a node already partially converted. fixed_name is a string previously returned by
|
|
||||||
// FixNodeName, new_name specifies the string FixNodeName should return on all further invocations
|
|
||||||
// which would previously have returned the old value.
|
|
||||||
//
|
|
||||||
// this also updates names in node animations, cameras and light sources and is thus slow.
|
|
||||||
//
|
|
||||||
// NOTE: the caller is responsible for ensuring that the new name is unique and does
|
|
||||||
// not collide with any other identifiers. The best way to ensure this is to only
|
|
||||||
// append to the old name, which is guaranteed to match these requirements.
|
|
||||||
void RenameNode(const std::string& fixed_name, const std::string& new_name);
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// takes a fbx node name and returns the identifier to be used in the assimp output scene.
|
// takes a fbx node name and returns the identifier to be used in the assimp output scene.
|
||||||
// the function is guaranteed to provide consistent results over multiple invocations
|
// the function is guaranteed to provide consistent results over multiple invocations
|
||||||
|
@ -281,7 +274,6 @@ private:
|
||||||
// XXX: better use multi_map ..
|
// XXX: better use multi_map ..
|
||||||
typedef std::map<std::string, std::vector<const AnimationCurveNode*> > NodeMap;
|
typedef std::map<std::string, std::vector<const AnimationCurveNode*> > NodeMap;
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertAnimationStack(const AnimationStack& st);
|
void ConvertAnimationStack(const AnimationStack& st);
|
||||||
|
|
||||||
|
@ -432,19 +424,11 @@ private:
|
||||||
typedef std::map<std::string, unsigned int> NodeAnimBitMap;
|
typedef std::map<std::string, unsigned int> NodeAnimBitMap;
|
||||||
NodeAnimBitMap node_anim_chain_bits;
|
NodeAnimBitMap node_anim_chain_bits;
|
||||||
|
|
||||||
// name -> has had its prefix_stripped?
|
NodeNameCache mNodeNames;
|
||||||
typedef std::map<std::string, bool> NodeNameMap;
|
|
||||||
NodeNameMap node_names;
|
|
||||||
|
|
||||||
typedef std::map<std::string, std::string> NameNameMap;
|
|
||||||
NameNameMap renamed_nodes;
|
|
||||||
|
|
||||||
double anim_fps;
|
double anim_fps;
|
||||||
|
|
||||||
aiScene* const out;
|
aiScene* const out;
|
||||||
const FBX::Document& doc;
|
const FBX::Document& doc;
|
||||||
|
|
||||||
std::vector<std::string> mLightNames;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,9 +45,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "FBXCommon.h"
|
#include "FBXCommon.h"
|
||||||
|
|
||||||
#include <assimp/StreamWriter.h> // StreamWriterLE
|
#include <assimp/StreamWriter.h> // StreamWriterLE
|
||||||
|
#include <assimp/Exceptional.h> // DeadlyExportError
|
||||||
#include <assimp/ai_assert.h>
|
#include <assimp/ai_assert.h>
|
||||||
|
#include <assimp/StringUtils.h> // ai_snprintf
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <ostream>
|
||||||
|
#include <sstream> // ostringstream
|
||||||
#include <memory> // shared_ptr
|
#include <memory> // shared_ptr
|
||||||
|
|
||||||
// AddP70<type> helpers... there's no usable pattern here,
|
// AddP70<type> helpers... there's no usable pattern here,
|
||||||
|
@ -145,33 +149,174 @@ void FBX::Node::AddP70time(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// public member functions for writing nodes to stream
|
||||||
|
|
||||||
|
void FBX::Node::Dump(
|
||||||
|
std::shared_ptr<Assimp::IOStream> outfile,
|
||||||
|
bool binary, int indent
|
||||||
|
) {
|
||||||
|
if (binary) {
|
||||||
|
Assimp::StreamWriterLE outstream(outfile);
|
||||||
|
DumpBinary(outstream);
|
||||||
|
} else {
|
||||||
|
std::ostringstream ss;
|
||||||
|
DumpAscii(ss, indent);
|
||||||
|
std::string s = ss.str();
|
||||||
|
outfile->Write(s.c_str(), s.size(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::Dump(
|
||||||
|
Assimp::StreamWriterLE &outstream,
|
||||||
|
bool binary, int indent
|
||||||
|
) {
|
||||||
|
if (binary) {
|
||||||
|
DumpBinary(outstream);
|
||||||
|
} else {
|
||||||
|
std::ostringstream ss;
|
||||||
|
DumpAscii(ss, indent);
|
||||||
|
outstream.PutString(ss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// public member functions for low-level writing
|
||||||
|
|
||||||
|
void FBX::Node::Begin(
|
||||||
|
Assimp::StreamWriterLE &s,
|
||||||
|
bool binary, int indent
|
||||||
|
) {
|
||||||
|
if (binary) {
|
||||||
|
BeginBinary(s);
|
||||||
|
} else {
|
||||||
|
// assume we're at the correct place to start already
|
||||||
|
(void)indent;
|
||||||
|
std::ostringstream ss;
|
||||||
|
BeginAscii(ss, indent);
|
||||||
|
s.PutString(ss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::DumpProperties(
|
||||||
|
Assimp::StreamWriterLE& s,
|
||||||
|
bool binary, int indent
|
||||||
|
) {
|
||||||
|
if (binary) {
|
||||||
|
DumpPropertiesBinary(s);
|
||||||
|
} else {
|
||||||
|
std::ostringstream ss;
|
||||||
|
DumpPropertiesAscii(ss, indent);
|
||||||
|
s.PutString(ss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::EndProperties(
|
||||||
|
Assimp::StreamWriterLE &s,
|
||||||
|
bool binary, int indent
|
||||||
|
) {
|
||||||
|
EndProperties(s, binary, indent, properties.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::EndProperties(
|
||||||
|
Assimp::StreamWriterLE &s,
|
||||||
|
bool binary, int indent,
|
||||||
|
size_t num_properties
|
||||||
|
) {
|
||||||
|
if (binary) {
|
||||||
|
EndPropertiesBinary(s, num_properties);
|
||||||
|
} else {
|
||||||
|
// nothing to do
|
||||||
|
(void)indent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::BeginChildren(
|
||||||
|
Assimp::StreamWriterLE &s,
|
||||||
|
bool binary, int indent
|
||||||
|
) {
|
||||||
|
if (binary) {
|
||||||
|
// nothing to do
|
||||||
|
} else {
|
||||||
|
std::ostringstream ss;
|
||||||
|
BeginChildrenAscii(ss, indent);
|
||||||
|
s.PutString(ss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::DumpChildren(
|
||||||
|
Assimp::StreamWriterLE& s,
|
||||||
|
bool binary, int indent
|
||||||
|
) {
|
||||||
|
if (binary) {
|
||||||
|
DumpChildrenBinary(s);
|
||||||
|
} else {
|
||||||
|
std::ostringstream ss;
|
||||||
|
DumpChildrenAscii(ss, indent);
|
||||||
|
s.PutString(ss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::End(
|
||||||
|
Assimp::StreamWriterLE &s,
|
||||||
|
bool binary, int indent,
|
||||||
|
bool has_children
|
||||||
|
) {
|
||||||
|
if (binary) {
|
||||||
|
EndBinary(s, has_children);
|
||||||
|
} else {
|
||||||
|
std::ostringstream ss;
|
||||||
|
EndAscii(ss, indent, has_children);
|
||||||
|
s.PutString(ss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// public member functions for writing to binary fbx
|
// public member functions for writing to binary fbx
|
||||||
|
|
||||||
void FBX::Node::Dump(std::shared_ptr<Assimp::IOStream> outfile)
|
void FBX::Node::DumpBinary(Assimp::StreamWriterLE &s)
|
||||||
{
|
|
||||||
Assimp::StreamWriterLE outstream(outfile);
|
|
||||||
Dump(outstream);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FBX::Node::Dump(Assimp::StreamWriterLE &s)
|
|
||||||
{
|
{
|
||||||
// write header section (with placeholders for some things)
|
// write header section (with placeholders for some things)
|
||||||
Begin(s);
|
BeginBinary(s);
|
||||||
|
|
||||||
// write properties
|
// write properties
|
||||||
DumpProperties(s);
|
DumpPropertiesBinary(s);
|
||||||
|
|
||||||
// go back and fill in property related placeholders
|
// go back and fill in property related placeholders
|
||||||
EndProperties(s, properties.size());
|
EndPropertiesBinary(s, properties.size());
|
||||||
|
|
||||||
// write children
|
// write children
|
||||||
DumpChildren(s);
|
DumpChildrenBinary(s);
|
||||||
|
|
||||||
// finish, filling in end offset placeholder
|
// finish, filling in end offset placeholder
|
||||||
End(s, !children.empty());
|
EndBinary(s, force_has_children || !children.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBX::Node::Begin(Assimp::StreamWriterLE &s)
|
|
||||||
|
// public member functions for writing to ascii fbx
|
||||||
|
|
||||||
|
void FBX::Node::DumpAscii(std::ostream &s, int indent)
|
||||||
|
{
|
||||||
|
// write name
|
||||||
|
BeginAscii(s, indent);
|
||||||
|
|
||||||
|
// write properties
|
||||||
|
DumpPropertiesAscii(s, indent);
|
||||||
|
|
||||||
|
if (force_has_children || !children.empty()) {
|
||||||
|
// begin children (with a '{')
|
||||||
|
BeginChildrenAscii(s, indent + 1);
|
||||||
|
// write children
|
||||||
|
DumpChildrenAscii(s, indent + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// finish (also closing the children bracket '}')
|
||||||
|
EndAscii(s, indent, force_has_children || !children.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// private member functions for low-level writing to fbx
|
||||||
|
|
||||||
|
void FBX::Node::BeginBinary(Assimp::StreamWriterLE &s)
|
||||||
{
|
{
|
||||||
// remember start pos so we can come back and write the end pos
|
// remember start pos so we can come back and write the end pos
|
||||||
this->start_pos = s.Tell();
|
this->start_pos = s.Tell();
|
||||||
|
@ -189,26 +334,14 @@ void FBX::Node::Begin(Assimp::StreamWriterLE &s)
|
||||||
this->property_start = s.Tell();
|
this->property_start = s.Tell();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBX::Node::DumpProperties(Assimp::StreamWriterLE& s)
|
void FBX::Node::DumpPropertiesBinary(Assimp::StreamWriterLE& s)
|
||||||
{
|
{
|
||||||
for (auto &p : properties) {
|
for (auto &p : properties) {
|
||||||
p.Dump(s);
|
p.DumpBinary(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBX::Node::DumpChildren(Assimp::StreamWriterLE& s)
|
void FBX::Node::EndPropertiesBinary(
|
||||||
{
|
|
||||||
for (FBX::Node& child : children) {
|
|
||||||
child.Dump(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FBX::Node::EndProperties(Assimp::StreamWriterLE &s)
|
|
||||||
{
|
|
||||||
EndProperties(s, properties.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
void FBX::Node::EndProperties(
|
|
||||||
Assimp::StreamWriterLE &s,
|
Assimp::StreamWriterLE &s,
|
||||||
size_t num_properties
|
size_t num_properties
|
||||||
) {
|
) {
|
||||||
|
@ -222,7 +355,14 @@ void FBX::Node::EndProperties(
|
||||||
s.Seek(pos);
|
s.Seek(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBX::Node::End(
|
void FBX::Node::DumpChildrenBinary(Assimp::StreamWriterLE& s)
|
||||||
|
{
|
||||||
|
for (FBX::Node& child : children) {
|
||||||
|
child.DumpBinary(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::EndBinary(
|
||||||
Assimp::StreamWriterLE &s,
|
Assimp::StreamWriterLE &s,
|
||||||
bool has_children
|
bool has_children
|
||||||
) {
|
) {
|
||||||
|
@ -237,48 +377,192 @@ void FBX::Node::End(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// static member functions
|
void FBX::Node::BeginAscii(std::ostream& s, int indent)
|
||||||
|
{
|
||||||
|
s << '\n';
|
||||||
|
for (int i = 0; i < indent; ++i) { s << '\t'; }
|
||||||
|
s << name << ": ";
|
||||||
|
}
|
||||||
|
|
||||||
// convenience function to create and write a property node,
|
void FBX::Node::DumpPropertiesAscii(std::ostream &s, int indent)
|
||||||
// holding a single property which is an array of values.
|
{
|
||||||
// does not copy the data, so is efficient for large arrays.
|
for (size_t i = 0; i < properties.size(); ++i) {
|
||||||
|
if (i > 0) { s << ", "; }
|
||||||
|
properties[i].DumpAscii(s, indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::BeginChildrenAscii(std::ostream& s, int indent)
|
||||||
|
{
|
||||||
|
// only call this if there are actually children
|
||||||
|
s << " {";
|
||||||
|
(void)indent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::DumpChildrenAscii(std::ostream& s, int indent)
|
||||||
|
{
|
||||||
|
// children will need a lot of padding and corralling
|
||||||
|
if (children.size() || force_has_children) {
|
||||||
|
for (size_t i = 0; i < children.size(); ++i) {
|
||||||
|
// no compression in ascii files, so skip this node if it exists
|
||||||
|
if (children[i].name == "EncryptionType") { continue; }
|
||||||
|
// the child can dump itself
|
||||||
|
children[i].DumpAscii(s, indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Node::EndAscii(std::ostream& s, int indent, bool has_children)
|
||||||
|
{
|
||||||
|
if (!has_children) { return; } // nothing to do
|
||||||
|
s << '\n';
|
||||||
|
for (int i = 0; i < indent; ++i) { s << '\t'; }
|
||||||
|
s << "}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// private helpers for static member functions
|
||||||
|
|
||||||
|
// ascii property node from vector of doubles
|
||||||
|
void FBX::Node::WritePropertyNodeAscii(
|
||||||
|
const std::string& name,
|
||||||
|
const std::vector<double>& v,
|
||||||
|
Assimp::StreamWriterLE& s,
|
||||||
|
int indent
|
||||||
|
){
|
||||||
|
char buffer[32];
|
||||||
|
FBX::Node node(name);
|
||||||
|
node.Begin(s, false, indent);
|
||||||
|
std::string vsize = std::to_string(v.size());
|
||||||
|
// *<size> {
|
||||||
|
s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n");
|
||||||
|
// indent + 1
|
||||||
|
for (int i = 0; i < indent + 1; ++i) { s.PutChar('\t'); }
|
||||||
|
// a: value,value,value,...
|
||||||
|
s.PutString("a: ");
|
||||||
|
int count = 0;
|
||||||
|
for (size_t i = 0; i < v.size(); ++i) {
|
||||||
|
if (i > 0) { s.PutChar(','); }
|
||||||
|
int len = ai_snprintf(buffer, sizeof(buffer), "%f", v[i]);
|
||||||
|
count += len;
|
||||||
|
if (count > 2048) { s.PutChar('\n'); count = 0; }
|
||||||
|
if (len < 0 || len > 31) {
|
||||||
|
// this should never happen
|
||||||
|
throw DeadlyExportError("failed to convert double to string");
|
||||||
|
}
|
||||||
|
for (int j = 0; j < len; ++j) { s.PutChar(buffer[j]); }
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
s.PutChar('\n');
|
||||||
|
for (int i = 0; i < indent; ++i) { s.PutChar('\t'); }
|
||||||
|
s.PutChar('}'); s.PutChar(' ');
|
||||||
|
node.End(s, false, indent, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ascii property node from vector of int32_t
|
||||||
|
void FBX::Node::WritePropertyNodeAscii(
|
||||||
|
const std::string& name,
|
||||||
|
const std::vector<int32_t>& v,
|
||||||
|
Assimp::StreamWriterLE& s,
|
||||||
|
int indent
|
||||||
|
){
|
||||||
|
char buffer[32];
|
||||||
|
FBX::Node node(name);
|
||||||
|
node.Begin(s, false, indent);
|
||||||
|
std::string vsize = std::to_string(v.size());
|
||||||
|
// *<size> {
|
||||||
|
s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n");
|
||||||
|
// indent + 1
|
||||||
|
for (int i = 0; i < indent + 1; ++i) { s.PutChar('\t'); }
|
||||||
|
// a: value,value,value,...
|
||||||
|
s.PutString("a: ");
|
||||||
|
int count = 0;
|
||||||
|
for (size_t i = 0; i < v.size(); ++i) {
|
||||||
|
if (i > 0) { s.PutChar(','); }
|
||||||
|
int len = ai_snprintf(buffer, sizeof(buffer), "%d", v[i]);
|
||||||
|
count += len;
|
||||||
|
if (count > 2048) { s.PutChar('\n'); count = 0; }
|
||||||
|
if (len < 0 || len > 31) {
|
||||||
|
// this should never happen
|
||||||
|
throw DeadlyExportError("failed to convert double to string");
|
||||||
|
}
|
||||||
|
for (int j = 0; j < len; ++j) { s.PutChar(buffer[j]); }
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
s.PutChar('\n');
|
||||||
|
for (int i = 0; i < indent; ++i) { s.PutChar('\t'); }
|
||||||
|
s.PutChar('}'); s.PutChar(' ');
|
||||||
|
node.End(s, false, indent, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// binary property node from vector of doubles
|
||||||
// TODO: optional zip compression!
|
// TODO: optional zip compression!
|
||||||
void FBX::Node::WritePropertyNode(
|
void FBX::Node::WritePropertyNodeBinary(
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::vector<double>& v,
|
const std::vector<double>& v,
|
||||||
Assimp::StreamWriterLE& s
|
Assimp::StreamWriterLE& s
|
||||||
){
|
){
|
||||||
Node node(name);
|
FBX::Node node(name);
|
||||||
node.Begin(s);
|
node.BeginBinary(s);
|
||||||
s.PutU1('d');
|
s.PutU1('d');
|
||||||
s.PutU4(uint32_t(v.size())); // number of elements
|
s.PutU4(uint32_t(v.size())); // number of elements
|
||||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||||
s.PutU4(uint32_t(v.size()) * 8); // data size
|
s.PutU4(uint32_t(v.size()) * 8); // data size
|
||||||
for (auto it = v.begin(); it != v.end(); ++it) { s.PutF8(*it); }
|
for (auto it = v.begin(); it != v.end(); ++it) { s.PutF8(*it); }
|
||||||
node.EndProperties(s, 1);
|
node.EndPropertiesBinary(s, 1);
|
||||||
node.End(s, false);
|
node.EndBinary(s, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// convenience function to create and write a property node,
|
// binary property node from vector of int32_t
|
||||||
// holding a single property which is an array of values.
|
|
||||||
// does not copy the data, so is efficient for large arrays.
|
|
||||||
// TODO: optional zip compression!
|
// TODO: optional zip compression!
|
||||||
void FBX::Node::WritePropertyNode(
|
void FBX::Node::WritePropertyNodeBinary(
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::vector<int32_t>& v,
|
const std::vector<int32_t>& v,
|
||||||
Assimp::StreamWriterLE& s
|
Assimp::StreamWriterLE& s
|
||||||
){
|
){
|
||||||
Node node(name);
|
FBX::Node node(name);
|
||||||
node.Begin(s);
|
node.BeginBinary(s);
|
||||||
s.PutU1('i');
|
s.PutU1('i');
|
||||||
s.PutU4(uint32_t(v.size())); // number of elements
|
s.PutU4(uint32_t(v.size())); // number of elements
|
||||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||||
s.PutU4(uint32_t(v.size()) * 4); // data size
|
s.PutU4(uint32_t(v.size()) * 4); // data size
|
||||||
for (auto it = v.begin(); it != v.end(); ++it) { s.PutI4(*it); }
|
for (auto it = v.begin(); it != v.end(); ++it) { s.PutI4(*it); }
|
||||||
node.EndProperties(s, 1);
|
node.EndPropertiesBinary(s, 1);
|
||||||
node.End(s, false);
|
node.EndBinary(s, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// public static member functions
|
||||||
|
|
||||||
|
// convenience function to create and write a property node,
|
||||||
|
// holding a single property which is an array of values.
|
||||||
|
// does not copy the data, so is efficient for large arrays.
|
||||||
|
void FBX::Node::WritePropertyNode(
|
||||||
|
const std::string& name,
|
||||||
|
const std::vector<double>& v,
|
||||||
|
Assimp::StreamWriterLE& s,
|
||||||
|
bool binary, int indent
|
||||||
|
){
|
||||||
|
if (binary) {
|
||||||
|
FBX::Node::WritePropertyNodeBinary(name, v, s);
|
||||||
|
} else {
|
||||||
|
FBX::Node::WritePropertyNodeAscii(name, v, s, indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convenience function to create and write a property node,
|
||||||
|
// holding a single property which is an array of values.
|
||||||
|
// does not copy the data, so is efficient for large arrays.
|
||||||
|
void FBX::Node::WritePropertyNode(
|
||||||
|
const std::string& name,
|
||||||
|
const std::vector<int32_t>& v,
|
||||||
|
Assimp::StreamWriterLE& s,
|
||||||
|
bool binary, int indent
|
||||||
|
){
|
||||||
|
if (binary) {
|
||||||
|
FBX::Node::WritePropertyNodeBinary(name, v, s);
|
||||||
|
} else {
|
||||||
|
FBX::Node::WritePropertyNodeAscii(name, v, s, indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
#endif // ASSIMP_BUILD_NO_EXPORT
|
#endif // ASSIMP_BUILD_NO_EXPORT
|
||||||
|
|
|
@ -66,14 +66,18 @@ public: // public data members
|
||||||
std::vector<FBX::Property> properties; // node properties
|
std::vector<FBX::Property> properties; // node properties
|
||||||
std::vector<FBX::Node> children; // child nodes
|
std::vector<FBX::Node> children; // child nodes
|
||||||
|
|
||||||
|
// some nodes always pretend they have children...
|
||||||
|
bool force_has_children = false;
|
||||||
|
|
||||||
public: // constructors
|
public: // constructors
|
||||||
Node() = default;
|
Node() = default;
|
||||||
Node(const std::string& n) : name(n) {}
|
Node(const std::string& n) : name(n) {}
|
||||||
Node(const std::string& n, const FBX::Property &p)
|
|
||||||
|
// convenience template to construct with properties directly
|
||||||
|
template <typename... More>
|
||||||
|
Node(const std::string& n, const More... more)
|
||||||
: name(n)
|
: name(n)
|
||||||
{ properties.push_back(p); }
|
{ AddProperties(more...); }
|
||||||
Node(const std::string& n, const std::vector<FBX::Property> &pv)
|
|
||||||
: name(n), properties(pv) {}
|
|
||||||
|
|
||||||
public: // functions to add properties or children
|
public: // functions to add properties or children
|
||||||
// add a single property to the node
|
// add a single property to the node
|
||||||
|
@ -138,19 +142,48 @@ public: // support specifically for dealing with Properties70 nodes
|
||||||
|
|
||||||
public: // member functions for writing data to a file or stream
|
public: // member functions for writing data to a file or stream
|
||||||
|
|
||||||
// write the full node as binary data to the given file or stream
|
// write the full node to the given file or stream
|
||||||
void Dump(std::shared_ptr<Assimp::IOStream> outfile);
|
void Dump(
|
||||||
void Dump(Assimp::StreamWriterLE &s);
|
std::shared_ptr<Assimp::IOStream> outfile,
|
||||||
|
bool binary, int indent
|
||||||
|
);
|
||||||
|
void Dump(Assimp::StreamWriterLE &s, bool binary, int indent);
|
||||||
|
|
||||||
// these other functions are for writing data piece by piece.
|
// these other functions are for writing data piece by piece.
|
||||||
// they must be used carefully.
|
// they must be used carefully.
|
||||||
// for usage examples see FBXExporter.cpp.
|
// for usage examples see FBXExporter.cpp.
|
||||||
void Begin(Assimp::StreamWriterLE &s);
|
void Begin(Assimp::StreamWriterLE &s, bool binary, int indent);
|
||||||
void DumpProperties(Assimp::StreamWriterLE& s);
|
void DumpProperties(Assimp::StreamWriterLE& s, bool binary, int indent);
|
||||||
void EndProperties(Assimp::StreamWriterLE &s);
|
void EndProperties(Assimp::StreamWriterLE &s, bool binary, int indent);
|
||||||
void EndProperties(Assimp::StreamWriterLE &s, size_t num_properties);
|
void EndProperties(
|
||||||
void DumpChildren(Assimp::StreamWriterLE& s);
|
Assimp::StreamWriterLE &s, bool binary, int indent,
|
||||||
void End(Assimp::StreamWriterLE &s, bool has_children);
|
size_t num_properties
|
||||||
|
);
|
||||||
|
void BeginChildren(Assimp::StreamWriterLE &s, bool binary, int indent);
|
||||||
|
void DumpChildren(Assimp::StreamWriterLE& s, bool binary, int indent);
|
||||||
|
void End(
|
||||||
|
Assimp::StreamWriterLE &s, bool binary, int indent,
|
||||||
|
bool has_children
|
||||||
|
);
|
||||||
|
|
||||||
|
private: // internal functions used for writing
|
||||||
|
|
||||||
|
void DumpBinary(Assimp::StreamWriterLE &s);
|
||||||
|
void DumpAscii(Assimp::StreamWriterLE &s, int indent);
|
||||||
|
void DumpAscii(std::ostream &s, int indent);
|
||||||
|
|
||||||
|
void BeginBinary(Assimp::StreamWriterLE &s);
|
||||||
|
void DumpPropertiesBinary(Assimp::StreamWriterLE& s);
|
||||||
|
void EndPropertiesBinary(Assimp::StreamWriterLE &s);
|
||||||
|
void EndPropertiesBinary(Assimp::StreamWriterLE &s, size_t num_properties);
|
||||||
|
void DumpChildrenBinary(Assimp::StreamWriterLE& s);
|
||||||
|
void EndBinary(Assimp::StreamWriterLE &s, bool has_children);
|
||||||
|
|
||||||
|
void BeginAscii(std::ostream &s, int indent);
|
||||||
|
void DumpPropertiesAscii(std::ostream &s, int indent);
|
||||||
|
void BeginChildrenAscii(std::ostream &s, int indent);
|
||||||
|
void DumpChildrenAscii(std::ostream &s, int indent);
|
||||||
|
void EndAscii(std::ostream &s, int indent, bool has_children);
|
||||||
|
|
||||||
private: // data used for binary dumps
|
private: // data used for binary dumps
|
||||||
size_t start_pos; // starting position in stream
|
size_t start_pos; // starting position in stream
|
||||||
|
@ -165,11 +198,12 @@ public: // static member functions
|
||||||
static void WritePropertyNode(
|
static void WritePropertyNode(
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const T value,
|
const T value,
|
||||||
Assimp::StreamWriterLE& s
|
Assimp::StreamWriterLE& s,
|
||||||
|
bool binary, int indent
|
||||||
) {
|
) {
|
||||||
FBX::Property p(value);
|
FBX::Property p(value);
|
||||||
FBX::Node node(name, p);
|
FBX::Node node(name, p);
|
||||||
node.Dump(s);
|
node.Dump(s, binary, indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// convenience function to create and write a property node,
|
// convenience function to create and write a property node,
|
||||||
|
@ -178,7 +212,8 @@ public: // static member functions
|
||||||
static void WritePropertyNode(
|
static void WritePropertyNode(
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::vector<double>& v,
|
const std::vector<double>& v,
|
||||||
Assimp::StreamWriterLE& s
|
Assimp::StreamWriterLE& s,
|
||||||
|
bool binary, int indent
|
||||||
);
|
);
|
||||||
|
|
||||||
// convenience function to create and write a property node,
|
// convenience function to create and write a property node,
|
||||||
|
@ -187,8 +222,34 @@ public: // static member functions
|
||||||
static void WritePropertyNode(
|
static void WritePropertyNode(
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
const std::vector<int32_t>& v,
|
const std::vector<int32_t>& v,
|
||||||
|
Assimp::StreamWriterLE& s,
|
||||||
|
bool binary, int indent
|
||||||
|
);
|
||||||
|
|
||||||
|
private: // static helper functions
|
||||||
|
static void WritePropertyNodeAscii(
|
||||||
|
const std::string& name,
|
||||||
|
const std::vector<double>& v,
|
||||||
|
Assimp::StreamWriterLE& s,
|
||||||
|
int indent
|
||||||
|
);
|
||||||
|
static void WritePropertyNodeAscii(
|
||||||
|
const std::string& name,
|
||||||
|
const std::vector<int32_t>& v,
|
||||||
|
Assimp::StreamWriterLE& s,
|
||||||
|
int indent
|
||||||
|
);
|
||||||
|
static void WritePropertyNodeBinary(
|
||||||
|
const std::string& name,
|
||||||
|
const std::vector<double>& v,
|
||||||
Assimp::StreamWriterLE& s
|
Assimp::StreamWriterLE& s
|
||||||
);
|
);
|
||||||
|
static void WritePropertyNodeBinary(
|
||||||
|
const std::string& name,
|
||||||
|
const std::vector<int32_t>& v,
|
||||||
|
Assimp::StreamWriterLE& s
|
||||||
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sstream> // stringstream
|
#include <ostream>
|
||||||
|
#include <locale>
|
||||||
|
#include <sstream> // ostringstream
|
||||||
|
|
||||||
|
|
||||||
// constructors for single element properties
|
// constructors for single element properties
|
||||||
|
@ -164,18 +166,18 @@ size_t FBX::Property::size()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBX::Property::Dump(Assimp::StreamWriterLE &s)
|
void FBX::Property::DumpBinary(Assimp::StreamWriterLE &s)
|
||||||
{
|
{
|
||||||
s.PutU1(type);
|
s.PutU1(type);
|
||||||
uint8_t* d;
|
uint8_t* d = data.data();
|
||||||
size_t N;
|
size_t N;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'C': s.PutU1(*(reinterpret_cast<uint8_t*>(data.data()))); return;
|
case 'C': s.PutU1(*(reinterpret_cast<uint8_t*>(d))); return;
|
||||||
case 'Y': s.PutI2(*(reinterpret_cast<int16_t*>(data.data()))); return;
|
case 'Y': s.PutI2(*(reinterpret_cast<int16_t*>(d))); return;
|
||||||
case 'I': s.PutI4(*(reinterpret_cast<int32_t*>(data.data()))); return;
|
case 'I': s.PutI4(*(reinterpret_cast<int32_t*>(d))); return;
|
||||||
case 'F': s.PutF4(*(reinterpret_cast<float*>(data.data()))); return;
|
case 'F': s.PutF4(*(reinterpret_cast<float*>(d))); return;
|
||||||
case 'D': s.PutF8(*(reinterpret_cast<double*>(data.data()))); return;
|
case 'D': s.PutF8(*(reinterpret_cast<double*>(d))); return;
|
||||||
case 'L': s.PutI8(*(reinterpret_cast<int64_t*>(data.data()))); return;
|
case 'L': s.PutI8(*(reinterpret_cast<int64_t*>(d))); return;
|
||||||
case 'S':
|
case 'S':
|
||||||
case 'R':
|
case 'R':
|
||||||
s.PutU4(uint32_t(data.size()));
|
s.PutU4(uint32_t(data.size()));
|
||||||
|
@ -187,7 +189,6 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s)
|
||||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||||
// TODO: compress if large?
|
// TODO: compress if large?
|
||||||
s.PutU4(uint32_t(data.size())); // data size
|
s.PutU4(uint32_t(data.size())); // data size
|
||||||
d = data.data();
|
|
||||||
for (size_t i = 0; i < N; ++i) {
|
for (size_t i = 0; i < N; ++i) {
|
||||||
s.PutI4((reinterpret_cast<int32_t*>(d))[i]);
|
s.PutI4((reinterpret_cast<int32_t*>(d))[i]);
|
||||||
}
|
}
|
||||||
|
@ -198,7 +199,6 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s)
|
||||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||||
// TODO: compress if large?
|
// TODO: compress if large?
|
||||||
s.PutU4(uint32_t(data.size())); // data size
|
s.PutU4(uint32_t(data.size())); // data size
|
||||||
d = data.data();
|
|
||||||
for (size_t i = 0; i < N; ++i) {
|
for (size_t i = 0; i < N; ++i) {
|
||||||
s.PutI8((reinterpret_cast<int64_t*>(d))[i]);
|
s.PutI8((reinterpret_cast<int64_t*>(d))[i]);
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,6 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s)
|
||||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||||
// TODO: compress if large?
|
// TODO: compress if large?
|
||||||
s.PutU4(uint32_t(data.size())); // data size
|
s.PutU4(uint32_t(data.size())); // data size
|
||||||
d = data.data();
|
|
||||||
for (size_t i = 0; i < N; ++i) {
|
for (size_t i = 0; i < N; ++i) {
|
||||||
s.PutF4((reinterpret_cast<float*>(d))[i]);
|
s.PutF4((reinterpret_cast<float*>(d))[i]);
|
||||||
}
|
}
|
||||||
|
@ -220,18 +219,146 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s)
|
||||||
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
s.PutU4(0); // no encoding (1 would be zip-compressed)
|
||||||
// TODO: compress if large?
|
// TODO: compress if large?
|
||||||
s.PutU4(uint32_t(data.size())); // data size
|
s.PutU4(uint32_t(data.size())); // data size
|
||||||
d = data.data();
|
|
||||||
for (size_t i = 0; i < N; ++i) {
|
for (size_t i = 0; i < N; ++i) {
|
||||||
s.PutF8((reinterpret_cast<double*>(d))[i]);
|
s.PutF8((reinterpret_cast<double*>(d))[i]);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
std::stringstream err;
|
std::ostringstream err;
|
||||||
err << "Tried to dump property with invalid type '";
|
err << "Tried to dump property with invalid type '";
|
||||||
err << type << "'!";
|
err << type << "'!";
|
||||||
throw DeadlyExportError(err.str());
|
throw DeadlyExportError(err.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FBX::Property::DumpAscii(Assimp::StreamWriterLE &outstream, int indent)
|
||||||
|
{
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss.imbue(std::locale::classic());
|
||||||
|
ss.precision(15); // this seems to match official FBX SDK exports
|
||||||
|
DumpAscii(ss, indent);
|
||||||
|
outstream.PutString(ss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBX::Property::DumpAscii(std::ostream& s, int indent)
|
||||||
|
{
|
||||||
|
// no writing type... or anything. just shove it into the stream.
|
||||||
|
uint8_t* d = data.data();
|
||||||
|
size_t N;
|
||||||
|
size_t swap = data.size();
|
||||||
|
size_t count = 0;
|
||||||
|
switch (type) {
|
||||||
|
case 'C':
|
||||||
|
if (*(reinterpret_cast<uint8_t*>(d))) { s << 'T'; }
|
||||||
|
else { s << 'F'; }
|
||||||
|
return;
|
||||||
|
case 'Y': s << *(reinterpret_cast<int16_t*>(d)); return;
|
||||||
|
case 'I': s << *(reinterpret_cast<int32_t*>(d)); return;
|
||||||
|
case 'F': s << *(reinterpret_cast<float*>(d)); return;
|
||||||
|
case 'D': s << *(reinterpret_cast<double*>(d)); return;
|
||||||
|
case 'L': s << *(reinterpret_cast<int64_t*>(d)); return;
|
||||||
|
case 'S':
|
||||||
|
// first search to see if it has "\x00\x01" in it -
|
||||||
|
// which separates fields which are reversed in the ascii version.
|
||||||
|
// yeah.
|
||||||
|
// FBX, yeah.
|
||||||
|
for (size_t i = 0; i < data.size(); ++i) {
|
||||||
|
if (data[i] == '\0') {
|
||||||
|
swap = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 'R':
|
||||||
|
s << '"';
|
||||||
|
// we might as well check this now,
|
||||||
|
// probably it will never happen
|
||||||
|
for (size_t i = 0; i < data.size(); ++i) {
|
||||||
|
char c = data[i];
|
||||||
|
if (c == '"') {
|
||||||
|
throw runtime_error("can't handle quotes in property string");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// first write the SWAPPED member (if any)
|
||||||
|
for (size_t i = swap + 2; i < data.size(); ++i) {
|
||||||
|
char c = data[i];
|
||||||
|
s << c;
|
||||||
|
}
|
||||||
|
// then a separator
|
||||||
|
if (swap != data.size()) {
|
||||||
|
s << "::";
|
||||||
|
}
|
||||||
|
// then the initial member
|
||||||
|
for (size_t i = 0; i < swap; ++i) {
|
||||||
|
char c = data[i];
|
||||||
|
s << c;
|
||||||
|
}
|
||||||
|
s << '"';
|
||||||
|
return;
|
||||||
|
case 'i':
|
||||||
|
N = data.size() / 4; // number of elements
|
||||||
|
s << '*' << N << " {\n";
|
||||||
|
for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
|
||||||
|
s << "a: ";
|
||||||
|
for (size_t i = 0; i < N; ++i) {
|
||||||
|
if (i > 0) { s << ','; }
|
||||||
|
if (count++ > 120) { s << '\n'; count = 0; }
|
||||||
|
s << (reinterpret_cast<int32_t*>(d))[i];
|
||||||
|
}
|
||||||
|
s << '\n';
|
||||||
|
for (int i = 0; i < indent; ++i) { s << '\t'; }
|
||||||
|
s << "} ";
|
||||||
|
return;
|
||||||
|
case 'l':
|
||||||
|
N = data.size() / 8;
|
||||||
|
s << '*' << N << " {\n";
|
||||||
|
for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
|
||||||
|
s << "a: ";
|
||||||
|
for (size_t i = 0; i < N; ++i) {
|
||||||
|
if (i > 0) { s << ','; }
|
||||||
|
if (count++ > 120) { s << '\n'; count = 0; }
|
||||||
|
s << (reinterpret_cast<int64_t*>(d))[i];
|
||||||
|
}
|
||||||
|
s << '\n';
|
||||||
|
for (int i = 0; i < indent; ++i) { s << '\t'; }
|
||||||
|
s << "} ";
|
||||||
|
return;
|
||||||
|
case 'f':
|
||||||
|
N = data.size() / 4;
|
||||||
|
s << '*' << N << " {\n";
|
||||||
|
for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
|
||||||
|
s << "a: ";
|
||||||
|
for (size_t i = 0; i < N; ++i) {
|
||||||
|
if (i > 0) { s << ','; }
|
||||||
|
if (count++ > 120) { s << '\n'; count = 0; }
|
||||||
|
s << (reinterpret_cast<float*>(d))[i];
|
||||||
|
}
|
||||||
|
s << '\n';
|
||||||
|
for (int i = 0; i < indent; ++i) { s << '\t'; }
|
||||||
|
s << "} ";
|
||||||
|
return;
|
||||||
|
case 'd':
|
||||||
|
N = data.size() / 8;
|
||||||
|
s << '*' << N << " {\n";
|
||||||
|
for (int i = 0; i < indent + 1; ++i) { s << '\t'; }
|
||||||
|
s << "a: ";
|
||||||
|
// set precision to something that can handle doubles
|
||||||
|
s.precision(15);
|
||||||
|
for (size_t i = 0; i < N; ++i) {
|
||||||
|
if (i > 0) { s << ','; }
|
||||||
|
if (count++ > 120) { s << '\n'; count = 0; }
|
||||||
|
s << (reinterpret_cast<double*>(d))[i];
|
||||||
|
}
|
||||||
|
s << '\n';
|
||||||
|
for (int i = 0; i < indent; ++i) { s << '\t'; }
|
||||||
|
s << "} ";
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
std::ostringstream err;
|
||||||
|
err << "Tried to dump property with invalid type '";
|
||||||
|
err << type << "'!";
|
||||||
|
throw runtime_error(err.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
#endif // ASSIMP_BUILD_NO_EXPORT
|
#endif // ASSIMP_BUILD_NO_EXPORT
|
||||||
|
|
|
@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <ostream>
|
||||||
#include <type_traits> // is_void
|
#include <type_traits> // is_void
|
||||||
|
|
||||||
namespace FBX {
|
namespace FBX {
|
||||||
|
@ -113,7 +114,10 @@ public:
|
||||||
size_t size();
|
size_t size();
|
||||||
|
|
||||||
// write this property node as binary data to the given stream
|
// write this property node as binary data to the given stream
|
||||||
void Dump(Assimp::StreamWriterLE &s);
|
void DumpBinary(Assimp::StreamWriterLE &s);
|
||||||
|
void DumpAscii(Assimp::StreamWriterLE &s, int indent=0);
|
||||||
|
void DumpAscii(std::ostream &s, int indent=0);
|
||||||
|
// note: make sure the ostream is in classic "C" locale
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char type;
|
char type;
|
||||||
|
|
|
@ -66,7 +66,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <iostream> // endl
|
|
||||||
|
|
||||||
// RESOURCES:
|
// RESOURCES:
|
||||||
// https://code.blender.org/2013/08/fbx-binary-file-format-specification/
|
// https://code.blender.org/2013/08/fbx-binary-file-format-specification/
|
||||||
|
@ -89,6 +88,8 @@ namespace FBX {
|
||||||
"\xfa\xbc\xab\x09\xd0\xc8\xd4\x66\xb1\x76\xfb\x83\x1c\xf7\x26\x7e";
|
"\xfa\xbc\xab\x09\xd0\xc8\xd4\x66\xb1\x76\xfb\x83\x1c\xf7\x26\x7e";
|
||||||
const std::string FOOT_MAGIC =
|
const std::string FOOT_MAGIC =
|
||||||
"\xf8\x5a\x8c\x6a\xde\xf5\xd9\x7e\xec\xe9\x0c\xe3\x75\x8f\x29\x0b";
|
"\xf8\x5a\x8c\x6a\xde\xf5\xd9\x7e\xec\xe9\x0c\xe3\x75\x8f\x29\x0b";
|
||||||
|
const std::string COMMENT_UNDERLINE =
|
||||||
|
";------------------------------------------------------------------";
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace Assimp;
|
using namespace Assimp;
|
||||||
|
@ -115,7 +116,7 @@ namespace Assimp {
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
// Worker function for exporting a scene to ASCII FBX.
|
// Worker function for exporting a scene to ASCII FBX.
|
||||||
// Prototyped and registered in Exporter.cpp
|
// Prototyped and registered in Exporter.cpp
|
||||||
/*void ExportSceneFBXA (
|
void ExportSceneFBXA (
|
||||||
const char* pFile,
|
const char* pFile,
|
||||||
IOSystem* pIOSystem,
|
IOSystem* pIOSystem,
|
||||||
const aiScene* pScene,
|
const aiScene* pScene,
|
||||||
|
@ -126,7 +127,7 @@ namespace Assimp {
|
||||||
|
|
||||||
// perform ascii export
|
// perform ascii export
|
||||||
exporter.ExportAscii(pFile, pIOSystem);
|
exporter.ExportAscii(pFile, pIOSystem);
|
||||||
}*/ // TODO
|
}
|
||||||
|
|
||||||
} // end of namespace Assimp
|
} // end of namespace Assimp
|
||||||
|
|
||||||
|
@ -194,27 +195,43 @@ void FBXExporter::ExportAscii (
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this isn't really necessary,
|
// write the ascii header
|
||||||
// but the Autodesk FBX SDK puts a similar comment at the top of the file.
|
WriteAsciiHeader();
|
||||||
// Theirs declares that the file copyright is owned by Autodesk...
|
|
||||||
std::stringstream head;
|
|
||||||
using std::endl;
|
|
||||||
head << "; FBX " << EXPORT_VERSION_STR << " project file" << endl;
|
|
||||||
head << "; Created by the Open Asset Import Library (Assimp)" << endl;
|
|
||||||
head << "; http://assimp.org" << endl;
|
|
||||||
head << "; -------------------------------------------------" << endl;
|
|
||||||
head << endl;
|
|
||||||
const std::string ascii_header = head.str();
|
|
||||||
outfile->Write(ascii_header.c_str(), ascii_header.size(), 1);
|
|
||||||
|
|
||||||
// write all the sections
|
// write all the sections
|
||||||
WriteAllNodes();
|
WriteAllNodes();
|
||||||
|
|
||||||
|
// make sure the file ends with a newline.
|
||||||
|
// note: if the file is opened in text mode,
|
||||||
|
// this should do the right cross-platform thing.
|
||||||
|
outfile->Write("\n", 1, 1);
|
||||||
|
|
||||||
// explicitly release file pointer,
|
// explicitly release file pointer,
|
||||||
// so we don't have to rely on class destruction.
|
// so we don't have to rely on class destruction.
|
||||||
outfile.reset();
|
outfile.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FBXExporter::WriteAsciiHeader()
|
||||||
|
{
|
||||||
|
// basically just a comment at the top of the file
|
||||||
|
std::stringstream head;
|
||||||
|
head << "; FBX " << EXPORT_VERSION_STR << " project file\n";
|
||||||
|
head << "; Created by the Open Asset Import Library (Assimp)\n";
|
||||||
|
head << "; http://assimp.org\n";
|
||||||
|
head << "; -------------------------------------------------\n";
|
||||||
|
const std::string ascii_header = head.str();
|
||||||
|
outfile->Write(ascii_header.c_str(), ascii_header.size(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FBXExporter::WriteAsciiSectionHeader(const std::string& title)
|
||||||
|
{
|
||||||
|
StreamWriterLE outstream(outfile);
|
||||||
|
std::stringstream s;
|
||||||
|
s << "\n\n; " << title << '\n';
|
||||||
|
s << FBX::COMMENT_UNDERLINE << "\n";
|
||||||
|
outstream.PutString(s.str());
|
||||||
|
}
|
||||||
|
|
||||||
void FBXExporter::WriteBinaryHeader()
|
void FBXExporter::WriteBinaryHeader()
|
||||||
{
|
{
|
||||||
// first a specific sequence of 23 bytes, always the same
|
// first a specific sequence of 23 bytes, always the same
|
||||||
|
@ -294,28 +311,39 @@ void FBXExporter::WriteAllNodes ()
|
||||||
//FBXHeaderExtension top-level node
|
//FBXHeaderExtension top-level node
|
||||||
void FBXExporter::WriteHeaderExtension ()
|
void FBXExporter::WriteHeaderExtension ()
|
||||||
{
|
{
|
||||||
|
if (!binary) {
|
||||||
|
// no title, follows directly from the top comment
|
||||||
|
}
|
||||||
FBX::Node n("FBXHeaderExtension");
|
FBX::Node n("FBXHeaderExtension");
|
||||||
StreamWriterLE outstream(outfile);
|
StreamWriterLE outstream(outfile);
|
||||||
|
int indent = 0;
|
||||||
|
|
||||||
// begin node
|
// begin node
|
||||||
n.Begin(outstream);
|
n.Begin(outstream, binary, indent);
|
||||||
|
|
||||||
// write properties
|
// write properties
|
||||||
// (none)
|
// (none)
|
||||||
|
|
||||||
// finish properties
|
// finish properties
|
||||||
n.EndProperties(outstream, 0);
|
n.EndProperties(outstream, binary, indent, 0);
|
||||||
|
|
||||||
|
// begin children
|
||||||
|
n.BeginChildren(outstream, binary, indent);
|
||||||
|
|
||||||
|
indent = 1;
|
||||||
|
|
||||||
// write child nodes
|
// write child nodes
|
||||||
FBX::Node::WritePropertyNode(
|
FBX::Node::WritePropertyNode(
|
||||||
"FBXHeaderVersion", int32_t(1003), outstream
|
"FBXHeaderVersion", int32_t(1003), outstream, binary, indent
|
||||||
);
|
);
|
||||||
FBX::Node::WritePropertyNode(
|
FBX::Node::WritePropertyNode(
|
||||||
"FBXVersion", int32_t(EXPORT_VERSION_INT), outstream
|
"FBXVersion", int32_t(EXPORT_VERSION_INT), outstream, binary, indent
|
||||||
);
|
|
||||||
FBX::Node::WritePropertyNode(
|
|
||||||
"EncryptionType", int32_t(0), outstream
|
|
||||||
);
|
);
|
||||||
|
if (binary) {
|
||||||
|
FBX::Node::WritePropertyNode(
|
||||||
|
"EncryptionType", int32_t(0), outstream, binary, indent
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
FBX::Node CreationTimeStamp("CreationTimeStamp");
|
FBX::Node CreationTimeStamp("CreationTimeStamp");
|
||||||
time_t rawtime;
|
time_t rawtime;
|
||||||
|
@ -329,36 +357,50 @@ void FBXExporter::WriteHeaderExtension ()
|
||||||
CreationTimeStamp.AddChild("Minute", int32_t(now->tm_min));
|
CreationTimeStamp.AddChild("Minute", int32_t(now->tm_min));
|
||||||
CreationTimeStamp.AddChild("Second", int32_t(now->tm_sec));
|
CreationTimeStamp.AddChild("Second", int32_t(now->tm_sec));
|
||||||
CreationTimeStamp.AddChild("Millisecond", int32_t(0));
|
CreationTimeStamp.AddChild("Millisecond", int32_t(0));
|
||||||
CreationTimeStamp.Dump(outstream);
|
CreationTimeStamp.Dump(outstream, binary, indent);
|
||||||
|
|
||||||
std::stringstream creator;
|
std::stringstream creator;
|
||||||
creator << "Open Asset Import Library (Assimp) " << aiGetVersionMajor()
|
creator << "Open Asset Import Library (Assimp) " << aiGetVersionMajor()
|
||||||
<< "." << aiGetVersionMinor() << "." << aiGetVersionRevision();
|
<< "." << aiGetVersionMinor() << "." << aiGetVersionRevision();
|
||||||
FBX::Node::WritePropertyNode("Creator", creator.str(), outstream);
|
FBX::Node::WritePropertyNode(
|
||||||
|
"Creator", creator.str(), outstream, binary, indent
|
||||||
|
);
|
||||||
|
|
||||||
FBX::Node sceneinfo("SceneInfo");
|
//FBX::Node sceneinfo("SceneInfo");
|
||||||
//sceneinfo.AddProperty("GlobalInfo" + FBX::SEPARATOR + "SceneInfo");
|
//sceneinfo.AddProperty("GlobalInfo" + FBX::SEPARATOR + "SceneInfo");
|
||||||
// not sure if any of this is actually needed,
|
// not sure if any of this is actually needed,
|
||||||
// so just write an empty node for now.
|
// so just write an empty node for now.
|
||||||
sceneinfo.Dump(outstream);
|
//sceneinfo.Dump(outstream, binary, indent);
|
||||||
|
|
||||||
|
indent = 0;
|
||||||
|
|
||||||
// finish node
|
// finish node
|
||||||
n.End(outstream, true);
|
n.End(outstream, binary, indent, true);
|
||||||
|
|
||||||
// that's it for FBXHeaderExtension...
|
// that's it for FBXHeaderExtension...
|
||||||
|
if (!binary) { return; }
|
||||||
|
|
||||||
// but binary files also need top-level FileID, CreationTime, Creator:
|
// but binary files also need top-level FileID, CreationTime, Creator:
|
||||||
std::vector<uint8_t> raw(GENERIC_FILEID.size());
|
std::vector<uint8_t> raw(GENERIC_FILEID.size());
|
||||||
for (size_t i = 0; i < GENERIC_FILEID.size(); ++i) {
|
for (size_t i = 0; i < GENERIC_FILEID.size(); ++i) {
|
||||||
raw[i] = uint8_t(GENERIC_FILEID[i]);
|
raw[i] = uint8_t(GENERIC_FILEID[i]);
|
||||||
}
|
}
|
||||||
FBX::Node::WritePropertyNode("FileId", raw, outstream);
|
FBX::Node::WritePropertyNode(
|
||||||
FBX::Node::WritePropertyNode("CreationTime", GENERIC_CTIME, outstream);
|
"FileId", raw, outstream, binary, indent
|
||||||
FBX::Node::WritePropertyNode("Creator", creator.str(), outstream);
|
);
|
||||||
|
FBX::Node::WritePropertyNode(
|
||||||
|
"CreationTime", GENERIC_CTIME, outstream, binary, indent
|
||||||
|
);
|
||||||
|
FBX::Node::WritePropertyNode(
|
||||||
|
"Creator", creator.str(), outstream, binary, indent
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBXExporter::WriteGlobalSettings ()
|
void FBXExporter::WriteGlobalSettings ()
|
||||||
{
|
{
|
||||||
|
if (!binary) {
|
||||||
|
// no title, follows directly from the header extension
|
||||||
|
}
|
||||||
FBX::Node gs("GlobalSettings");
|
FBX::Node gs("GlobalSettings");
|
||||||
gs.AddChild("Version", int32_t(1000));
|
gs.AddChild("Version", int32_t(1000));
|
||||||
|
|
||||||
|
@ -385,11 +427,15 @@ void FBXExporter::WriteGlobalSettings ()
|
||||||
p.AddP70int("CurrentTimeMarker", -1);
|
p.AddP70int("CurrentTimeMarker", -1);
|
||||||
gs.AddChild(p);
|
gs.AddChild(p);
|
||||||
|
|
||||||
gs.Dump(outfile);
|
gs.Dump(outfile, binary, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBXExporter::WriteDocuments ()
|
void FBXExporter::WriteDocuments ()
|
||||||
{
|
{
|
||||||
|
if (!binary) {
|
||||||
|
WriteAsciiSectionHeader("Documents Description");
|
||||||
|
}
|
||||||
|
|
||||||
// not sure what the use of multiple documents would be,
|
// not sure what the use of multiple documents would be,
|
||||||
// or whether any end-application supports it
|
// or whether any end-application supports it
|
||||||
FBX::Node docs("Documents");
|
FBX::Node docs("Documents");
|
||||||
|
@ -411,15 +457,19 @@ void FBXExporter::WriteDocuments ()
|
||||||
doc.AddChild("RootNode", int64_t(0));
|
doc.AddChild("RootNode", int64_t(0));
|
||||||
|
|
||||||
docs.AddChild(doc);
|
docs.AddChild(doc);
|
||||||
docs.Dump(outfile);
|
docs.Dump(outfile, binary, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBXExporter::WriteReferences ()
|
void FBXExporter::WriteReferences ()
|
||||||
{
|
{
|
||||||
|
if (!binary) {
|
||||||
|
WriteAsciiSectionHeader("Document References");
|
||||||
|
}
|
||||||
// always empty for now.
|
// always empty for now.
|
||||||
// not really sure what this is for.
|
// not really sure what this is for.
|
||||||
FBX::Node n("References");
|
FBX::Node n("References");
|
||||||
n.Dump(outfile);
|
n.force_has_children = true;
|
||||||
|
n.Dump(outfile, binary, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -468,9 +518,6 @@ size_t count_images(const aiScene* scene) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//for (auto &s : images) {
|
|
||||||
// std::cout << "found image: " << s << std::endl;
|
|
||||||
//}
|
|
||||||
return images.size();
|
return images.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,6 +557,11 @@ void FBXExporter::WriteDefinitions ()
|
||||||
// determining how many of each type of object there are
|
// determining how many of each type of object there are
|
||||||
// and specifying the base properties to use when otherwise unspecified.
|
// and specifying the base properties to use when otherwise unspecified.
|
||||||
|
|
||||||
|
// ascii section header
|
||||||
|
if (!binary) {
|
||||||
|
WriteAsciiSectionHeader("Object definitions");
|
||||||
|
}
|
||||||
|
|
||||||
// we need to count the objects
|
// we need to count the objects
|
||||||
int32_t count;
|
int32_t count;
|
||||||
int32_t total_count = 0;
|
int32_t total_count = 0;
|
||||||
|
@ -520,7 +572,7 @@ void FBXExporter::WriteDefinitions ()
|
||||||
|
|
||||||
// GlobalSettings
|
// GlobalSettings
|
||||||
// this seems to always be here in Maya exports
|
// this seems to always be here in Maya exports
|
||||||
n = FBX::Node("ObjectType", Property("GlobalSettings"));
|
n = FBX::Node("ObjectType", "GlobalSettings");
|
||||||
count = 1;
|
count = 1;
|
||||||
n.AddChild("Count", count);
|
n.AddChild("Count", count);
|
||||||
object_nodes.push_back(n);
|
object_nodes.push_back(n);
|
||||||
|
@ -531,9 +583,9 @@ void FBXExporter::WriteDefinitions ()
|
||||||
// but no harm seems to come of leaving it out.
|
// but no harm seems to come of leaving it out.
|
||||||
count = mScene->mNumAnimations;
|
count = mScene->mNumAnimations;
|
||||||
if (count) {
|
if (count) {
|
||||||
n = FBX::Node("ObjectType", Property("AnimationStack"));
|
n = FBX::Node("ObjectType", "AnimationStack");
|
||||||
n.AddChild("Count", count);
|
n.AddChild("Count", count);
|
||||||
pt = FBX::Node("PropertyTemplate", Property("FbxAnimStack"));
|
pt = FBX::Node("PropertyTemplate", "FbxAnimStack");
|
||||||
p = FBX::Node("Properties70");
|
p = FBX::Node("Properties70");
|
||||||
p.AddP70string("Description", "");
|
p.AddP70string("Description", "");
|
||||||
p.AddP70time("LocalStart", 0);
|
p.AddP70time("LocalStart", 0);
|
||||||
|
@ -553,9 +605,9 @@ void FBXExporter::WriteDefinitions ()
|
||||||
// so there will be one per aiAnimation
|
// so there will be one per aiAnimation
|
||||||
count = mScene->mNumAnimations;
|
count = mScene->mNumAnimations;
|
||||||
if (count) {
|
if (count) {
|
||||||
n = FBX::Node("ObjectType", Property("AnimationLayer"));
|
n = FBX::Node("ObjectType", "AnimationLayer");
|
||||||
n.AddChild("Count", count);
|
n.AddChild("Count", count);
|
||||||
pt = FBX::Node("PropertyTemplate", Property("FBXAnimLayer"));
|
pt = FBX::Node("PropertyTemplate", "FBXAnimLayer");
|
||||||
p = FBX::Node("Properties70");
|
p = FBX::Node("Properties70");
|
||||||
p.AddP70("Weight", "Number", "", "A", double(100));
|
p.AddP70("Weight", "Number", "", "A", double(100));
|
||||||
p.AddP70bool("Mute", 0);
|
p.AddP70bool("Mute", 0);
|
||||||
|
@ -583,9 +635,9 @@ void FBXExporter::WriteDefinitions ()
|
||||||
count = 1; // TODO: select properly
|
count = 1; // TODO: select properly
|
||||||
if (count) {
|
if (count) {
|
||||||
// FbxSkeleton
|
// FbxSkeleton
|
||||||
n = FBX::Node("ObjectType", Property("NodeAttribute"));
|
n = FBX::Node("ObjectType", "NodeAttribute");
|
||||||
n.AddChild("Count", count);
|
n.AddChild("Count", count);
|
||||||
pt = FBX::Node("PropertyTemplate", Property("FbxSkeleton"));
|
pt = FBX::Node("PropertyTemplate", "FbxSkeleton");
|
||||||
p = FBX::Node("Properties70");
|
p = FBX::Node("Properties70");
|
||||||
p.AddP70color("Color", 0.8, 0.8, 0.8);
|
p.AddP70color("Color", 0.8, 0.8, 0.8);
|
||||||
p.AddP70double("Size", 33.333333333333);
|
p.AddP70double("Size", 33.333333333333);
|
||||||
|
@ -601,9 +653,9 @@ void FBXExporter::WriteDefinitions ()
|
||||||
// <~~ node heirarchy
|
// <~~ node heirarchy
|
||||||
count = int32_t(count_nodes(mScene->mRootNode)) - 1; // (not counting root node)
|
count = int32_t(count_nodes(mScene->mRootNode)) - 1; // (not counting root node)
|
||||||
if (count) {
|
if (count) {
|
||||||
n = FBX::Node("ObjectType", Property("Model"));
|
n = FBX::Node("ObjectType", "Model");
|
||||||
n.AddChild("Count", count);
|
n.AddChild("Count", count);
|
||||||
pt = FBX::Node("PropertyTemplate", Property("FbxNode"));
|
pt = FBX::Node("PropertyTemplate", "FbxNode");
|
||||||
p = FBX::Node("Properties70");
|
p = FBX::Node("Properties70");
|
||||||
p.AddP70enum("QuaternionInterpolate", 0);
|
p.AddP70enum("QuaternionInterpolate", 0);
|
||||||
p.AddP70vector("RotationOffset", 0.0, 0.0, 0.0);
|
p.AddP70vector("RotationOffset", 0.0, 0.0, 0.0);
|
||||||
|
@ -698,9 +750,9 @@ void FBXExporter::WriteDefinitions ()
|
||||||
// <~~ aiMesh
|
// <~~ aiMesh
|
||||||
count = mScene->mNumMeshes;
|
count = mScene->mNumMeshes;
|
||||||
if (count) {
|
if (count) {
|
||||||
n = FBX::Node("ObjectType", Property("Geometry"));
|
n = FBX::Node("ObjectType", "Geometry");
|
||||||
n.AddChild("Count", count);
|
n.AddChild("Count", count);
|
||||||
pt = FBX::Node("PropertyTemplate", Property("FbxMesh"));
|
pt = FBX::Node("PropertyTemplate", "FbxMesh");
|
||||||
p = FBX::Node("Properties70");
|
p = FBX::Node("Properties70");
|
||||||
p.AddP70color("Color", 0, 0, 0);
|
p.AddP70color("Color", 0, 0, 0);
|
||||||
p.AddP70vector("BBoxMin", 0, 0, 0);
|
p.AddP70vector("BBoxMin", 0, 0, 0);
|
||||||
|
@ -724,7 +776,7 @@ void FBXExporter::WriteDefinitions ()
|
||||||
count = mScene->mNumMaterials;
|
count = mScene->mNumMaterials;
|
||||||
if (count) {
|
if (count) {
|
||||||
bool has_phong = has_phong_mat(mScene);
|
bool has_phong = has_phong_mat(mScene);
|
||||||
n = FBX::Node("ObjectType", Property("Material"));
|
n = FBX::Node("ObjectType", "Material");
|
||||||
n.AddChild("Count", count);
|
n.AddChild("Count", count);
|
||||||
pt = FBX::Node("PropertyTemplate");
|
pt = FBX::Node("PropertyTemplate");
|
||||||
if (has_phong) {
|
if (has_phong) {
|
||||||
|
@ -771,9 +823,9 @@ void FBXExporter::WriteDefinitions ()
|
||||||
// one for each image file.
|
// one for each image file.
|
||||||
count = int32_t(count_images(mScene));
|
count = int32_t(count_images(mScene));
|
||||||
if (count) {
|
if (count) {
|
||||||
n = FBX::Node("ObjectType", Property("Video"));
|
n = FBX::Node("ObjectType", "Video");
|
||||||
n.AddChild("Count", count);
|
n.AddChild("Count", count);
|
||||||
pt = FBX::Node("PropertyTemplate", Property("FbxVideo"));
|
pt = FBX::Node("PropertyTemplate", "FbxVideo");
|
||||||
p = FBX::Node("Properties70");
|
p = FBX::Node("Properties70");
|
||||||
p.AddP70bool("ImageSequence", 0);
|
p.AddP70bool("ImageSequence", 0);
|
||||||
p.AddP70int("ImageSequenceOffset", 0);
|
p.AddP70int("ImageSequenceOffset", 0);
|
||||||
|
@ -800,9 +852,9 @@ void FBXExporter::WriteDefinitions ()
|
||||||
// <~~ aiTexture
|
// <~~ aiTexture
|
||||||
count = int32_t(count_textures(mScene));
|
count = int32_t(count_textures(mScene));
|
||||||
if (count) {
|
if (count) {
|
||||||
n = FBX::Node("ObjectType", Property("Texture"));
|
n = FBX::Node("ObjectType", "Texture");
|
||||||
n.AddChild("Count", count);
|
n.AddChild("Count", count);
|
||||||
pt = FBX::Node("PropertyTemplate", Property("FbxFileTexture"));
|
pt = FBX::Node("PropertyTemplate", "FbxFileTexture");
|
||||||
p = FBX::Node("Properties70");
|
p = FBX::Node("Properties70");
|
||||||
p.AddP70enum("TextureTypeUse", 0);
|
p.AddP70enum("TextureTypeUse", 0);
|
||||||
p.AddP70numberA("Texture alpha", 1.0);
|
p.AddP70numberA("Texture alpha", 1.0);
|
||||||
|
@ -829,9 +881,9 @@ void FBXExporter::WriteDefinitions ()
|
||||||
// AnimationCurveNode / FbxAnimCurveNode
|
// AnimationCurveNode / FbxAnimCurveNode
|
||||||
count = mScene->mNumAnimations * 3;
|
count = mScene->mNumAnimations * 3;
|
||||||
if (count) {
|
if (count) {
|
||||||
n = FBX::Node("ObjectType", Property("AnimationCurveNode"));
|
n = FBX::Node("ObjectType", "AnimationCurveNode");
|
||||||
n.AddChild("Count", count);
|
n.AddChild("Count", count);
|
||||||
pt = FBX::Node("PropertyTemplate", Property("FbxAnimCurveNode"));
|
pt = FBX::Node("PropertyTemplate", "FbxAnimCurveNode");
|
||||||
p = FBX::Node("Properties70");
|
p = FBX::Node("Properties70");
|
||||||
p.AddP70("d", "Compound", "", "");
|
p.AddP70("d", "Compound", "", "");
|
||||||
pt.AddChild(p);
|
pt.AddChild(p);
|
||||||
|
@ -843,7 +895,7 @@ void FBXExporter::WriteDefinitions ()
|
||||||
// AnimationCurve / FbxAnimCurve
|
// AnimationCurve / FbxAnimCurve
|
||||||
count = mScene->mNumAnimations * 9;
|
count = mScene->mNumAnimations * 9;
|
||||||
if (count) {
|
if (count) {
|
||||||
n = FBX::Node("ObjectType", Property("AnimationCurve"));
|
n = FBX::Node("ObjectType", "AnimationCurve");
|
||||||
n.AddChild("Count", count);
|
n.AddChild("Count", count);
|
||||||
object_nodes.push_back(n);
|
object_nodes.push_back(n);
|
||||||
total_count += count;
|
total_count += count;
|
||||||
|
@ -856,7 +908,7 @@ void FBXExporter::WriteDefinitions ()
|
||||||
if (mesh->HasBones()) { ++count; }
|
if (mesh->HasBones()) { ++count; }
|
||||||
}
|
}
|
||||||
if (count) {
|
if (count) {
|
||||||
n = FBX::Node("ObjectType", Property("Pose"));
|
n = FBX::Node("ObjectType", "Pose");
|
||||||
n.AddChild("Count", count);
|
n.AddChild("Count", count);
|
||||||
object_nodes.push_back(n);
|
object_nodes.push_back(n);
|
||||||
total_count += count;
|
total_count += count;
|
||||||
|
@ -865,7 +917,7 @@ void FBXExporter::WriteDefinitions ()
|
||||||
// Deformer
|
// Deformer
|
||||||
count = int32_t(count_deformers(mScene));
|
count = int32_t(count_deformers(mScene));
|
||||||
if (count) {
|
if (count) {
|
||||||
n = FBX::Node("ObjectType", Property("Deformer"));
|
n = FBX::Node("ObjectType", "Deformer");
|
||||||
n.AddChild("Count", count);
|
n.AddChild("Count", count);
|
||||||
object_nodes.push_back(n);
|
object_nodes.push_back(n);
|
||||||
total_count += count;
|
total_count += count;
|
||||||
|
@ -874,9 +926,9 @@ void FBXExporter::WriteDefinitions ()
|
||||||
// (template)
|
// (template)
|
||||||
count = 0;
|
count = 0;
|
||||||
if (count) {
|
if (count) {
|
||||||
n = FBX::Node("ObjectType", Property(""));
|
n = FBX::Node("ObjectType", "");
|
||||||
n.AddChild("Count", count);
|
n.AddChild("Count", count);
|
||||||
pt = FBX::Node("PropertyTemplate", Property(""));
|
pt = FBX::Node("PropertyTemplate", "");
|
||||||
p = FBX::Node("Properties70");
|
p = FBX::Node("Properties70");
|
||||||
pt.AddChild(p);
|
pt.AddChild(p);
|
||||||
n.AddChild(pt);
|
n.AddChild(pt);
|
||||||
|
@ -889,7 +941,7 @@ void FBXExporter::WriteDefinitions ()
|
||||||
defs.AddChild("Version", int32_t(100));
|
defs.AddChild("Version", int32_t(100));
|
||||||
defs.AddChild("Count", int32_t(total_count));
|
defs.AddChild("Count", int32_t(total_count));
|
||||||
for (auto &n : object_nodes) { defs.AddChild(n); }
|
for (auto &n : object_nodes) { defs.AddChild(n); }
|
||||||
defs.Dump(outfile);
|
defs.Dump(outfile, binary, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -935,14 +987,20 @@ int64_t to_ktime(double ticks, const aiAnimation* anim) {
|
||||||
|
|
||||||
void FBXExporter::WriteObjects ()
|
void FBXExporter::WriteObjects ()
|
||||||
{
|
{
|
||||||
|
if (!binary) {
|
||||||
|
WriteAsciiSectionHeader("Object properties");
|
||||||
|
}
|
||||||
// numbers should match those given in definitions! make sure to check
|
// numbers should match those given in definitions! make sure to check
|
||||||
StreamWriterLE outstream(outfile);
|
StreamWriterLE outstream(outfile);
|
||||||
FBX::Node object_node("Objects");
|
FBX::Node object_node("Objects");
|
||||||
object_node.Begin(outstream);
|
int indent = 0;
|
||||||
object_node.EndProperties(outstream);
|
object_node.Begin(outstream, binary, indent);
|
||||||
|
object_node.EndProperties(outstream, binary, indent);
|
||||||
|
object_node.BeginChildren(outstream, binary, indent);
|
||||||
|
|
||||||
// geometry (aiMesh)
|
// geometry (aiMesh)
|
||||||
mesh_uids.clear();
|
mesh_uids.clear();
|
||||||
|
indent = 1;
|
||||||
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
|
for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
|
||||||
// it's all about this mesh
|
// it's all about this mesh
|
||||||
aiMesh* m = mScene->mMeshes[mi];
|
aiMesh* m = mScene->mMeshes[mi];
|
||||||
|
@ -954,9 +1012,11 @@ void FBXExporter::WriteObjects ()
|
||||||
n.AddProperty(uid);
|
n.AddProperty(uid);
|
||||||
n.AddProperty(FBX::SEPARATOR + "Geometry");
|
n.AddProperty(FBX::SEPARATOR + "Geometry");
|
||||||
n.AddProperty("Mesh");
|
n.AddProperty("Mesh");
|
||||||
n.Begin(outstream);
|
n.Begin(outstream, binary, indent);
|
||||||
n.DumpProperties(outstream);
|
n.DumpProperties(outstream, binary, indent);
|
||||||
n.EndProperties(outstream);
|
n.EndProperties(outstream, binary, indent);
|
||||||
|
n.BeginChildren(outstream, binary, indent);
|
||||||
|
indent = 2;
|
||||||
|
|
||||||
// output vertex data - each vertex should be unique (probably)
|
// output vertex data - each vertex should be unique (probably)
|
||||||
std::vector<double> flattened_vertices;
|
std::vector<double> flattened_vertices;
|
||||||
|
@ -980,7 +1040,7 @@ void FBXExporter::WriteObjects ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FBX::Node::WritePropertyNode(
|
FBX::Node::WritePropertyNode(
|
||||||
"Vertices", flattened_vertices, outstream
|
"Vertices", flattened_vertices, outstream, binary, indent
|
||||||
);
|
);
|
||||||
|
|
||||||
// output polygon data as a flattened array of vertex indices.
|
// output polygon data as a flattened array of vertex indices.
|
||||||
|
@ -996,30 +1056,38 @@ void FBXExporter::WriteObjects ()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
FBX::Node::WritePropertyNode(
|
FBX::Node::WritePropertyNode(
|
||||||
"PolygonVertexIndex", polygon_data, outstream
|
"PolygonVertexIndex", polygon_data, outstream, binary, indent
|
||||||
);
|
);
|
||||||
|
|
||||||
// here could be edges but they're insane.
|
// here could be edges but they're insane.
|
||||||
// it's optional anyway, so let's ignore it.
|
// it's optional anyway, so let's ignore it.
|
||||||
|
|
||||||
FBX::Node::WritePropertyNode(
|
FBX::Node::WritePropertyNode(
|
||||||
"GeometryVersion", int32_t(124), outstream
|
"GeometryVersion", int32_t(124), outstream, binary, indent
|
||||||
);
|
);
|
||||||
|
|
||||||
// normals, if any
|
// normals, if any
|
||||||
if (m->HasNormals()) {
|
if (m->HasNormals()) {
|
||||||
FBX::Node normals("LayerElementNormal", Property(int32_t(0)));
|
FBX::Node normals("LayerElementNormal", int32_t(0));
|
||||||
normals.Begin(outstream);
|
normals.Begin(outstream, binary, indent);
|
||||||
normals.DumpProperties(outstream);
|
normals.DumpProperties(outstream, binary, indent);
|
||||||
normals.EndProperties(outstream);
|
normals.EndProperties(outstream, binary, indent);
|
||||||
FBX::Node::WritePropertyNode("Version", int32_t(101), outstream);
|
normals.BeginChildren(outstream, binary, indent);
|
||||||
FBX::Node::WritePropertyNode("Name", "", outstream);
|
indent = 3;
|
||||||
FBX::Node::WritePropertyNode(
|
FBX::Node::WritePropertyNode(
|
||||||
"MappingInformationType", "ByPolygonVertex", outstream
|
"Version", int32_t(101), outstream, binary, indent
|
||||||
|
);
|
||||||
|
FBX::Node::WritePropertyNode(
|
||||||
|
"Name", "", outstream, binary, indent
|
||||||
|
);
|
||||||
|
FBX::Node::WritePropertyNode(
|
||||||
|
"MappingInformationType", "ByPolygonVertex",
|
||||||
|
outstream, binary, indent
|
||||||
);
|
);
|
||||||
// TODO: vertex-normals or indexed normals when appropriate
|
// TODO: vertex-normals or indexed normals when appropriate
|
||||||
FBX::Node::WritePropertyNode(
|
FBX::Node::WritePropertyNode(
|
||||||
"ReferenceInformationType", "Direct", outstream
|
"ReferenceInformationType", "Direct",
|
||||||
|
outstream, binary, indent
|
||||||
);
|
);
|
||||||
std::vector<double> normal_data;
|
std::vector<double> normal_data;
|
||||||
normal_data.reserve(3 * polygon_data.size());
|
normal_data.reserve(3 * polygon_data.size());
|
||||||
|
@ -1032,10 +1100,13 @@ void FBXExporter::WriteObjects ()
|
||||||
normal_data.push_back(n.z);
|
normal_data.push_back(n.z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FBX::Node::WritePropertyNode("Normals", normal_data, outstream);
|
FBX::Node::WritePropertyNode(
|
||||||
|
"Normals", normal_data, outstream, binary, indent
|
||||||
|
);
|
||||||
// note: version 102 has a NormalsW also... not sure what it is,
|
// note: version 102 has a NormalsW also... not sure what it is,
|
||||||
// so we can stick with version 101 for now.
|
// so we can stick with version 101 for now.
|
||||||
normals.End(outstream, true);
|
indent = 2;
|
||||||
|
normals.End(outstream, binary, indent, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// uvs, if any
|
// uvs, if any
|
||||||
|
@ -1055,19 +1126,27 @@ void FBXExporter::WriteObjects ()
|
||||||
err << " but may be incorrectly interpreted on load.";
|
err << " but may be incorrectly interpreted on load.";
|
||||||
DefaultLogger::get()->warn(err.str());
|
DefaultLogger::get()->warn(err.str());
|
||||||
}
|
}
|
||||||
FBX::Node uv("LayerElementUV", Property(int32_t(uvi)));
|
FBX::Node uv("LayerElementUV", int32_t(uvi));
|
||||||
uv.Begin(outstream);
|
uv.Begin(outstream, binary, indent);
|
||||||
uv.DumpProperties(outstream);
|
uv.DumpProperties(outstream, binary, indent);
|
||||||
uv.EndProperties(outstream);
|
uv.EndProperties(outstream, binary, indent);
|
||||||
FBX::Node::WritePropertyNode("Version", int32_t(101), outstream);
|
uv.BeginChildren(outstream, binary, indent);
|
||||||
|
indent = 3;
|
||||||
|
FBX::Node::WritePropertyNode(
|
||||||
|
"Version", int32_t(101), outstream, binary, indent
|
||||||
|
);
|
||||||
// it doesn't seem like assimp keeps the uv map name,
|
// it doesn't seem like assimp keeps the uv map name,
|
||||||
// so just leave it blank.
|
// so just leave it blank.
|
||||||
FBX::Node::WritePropertyNode("Name", "", outstream);
|
|
||||||
FBX::Node::WritePropertyNode(
|
FBX::Node::WritePropertyNode(
|
||||||
"MappingInformationType", "ByPolygonVertex", outstream
|
"Name", "", outstream, binary, indent
|
||||||
);
|
);
|
||||||
FBX::Node::WritePropertyNode(
|
FBX::Node::WritePropertyNode(
|
||||||
"ReferenceInformationType", "IndexToDirect", outstream
|
"MappingInformationType", "ByPolygonVertex",
|
||||||
|
outstream, binary, indent
|
||||||
|
);
|
||||||
|
FBX::Node::WritePropertyNode(
|
||||||
|
"ReferenceInformationType", "IndexToDirect",
|
||||||
|
outstream, binary, indent
|
||||||
);
|
);
|
||||||
|
|
||||||
std::vector<double> uv_data;
|
std::vector<double> uv_data;
|
||||||
|
@ -1092,27 +1171,32 @@ void FBXExporter::WriteObjects ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FBX::Node::WritePropertyNode("UV", uv_data, outstream);
|
FBX::Node::WritePropertyNode(
|
||||||
FBX::Node::WritePropertyNode("UVIndex", uv_indices, outstream);
|
"UV", uv_data, outstream, binary, indent
|
||||||
uv.End(outstream, true);
|
);
|
||||||
|
FBX::Node::WritePropertyNode(
|
||||||
|
"UVIndex", uv_indices, outstream, binary, indent
|
||||||
|
);
|
||||||
|
indent = 2;
|
||||||
|
uv.End(outstream, binary, indent, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// i'm not really sure why this material section exists,
|
// i'm not really sure why this material section exists,
|
||||||
// as the material is linked via "Connections".
|
// as the material is linked via "Connections".
|
||||||
// it seems to always have the same "0" value.
|
// it seems to always have the same "0" value.
|
||||||
FBX::Node mat("LayerElementMaterial", Property(int32_t(0)));
|
FBX::Node mat("LayerElementMaterial", int32_t(0));
|
||||||
mat.AddChild("Version", int32_t(101));
|
mat.AddChild("Version", int32_t(101));
|
||||||
mat.AddChild("Name", "");
|
mat.AddChild("Name", "");
|
||||||
mat.AddChild("MappingInformationType", "AllSame");
|
mat.AddChild("MappingInformationType", "AllSame");
|
||||||
mat.AddChild("ReferenceInformationType", "IndexToDirect");
|
mat.AddChild("ReferenceInformationType", "IndexToDirect");
|
||||||
std::vector<int32_t> mat_indices = {0};
|
std::vector<int32_t> mat_indices = {0};
|
||||||
mat.AddChild("Materials", mat_indices);
|
mat.AddChild("Materials", mat_indices);
|
||||||
mat.Dump(outstream);
|
mat.Dump(outstream, binary, indent);
|
||||||
|
|
||||||
// finally we have the layer specifications,
|
// finally we have the layer specifications,
|
||||||
// which select the normals / UV set / etc to use.
|
// which select the normals / UV set / etc to use.
|
||||||
// TODO: handle multiple uv sets correctly?
|
// TODO: handle multiple uv sets correctly?
|
||||||
FBX::Node layer("Layer", Property(int32_t(0)));
|
FBX::Node layer("Layer", int32_t(0));
|
||||||
layer.AddChild("Version", int32_t(100));
|
layer.AddChild("Version", int32_t(100));
|
||||||
FBX::Node le("LayerElement");
|
FBX::Node le("LayerElement");
|
||||||
le.AddChild("Type", "LayerElementNormal");
|
le.AddChild("Type", "LayerElementNormal");
|
||||||
|
@ -1126,10 +1210,11 @@ void FBXExporter::WriteObjects ()
|
||||||
le.AddChild("Type", "LayerElementUV");
|
le.AddChild("Type", "LayerElementUV");
|
||||||
le.AddChild("TypedIndex", int32_t(0));
|
le.AddChild("TypedIndex", int32_t(0));
|
||||||
layer.AddChild(le);
|
layer.AddChild(le);
|
||||||
layer.Dump(outstream);
|
layer.Dump(outstream, binary, indent);
|
||||||
|
|
||||||
// finish the node record
|
// finish the node record
|
||||||
n.End(outstream, true);
|
indent = 1;
|
||||||
|
n.End(outstream, binary, indent, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// aiMaterial
|
// aiMaterial
|
||||||
|
@ -1273,7 +1358,7 @@ void FBXExporter::WriteObjects ()
|
||||||
|
|
||||||
n.AddChild(p);
|
n.AddChild(p);
|
||||||
|
|
||||||
n.Dump(outstream);
|
n.Dump(outstream, binary, indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we need to look up all the images we're using,
|
// we need to look up all the images we're using,
|
||||||
|
@ -1321,7 +1406,7 @@ void FBXExporter::WriteObjects ()
|
||||||
n.AddChild("UseMipMap", int32_t(0));
|
n.AddChild("UseMipMap", int32_t(0));
|
||||||
n.AddChild("Filename", path);
|
n.AddChild("Filename", path);
|
||||||
n.AddChild("RelativeFilename", path);
|
n.AddChild("RelativeFilename", path);
|
||||||
n.Dump(outstream);
|
n.Dump(outstream, binary, indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Textures
|
// Textures
|
||||||
|
@ -1408,14 +1493,12 @@ void FBXExporter::WriteObjects ()
|
||||||
const int64_t texture_uid = generate_uid();
|
const int64_t texture_uid = generate_uid();
|
||||||
|
|
||||||
// link the texture to the material
|
// link the texture to the material
|
||||||
FBX::Node c("C");
|
connections.emplace_back(
|
||||||
c.AddProperties("OP", texture_uid, material_uid, prop_name);
|
"C", "OP", texture_uid, material_uid, prop_name
|
||||||
connections.push_back(c);
|
);
|
||||||
|
|
||||||
// link the image data to the texture
|
// link the image data to the texture
|
||||||
c = FBX::Node("C");
|
connections.emplace_back("C", "OO", image_uid, texture_uid);
|
||||||
c.AddProperties("OO", image_uid, texture_uid);
|
|
||||||
connections.push_back(c);
|
|
||||||
|
|
||||||
// now write the actual texture node
|
// now write the actual texture node
|
||||||
FBX::Node tnode("Texture");
|
FBX::Node tnode("Texture");
|
||||||
|
@ -1438,11 +1521,11 @@ void FBXExporter::WriteObjects ()
|
||||||
tnode.AddChild("RelativeFilename", texture_path);
|
tnode.AddChild("RelativeFilename", texture_path);
|
||||||
tnode.AddChild("ModelUVTranslation", double(0.0), double(0.0));
|
tnode.AddChild("ModelUVTranslation", double(0.0), double(0.0));
|
||||||
tnode.AddChild("ModelUVScaling", double(1.0), double(1.0));
|
tnode.AddChild("ModelUVScaling", double(1.0), double(1.0));
|
||||||
tnode.AddChild("Texture_Alpha_Soutce", "None");
|
tnode.AddChild("Texture_Alpha_Source", "None");
|
||||||
tnode.AddChild(
|
tnode.AddChild(
|
||||||
"Cropping", int32_t(0), int32_t(0), int32_t(0), int32_t(0)
|
"Cropping", int32_t(0), int32_t(0), int32_t(0), int32_t(0)
|
||||||
);
|
);
|
||||||
tnode.Dump(outstream);
|
tnode.Dump(outstream, binary, indent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1595,12 +1678,10 @@ void FBXExporter::WriteObjects ()
|
||||||
// "acuracy"... this is not a typo....
|
// "acuracy"... this is not a typo....
|
||||||
dnode.AddChild("Link_DeformAcuracy", double(50));
|
dnode.AddChild("Link_DeformAcuracy", double(50));
|
||||||
dnode.AddChild("SkinningType", "Linear"); // TODO: other modes?
|
dnode.AddChild("SkinningType", "Linear"); // TODO: other modes?
|
||||||
dnode.Dump(outstream);
|
dnode.Dump(outstream, binary, indent);
|
||||||
|
|
||||||
// connect it
|
// connect it
|
||||||
FBX::Node c("C");
|
connections.emplace_back("C", "OO", deformer_uid, mesh_uids[mi]);
|
||||||
c.AddProperties("OO", deformer_uid, mesh_uids[mi]);
|
|
||||||
connections.push_back(c); // TODO: emplace_back
|
|
||||||
|
|
||||||
// we will be indexing by vertex...
|
// we will be indexing by vertex...
|
||||||
// but there might be a different number of "vertices"
|
// but there might be a different number of "vertices"
|
||||||
|
@ -1703,7 +1784,7 @@ void FBXExporter::WriteObjects ()
|
||||||
|
|
||||||
// this should be the same as the bone's mOffsetMatrix.
|
// this should be the same as the bone's mOffsetMatrix.
|
||||||
// if it's not the same, the skeleton isn't in the bind pose.
|
// if it's not the same, the skeleton isn't in the bind pose.
|
||||||
const float epsilon = 1e-5f; // some error is to be expected
|
const float epsilon = 1e-4f; // some error is to be expected
|
||||||
bool bone_xform_okay = true;
|
bool bone_xform_okay = true;
|
||||||
if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) {
|
if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) {
|
||||||
not_in_bind_pose.insert(b);
|
not_in_bind_pose.insert(b);
|
||||||
|
@ -1741,17 +1822,17 @@ void FBXExporter::WriteObjects ()
|
||||||
// there's not really any way around this at the moment.
|
// there's not really any way around this at the moment.
|
||||||
|
|
||||||
// done
|
// done
|
||||||
sdnode.Dump(outstream);
|
sdnode.Dump(outstream, binary, indent);
|
||||||
|
|
||||||
// lastly, connect to the parent deformer
|
// lastly, connect to the parent deformer
|
||||||
c = FBX::Node("C");
|
connections.emplace_back(
|
||||||
c.AddProperties("OO", subdeformer_uid, deformer_uid);
|
"C", "OO", subdeformer_uid, deformer_uid
|
||||||
connections.push_back(c); // TODO: emplace_back
|
);
|
||||||
|
|
||||||
// we also need to connect the limb node to the subdeformer.
|
// we also need to connect the limb node to the subdeformer.
|
||||||
c = FBX::Node("C");
|
connections.emplace_back(
|
||||||
c.AddProperties("OO", node_uids[bone_node], subdeformer_uid);
|
"C", "OO", node_uids[bone_node], subdeformer_uid
|
||||||
connections.push_back(c); // TODO: emplace_back
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we cannot create a valid FBX file, simply die.
|
// if we cannot create a valid FBX file, simply die.
|
||||||
|
@ -1859,7 +1940,7 @@ void FBXExporter::WriteObjects ()
|
||||||
}
|
}
|
||||||
|
|
||||||
// now write it
|
// now write it
|
||||||
bpnode.Dump(outstream);
|
bpnode.Dump(outstream, binary, indent);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
// TODO: cameras, lights
|
// TODO: cameras, lights
|
||||||
|
@ -1918,11 +1999,8 @@ void FBXExporter::WriteObjects ()
|
||||||
|
|
||||||
// this node absurdly always pretends it has children
|
// this node absurdly always pretends it has children
|
||||||
// (in this case it does, but just in case...)
|
// (in this case it does, but just in case...)
|
||||||
asnode.Begin(outstream);
|
asnode.force_has_children = true;
|
||||||
asnode.DumpProperties(outstream);
|
asnode.Dump(outstream, binary, indent);
|
||||||
asnode.EndProperties(outstream);
|
|
||||||
asnode.DumpChildren(outstream);
|
|
||||||
asnode.End(outstream, true);
|
|
||||||
|
|
||||||
// note: animation stacks are not connected to anything
|
// note: animation stacks are not connected to anything
|
||||||
}
|
}
|
||||||
|
@ -1936,16 +2014,13 @@ void FBXExporter::WriteObjects ()
|
||||||
alnode.AddProperties(animlayer_uid, FBX::SEPARATOR + "AnimLayer", "");
|
alnode.AddProperties(animlayer_uid, FBX::SEPARATOR + "AnimLayer", "");
|
||||||
|
|
||||||
// this node absurdly always pretends it has children
|
// this node absurdly always pretends it has children
|
||||||
alnode.Begin(outstream);
|
alnode.force_has_children = true;
|
||||||
alnode.DumpProperties(outstream);
|
alnode.Dump(outstream, binary, indent);
|
||||||
alnode.EndProperties(outstream);
|
|
||||||
alnode.DumpChildren(outstream);
|
|
||||||
alnode.End(outstream, true);
|
|
||||||
|
|
||||||
// connect to the relevant animstack
|
// connect to the relevant animstack
|
||||||
FBX::Node c("C");
|
connections.emplace_back(
|
||||||
c.AddProperties("OO", animlayer_uid, animation_stack_uids[ai]);
|
"C", "OO", animlayer_uid, animation_stack_uids[ai]
|
||||||
connections.push_back(c); // TODO: emplace_back
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// AnimCurveNode - three per aiNodeAnim
|
// AnimCurveNode - three per aiNodeAnim
|
||||||
|
@ -2057,7 +2132,8 @@ void FBXExporter::WriteObjects ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object_node.End(outstream, true);
|
indent = 0;
|
||||||
|
object_node.End(outstream, binary, indent, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// convenience map of magic node name strings to FBX properties,
|
// convenience map of magic node name strings to FBX properties,
|
||||||
|
@ -2083,13 +2159,14 @@ const std::map<std::string,std::pair<std::string,char>> transform_types = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// write a single model node to the stream
|
// write a single model node to the stream
|
||||||
void WriteModelNode(
|
void FBXExporter::WriteModelNode(
|
||||||
StreamWriterLE& outstream,
|
StreamWriterLE& outstream,
|
||||||
|
bool binary,
|
||||||
const aiNode* node,
|
const aiNode* node,
|
||||||
int64_t node_uid,
|
int64_t node_uid,
|
||||||
const std::string& type,
|
const std::string& type,
|
||||||
const std::vector<std::pair<std::string,aiVector3D>>& transform_chain,
|
const std::vector<std::pair<std::string,aiVector3D>>& transform_chain,
|
||||||
TransformInheritance inherit_type=TransformInheritance_RSrs
|
TransformInheritance inherit_type
|
||||||
){
|
){
|
||||||
const aiVector3D zero = {0, 0, 0};
|
const aiVector3D zero = {0, 0, 0};
|
||||||
const aiVector3D one = {1, 1, 1};
|
const aiVector3D one = {1, 1, 1};
|
||||||
|
@ -2157,7 +2234,7 @@ void WriteModelNode(
|
||||||
m.AddChild("Shading", Property(true));
|
m.AddChild("Shading", Property(true));
|
||||||
m.AddChild("Culling", Property("CullingOff"));
|
m.AddChild("Culling", Property("CullingOff"));
|
||||||
|
|
||||||
m.Dump(outstream);
|
m.Dump(outstream, binary, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// wrapper for WriteModelNodes to create and pass a blank transform chain
|
// wrapper for WriteModelNodes to create and pass a blank transform chain
|
||||||
|
@ -2181,15 +2258,6 @@ void FBXExporter::WriteModelNodes(
|
||||||
// first collapse any expanded transformation chains created by FBX import.
|
// first collapse any expanded transformation chains created by FBX import.
|
||||||
std::string node_name(node->mName.C_Str());
|
std::string node_name(node->mName.C_Str());
|
||||||
if (node_name.find(MAGIC_NODE_TAG) != std::string::npos) {
|
if (node_name.find(MAGIC_NODE_TAG) != std::string::npos) {
|
||||||
if (node->mNumChildren != 1) {
|
|
||||||
// this should never happen
|
|
||||||
std::stringstream err;
|
|
||||||
err << "FBX transformation node should have exactly 1 child,";
|
|
||||||
err << " but " << node->mNumChildren << " found";
|
|
||||||
err << " on node \"" << node_name << "\"!";
|
|
||||||
throw DeadlyExportError(err.str());
|
|
||||||
}
|
|
||||||
aiNode* next_node = node->mChildren[0];
|
|
||||||
auto pos = node_name.find(MAGIC_NODE_TAG) + MAGIC_NODE_TAG.size() + 1;
|
auto pos = node_name.find(MAGIC_NODE_TAG) + MAGIC_NODE_TAG.size() + 1;
|
||||||
std::string type_name = node_name.substr(pos);
|
std::string type_name = node_name.substr(pos);
|
||||||
auto elem = transform_types.find(type_name);
|
auto elem = transform_types.find(type_name);
|
||||||
|
@ -2223,10 +2291,16 @@ void FBXExporter::WriteModelNodes(
|
||||||
err << elem->second.second;
|
err << elem->second.second;
|
||||||
throw DeadlyExportError(err.str());
|
throw DeadlyExportError(err.str());
|
||||||
}
|
}
|
||||||
// now just continue to the next node
|
// now continue on to any child nodes
|
||||||
WriteModelNodes(
|
for (unsigned i = 0; i < node->mNumChildren; ++i) {
|
||||||
outstream, next_node, parent_uid, limbnodes, transform_chain
|
WriteModelNodes(
|
||||||
);
|
outstream,
|
||||||
|
node->mChildren[i],
|
||||||
|
parent_uid,
|
||||||
|
limbnodes,
|
||||||
|
transform_chain
|
||||||
|
);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2240,9 +2314,7 @@ void FBXExporter::WriteModelNodes(
|
||||||
node_uid = generate_uid();
|
node_uid = generate_uid();
|
||||||
node_uids[node] = node_uid;
|
node_uids[node] = node_uid;
|
||||||
}
|
}
|
||||||
FBX::Node c("C");
|
connections.emplace_back("C", "OO", node_uid, parent_uid);
|
||||||
c.AddProperties("OO", node_uid, parent_uid);
|
|
||||||
connections.push_back(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// what type of node is this?
|
// what type of node is this?
|
||||||
|
@ -2250,21 +2322,23 @@ void FBXExporter::WriteModelNodes(
|
||||||
// handled later
|
// handled later
|
||||||
} else if (node->mNumMeshes == 1) {
|
} else if (node->mNumMeshes == 1) {
|
||||||
// connect to child mesh, which should have been written previously
|
// connect to child mesh, which should have been written previously
|
||||||
FBX::Node c("C");
|
connections.emplace_back(
|
||||||
c.AddProperties("OO", mesh_uids[node->mMeshes[0]], node_uid);
|
"C", "OO", mesh_uids[node->mMeshes[0]], node_uid
|
||||||
connections.push_back(c);
|
);
|
||||||
// also connect to the material for the child mesh
|
// also connect to the material for the child mesh
|
||||||
c = FBX::Node("C");
|
connections.emplace_back(
|
||||||
c.AddProperties(
|
"C", "OO",
|
||||||
"OO",
|
|
||||||
material_uids[mScene->mMeshes[node->mMeshes[0]]->mMaterialIndex],
|
material_uids[mScene->mMeshes[node->mMeshes[0]]->mMaterialIndex],
|
||||||
node_uid
|
node_uid
|
||||||
);
|
);
|
||||||
connections.push_back(c);
|
|
||||||
// write model node
|
// write model node
|
||||||
WriteModelNode(outstream, node, node_uid, "Mesh", transform_chain);
|
WriteModelNode(
|
||||||
|
outstream, binary, node, node_uid, "Mesh", transform_chain
|
||||||
|
);
|
||||||
} else if (limbnodes.count(node)) {
|
} else if (limbnodes.count(node)) {
|
||||||
WriteModelNode(outstream, node, node_uid, "LimbNode", transform_chain);
|
WriteModelNode(
|
||||||
|
outstream, binary, node, node_uid, "LimbNode", transform_chain
|
||||||
|
);
|
||||||
// we also need to write a nodeattribute to mark it as a skeleton
|
// we also need to write a nodeattribute to mark it as a skeleton
|
||||||
int64_t node_attribute_uid = generate_uid();
|
int64_t node_attribute_uid = generate_uid();
|
||||||
FBX::Node na("NodeAttribute");
|
FBX::Node na("NodeAttribute");
|
||||||
|
@ -2272,14 +2346,14 @@ void FBXExporter::WriteModelNodes(
|
||||||
node_attribute_uid, FBX::SEPARATOR + "NodeAttribute", "LimbNode"
|
node_attribute_uid, FBX::SEPARATOR + "NodeAttribute", "LimbNode"
|
||||||
);
|
);
|
||||||
na.AddChild("TypeFlags", Property("Skeleton"));
|
na.AddChild("TypeFlags", Property("Skeleton"));
|
||||||
na.Dump(outstream);
|
na.Dump(outstream, binary, 1);
|
||||||
// and connect them
|
// and connect them
|
||||||
FBX::Node c("C");
|
connections.emplace_back("C", "OO", node_attribute_uid, node_uid);
|
||||||
c.AddProperties("OO", node_attribute_uid, node_uid);
|
|
||||||
connections.push_back(c);
|
|
||||||
} else {
|
} else {
|
||||||
// generate a null node so we can add children to it
|
// generate a null node so we can add children to it
|
||||||
WriteModelNode(outstream, node, node_uid, "Null", transform_chain);
|
WriteModelNode(
|
||||||
|
outstream, binary, node, node_uid, "Null", transform_chain
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if more than one child mesh, make nodes for each mesh
|
// if more than one child mesh, make nodes for each mesh
|
||||||
|
@ -2288,23 +2362,19 @@ void FBXExporter::WriteModelNodes(
|
||||||
// make a new model node
|
// make a new model node
|
||||||
int64_t new_node_uid = generate_uid();
|
int64_t new_node_uid = generate_uid();
|
||||||
// connect to parent node
|
// connect to parent node
|
||||||
FBX::Node c("C");
|
connections.emplace_back("C", "OO", new_node_uid, node_uid);
|
||||||
c.AddProperties("OO", new_node_uid, node_uid);
|
|
||||||
connections.push_back(c);
|
|
||||||
// connect to child mesh, which should have been written previously
|
// connect to child mesh, which should have been written previously
|
||||||
c = FBX::Node("C");
|
connections.emplace_back(
|
||||||
c.AddProperties("OO", mesh_uids[node->mMeshes[i]], new_node_uid);
|
"C", "OO", mesh_uids[node->mMeshes[i]], new_node_uid
|
||||||
connections.push_back(c);
|
);
|
||||||
// also connect to the material for the child mesh
|
// also connect to the material for the child mesh
|
||||||
c = FBX::Node("C");
|
connections.emplace_back(
|
||||||
c.AddProperties(
|
"C", "OO",
|
||||||
"OO",
|
|
||||||
material_uids[
|
material_uids[
|
||||||
mScene->mMeshes[node->mMeshes[i]]->mMaterialIndex
|
mScene->mMeshes[node->mMeshes[i]]->mMaterialIndex
|
||||||
],
|
],
|
||||||
new_node_uid
|
new_node_uid
|
||||||
);
|
);
|
||||||
connections.push_back(c);
|
|
||||||
// write model node
|
// write model node
|
||||||
FBX::Node m("Model");
|
FBX::Node m("Model");
|
||||||
// take name from mesh name, if it exists
|
// take name from mesh name, if it exists
|
||||||
|
@ -2315,7 +2385,7 @@ void FBXExporter::WriteModelNodes(
|
||||||
FBX::Node p("Properties70");
|
FBX::Node p("Properties70");
|
||||||
p.AddP70enum("InheritType", 1);
|
p.AddP70enum("InheritType", 1);
|
||||||
m.AddChild(p);
|
m.AddChild(p);
|
||||||
m.Dump(outstream);
|
m.Dump(outstream, binary, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2344,15 +2414,11 @@ void FBXExporter::WriteAnimationCurveNode(
|
||||||
p.AddP70numberA("d|Y", default_value.y);
|
p.AddP70numberA("d|Y", default_value.y);
|
||||||
p.AddP70numberA("d|Z", default_value.z);
|
p.AddP70numberA("d|Z", default_value.z);
|
||||||
n.AddChild(p);
|
n.AddChild(p);
|
||||||
n.Dump(outstream);
|
n.Dump(outstream, binary, 1);
|
||||||
// connect to layer
|
// connect to layer
|
||||||
FBX::Node cl("C");
|
this->connections.emplace_back("C", "OO", uid, layer_uid);
|
||||||
cl.AddProperties("OO", uid, layer_uid);
|
|
||||||
this->connections.push_back(cl); // TODO: emplace_back
|
|
||||||
// connect to bone
|
// connect to bone
|
||||||
FBX::Node cb("C");
|
this->connections.emplace_back("C", "OP", uid, node_uid, property_name);
|
||||||
cb.AddProperties("OP", uid, node_uid, property_name);
|
|
||||||
this->connections.push_back(cb); // TODO: emplace_back
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2379,10 +2445,10 @@ void FBXExporter::WriteAnimationCurve(
|
||||||
"KeyAttrRefCount",
|
"KeyAttrRefCount",
|
||||||
std::vector<int32_t>{static_cast<int32_t>(times.size())}
|
std::vector<int32_t>{static_cast<int32_t>(times.size())}
|
||||||
);
|
);
|
||||||
n.Dump(outstream);
|
n.Dump(outstream, binary, 1);
|
||||||
FBX::Node c("C");
|
this->connections.emplace_back(
|
||||||
c.AddProperties("OP", curve_uid, curvenode_uid, property_link);
|
"C", "OP", curve_uid, curvenode_uid, property_link
|
||||||
this->connections.push_back(c); // TODO: emplace_back
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2390,13 +2456,18 @@ void FBXExporter::WriteConnections ()
|
||||||
{
|
{
|
||||||
// we should have completed the connection graph already,
|
// we should have completed the connection graph already,
|
||||||
// so basically just dump it here
|
// so basically just dump it here
|
||||||
|
if (!binary) {
|
||||||
|
WriteAsciiSectionHeader("Object connections");
|
||||||
|
}
|
||||||
|
// TODO: comments with names in the ascii version
|
||||||
FBX::Node conn("Connections");
|
FBX::Node conn("Connections");
|
||||||
StreamWriterLE outstream(outfile);
|
StreamWriterLE outstream(outfile);
|
||||||
conn.Begin(outstream);
|
conn.Begin(outstream, binary, 0);
|
||||||
|
conn.BeginChildren(outstream, binary, 0);
|
||||||
for (auto &n : connections) {
|
for (auto &n : connections) {
|
||||||
n.Dump(outstream);
|
n.Dump(outstream, binary, 1);
|
||||||
}
|
}
|
||||||
conn.End(outstream, !connections.empty());
|
conn.End(outstream, binary, 0, !connections.empty());
|
||||||
connections.clear();
|
connections.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
|
||||||
|
|
||||||
#include "FBXExportNode.h" // FBX::Node
|
#include "FBXExportNode.h" // FBX::Node
|
||||||
|
#include "FBXCommon.h" // FBX::TransformInheritance
|
||||||
|
|
||||||
#include <assimp/types.h>
|
#include <assimp/types.h>
|
||||||
//#include <assimp/material.h>
|
//#include <assimp/material.h>
|
||||||
|
@ -104,6 +105,9 @@ namespace Assimp
|
||||||
void WriteBinaryHeader();
|
void WriteBinaryHeader();
|
||||||
void WriteBinaryFooter();
|
void WriteBinaryFooter();
|
||||||
|
|
||||||
|
// ascii files have a comment at the top
|
||||||
|
void WriteAsciiHeader();
|
||||||
|
|
||||||
// WriteAllNodes does the actual export.
|
// WriteAllNodes does the actual export.
|
||||||
// It just calls all the Write<Section> methods below in order.
|
// It just calls all the Write<Section> methods below in order.
|
||||||
void WriteAllNodes();
|
void WriteAllNodes();
|
||||||
|
@ -126,6 +130,7 @@ namespace Assimp
|
||||||
// WriteTakes(); // deprecated since at least 2015 (fbx 7.4)
|
// WriteTakes(); // deprecated since at least 2015 (fbx 7.4)
|
||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
|
void WriteAsciiSectionHeader(const std::string& title);
|
||||||
void WriteModelNodes(
|
void WriteModelNodes(
|
||||||
Assimp::StreamWriterLE& s,
|
Assimp::StreamWriterLE& s,
|
||||||
const aiNode* node,
|
const aiNode* node,
|
||||||
|
@ -139,6 +144,15 @@ namespace Assimp
|
||||||
const std::unordered_set<const aiNode*>& limbnodes,
|
const std::unordered_set<const aiNode*>& limbnodes,
|
||||||
std::vector<std::pair<std::string,aiVector3D>>& transform_chain
|
std::vector<std::pair<std::string,aiVector3D>>& transform_chain
|
||||||
);
|
);
|
||||||
|
void WriteModelNode( // nor this
|
||||||
|
StreamWriterLE& s,
|
||||||
|
bool binary,
|
||||||
|
const aiNode* node,
|
||||||
|
int64_t node_uid,
|
||||||
|
const std::string& type,
|
||||||
|
const std::vector<std::pair<std::string,aiVector3D>>& xfm_chain,
|
||||||
|
FBX::TransformInheritance ti_type=FBX::TransformInheritance_RSrs
|
||||||
|
);
|
||||||
void WriteAnimationCurveNode(
|
void WriteAnimationCurveNode(
|
||||||
StreamWriterLE& outstream,
|
StreamWriterLE& outstream,
|
||||||
int64_t uid,
|
int64_t uid,
|
||||||
|
|
|
@ -42,22 +42,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
/** @file Stuff to deal with aiScene::mPrivate
|
/** @file Stuff to deal with aiScene::mPrivate
|
||||||
*/
|
*/
|
||||||
|
#pragma once
|
||||||
#ifndef AI_SCENEPRIVATE_H_INCLUDED
|
#ifndef AI_SCENEPRIVATE_H_INCLUDED
|
||||||
#define AI_SCENEPRIVATE_H_INCLUDED
|
#define AI_SCENEPRIVATE_H_INCLUDED
|
||||||
|
|
||||||
|
#include <assimp/ai_assert.h>
|
||||||
#include <assimp/scene.h>
|
#include <assimp/scene.h>
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
class Importer;
|
class Importer;
|
||||||
|
|
||||||
struct ScenePrivateData {
|
struct ScenePrivateData {
|
||||||
|
|
||||||
ScenePrivateData()
|
ScenePrivateData()
|
||||||
: mOrigImporter()
|
: mOrigImporter( nullptr )
|
||||||
, mPPStepsApplied()
|
, mPPStepsApplied( 0 )
|
||||||
, mIsCopy()
|
, mIsCopy( false ) {
|
||||||
{}
|
// empty
|
||||||
|
}
|
||||||
|
|
||||||
// Importer that originally loaded the scene though the C-API
|
// Importer that originally loaded the scene though the C-API
|
||||||
// If set, this object is owned by this private data instance.
|
// If set, this object is owned by this private data instance.
|
||||||
|
@ -75,14 +78,24 @@ struct ScenePrivateData {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Access private data stored in the scene
|
// Access private data stored in the scene
|
||||||
inline ScenePrivateData* ScenePriv(aiScene* in) {
|
inline
|
||||||
|
ScenePrivateData* ScenePriv(aiScene* in) {
|
||||||
|
ai_assert( nullptr != in );
|
||||||
|
if ( nullptr == in ) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
return static_cast<ScenePrivateData*>(in->mPrivate);
|
return static_cast<ScenePrivateData*>(in->mPrivate);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const ScenePrivateData* ScenePriv(const aiScene* in) {
|
inline
|
||||||
|
const ScenePrivateData* ScenePriv(const aiScene* in) {
|
||||||
|
ai_assert( nullptr != in );
|
||||||
|
if ( nullptr == in ) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
return static_cast<const ScenePrivateData*>(in->mPrivate);
|
return static_cast<const ScenePrivateData*>(in->mPrivate);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // Namespace Assimp
|
||||||
|
|
||||||
#endif
|
#endif // AI_SCENEPRIVATE_H_INCLUDED
|
||||||
|
|
|
@ -316,11 +316,9 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref<Texture>& texture, aiTe
|
||||||
std::string path = tex.C_Str();
|
std::string path = tex.C_Str();
|
||||||
|
|
||||||
if (path.size() > 0) {
|
if (path.size() > 0) {
|
||||||
if (path[0] != '*') {
|
std::map<std::string, unsigned int>::iterator it = mTexturesByPath.find(path);
|
||||||
std::map<std::string, unsigned int>::iterator it = mTexturesByPath.find(path);
|
if (it != mTexturesByPath.end()) {
|
||||||
if (it != mTexturesByPath.end()) {
|
texture = mAsset->textures.Get(it->second);
|
||||||
texture = mAsset->textures.Get(it->second);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!texture) {
|
if (!texture) {
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2018, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the following
|
||||||
|
conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
#include "simd.h"
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
|
||||||
|
bool CPUSupportsSSE2() {
|
||||||
|
#if defined(__x86_64__) || defined(_M_X64)
|
||||||
|
//* x86_64 always has SSE2 instructions */
|
||||||
|
return true;
|
||||||
|
#elif defined(__GNUC__) && defined(i386)
|
||||||
|
// for GCC x86 we check cpuid
|
||||||
|
unsigned int d;
|
||||||
|
__asm__(
|
||||||
|
"pushl %%ebx\n\t"
|
||||||
|
"cpuid\n\t"
|
||||||
|
"popl %%ebx\n\t"
|
||||||
|
: "=d" ( d )
|
||||||
|
:"a" ( 1 ) );
|
||||||
|
return ( d & 0x04000000 ) != 0;
|
||||||
|
#elif (defined(_MSC_VER) && defined(_M_IX86))
|
||||||
|
// also check cpuid for MSVC x86
|
||||||
|
unsigned int d;
|
||||||
|
__asm {
|
||||||
|
xor eax, eax
|
||||||
|
inc eax
|
||||||
|
push ebx
|
||||||
|
cpuid
|
||||||
|
pop ebx
|
||||||
|
mov d, edx
|
||||||
|
}
|
||||||
|
return ( d & 0x04000000 ) != 0;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Namespace Assimp
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2018, assimp team
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the following
|
||||||
|
conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <assimp/defs.h>
|
||||||
|
|
||||||
|
namespace Assimp {
|
||||||
|
|
||||||
|
/// @brief Checks if the platform supports SSE2 optimization
|
||||||
|
/// @return true, if SSE2 is supported. false if SSE2 is not supported.
|
||||||
|
bool ASSIMP_API CPUSupportsSSE2();
|
||||||
|
|
||||||
|
} // Namespace Assimp
|
|
@ -283,7 +283,6 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
/** Generic read method. ByteSwap::Swap(T*) *must* be defined */
|
/** Generic read method. ByteSwap::Swap(T*) *must* be defined */
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -300,6 +299,7 @@ private:
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
void InternBegin() {
|
void InternBegin() {
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
|
|
|
@ -203,6 +203,12 @@ public:
|
||||||
Put(n);
|
Put(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
/** Write a single character to the stream */
|
||||||
|
void PutChar(char c) {
|
||||||
|
Put(c);
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
/** Write an aiString to the stream */
|
/** Write an aiString to the stream */
|
||||||
void PutString(const aiString& s)
|
void PutString(const aiString& s)
|
||||||
|
@ -249,8 +255,6 @@ public:
|
||||||
cursor = new_cursor;
|
cursor = new_cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
/** Generic write method. ByteSwap::Swap(T*) *must* be defined */
|
/** Generic write method. ByteSwap::Swap(T*) *must* be defined */
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -53,6 +53,7 @@ endif()
|
||||||
LINK_DIRECTORIES( ${Assimp_BINARY_DIR} ${AssetImporter_BINARY_DIR}/lib )
|
LINK_DIRECTORIES( ${Assimp_BINARY_DIR} ${AssetImporter_BINARY_DIR}/lib )
|
||||||
|
|
||||||
SET( COMMON
|
SET( COMMON
|
||||||
|
unit/utSimd.cpp
|
||||||
unit/utIOSystem.cpp
|
unit/utIOSystem.cpp
|
||||||
unit/utIOStreamBuffer.cpp
|
unit/utIOStreamBuffer.cpp
|
||||||
unit/utIssues.cpp
|
unit/utIssues.cpp
|
||||||
|
|
|
@ -45,5 +45,5 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
using namespace ::Assimp;
|
using namespace ::Assimp;
|
||||||
|
|
||||||
AbstractImportExportBase::~AbstractImportExportBase() {
|
AbstractImportExportBase::~AbstractImportExportBase() {
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2018, assimp team
|
Copyright (c) 2006-2018, 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,
|
||||||
|
@ -106,4 +104,4 @@ TEST_F( utAnim, aiAnimationTest ) {
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
EXPECT_TRUE( ok );
|
EXPECT_TRUE( ok );
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Open Asset Import Library (assimp)
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (c) 2006-2018, assimp team
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
with or without modification, are permitted provided that the following
|
||||||
|
conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the
|
||||||
|
following disclaimer in the documentation and/or other
|
||||||
|
materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the assimp team, nor the names of its
|
||||||
|
contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior
|
||||||
|
written permission of the assimp team.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "UnitTestPCH.h"
|
||||||
|
|
||||||
|
#include "simd.h"
|
||||||
|
|
||||||
|
using namespace ::Assimp;
|
||||||
|
|
||||||
|
class utSimd : public ::testing::Test {
|
||||||
|
protected:
|
||||||
|
// empty
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F( utSimd, SSE2SupportedTest ) {
|
||||||
|
bool isSupported;
|
||||||
|
|
||||||
|
isSupported = CPUSupportsSSE2();
|
||||||
|
if ( isSupported ) {
|
||||||
|
std::cout << "Supported" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "Not supported" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
|
@ -46,12 +46,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "Main.h"
|
#include "Main.h"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
const char* AICMD_MSG_INFO_HELP_E =
|
const char* AICMD_MSG_INFO_HELP_E =
|
||||||
"assimp info <file> [-r] [-v]\n"
|
"assimp info <file> [-r] [-v]\n"
|
||||||
"\tPrint basic structure of a 3D model\n"
|
"\tPrint basic structure of a 3D model\n"
|
||||||
"\t-r,--raw: No postprocessing, do a raw import\n"
|
"\t-r,--raw: No postprocessing, do a raw import\n"
|
||||||
"\t-v,--verbose: Print verbose info such as node transform data\n";
|
"\t-v,--verbose: Print verbose info such as node transform data\n";
|
||||||
|
|
||||||
|
const std::string TREE_BRANCH_ASCII = "|-";
|
||||||
|
const std::string TREE_BRANCH_UTF8 = "\xe2\x94\x9c\xe2\x95\xb4";
|
||||||
|
const std::string TREE_STOP_ASCII = "'-";
|
||||||
|
const std::string TREE_STOP_UTF8 = "\xe2\x94\x94\xe2\x95\xb4";
|
||||||
|
const std::string TREE_CONTINUE_ASCII = "| ";
|
||||||
|
const std::string TREE_CONTINUE_UTF8 = "\xe2\x94\x82 ";
|
||||||
|
|
||||||
|
// note: by default this is outputing utf-8 text.
|
||||||
|
// this is well supported on pretty much any linux terminal.
|
||||||
|
// if this causes problems on some platform,
|
||||||
|
// put an #ifdef to use the ascii version for that platform.
|
||||||
|
const std::string TREE_BRANCH = TREE_BRANCH_UTF8;
|
||||||
|
const std::string TREE_STOP = TREE_STOP_UTF8;
|
||||||
|
const std::string TREE_CONTINUE = TREE_CONTINUE_UTF8;
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------
|
||||||
unsigned int CountNodes(const aiNode* root)
|
unsigned int CountNodes(const aiNode* root)
|
||||||
|
@ -184,46 +203,77 @@ std::string FindPTypes(const aiScene* scene)
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------
|
||||||
void PrintHierarchy(const aiNode* root, unsigned int maxnest, unsigned int maxline,
|
// Prettily print the node graph to stdout
|
||||||
unsigned int cline, bool verbose, unsigned int cnest=0)
|
void PrintHierarchy(
|
||||||
{
|
const aiNode* node,
|
||||||
if (cline++ >= maxline || cnest >= maxnest) {
|
const std::string &indent,
|
||||||
return;
|
bool verbose,
|
||||||
|
bool last = false,
|
||||||
|
bool first = true
|
||||||
|
){
|
||||||
|
// tree visualization
|
||||||
|
std::string branchchar;
|
||||||
|
if (first) { branchchar = ""; }
|
||||||
|
else if (last) { branchchar = TREE_STOP; } // "'-"
|
||||||
|
else { branchchar = TREE_BRANCH; } // "|-"
|
||||||
|
|
||||||
|
// print the indent and the branch character and the name
|
||||||
|
std::cout << indent << branchchar << node->mName.C_Str();
|
||||||
|
|
||||||
|
// if there are meshes attached, indicate this
|
||||||
|
if (node->mNumMeshes) {
|
||||||
|
std::cout << " (mesh ";
|
||||||
|
bool sep = false;
|
||||||
|
for (size_t i=0; i < node->mNumMeshes; ++i) {
|
||||||
|
unsigned int mesh_index = node->mMeshes[i];
|
||||||
|
if (sep) { std::cout << ", "; }
|
||||||
|
std::cout << mesh_index;
|
||||||
|
sep = true;
|
||||||
|
}
|
||||||
|
std::cout << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned int i = 0; i < cnest; ++i) {
|
// finish the line
|
||||||
printf("-- ");
|
std::cout << std::endl;
|
||||||
}
|
|
||||||
printf("\'%s\', meshes: %u\n",root->mName.data,root->mNumMeshes);
|
|
||||||
|
|
||||||
|
// in verbose mode, print the transform data as well
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
// print the actual transform
|
// indent to use
|
||||||
//printf(",");
|
std::string indentadd;
|
||||||
|
if (last) { indentadd += " "; }
|
||||||
|
else { indentadd += TREE_CONTINUE; } // "| "..
|
||||||
|
if (node->mNumChildren == 0) { indentadd += " "; }
|
||||||
|
else { indentadd += TREE_CONTINUE; } // .."| "
|
||||||
aiVector3D s, r, t;
|
aiVector3D s, r, t;
|
||||||
root->mTransformation.Decompose(s, r, t);
|
node->mTransformation.Decompose(s, r, t);
|
||||||
if (s.x != 1.0 || s.y != 1.0 || s.z != 1.0) {
|
if (s.x != 1.0 || s.y != 1.0 || s.z != 1.0) {
|
||||||
for(unsigned int i = 0; i < cnest; ++i) { printf(" "); }
|
std::cout << indent << indentadd;
|
||||||
printf(" S:[%f %f %f]\n", s.x, s.y, s.z);
|
printf(" S:[%f %f %f]\n", s.x, s.y, s.z);
|
||||||
}
|
}
|
||||||
if (r.x || r.y || r.z) {
|
if (r.x || r.y || r.z) {
|
||||||
for(unsigned int i = 0; i < cnest; ++i) { printf(" "); }
|
std::cout << indent << indentadd;
|
||||||
printf(" R:[%f %f %f]\n", r.x, r.y, r.z);
|
printf(" R:[%f %f %f]\n", r.x, r.y, r.z);
|
||||||
}
|
}
|
||||||
if (t.x || t.y || t.z) {
|
if (t.x || t.y || t.z) {
|
||||||
for(unsigned int i = 0; i < cnest; ++i) { printf(" "); }
|
std::cout << indent << indentadd;
|
||||||
printf(" T:[%f %f %f]\n", t.x, t.y, t.z);
|
printf(" T:[%f %f %f]\n", t.x, t.y, t.z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//printf("\n");
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < root->mNumChildren; ++i ) {
|
// and recurse
|
||||||
PrintHierarchy(root->mChildren[i],maxnest,maxline,cline,verbose,cnest+1);
|
std::string nextIndent;
|
||||||
if(i == root->mNumChildren-1) {
|
if (first) { nextIndent = indent; }
|
||||||
for(unsigned int i = 0; i < cnest; ++i) {
|
else if (last) { nextIndent = indent + " "; }
|
||||||
printf(" ");
|
else { nextIndent = indent + TREE_CONTINUE; } // "| "
|
||||||
}
|
for (size_t i = 0; i < node->mNumChildren; ++i) {
|
||||||
printf("<--\n");
|
bool lastone = (i == node->mNumChildren - 1);
|
||||||
}
|
PrintHierarchy(
|
||||||
|
node->mChildren[i],
|
||||||
|
nextIndent,
|
||||||
|
verbose,
|
||||||
|
lastone,
|
||||||
|
false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,8 +456,7 @@ int Assimp_Info (const char* const* params, unsigned int num)
|
||||||
|
|
||||||
// node hierarchy
|
// node hierarchy
|
||||||
printf("\nNode hierarchy:\n");
|
printf("\nNode hierarchy:\n");
|
||||||
unsigned int cline=0;
|
PrintHierarchy(scene->mRootNode,"",verbose);
|
||||||
PrintHierarchy(scene->mRootNode,20,1000,cline,verbose);
|
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -560,6 +560,30 @@ void CGLView::Enable_Textures(const bool pEnable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CGLView::Enable_Axes(const bool pEnable){
|
||||||
|
if(pEnable)
|
||||||
|
{
|
||||||
|
this->mAxesEnabled = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->mAxesEnabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGLView::Enable_Reload_Textures(const bool pEnable)
|
||||||
|
{
|
||||||
|
if(pEnable)
|
||||||
|
{
|
||||||
|
this->mReloadTexturesEnabled = true;
|
||||||
|
// this->mScene->ImportTextures(this->mScene->pScenePath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->mReloadTexturesEnabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************************************/
|
/********************************************************************/
|
||||||
/*********************** Override functions ************************/
|
/*********************** Override functions ************************/
|
||||||
/********************************************************************/
|
/********************************************************************/
|
||||||
|
@ -609,6 +633,7 @@ void CGLView::drawCoordSystem() {
|
||||||
// Z, -Z
|
// Z, -Z
|
||||||
qglColor(QColor(Qt::blue)), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, 0.0, 100000.0);
|
qglColor(QColor(Qt::blue)), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, 0.0, 100000.0);
|
||||||
qglColor(QColor(Qt::yellow)), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, 0.0, -100000.0);
|
qglColor(QColor(Qt::yellow)), glVertex3f(0.0, 0.0, 0.0), glVertex3f(0.0, 0.0, -100000.0);
|
||||||
|
qglColor(QColor(Qt::white));
|
||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -629,7 +654,10 @@ void CGLView::paintGL()
|
||||||
if ( mLightingEnabled ) {
|
if ( mLightingEnabled ) {
|
||||||
glDisable( GL_LIGHTING );///TODO: display list
|
glDisable( GL_LIGHTING );///TODO: display list
|
||||||
}
|
}
|
||||||
drawCoordSystem();
|
if (this->mAxesEnabled == true)
|
||||||
|
{
|
||||||
|
drawCoordSystem();
|
||||||
|
}
|
||||||
|
|
||||||
glDisable(GL_COLOR_MATERIAL);
|
glDisable(GL_COLOR_MATERIAL);
|
||||||
if(mLightingEnabled) glEnable(GL_LIGHTING);
|
if(mLightingEnabled) glEnable(GL_LIGHTING);
|
||||||
|
|
|
@ -75,7 +75,9 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
bool mAxesEnabled = true;
|
||||||
|
// Textures
|
||||||
|
bool mReloadTexturesEnabled = false; // If true then textures will reload when the window is activated.
|
||||||
/// \enum ELightType
|
/// \enum ELightType
|
||||||
/// Type of light source.
|
/// Type of light source.
|
||||||
enum class ELightType { Directional, Point, Spot };
|
enum class ELightType { Directional, Point, Spot };
|
||||||
|
@ -155,7 +157,6 @@ private:
|
||||||
GLdouble mCamera_Viewport_AspectRatio;///< Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height).
|
GLdouble mCamera_Viewport_AspectRatio;///< Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height).
|
||||||
// Lighting
|
// Lighting
|
||||||
bool mLightingEnabled = false;///< If true then OpenGL lighting is enabled (glEnable(GL_LIGHTING)), if false - disabled.
|
bool mLightingEnabled = false;///< If true then OpenGL lighting is enabled (glEnable(GL_LIGHTING)), if false - disabled.
|
||||||
// Textures
|
|
||||||
///TODO: map is goooood, but not for case when one image can be used in different materials with difference in: texture transformation, targeting of the
|
///TODO: map is goooood, but not for case when one image can be used in different materials with difference in: texture transformation, targeting of the
|
||||||
/// texture (ambient or emission, or even height map), texture properties.
|
/// texture (ambient or emission, or even height map), texture properties.
|
||||||
QMap<QString, GLuint> mTexture_IDMap;///< Map image filenames to textures ID's.
|
QMap<QString, GLuint> mTexture_IDMap;///< Map image filenames to textures ID's.
|
||||||
|
@ -306,6 +307,12 @@ public:
|
||||||
/// \param [in] pEnable - if true then enable textures, false - disable textures.
|
/// \param [in] pEnable - if true then enable textures, false - disable textures.
|
||||||
void Enable_Textures(const bool pEnable);
|
void Enable_Textures(const bool pEnable);
|
||||||
|
|
||||||
|
void Enable_Axes(const bool pEnable);
|
||||||
|
/// \fn void Enable_Textures(const bool pEnable)
|
||||||
|
/// Control textures drawing.
|
||||||
|
/// \param [in] pEnable - if true then enable textures, false - disable textures.
|
||||||
|
void Enable_Reload_Textures(const bool pEnable);
|
||||||
|
|
||||||
/********************************************************************/
|
/********************************************************************/
|
||||||
/******************** Lighting control functions ********************/
|
/******************** Lighting control functions ********************/
|
||||||
/********************************************************************/
|
/********************************************************************/
|
||||||
|
|
|
@ -48,6 +48,7 @@ QTime time_begin = QTime::currentTime();
|
||||||
ui->cbxLighting->setChecked(true); mGLView->Lighting_Enable();
|
ui->cbxLighting->setChecked(true); mGLView->Lighting_Enable();
|
||||||
ui->cbxBBox->setChecked(false); mGLView->Enable_SceneBBox(false);
|
ui->cbxBBox->setChecked(false); mGLView->Enable_SceneBBox(false);
|
||||||
ui->cbxTextures->setChecked(true); mGLView->Enable_Textures(true);
|
ui->cbxTextures->setChecked(true); mGLView->Enable_Textures(true);
|
||||||
|
ui->cbxReloadTextures->setChecked(true); mGLView->Enable_Reload_Textures(false);
|
||||||
//
|
//
|
||||||
// Fill info labels
|
// Fill info labels
|
||||||
//
|
//
|
||||||
|
@ -194,6 +195,13 @@ GLfloat step;
|
||||||
/********************************************************************/
|
/********************************************************************/
|
||||||
/********************** Constructor/Destructor **********************/
|
/********************** Constructor/Destructor **********************/
|
||||||
/********************************************************************/
|
/********************************************************************/
|
||||||
|
bool MainWindow::event(QEvent *e)
|
||||||
|
{
|
||||||
|
if (e->type() == QEvent::WindowActivate && this->mGLView->mReloadTexturesEnabled == true) {
|
||||||
|
qInfo() << "Window Activated";
|
||||||
|
}
|
||||||
|
return QWidget::event(e);
|
||||||
|
}
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent)
|
MainWindow::MainWindow(QWidget *parent)
|
||||||
: QMainWindow(parent), ui(new Ui::MainWindow),
|
: QMainWindow(parent), ui(new Ui::MainWindow),
|
||||||
|
@ -364,6 +372,18 @@ void MainWindow::on_cbxBBox_clicked(bool checked)
|
||||||
mGLView->updateGL();
|
mGLView->updateGL();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_cbxDrawAxes_clicked(bool checked)
|
||||||
|
{
|
||||||
|
mGLView->Enable_Axes(checked);
|
||||||
|
mGLView->updateGL();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_cbxReloadTextures_clicked(bool checked)
|
||||||
|
{
|
||||||
|
mGLView->Enable_Reload_Textures(checked);
|
||||||
|
mGLView->updateGL();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::on_cbxTextures_clicked(bool checked)
|
void MainWindow::on_cbxTextures_clicked(bool checked)
|
||||||
{
|
{
|
||||||
mGLView->Enable_Textures(checked);
|
mGLView->Enable_Textures(checked);
|
||||||
|
|
|
@ -90,7 +90,7 @@ protected:
|
||||||
/// \param [in] pEvent - pointer to event data.
|
/// \param [in] pEvent - pointer to event data.
|
||||||
void keyPressEvent(QKeyEvent* pEvent) override;
|
void keyPressEvent(QKeyEvent* pEvent) override;
|
||||||
|
|
||||||
|
bool event(QEvent*);
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/********************************************************************/
|
/********************************************************************/
|
||||||
|
@ -133,4 +133,6 @@ private slots:
|
||||||
void on_lstCamera_clicked(const QModelIndex &index);
|
void on_lstCamera_clicked(const QModelIndex &index);
|
||||||
void on_cbxBBox_clicked(bool checked);
|
void on_cbxBBox_clicked(bool checked);
|
||||||
void on_cbxTextures_clicked(bool checked);
|
void on_cbxTextures_clicked(bool checked);
|
||||||
|
void on_cbxDrawAxes_clicked(bool checked);
|
||||||
|
void on_cbxReloadTextures_clicked(bool checked);
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>641</width>
|
<width>641</width>
|
||||||
<height>734</height>
|
<height>778</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -501,6 +501,23 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QCheckBox" name="cbxDrawAxes">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show Axes</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QCheckBox" name="cbxReloadTextures">
|
||||||
|
<property name="text">
|
||||||
|
<string>Live Reload Textures</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -513,4 +530,7 @@
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
<slots>
|
||||||
|
<signal>installEventFilter()</signal>
|
||||||
|
</slots>
|
||||||
</ui>
|
</ui>
|
||||||
|
|
Loading…
Reference in New Issue