Merge pull request #7 from assimp/master

Update fork
pull/1350/head
Madrich 2015-07-14 08:54:49 +02:00
commit 2dd393b800
479 changed files with 165625 additions and 165185 deletions

22
.editorconfig 100644
View File

@ -0,0 +1,22 @@
# See <http://EditorConfig.org> for details
root = true
[CMakeLists.txt,*.cmake{,.in}]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_size = 2
indent_style = space
[*.h.in]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_size = 4
indent_style = space
[*.txt]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

8
.gitattributes vendored 100644
View File

@ -0,0 +1,8 @@
# Declare files that will always have LF line endings on checkout.
*.cpp text eol=lf
*.h text eol=lf
*.c text eol=lf
*.hpp text eol=lf
*.txt text eol=lf
*.cmake text eol=lf
*.sh text eol=lf

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
.idea
build build
.project .project
*.kdev4* *.kdev4*

16
.travis.sh 100755
View File

@ -0,0 +1,16 @@
function generate()
{
cmake -G "Unix Makefiles" -DASSIMP_ENABLE_BOOST_WORKAROUND=YES -DASSIMP_NO_EXPORT=$TRAVIS_NO_EXPORT -DBUILD_SHARED_LIBS=$SHARED_BUILD
}
if [ $ANDROID ]; then
ant -v -Dmy.dir=${TRAVIS_BUILD_DIR} -f ${TRAVIS_BUILD_DIR}/port/jassimp/build.xml ndk-jni
else
generate \
&& make \
&& sudo make install \
&& sudo ldconfig \
&& (cd test/unit; ../../bin/unit) \
&& (cd test/regression; chmod 755 run.py; ./run.py; \
chmod 755 result_checker.py; ./result_checker.py)
fi

View File

@ -28,18 +28,4 @@ install:
- if [ $ANDROID ]; then wget -c http://dl.google.com/android/ndk/android-ndk-${PV}-${PLATF}.tar.bz2 && tar xf android-ndk-${PV}-${PLATF}.tar.bz2 ; fi - if [ $ANDROID ]; then wget -c http://dl.google.com/android/ndk/android-ndk-${PV}-${PLATF}.tar.bz2 && tar xf android-ndk-${PV}-${PLATF}.tar.bz2 ; fi
script: script:
- if [ $ANDROID ]; then - . ./.travis.sh
ant -v -Dmy.dir=${TRAVIS_BUILD_DIR} -f ${TRAVIS_BUILD_DIR}/port/jassimp/build.xml ndk-jni ;
else
cmake -G "Unix Makefiles" -DASSIMP_ENABLE_BOOST_WORKAROUND=YES -DASSIMP_NO_EXPORT=$TRAVIS_NO_EXPORT -DBUILD_SHARED_LIBS=$SHARED_BUILD ;
make ;
sudo make install ;
sudo ldconfig ;
cd test/unit ;
../../bin/unit ;
cd ../regression ;
chmod 755 run.py ;
./run.py ;
chmod 755 result_checker.py ;
./result_checker.py;
fi

View File

@ -7,10 +7,10 @@
# Compute paths # Compute paths
get_filename_component(FOOBAR_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) get_filename_component(FOOBAR_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
if(EXISTS "${FOOBAR_CMAKE_DIR}/CMakeCache.txt") if(EXISTS "${FOOBAR_CMAKE_DIR}/CMakeCache.txt")
# In build tree # In build tree
include("${FOOBAR_CMAKE_DIR}/FooBarBuildTreeSettings.cmake") include("${FOOBAR_CMAKE_DIR}/FooBarBuildTreeSettings.cmake")
else() else()
set(FOOBAR_INCLUDE_DIRS "${FOOBAR_CMAKE_DIR}/@CONF_REL_INCLUDE_DIR@") set(FOOBAR_INCLUDE_DIRS "${FOOBAR_CMAKE_DIR}/@CONF_REL_INCLUDE_DIR@")
endif() endif()
# Our library dependencies (contains definitions for IMPORTED targets) # Our library dependencies (contains definitions for IMPORTED targets)

View File

@ -4,8 +4,8 @@ PROJECT( Assimp )
option(BUILD_SHARED_LIBS "Build package with shared libraries." ON) option(BUILD_SHARED_LIBS "Build package with shared libraries." ON)
if(NOT BUILD_SHARED_LIBS) if(NOT BUILD_SHARED_LIBS)
#set(CMAKE_EXE_LINKER_FLAGS "-static") #set(CMAKE_EXE_LINKER_FLAGS "-static")
set(LINK_SEARCH_START_STATIC TRUE) set(LINK_SEARCH_START_STATIC TRUE)
endif(NOT BUILD_SHARED_LIBS) endif(NOT BUILD_SHARED_LIBS)
# Define here the needed parameters # Define here the needed parameters
@ -18,31 +18,32 @@ 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
add_definitions( -DOPENDDL_NO_USE_CPP11 ) add_definitions( -DOPENDDL_NO_USE_CPP11 )
# Get the current working branch # Get the current working branch
execute_process( execute_process(
COMMAND git rev-parse --abbrev-ref HEAD COMMAND git rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_BRANCH OUTPUT_VARIABLE GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_STRIP_TRAILING_WHITESPACE
) )
# Get the latest abbreviated commit hash of the working branch # Get the latest abbreviated commit hash of the working branch
execute_process( execute_process(
COMMAND git log -1 --format=%h COMMAND git log -1 --format=%h
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_HASH OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_STRIP_TRAILING_WHITESPACE
) )
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)
configure_file( configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/revision.h.in ${CMAKE_CURRENT_SOURCE_DIR}/revision.h.in
${CMAKE_CURRENT_BINARY_DIR}/revision.h ${CMAKE_CURRENT_BINARY_DIR}/revision.h
) )
include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_BINARY_DIR})
@ -58,16 +59,16 @@ option(ASSIMP_ANDROID_JNIIOSYSTEM "Android JNI IOSystem support is active" OFF)
# Workaround to be able to deal with compiler bug "Too many sections" with mingw. # Workaround to be able to deal with compiler bug "Too many sections" with mingw.
if( CMAKE_COMPILER_IS_MINGW ) if( CMAKE_COMPILER_IS_MINGW )
ADD_DEFINITIONS(-DASSIMP_BUILD_NO_IFC_IMPORTER ) ADD_DEFINITIONS(-DASSIMP_BUILD_NO_IFC_IMPORTER )
endif() endif()
if((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT CMAKE_COMPILER_IS_MINGW) if((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT CMAKE_COMPILER_IS_MINGW)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") # this is a very important switch and some libraries seem now to have it.... set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") # this is a very important switch and some libraries seem now to have it....
# hide all not-exported symbols # hide all not-exported symbols
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall" ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall" )
elseif(MSVC) elseif(MSVC)
# enable multi-core compilation with MSVC # enable multi-core compilation with MSVC
add_definitions(/MP) add_definitions(/MP)
endif() endif()
INCLUDE (FindPkgConfig) INCLUDE (FindPkgConfig)
@ -80,51 +81,51 @@ INCLUDE (PrecompiledHeader)
# source tree. During an out-of-source build, however, do not litter this # source tree. During an out-of-source build, however, do not litter this
# directory, since that is probably what the user wanted to avoid. # directory, since that is probably what the user wanted to avoid.
IF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR ) IF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib" ) SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib" )
SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib" ) SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib" )
SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/bin" ) SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/bin" )
ENDIF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR ) ENDIF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
# Cache these to allow the user to override them manually. # Cache these to allow the user to override them manually.
SET( ASSIMP_LIB_INSTALL_DIR "lib" CACHE PATH SET( ASSIMP_LIB_INSTALL_DIR "lib" CACHE PATH
"Path the built library files are installed to." ) "Path the built library files are installed to." )
SET( ASSIMP_INCLUDE_INSTALL_DIR "include" CACHE PATH SET( ASSIMP_INCLUDE_INSTALL_DIR "include" CACHE PATH
"Path the header files are installed to." ) "Path the header files are installed to." )
SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE PATH SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE PATH
"Path the tool executables are installed to." ) "Path the tool executables are installed to." )
SET(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfitx for lib, samples and tools") SET(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfitx for lib, samples and tools")
# Only generate this target if no higher-level project already has # Only generate this target if no higher-level project already has
IF (NOT TARGET uninstall) IF (NOT TARGET uninstall)
# add make uninstall capability # add make uninstall capability
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
ENDIF() ENDIF()
# Globally enable Boost resp. the Boost workaround – it is also needed by the # Globally enable Boost resp. the Boost workaround – it is also needed by the
# tools which include the Assimp headers. # tools which include the Assimp headers.
option ( ASSIMP_ENABLE_BOOST_WORKAROUND option ( ASSIMP_ENABLE_BOOST_WORKAROUND
"If a simple implementation of the used Boost functions is used. Slightly reduces functionality, but enables builds without Boost available." "If a simple implementation of the used Boost functions is used. Slightly reduces functionality, but enables builds without Boost available."
ON ON
) )
IF ( ASSIMP_ENABLE_BOOST_WORKAROUND ) IF ( ASSIMP_ENABLE_BOOST_WORKAROUND )
INCLUDE_DIRECTORIES( code/BoostWorkaround ) INCLUDE_DIRECTORIES( code/BoostWorkaround )
ADD_DEFINITIONS( -DASSIMP_BUILD_BOOST_WORKAROUND ) ADD_DEFINITIONS( -DASSIMP_BUILD_BOOST_WORKAROUND )
MESSAGE( STATUS "Building a non-boost version of Assimp." ) MESSAGE( STATUS "Building a non-boost version of Assimp." )
ELSE ( ASSIMP_ENABLE_BOOST_WORKAROUND ) ELSE ( ASSIMP_ENABLE_BOOST_WORKAROUND )
SET( Boost_DETAILED_FAILURE_MSG ON ) SET( Boost_DETAILED_FAILURE_MSG ON )
SET( Boost_ADDITIONAL_VERSIONS "1.47" "1.47.0" "1.48.0" "1.48" "1.49" "1.49.0" "1.50" "1.50.0" "1.51" "1.51.0" "1.52.0" "1.53.0" "1.54.0" "1.55" "1.55.0" "1.56" "1.56.0" "1.57" "1.57.0" "1.58" "1.58.0" ) SET( Boost_ADDITIONAL_VERSIONS "1.47" "1.47.0" "1.48.0" "1.48" "1.49" "1.49.0" "1.50" "1.50.0" "1.51" "1.51.0" "1.52.0" "1.53.0" "1.54.0" "1.55" "1.55.0" "1.56" "1.56.0" "1.57" "1.57.0" "1.58" "1.58.0" )
FIND_PACKAGE( Boost ) FIND_PACKAGE( Boost )
IF ( NOT Boost_FOUND ) IF ( NOT Boost_FOUND )
MESSAGE( FATAL_ERROR MESSAGE( FATAL_ERROR
"Boost libraries (http://www.boost.org/) not found. " "Boost libraries (http://www.boost.org/) not found. "
"You can build a non-boost version of Assimp with slightly reduced " "You can build a non-boost version of Assimp with slightly reduced "
"functionality by specifying -DASSIMP_ENABLE_BOOST_WORKAROUND=ON." "functionality by specifying -DASSIMP_ENABLE_BOOST_WORKAROUND=ON."
) )
ENDIF ( NOT Boost_FOUND ) ENDIF ( NOT Boost_FOUND )
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIRS} ) INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIRS} )
ENDIF ( ASSIMP_ENABLE_BOOST_WORKAROUND ) ENDIF ( ASSIMP_ENABLE_BOOST_WORKAROUND )
# cmake configuration files # cmake configuration files
@ -132,9 +133,11 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in" "${C
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 )
option ( ASSIMP_NO_EXPORT option ( ASSIMP_NO_EXPORT
"Disable Assimp's export functionality." "Disable Assimp's export functionality."
OFF OFF
) )
if( CMAKE_COMPILER_IS_GNUCXX ) if( CMAKE_COMPILER_IS_GNUCXX )
@ -145,134 +148,134 @@ endif( CMAKE_COMPILER_IS_GNUCXX )
# Search for zlib # Search for zlib
find_package(ZLIB) find_package(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)
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
# Search for unzip # Search for unzip
if (PKG_CONFIG_FOUND) if (PKG_CONFIG_FOUND)
PKG_CHECK_MODULES(UNZIP minizip) PKG_CHECK_MODULES(UNZIP minizip)
endif (PKG_CONFIG_FOUND) endif (PKG_CONFIG_FOUND)
IF ( ASSIMP_NO_EXPORT ) IF ( ASSIMP_NO_EXPORT )
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_EXPORT) ADD_DEFINITIONS( -DASSIMP_BUILD_NO_EXPORT)
MESSAGE( STATUS "Build an import-only version of Assimp." ) MESSAGE( STATUS "Build an import-only version of Assimp." )
ENDIF( ASSIMP_NO_EXPORT ) ENDIF( ASSIMP_NO_EXPORT )
SET ( ASSIMP_BUILD_ARCHITECTURE "" CACHE STRING SET ( ASSIMP_BUILD_ARCHITECTURE "" CACHE STRING
"describe the current architecture." "describe the current architecture."
) )
IF ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "") IF ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "")
ELSE ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "") ELSE ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "")
ADD_DEFINITIONS ( -D'ASSIMP_BUILD_ARCHITECTURE="${ASSIMP_BUILD_ARCHITECTURE}"' ) ADD_DEFINITIONS ( -D'ASSIMP_BUILD_ARCHITECTURE="${ASSIMP_BUILD_ARCHITECTURE}"' )
ENDIF ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "") ENDIF ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "")
# ${CMAKE_GENERATOR} # ${CMAKE_GENERATOR}
SET ( ASSIMP_BUILD_COMPILER "" CACHE STRING SET ( ASSIMP_BUILD_COMPILER "" CACHE STRING
"describe the current compiler." "describe the current compiler."
) )
IF ( ASSIMP_BUILD_COMPILER STREQUAL "") IF ( ASSIMP_BUILD_COMPILER STREQUAL "")
ELSE ( ASSIMP_BUILD_COMPILER STREQUAL "") ELSE ( ASSIMP_BUILD_COMPILER STREQUAL "")
ADD_DEFINITIONS ( -D'ASSIMP_BUILD_COMPILER="${ASSIMP_BUILD_COMPILER}"' ) ADD_DEFINITIONS ( -D'ASSIMP_BUILD_COMPILER="${ASSIMP_BUILD_COMPILER}"' )
ENDIF ( ASSIMP_BUILD_COMPILER STREQUAL "") ENDIF ( ASSIMP_BUILD_COMPILER STREQUAL "")
MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER ) MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER )
SET ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER OFF CACHE BOOL SET ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER OFF CACHE BOOL
"Build the C4D importer, which relies on the non-free Melange SDK." "Build the C4D importer, which relies on the non-free Melange SDK."
) )
IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
IF ( MSVC ) IF ( MSVC )
SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/_melange/includes") SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/_melange/includes")
# pick the correct prebuilt library # pick the correct prebuilt library
IF(MSVC11) IF(MSVC11)
SET(C4D_LIB_POSTFIX "_2012md") SET(C4D_LIB_POSTFIX "_2012md")
ELSEIF(MSVC10) ELSEIF(MSVC10)
SET(C4D_LIB_POSTFIX "_2010md") SET(C4D_LIB_POSTFIX "_2010md")
ELSEIF(MSVC90) ELSEIF(MSVC90)
SET(C4D_LIB_POSTFIX "_2008md") SET(C4D_LIB_POSTFIX "_2008md")
ELSE() ELSE()
MESSAGE( FATAL_ERROR MESSAGE( FATAL_ERROR
"C4D is currently only supported with MSVC 9, 10, 11" "C4D is currently only supported with MSVC 9, 10, 11"
) )
ENDIF() ENDIF()
IF(CMAKE_CL_64) IF(CMAKE_CL_64)
SET(C4D_LIB_ARCH_POSTFIX "_x64") SET(C4D_LIB_ARCH_POSTFIX "_x64")
ELSE() ELSE()
SET(C4D_LIB_ARCH_POSTFIX "") SET(C4D_LIB_ARCH_POSTFIX "")
ENDIF() ENDIF()
SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/_melange/lib/WIN") SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/_melange/lib/WIN")
SET(C4D_DEBUG_LIBRARY "${C4D_LIB_BASE_PATH}/debug/_melange_lib${C4D_LIB_ARCH_POSTFIX}${C4D_LIB_POSTFIX}.lib") SET(C4D_DEBUG_LIBRARY "${C4D_LIB_BASE_PATH}/debug/_melange_lib${C4D_LIB_ARCH_POSTFIX}${C4D_LIB_POSTFIX}.lib")
SET(C4D_RELEASE_LIBRARY "${C4D_LIB_BASE_PATH}/release/_melange_lib${C4D_LIB_ARCH_POSTFIX}${C4D_LIB_POSTFIX}.lib") SET(C4D_RELEASE_LIBRARY "${C4D_LIB_BASE_PATH}/release/_melange_lib${C4D_LIB_ARCH_POSTFIX}${C4D_LIB_POSTFIX}.lib")
# winsock and winmm are necessary dependencies of melange (this is undocumented, but true.) # winsock and winmm are necessary dependencies of melange (this is undocumented, but true.)
SET(C4D_EXTRA_LIBRARIES WSock32.lib Winmm.lib) SET(C4D_EXTRA_LIBRARIES WSock32.lib Winmm.lib)
ELSE () ELSE ()
MESSAGE( FATAL_ERROR MESSAGE( FATAL_ERROR
"C4D is currently only available on Windows with melange SDK installed in contrib/Melange" "C4D is currently only available on Windows with melange SDK installed in contrib/Melange"
) )
ENDIF ( MSVC ) ENDIF ( MSVC )
else (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) else (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER ) ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER )
ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
ADD_SUBDIRECTORY( code/ ) ADD_SUBDIRECTORY( code/ )
option ( ASSIMP_BUILD_ASSIMP_TOOLS option ( ASSIMP_BUILD_ASSIMP_TOOLS
"If the supplementary tools for Assimp are built in addition to the library." "If the supplementary tools for Assimp are built in addition to the library."
ON ON
) )
IF ( ASSIMP_BUILD_ASSIMP_TOOLS ) IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
IF ( WIN32 ) IF ( WIN32 AND DirectX_FOUND )
ADD_SUBDIRECTORY( tools/assimp_view/ ) ADD_SUBDIRECTORY( tools/assimp_view/ )
ENDIF ( WIN32 ) ENDIF ( WIN32 AND DirectX_FOUND )
ADD_SUBDIRECTORY( tools/assimp_cmd/ ) ADD_SUBDIRECTORY( tools/assimp_cmd/ )
ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS ) ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
option ( ASSIMP_BUILD_SAMPLES option ( ASSIMP_BUILD_SAMPLES
"If the official samples are built as well (needs Glut)." "If the official samples are built as well (needs Glut)."
OFF OFF
) )
IF ( ASSIMP_BUILD_SAMPLES) IF ( ASSIMP_BUILD_SAMPLES)
IF ( WIN32 ) IF ( WIN32 )
ADD_SUBDIRECTORY( samples/SimpleTexturedOpenGL/ ) ADD_SUBDIRECTORY( samples/SimpleTexturedOpenGL/ )
ENDIF ( WIN32 ) ENDIF ( WIN32 )
ADD_SUBDIRECTORY( samples/SimpleOpenGL/ ) ADD_SUBDIRECTORY( samples/SimpleOpenGL/ )
ENDIF ( ASSIMP_BUILD_SAMPLES ) ENDIF ( ASSIMP_BUILD_SAMPLES )
option ( ASSIMP_BUILD_TESTS option ( ASSIMP_BUILD_TESTS
"If the test suite for Assimp is built in addition to the library." "If the test suite for Assimp is built in addition to the library."
ON ON
) )
IF ( ASSIMP_BUILD_TESTS ) IF ( ASSIMP_BUILD_TESTS )
ADD_SUBDIRECTORY( test/ ) ADD_SUBDIRECTORY( test/ )
ENDIF ( ASSIMP_BUILD_TESTS ) ENDIF ( ASSIMP_BUILD_TESTS )
IF(MSVC) IF(MSVC)
option ( ASSIMP_INSTALL_PDB option ( ASSIMP_INSTALL_PDB
"Install MSVC debug files." "Install MSVC debug files."
ON ON
) )
ENDIF(MSVC) ENDIF(MSVC)
# Generate a pkg-config .pc for the Assimp library. # Generate a pkg-config .pc for the Assimp library.
@ -280,50 +283,50 @@ CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/assimp.pc.in" "${PROJECT_BINARY_DIR}/assi
INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTALL_DIR}/pkgconfig/ COMPONENT ${LIBASSIMP-DEV_COMPONENT}) INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTALL_DIR}/pkgconfig/ COMPONENT ${LIBASSIMP-DEV_COMPONENT})
if(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES) if(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
# Packing information # Packing information
set(CPACK_PACKAGE_NAME "assimp{ASSIMP_VERSION_MAJOR}") set(CPACK_PACKAGE_NAME "assimp{ASSIMP_VERSION_MAJOR}")
set(CPACK_PACKAGE_CONTACT "" CACHE STRING "Package maintainer and PGP signer.") set(CPACK_PACKAGE_CONTACT "" CACHE STRING "Package maintainer and PGP signer.")
set(CPACK_PACKAGE_VENDOR "http://assimp.sourceforge.net/") set(CPACK_PACKAGE_VENDOR "http://assimp.sourceforge.net/")
set(CPACK_PACKAGE_DISPLAY_NAME "Assimp ${ASSIMP_VERSION}") set(CPACK_PACKAGE_DISPLAY_NAME "Assimp ${ASSIMP_VERSION}")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY " - Open Asset Import Library ${ASSIMP_VERSION}") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY " - Open Asset Import Library ${ASSIMP_VERSION}")
set(CPACK_PACKAGE_VERSION "${ASSIMP_VERSION}.${ASSIMP_PACKAGE_VERSION}" ) set(CPACK_PACKAGE_VERSION "${ASSIMP_VERSION}.${ASSIMP_PACKAGE_VERSION}" )
set(CPACK_PACKAGE_VERSION_MAJOR "${ASSIMP_VERSION_MAJOR}") set(CPACK_PACKAGE_VERSION_MAJOR "${ASSIMP_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${ASSIMP_VERSION_MINOR}") set(CPACK_PACKAGE_VERSION_MINOR "${ASSIMP_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${ASSIMP_VERSION_PATCH}") set(CPACK_PACKAGE_VERSION_PATCH "${ASSIMP_VERSION_PATCH}")
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}" )
set(CPACK_COMPONENT_${LIBASSIMP_COMPONENT_UPPER}_DISPLAY_NAME "libraries") set(CPACK_COMPONENT_${LIBASSIMP_COMPONENT_UPPER}_DISPLAY_NAME "libraries")
set(CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT_UPPER}_DISPLAY_NAME "common headers and installs") set(CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT_UPPER}_DISPLAY_NAME "common headers and installs")
set(CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT_UPPER}_DEPENDS $ "{LIBASSIMP_COMPONENT}" ) set(CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT_UPPER}_DEPENDS $ "{LIBASSIMP_COMPONENT}" )
set(CPACK_COMPONENT_ASSIMP-DEV_DISPLAY_NAME "${CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT}_DISPLAY_NAME}" ) set(CPACK_COMPONENT_ASSIMP-DEV_DISPLAY_NAME "${CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT}_DISPLAY_NAME}" )
set(CPACK_COMPONENT_ASSIMP-DEV_DEPENDS "${LIBASSIMP-DEV_COMPONENT}" ) set(CPACK_COMPONENT_ASSIMP-DEV_DEPENDS "${LIBASSIMP-DEV_COMPONENT}" )
set(CPACK_DEBIAN_BUILD_DEPENDS debhelper cmake libboost-dev libboost-thread-dev libboost-math-dev zlib1g-dev pkg-config) set(CPACK_DEBIAN_BUILD_DEPENDS debhelper cmake libboost-dev libboost-thread-dev libboost-math-dev zlib1g-dev pkg-config)
# debian # debian
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_DEBIAN_CMAKE_OPTIONS "-DBUILD_ASSIMP_SAMPLES:BOOL=${ASSIMP_BUILD_SAMPLES}") set(CPACK_DEBIAN_CMAKE_OPTIONS "-DBUILD_ASSIMP_SAMPLES:BOOL=${ASSIMP_BUILD_SAMPLES}")
set(CPACK_DEBIAN_PACKAGE_SECTION "libs" ) set(CPACK_DEBIAN_PACKAGE_SECTION "libs" )
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_COMPONENTS_ALL}") set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_COMPONENTS_ALL}")
set(CPACK_DEBIAN_PACKAGE_SUGGESTS) set(CPACK_DEBIAN_PACKAGE_SUGGESTS)
set(CPACK_DEBIAN_PACKAGE_NAME "assimp") set(CPACK_DEBIAN_PACKAGE_NAME "assimp")
set(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES contrib/cppunit-1.12.1 contrib/cppunit_note.txt contrib/zlib workspaces test doc obj samples packaging) set(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES contrib/cppunit-1.12.1 contrib/cppunit_note.txt contrib/zlib workspaces test doc obj samples packaging)
set(CPACK_DEBIAN_PACKAGE_SOURCE_COPY svn export --force) set(CPACK_DEBIAN_PACKAGE_SOURCE_COPY svn export --force)
set(CPACK_DEBIAN_CHANGELOG) set(CPACK_DEBIAN_CHANGELOG)
execute_process(COMMAND lsb_release -is execute_process(COMMAND lsb_release -is
OUTPUT_VARIABLE _lsb_distribution OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE _lsb_distribution OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE _lsb_release_failed) RESULT_VARIABLE _lsb_release_failed)
set(CPACK_DEBIAN_DISTRIBUTION_NAME ${_lsb_distribution} CACHE STRING "Name of the distrubiton") set(CPACK_DEBIAN_DISTRIBUTION_NAME ${_lsb_distribution} CACHE STRING "Name of the distrubiton")
string(TOLOWER ${CPACK_DEBIAN_DISTRIBUTION_NAME} CPACK_DEBIAN_DISTRIBUTION_NAME) string(TOLOWER ${CPACK_DEBIAN_DISTRIBUTION_NAME} CPACK_DEBIAN_DISTRIBUTION_NAME)
if( ${CPACK_DEBIAN_DISTRIBUTION_NAME} STREQUAL "ubuntu" ) if( ${CPACK_DEBIAN_DISTRIBUTION_NAME} STREQUAL "ubuntu" )
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()

View File

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

View File

@ -7,9 +7,15 @@ APIs are provided for C and C++. There are various bindings to other languages (
Additionally, assimp features various __mesh post processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more. Additionally, assimp features various __mesh post processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more.
This is the development trunk containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [assimp.sf.net](http://assimp.sf.net) or from *nix package repositories. According to [Travis-CI] (https://travis-ci.org/), the current build status is: This is the development trunk containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [assimp.sf.net](http://assimp.sf.net) or from *nix package repositories.
The current build status is:
[![Build Status](https://travis-ci.org/assimp/assimp.png)](https://travis-ci.org/assimp/assimp) Linux [![Linux Build Status](https://travis-ci.org/assimp/assimp.png)](https://travis-ci.org/assimp/assimp)
Windows [![Windows Build Status](https://ci.appveyor.com/api/projects/status/tmo433wax6u6cjp4?svg=true)](https://ci.appveyor.com/project/kimkulling/assimp)
Coverity<a href="https://scan.coverity.com/projects/5607">
<img alt="Coverity Scan Build Status"
src="https://scan.coverity.com/projects/5607/badge.svg"/>
</a>
__[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.__ __[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.__
@ -36,6 +42,7 @@ __Importers__:
- STL - STL
- X - X
- OBJ - OBJ
- OpenGEX
- SMD - SMD
- LWO - LWO
- LXO - LXO

24
appveyor.yml 100644
View File

@ -0,0 +1,24 @@
# AppVeyor file
# http://www.appveyor.com/docs/appveyor-yml
# Operating system (build VM template)
os: Previous Windows Server 2012 R2 # using previous worker images since default worker has problem installing DART-Prerequisites.msi
# clone directory
clone_folder: c:\projects\assimp
# branches to build
branches:
# whitelist
only:
- master
platform: x64
configuration: Release
build:
build_script:
- cd c:\projects\assimp
- cmake CMakeLists.txt -G "Visual Studio 11"
- msbuild /m /p:Configuration=Release /p:Platform="Win32" Assimp.sln

View File

@ -2,30 +2,30 @@ find_package(Threads REQUIRED)
include(ExternalProject) include(ExternalProject)
if(MSYS OR MINGW) if(MSYS OR MINGW)
set(DISABLE_PTHREADS ON) set(DISABLE_PTHREADS ON)
else() else()
set(DISABLE_PTHREADS OFF) set(DISABLE_PTHREADS OFF)
endif() endif()
if (MSVC) if (MSVC)
set(RELEASE_LIB_DIR ReleaseLibs) set(RELEASE_LIB_DIR ReleaseLibs)
set(DEBUG_LIB_DIR DebugLibs) set(DEBUG_LIB_DIR DebugLibs)
else() else()
set(RELEASE_LIB_DIR "") set(RELEASE_LIB_DIR "")
set(DEBUG_LIB_DIR "") set(DEBUG_LIB_DIR "")
endif() endif()
set(GTEST_CMAKE_ARGS set(GTEST_CMAKE_ARGS
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
"-Dgtest_force_shared_crt=ON" "-Dgtest_force_shared_crt=ON"
"-Dgtest_disable_pthreads:BOOL=${DISABLE_PTHREADS}") "-Dgtest_disable_pthreads:BOOL=${DISABLE_PTHREADS}")
set(GTEST_RELEASE_LIB_DIR "") set(GTEST_RELEASE_LIB_DIR "")
set(GTEST_DEBUGLIB_DIR "") set(GTEST_DEBUGLIB_DIR "")
if (MSVC) if (MSVC)
set(GTEST_CMAKE_ARGS ${GTEST_CMAKE_ARGS} set(GTEST_CMAKE_ARGS ${GTEST_CMAKE_ARGS}
"-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG:PATH=${DEBUG_LIB_DIR}" "-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG:PATH=${DEBUG_LIB_DIR}"
"-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE:PATH=${RELEASE_LIB_DIR}") "-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE:PATH=${RELEASE_LIB_DIR}")
set(GTEST_LIB_DIR) set(GTEST_LIB_DIR)
endif() endif()
set(GTEST_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/gtest") set(GTEST_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/gtest")
@ -33,40 +33,40 @@ set(GTEST_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/gtest")
# try to find git - if found, setup gtest # try to find git - if found, setup gtest
find_package(Git) find_package(Git)
if(NOT GIT_FOUND) if(NOT GIT_FOUND)
set(AddGTest_FOUND false CACHE BOOL "Was gtest setup correctly?") set(AddGTest_FOUND false CACHE BOOL "Was gtest setup correctly?")
else(NOT GIT_FOUND) else(NOT GIT_FOUND)
set(AddGTest_FOUND true CACHE BOOL "Was gtest setup correctly?") set(AddGTest_FOUND true CACHE BOOL "Was gtest setup correctly?")
ExternalProject_Add(gtest ExternalProject_Add(gtest
GIT_REPOSITORY https://chromium.googlesource.com/external/googletest GIT_REPOSITORY https://chromium.googlesource.com/external/googletest
TIMEOUT 10 TIMEOUT 10
PREFIX "${GTEST_PREFIX}" PREFIX "${GTEST_PREFIX}"
CMAKE_ARGS "${GTEST_CMAKE_ARGS}" CMAKE_ARGS "${GTEST_CMAKE_ARGS}"
LOG_DOWNLOAD ON LOG_DOWNLOAD ON
LOG_CONFIGURE ON LOG_CONFIGURE ON
LOG_BUILD ON LOG_BUILD ON
# Disable install # Disable install
INSTALL_COMMAND "" INSTALL_COMMAND ""
) )
set(LIB_PREFIX "${CMAKE_STATIC_LIBRARY_PREFIX}") set(LIB_PREFIX "${CMAKE_STATIC_LIBRARY_PREFIX}")
set(LIB_SUFFIX "${CMAKE_STATIC_LIBRARY_SUFFIX}") set(LIB_SUFFIX "${CMAKE_STATIC_LIBRARY_SUFFIX}")
set(GTEST_LOCATION "${GTEST_PREFIX}/src/gtest-build") set(GTEST_LOCATION "${GTEST_PREFIX}/src/gtest-build")
set(GTEST_DEBUG_LIBRARIES set(GTEST_DEBUG_LIBRARIES
"${GTEST_LOCATION}/${DEBUG_LIB_DIR}/${LIB_PREFIX}gtest${LIB_SUFFIX}" "${GTEST_LOCATION}/${DEBUG_LIB_DIR}/${LIB_PREFIX}gtest${LIB_SUFFIX}"
"${CMAKE_THREAD_LIBS_INIT}") "${CMAKE_THREAD_LIBS_INIT}")
SET(GTEST_RELEASE_LIBRARIES SET(GTEST_RELEASE_LIBRARIES
"${GTEST_LOCATION}/${RELEASE_LIB_DIR}/${LIB_PREFIX}gtest${LIB_SUFFIX}" "${GTEST_LOCATION}/${RELEASE_LIB_DIR}/${LIB_PREFIX}gtest${LIB_SUFFIX}"
"${CMAKE_THREAD_LIBS_INIT}") "${CMAKE_THREAD_LIBS_INIT}")
if(MSVC_VERSION EQUAL 1700) if(MSVC_VERSION EQUAL 1700)
add_definitions(-D_VARIADIC_MAX=10) add_definitions(-D_VARIADIC_MAX=10)
endif() endif()
ExternalProject_Get_Property(gtest source_dir) ExternalProject_Get_Property(gtest source_dir)
include_directories(${source_dir}/include) include_directories(${source_dir}/include)
include_directories(${source_dir}/gtest/include) include_directories(${source_dir}/gtest/include)
ExternalProject_Get_Property(gtest binary_dir) ExternalProject_Get_Property(gtest binary_dir)
link_directories(${binary_dir}) link_directories(${binary_dir})
endif(NOT GIT_FOUND) endif(NOT GIT_FOUND)

View File

@ -35,13 +35,13 @@ if(WIN32) # The only platform it makes sense to check for DirectX SDK
"C:/Program Files (x86)/Microsoft DirectX SDK*" "C:/Program Files (x86)/Microsoft DirectX SDK*"
"C:/apps/Microsoft DirectX SDK*" "C:/apps/Microsoft DirectX SDK*"
"C:/Program Files/Microsoft DirectX SDK*" "C:/Program Files/Microsoft DirectX SDK*"
"$ENV{ProgramFiles}/Microsoft DirectX SDK*" "$ENV{ProgramFiles}/Microsoft DirectX SDK*"
) )
create_search_paths(DirectX) create_search_paths(DirectX)
# redo search if prefix path changed # redo search if prefix path changed
clear_if_changed(DirectX_PREFIX_PATH clear_if_changed(DirectX_PREFIX_PATH
DirectX_LIBRARY DirectX_LIBRARY
DirectX_INCLUDE_DIR DirectX_INCLUDE_DIR
) )
find_path(DirectX_INCLUDE_DIR NAMES d3d9.h HINTS ${DirectX_INC_SEARCH_PATH}) find_path(DirectX_INCLUDE_DIR NAMES d3d9.h HINTS ${DirectX_INC_SEARCH_PATH})
@ -78,23 +78,23 @@ if(WIN32) # The only platform it makes sense to check for DirectX SDK
# look for D3D11 components # look for D3D11 components
if (DirectX_FOUND) if (DirectX_FOUND)
find_path(DirectX_D3D11_INCLUDE_DIR NAMES D3D11Shader.h HINTS ${DirectX_INC_SEARCH_PATH}) find_path(DirectX_D3D11_INCLUDE_DIR NAMES D3D11Shader.h HINTS ${DirectX_INC_SEARCH_PATH})
get_filename_component(DirectX_LIBRARY_DIR "${DirectX_LIBRARY}" PATH) get_filename_component(DirectX_LIBRARY_DIR "${DirectX_LIBRARY}" PATH)
message(STATUS "DX lib dir: ${DirectX_LIBRARY_DIR}") message(STATUS "DX lib dir: ${DirectX_LIBRARY_DIR}")
find_library(DirectX_D3D11_LIBRARY NAMES d3d11 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) find_library(DirectX_D3D11_LIBRARY NAMES d3d11 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
find_library(DirectX_D3DX11_LIBRARY NAMES d3dx11 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) find_library(DirectX_D3DX11_LIBRARY NAMES d3dx11 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
if (DirectX_D3D11_INCLUDE_DIR AND DirectX_D3D11_LIBRARY) if (DirectX_D3D11_INCLUDE_DIR AND DirectX_D3D11_LIBRARY)
set(DirectX_D3D11_FOUND TRUE) set(DirectX_D3D11_FOUND TRUE)
set(DirectX_D3D11_INCLUDE_DIR ${DirectX_D3D11_INCLUDE_DIR}) set(DirectX_D3D11_INCLUDE_DIR ${DirectX_D3D11_INCLUDE_DIR})
set(DirectX_D3D11_LIBRARIES ${DirectX_D3D11_LIBRARIES} set(DirectX_D3D11_LIBRARIES ${DirectX_D3D11_LIBRARIES}
${DirectX_D3D11_LIBRARY} ${DirectX_D3D11_LIBRARY}
${DirectX_D3DX11_LIBRARY} ${DirectX_D3DX11_LIBRARY}
${DirectX_DXGI_LIBRARY} ${DirectX_DXGI_LIBRARY}
${DirectX_DXERR_LIBRARY} ${DirectX_DXERR_LIBRARY}
${DirectX_DXGUID_LIBRARY} ${DirectX_DXGUID_LIBRARY}
${DirectX_D3DCOMPILER_LIBRARY} ${DirectX_D3DCOMPILER_LIBRARY}
) )
endif () endif ()
mark_as_advanced(DirectX_D3D11_INCLUDE_DIR DirectX_D3D11_LIBRARY DirectX_D3DX11_LIBRARY) mark_as_advanced(DirectX_D3D11_INCLUDE_DIR DirectX_D3D11_LIBRARY DirectX_D3DX11_LIBRARY)
endif () endif ()
endif(WIN32) endif(WIN32)

View File

@ -1,25 +1,25 @@
FIND_PATH( FIND_PATH(
assimp_INCLUDE_DIRS assimp_INCLUDE_DIRS
NAMES postprocess.h scene.h version.h config.h cimport.h NAMES postprocess.h scene.h version.h config.h cimport.h
PATHS /usr/local/include/ PATHS /usr/local/include/
) )
FIND_LIBRARY( FIND_LIBRARY(
assimp_LIBRARIES assimp_LIBRARIES
NAMES assimp NAMES assimp
PATHS /usr/local/lib/ PATHS /usr/local/lib/
) )
IF (assimp_INCLUDE_DIRS AND assimp_LIBRARIES) IF (assimp_INCLUDE_DIRS AND assimp_LIBRARIES)
SET(assimp_FOUND TRUE) SET(assimp_FOUND TRUE)
ENDIF (assimp_INCLUDE_DIRS AND assimp_LIBRARIES) ENDIF (assimp_INCLUDE_DIRS AND assimp_LIBRARIES)
IF (assimp_FOUND) IF (assimp_FOUND)
IF (NOT assimp_FIND_QUIETLY) IF (NOT assimp_FIND_QUIETLY)
MESSAGE(STATUS "Found asset importer library: ${assimp_LIBRARIES}") MESSAGE(STATUS "Found asset importer library: ${assimp_LIBRARIES}")
ENDIF (NOT assimp_FIND_QUIETLY) ENDIF (NOT assimp_FIND_QUIETLY)
ELSE (assimp_FOUND) ELSE (assimp_FOUND)
IF (assimp_FIND_REQUIRED) IF (assimp_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find asset importer library") MESSAGE(FATAL_ERROR "Could not find asset importer library")
ENDIF (assimp_FIND_REQUIRED) ENDIF (assimp_FIND_REQUIRED)
ENDIF (assimp_FOUND) ENDIF (assimp_FOUND)

View File

@ -5,18 +5,18 @@ MACRO(ADD_MSVC_PRECOMPILED_HEADER PrecompiledHeader PrecompiledSource SourcesVar
SET(Sources ${${SourcesVar}}) SET(Sources ${${SourcesVar}})
SET_SOURCE_FILES_PROPERTIES(${PrecompiledSource} SET_SOURCE_FILES_PROPERTIES(${PrecompiledSource}
PROPERTIES COMPILE_FLAGS "/Yc\"${PrecompiledHeader}\" /Fp\"${PrecompiledBinary}\"" PROPERTIES COMPILE_FLAGS "/Yc\"${PrecompiledHeader}\" /Fp\"${PrecompiledBinary}\""
OBJECT_OUTPUTS "${PrecompiledBinary}") OBJECT_OUTPUTS "${PrecompiledBinary}")
# Do not consider .c files # Do not consider .c files
foreach(fname ${Sources}) foreach(fname ${Sources})
GET_FILENAME_COMPONENT(fext ${fname} EXT) GET_FILENAME_COMPONENT(fext ${fname} EXT)
if(fext STREQUAL ".cpp") if(fext STREQUAL ".cpp")
SET_SOURCE_FILES_PROPERTIES(${fname} SET_SOURCE_FILES_PROPERTIES(${fname}
PROPERTIES COMPILE_FLAGS "/Yu\"${PrecompiledBinary}\" /FI\"${PrecompiledBinary}\" /Fp\"${PrecompiledBinary}\"" PROPERTIES COMPILE_FLAGS "/Yu\"${PrecompiledBinary}\" /FI\"${PrecompiledBinary}\" /Fp\"${PrecompiledBinary}\""
OBJECT_DEPENDS "${PrecompiledBinary}") OBJECT_DEPENDS "${PrecompiledBinary}")
endif(fext STREQUAL ".cpp") endif(fext STREQUAL ".cpp")
endforeach(fname) endforeach(fname)
ENDIF(MSVC) ENDIF(MSVC)
# Add precompiled header to SourcesVar # Add precompiled header to SourcesVar

View File

@ -0,0 +1,8 @@
# See <http://EditorConfig.org> for details
[*.{h,hpp,c,cpp}]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_size = 4
indent_style = space

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -53,129 +53,129 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory> #include <memory>
using namespace Assimp; using namespace Assimp;
namespace Assimp { namespace Assimp {
namespace { namespace {
////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////
// Scope utility to write a 3DS file chunk. // Scope utility to write a 3DS file chunk.
// //
// Upon construction, the chunk header is written with the chunk type (flags) // Upon construction, the chunk header is written with the chunk type (flags)
// filled out, but the chunk size left empty. Upon destruction, the correct chunk // filled out, but the chunk size left empty. Upon destruction, the correct chunk
// size based on the then-position of the output stream cursor is filled in. // size based on the then-position of the output stream cursor is filled in.
class ChunkWriter { class ChunkWriter {
enum { enum {
CHUNK_SIZE_NOT_SET = 0xdeadbeef CHUNK_SIZE_NOT_SET = 0xdeadbeef
, SIZE_OFFSET = 2 , SIZE_OFFSET = 2
}; };
public: public:
ChunkWriter(StreamWriterLE& writer, uint16_t chunk_type) ChunkWriter(StreamWriterLE& writer, uint16_t chunk_type)
: writer(writer) : writer(writer)
{ {
chunk_start_pos = writer.GetCurrentPos(); chunk_start_pos = writer.GetCurrentPos();
writer.PutU2(chunk_type); writer.PutU2(chunk_type);
writer.PutU4(CHUNK_SIZE_NOT_SET); writer.PutU4(CHUNK_SIZE_NOT_SET);
} }
~ChunkWriter() { ~ChunkWriter() {
std::size_t head_pos = writer.GetCurrentPos(); std::size_t head_pos = writer.GetCurrentPos();
ai_assert(head_pos > chunk_start_pos); ai_assert(head_pos > chunk_start_pos);
const std::size_t chunk_size = head_pos - chunk_start_pos; const std::size_t chunk_size = head_pos - chunk_start_pos;
writer.SetCurrentPos(chunk_start_pos + SIZE_OFFSET); writer.SetCurrentPos(chunk_start_pos + SIZE_OFFSET);
writer.PutU4(chunk_size); writer.PutU4(chunk_size);
writer.SetCurrentPos(head_pos); writer.SetCurrentPos(head_pos);
} }
private: private:
StreamWriterLE& writer; StreamWriterLE& writer;
std::size_t chunk_start_pos; std::size_t chunk_start_pos;
}; };
// Return an unique name for a given |mesh| attached to |node| that // Return an unique name for a given |mesh| attached to |node| that
// preserves the mesh's given name if it has one. |index| is the index // preserves the mesh's given name if it has one. |index| is the index
// of the mesh in |aiScene::mMeshes|. // of the mesh in |aiScene::mMeshes|.
std::string GetMeshName(const aiMesh& mesh, unsigned int index, const aiNode& node) { std::string GetMeshName(const aiMesh& mesh, unsigned int index, const aiNode& node) {
static const std::string underscore = "_"; static const std::string underscore = "_";
char postfix[10] = {0}; char postfix[10] = {0};
ASSIMP_itoa10(postfix, index); ASSIMP_itoa10(postfix, index);
std::string result = node.mName.C_Str(); std::string result = node.mName.C_Str();
if (mesh.mName.length > 0) { if (mesh.mName.length > 0) {
result += underscore + mesh.mName.C_Str(); result += underscore + mesh.mName.C_Str();
} }
return result + underscore + postfix; return result + underscore + postfix;
} }
// Return an unique name for a given |mat| with original position |index| // Return an unique name for a given |mat| with original position |index|
// in |aiScene::mMaterials|. The name preserves the original material // in |aiScene::mMaterials|. The name preserves the original material
// name if possible. // name if possible.
std::string GetMaterialName(const aiMaterial& mat, unsigned int index) { std::string GetMaterialName(const aiMaterial& mat, unsigned int index) {
static const std::string underscore = "_"; static const std::string underscore = "_";
char postfix[10] = {0}; char postfix[10] = {0};
ASSIMP_itoa10(postfix, index); ASSIMP_itoa10(postfix, index);
aiString mat_name; aiString mat_name;
if (AI_SUCCESS == mat.Get(AI_MATKEY_NAME, mat_name)) { if (AI_SUCCESS == mat.Get(AI_MATKEY_NAME, mat_name)) {
return mat_name.C_Str() + underscore + postfix; return mat_name.C_Str() + underscore + postfix;
} }
return "Material" + underscore + postfix; return "Material" + underscore + postfix;
} }
// Collect world transformations for each node // Collect world transformations for each node
void CollectTrafos(const aiNode* node, std::map<const aiNode*, aiMatrix4x4>& trafos) { void CollectTrafos(const aiNode* node, std::map<const aiNode*, aiMatrix4x4>& trafos) {
const aiMatrix4x4& parent = node->mParent ? trafos[node->mParent] : aiMatrix4x4(); const aiMatrix4x4& parent = node->mParent ? trafos[node->mParent] : aiMatrix4x4();
trafos[node] = parent * node->mTransformation; trafos[node] = parent * node->mTransformation;
for (unsigned int i = 0; i < node->mNumChildren; ++i) { for (unsigned int i = 0; i < node->mNumChildren; ++i) {
CollectTrafos(node->mChildren[i], trafos); CollectTrafos(node->mChildren[i], trafos);
} }
} }
// Generate a flat list of the meshes (by index) assigned to each node // Generate a flat list of the meshes (by index) assigned to each node
void CollectMeshes(const aiNode* node, std::multimap<const aiNode*, unsigned int>& meshes) { void CollectMeshes(const aiNode* node, std::multimap<const aiNode*, unsigned int>& meshes) {
for (unsigned int i = 0; i < node->mNumMeshes; ++i) { for (unsigned int i = 0; i < node->mNumMeshes; ++i) {
meshes.insert(std::make_pair(node, node->mMeshes[i])); meshes.insert(std::make_pair(node, node->mMeshes[i]));
} }
for (unsigned int i = 0; i < node->mNumChildren; ++i) { for (unsigned int i = 0; i < node->mNumChildren; ++i) {
CollectMeshes(node->mChildren[i], meshes); CollectMeshes(node->mChildren[i], meshes);
} }
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Worker function for exporting a scene to 3DS. Prototyped and registered in Exporter.cpp // Worker function for exporting a scene to 3DS. Prototyped and registered in Exporter.cpp
void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
{ {
boost::shared_ptr<IOStream> outfile (pIOSystem->Open(pFile, "wb")); boost::shared_ptr<IOStream> outfile (pIOSystem->Open(pFile, "wb"));
if(!outfile) { if(!outfile) {
throw DeadlyExportError("Could not open output .3ds file: " + std::string(pFile)); throw DeadlyExportError("Could not open output .3ds file: " + std::string(pFile));
} }
// TODO: This extra copy should be avoided and all of this made a preprocess // TODO: This extra copy should be avoided and all of this made a preprocess
// requirement of the 3DS exporter. // requirement of the 3DS exporter.
// //
// 3DS meshes can be max 0xffff (16 Bit) vertices and faces, respectively. // 3DS meshes can be max 0xffff (16 Bit) vertices and faces, respectively.
// SplitLargeMeshes can do this, but it requires the correct limit to be set // SplitLargeMeshes can do this, but it requires the correct limit to be set
// which is not possible with the current way of specifying preprocess steps // which is not possible with the current way of specifying preprocess steps
// in |Exporter::ExportFormatEntry|. // in |Exporter::ExportFormatEntry|.
aiScene* scenecopy_tmp; aiScene* scenecopy_tmp;
SceneCombiner::CopyScene(&scenecopy_tmp,pScene); SceneCombiner::CopyScene(&scenecopy_tmp,pScene);
std::auto_ptr<aiScene> scenecopy(scenecopy_tmp); std::auto_ptr<aiScene> scenecopy(scenecopy_tmp);
SplitLargeMeshesProcess_Triangle tri_splitter; SplitLargeMeshesProcess_Triangle tri_splitter;
tri_splitter.SetLimit(0xffff); tri_splitter.SetLimit(0xffff);
tri_splitter.Execute(scenecopy.get()); tri_splitter.Execute(scenecopy.get());
SplitLargeMeshesProcess_Vertex vert_splitter; SplitLargeMeshesProcess_Vertex vert_splitter;
vert_splitter.SetLimit(0xffff); vert_splitter.SetLimit(0xffff);
vert_splitter.Execute(scenecopy.get()); vert_splitter.Execute(scenecopy.get());
// Invoke the actual exporter // Invoke the actual exporter
Discreet3DSExporter exporter(outfile, scenecopy.get()); Discreet3DSExporter exporter(outfile, scenecopy.get());
} }
} // end of namespace Assimp } // end of namespace Assimp
@ -185,379 +185,379 @@ Discreet3DSExporter:: Discreet3DSExporter(boost::shared_ptr<IOStream> outfile, c
: scene(scene) : scene(scene)
, writer(outfile) , writer(outfile)
{ {
CollectTrafos(scene->mRootNode, trafos); CollectTrafos(scene->mRootNode, trafos);
CollectMeshes(scene->mRootNode, meshes); CollectMeshes(scene->mRootNode, meshes);
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAIN); ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAIN);
{ {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJMESH); ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJMESH);
WriteMaterials(); WriteMaterials();
WriteMeshes(); WriteMeshes();
{ {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MASTER_SCALE); ChunkWriter chunk(writer, Discreet3DS::CHUNK_MASTER_SCALE);
writer.PutF4(1.0f); writer.PutF4(1.0f);
} }
} }
{ {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_KEYFRAMER); ChunkWriter chunk(writer, Discreet3DS::CHUNK_KEYFRAMER);
WriteHierarchy(*scene->mRootNode, -1, -1); WriteHierarchy(*scene->mRootNode, -1, -1);
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling_level) int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling_level)
{ {
// 3DS scene hierarchy is serialized as in http://www.martinreddy.net/gfx/3d/3DS.spec // 3DS scene hierarchy is serialized as in http://www.martinreddy.net/gfx/3d/3DS.spec
{ {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO); ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO);
{ {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME); ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME);
// Assimp node names are unique and distinct from all mesh-node // Assimp node names are unique and distinct from all mesh-node
// names we generate; thus we can use them as-is // names we generate; thus we can use them as-is
WriteString(node.mName); WriteString(node.mName);
// Two unknown int16 values - it is even unclear if 0 is a safe value // Two unknown int16 values - it is even unclear if 0 is a safe value
// but luckily importers do not know better either. // but luckily importers do not know better either.
writer.PutI4(0); writer.PutI4(0);
int16_t hierarchy_pos = static_cast<int16_t>(seq); int16_t hierarchy_pos = static_cast<int16_t>(seq);
if (sibling_level != -1) { if (sibling_level != -1) {
hierarchy_pos = sibling_level; hierarchy_pos = sibling_level;
} }
// Write the hierarchy position // Write the hierarchy position
writer.PutI2(hierarchy_pos); writer.PutI2(hierarchy_pos);
} }
} }
// TODO: write transformation chunks // TODO: write transformation chunks
++seq; ++seq;
sibling_level = seq; sibling_level = seq;
// Write all children // Write all children
for (unsigned int i = 0; i < node.mNumChildren; ++i) { for (unsigned int i = 0; i < node.mNumChildren; ++i) {
seq = WriteHierarchy(*node.mChildren[i], seq, i == 0 ? -1 : sibling_level); seq = WriteHierarchy(*node.mChildren[i], seq, i == 0 ? -1 : sibling_level);
} }
// Write all meshes as separate nodes to be able to reference the meshes by name // Write all meshes as separate nodes to be able to reference the meshes by name
for (unsigned int i = 0; i < node.mNumMeshes; ++i) { for (unsigned int i = 0; i < node.mNumMeshes; ++i) {
const bool first_child = node.mNumChildren == 0 && i == 0; const bool first_child = node.mNumChildren == 0 && i == 0;
const unsigned int mesh_idx = node.mMeshes[i]; const unsigned int mesh_idx = node.mMeshes[i];
const aiMesh& mesh = *scene->mMeshes[mesh_idx]; const aiMesh& mesh = *scene->mMeshes[mesh_idx];
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO); ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO);
{ {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME); ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME);
WriteString(GetMeshName(mesh, mesh_idx, node)); WriteString(GetMeshName(mesh, mesh_idx, node));
writer.PutI4(0); writer.PutI4(0);
writer.PutI2(static_cast<int16_t>(first_child ? seq : sibling_level)); writer.PutI2(static_cast<int16_t>(first_child ? seq : sibling_level));
++seq; ++seq;
} }
} }
return seq; return seq;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteMaterials() void Discreet3DSExporter::WriteMaterials()
{ {
for (unsigned int i = 0; i < scene->mNumMaterials; ++i) { for (unsigned int i = 0; i < scene->mNumMaterials; ++i) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATERIAL); ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATERIAL);
const aiMaterial& mat = *scene->mMaterials[i]; const aiMaterial& mat = *scene->mMaterials[i];
{ {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATNAME); ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATNAME);
const std::string& name = GetMaterialName(mat, i); const std::string& name = GetMaterialName(mat, i);
WriteString(name); WriteString(name);
} }
aiColor3D color; aiColor3D color;
if (mat.Get(AI_MATKEY_COLOR_DIFFUSE, color) == AI_SUCCESS) { if (mat.Get(AI_MATKEY_COLOR_DIFFUSE, color) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_DIFFUSE); ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_DIFFUSE);
WriteColor(color); WriteColor(color);
} }
if (mat.Get(AI_MATKEY_COLOR_SPECULAR, color) == AI_SUCCESS) { if (mat.Get(AI_MATKEY_COLOR_SPECULAR, color) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SPECULAR); ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SPECULAR);
WriteColor(color); WriteColor(color);
} }
if (mat.Get(AI_MATKEY_COLOR_AMBIENT, color) == AI_SUCCESS) { if (mat.Get(AI_MATKEY_COLOR_AMBIENT, color) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_AMBIENT); ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_AMBIENT);
WriteColor(color); WriteColor(color);
} }
if (mat.Get(AI_MATKEY_COLOR_EMISSIVE, color) == AI_SUCCESS) { if (mat.Get(AI_MATKEY_COLOR_EMISSIVE, color) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SELF_ILLUM); ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SELF_ILLUM);
WriteColor(color); WriteColor(color);
} }
aiShadingMode shading_mode = aiShadingMode_Flat; aiShadingMode shading_mode = aiShadingMode_Flat;
if (mat.Get(AI_MATKEY_SHADING_MODEL, shading_mode) == AI_SUCCESS) { if (mat.Get(AI_MATKEY_SHADING_MODEL, shading_mode) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHADING); ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHADING);
Discreet3DS::shadetype3ds shading_mode_out; Discreet3DS::shadetype3ds shading_mode_out;
switch(shading_mode) { switch(shading_mode) {
case aiShadingMode_Flat: case aiShadingMode_Flat:
case aiShadingMode_NoShading: case aiShadingMode_NoShading:
shading_mode_out = Discreet3DS::Flat; shading_mode_out = Discreet3DS::Flat;
break; break;
case aiShadingMode_Gouraud: case aiShadingMode_Gouraud:
case aiShadingMode_Toon: case aiShadingMode_Toon:
case aiShadingMode_OrenNayar: case aiShadingMode_OrenNayar:
case aiShadingMode_Minnaert: case aiShadingMode_Minnaert:
shading_mode_out = Discreet3DS::Gouraud; shading_mode_out = Discreet3DS::Gouraud;
break; break;
case aiShadingMode_Phong: case aiShadingMode_Phong:
case aiShadingMode_Blinn: case aiShadingMode_Blinn:
case aiShadingMode_CookTorrance: case aiShadingMode_CookTorrance:
case aiShadingMode_Fresnel: case aiShadingMode_Fresnel:
shading_mode_out = Discreet3DS::Phong; shading_mode_out = Discreet3DS::Phong;
break; break;
default: default:
shading_mode_out = Discreet3DS::Flat; shading_mode_out = Discreet3DS::Flat;
ai_assert(false); ai_assert(false);
}; };
writer.PutU2(static_cast<uint16_t>(shading_mode_out)); writer.PutU2(static_cast<uint16_t>(shading_mode_out));
} }
float f; float f;
if (mat.Get(AI_MATKEY_SHININESS, f) == AI_SUCCESS) { if (mat.Get(AI_MATKEY_SHININESS, f) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHININESS); ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHININESS);
WritePercentChunk(f); WritePercentChunk(f);
} }
if (mat.Get(AI_MATKEY_SHININESS_STRENGTH, f) == AI_SUCCESS) { if (mat.Get(AI_MATKEY_SHININESS_STRENGTH, f) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHININESS_PERCENT); ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHININESS_PERCENT);
WritePercentChunk(f); WritePercentChunk(f);
} }
int twosided; int twosided;
if (mat.Get(AI_MATKEY_TWOSIDED, twosided) == AI_SUCCESS && twosided != 0) { if (mat.Get(AI_MATKEY_TWOSIDED, twosided) == AI_SUCCESS && twosided != 0) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_TWO_SIDE); ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_TWO_SIDE);
writer.PutI2(1); writer.PutI2(1);
} }
WriteTexture(mat, aiTextureType_DIFFUSE, Discreet3DS::CHUNK_MAT_TEXTURE); WriteTexture(mat, aiTextureType_DIFFUSE, Discreet3DS::CHUNK_MAT_TEXTURE);
WriteTexture(mat, aiTextureType_HEIGHT, Discreet3DS::CHUNK_MAT_BUMPMAP); WriteTexture(mat, aiTextureType_HEIGHT, Discreet3DS::CHUNK_MAT_BUMPMAP);
WriteTexture(mat, aiTextureType_OPACITY, Discreet3DS::CHUNK_MAT_OPACMAP); WriteTexture(mat, aiTextureType_OPACITY, Discreet3DS::CHUNK_MAT_OPACMAP);
WriteTexture(mat, aiTextureType_SHININESS, Discreet3DS::CHUNK_MAT_MAT_SHINMAP); WriteTexture(mat, aiTextureType_SHININESS, Discreet3DS::CHUNK_MAT_MAT_SHINMAP);
WriteTexture(mat, aiTextureType_SPECULAR, Discreet3DS::CHUNK_MAT_SPECMAP); WriteTexture(mat, aiTextureType_SPECULAR, Discreet3DS::CHUNK_MAT_SPECMAP);
WriteTexture(mat, aiTextureType_EMISSIVE, Discreet3DS::CHUNK_MAT_SELFIMAP); WriteTexture(mat, aiTextureType_EMISSIVE, Discreet3DS::CHUNK_MAT_SELFIMAP);
WriteTexture(mat, aiTextureType_REFLECTION, Discreet3DS::CHUNK_MAT_REFLMAP); WriteTexture(mat, aiTextureType_REFLECTION, Discreet3DS::CHUNK_MAT_REFLMAP);
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags) void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags)
{ {
aiString path; aiString path;
aiTextureMapMode map_mode[2] = { aiTextureMapMode map_mode[2] = {
aiTextureMapMode_Wrap, aiTextureMapMode_Wrap aiTextureMapMode_Wrap, aiTextureMapMode_Wrap
}; };
float blend = 1.0f; float blend = 1.0f;
if (mat.GetTexture(type, 0, &path, NULL, NULL, &blend, NULL, map_mode) != AI_SUCCESS || !path.length) { if (mat.GetTexture(type, 0, &path, NULL, NULL, &blend, NULL, map_mode) != AI_SUCCESS || !path.length) {
return; return;
} }
// TODO: handle embedded textures properly // TODO: handle embedded textures properly
if (path.data[0] == '*') { if (path.data[0] == '*') {
DefaultLogger::get()->error("Ignoring embedded texture for export: " + std::string(path.C_Str())); DefaultLogger::get()->error("Ignoring embedded texture for export: " + std::string(path.C_Str()));
return; return;
} }
ChunkWriter chunk(writer, chunk_flags); ChunkWriter chunk(writer, chunk_flags);
{ {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPFILE); ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPFILE);
WriteString(path); WriteString(path);
} }
WritePercentChunk(blend); WritePercentChunk(blend);
{ {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MAP_TILING); ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MAP_TILING);
uint16_t val = 0; // WRAP uint16_t val = 0; // WRAP
if (map_mode[0] == aiTextureMapMode_Mirror) { if (map_mode[0] == aiTextureMapMode_Mirror) {
val = 0x2; val = 0x2;
} }
else if (map_mode[0] == aiTextureMapMode_Decal) { else if (map_mode[0] == aiTextureMapMode_Decal) {
val = 0x10; val = 0x10;
} }
writer.PutU2(val); writer.PutU2(val);
} }
// TODO: export texture transformation (i.e. UV offset, scale, rotation) // TODO: export texture transformation (i.e. UV offset, scale, rotation)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteMeshes() void Discreet3DSExporter::WriteMeshes()
{ {
// NOTE: 3DS allows for instances. However: // NOTE: 3DS allows for instances. However:
// i) not all importers support reading them // i) not all importers support reading them
// ii) instances are not as flexible as they are in assimp, in particular, // ii) instances are not as flexible as they are in assimp, in particular,
// nodes can carry (and instance) only one mesh. // nodes can carry (and instance) only one mesh.
// //
// This exporter currently deep clones all instanced meshes, i.e. for each mesh // This exporter currently deep clones all instanced meshes, i.e. for each mesh
// attached to a node a full TRIMESH chunk is written to the file. // attached to a node a full TRIMESH chunk is written to the file.
// //
// Furthermore, the TRIMESH is transformed into world space so that it will // Furthermore, the TRIMESH is transformed into world space so that it will
// appear correctly if importers don't read the scene hierarchy at all. // appear correctly if importers don't read the scene hierarchy at all.
for (MeshesByNodeMap::const_iterator it = meshes.begin(); it != meshes.end(); ++it) { for (MeshesByNodeMap::const_iterator it = meshes.begin(); it != meshes.end(); ++it) {
const aiNode& node = *(*it).first; const aiNode& node = *(*it).first;
const unsigned int mesh_idx = (*it).second; const unsigned int mesh_idx = (*it).second;
const aiMesh& mesh = *scene->mMeshes[mesh_idx]; const aiMesh& mesh = *scene->mMeshes[mesh_idx];
// This should not happen if the SLM step is correctly executed // This should not happen if the SLM step is correctly executed
// before the scene is handed to the exporter // before the scene is handed to the exporter
ai_assert(mesh.mNumVertices <= 0xffff); ai_assert(mesh.mNumVertices <= 0xffff);
ai_assert(mesh.mNumFaces <= 0xffff); ai_assert(mesh.mNumFaces <= 0xffff);
const aiMatrix4x4& trafo = trafos[&node]; const aiMatrix4x4& trafo = trafos[&node];
ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJBLOCK); ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJBLOCK);
// Mesh name is tied to the node it is attached to so it can later be referenced // Mesh name is tied to the node it is attached to so it can later be referenced
const std::string& name = GetMeshName(mesh, mesh_idx, node); const std::string& name = GetMeshName(mesh, mesh_idx, node);
WriteString(name); WriteString(name);
// TRIMESH chunk // TRIMESH chunk
ChunkWriter chunk2(writer, Discreet3DS::CHUNK_TRIMESH); ChunkWriter chunk2(writer, Discreet3DS::CHUNK_TRIMESH);
// Vertices in world space // Vertices in world space
{ {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_VERTLIST); ChunkWriter chunk(writer, Discreet3DS::CHUNK_VERTLIST);
const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices); const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
writer.PutU2(count); writer.PutU2(count);
for (unsigned int i = 0; i < mesh.mNumVertices; ++i) { for (unsigned int i = 0; i < mesh.mNumVertices; ++i) {
const aiVector3D& v = trafo * mesh.mVertices[i]; const aiVector3D& v = trafo * mesh.mVertices[i];
writer.PutF4(v.x); writer.PutF4(v.x);
writer.PutF4(v.y); writer.PutF4(v.y);
writer.PutF4(v.z); writer.PutF4(v.z);
} }
} }
// UV coordinates // UV coordinates
if (mesh.HasTextureCoords(0)) { if (mesh.HasTextureCoords(0)) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPLIST); ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPLIST);
const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices); const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
writer.PutU2(count); writer.PutU2(count);
for (unsigned int i = 0; i < mesh.mNumVertices; ++i) { for (unsigned int i = 0; i < mesh.mNumVertices; ++i) {
const aiVector3D& v = mesh.mTextureCoords[0][i]; const aiVector3D& v = mesh.mTextureCoords[0][i];
writer.PutF4(v.x); writer.PutF4(v.x);
writer.PutF4(v.y); writer.PutF4(v.y);
} }
} }
// Faces (indices) // Faces (indices)
{ {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACELIST); ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACELIST);
ai_assert(mesh.mNumFaces <= 0xffff); ai_assert(mesh.mNumFaces <= 0xffff);
// Count triangles, discard lines and points // Count triangles, discard lines and points
uint16_t count = 0; uint16_t count = 0;
for (unsigned int i = 0; i < mesh.mNumFaces; ++i) { for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
const aiFace& f = mesh.mFaces[i]; const aiFace& f = mesh.mFaces[i];
if (f.mNumIndices < 3) { if (f.mNumIndices < 3) {
continue; continue;
} }
// TRIANGULATE step is a pre-requisite so we should not see polys here // TRIANGULATE step is a pre-requisite so we should not see polys here
ai_assert(f.mNumIndices == 3); ai_assert(f.mNumIndices == 3);
++count; ++count;
} }
writer.PutU2(count); writer.PutU2(count);
for (unsigned int i = 0; i < mesh.mNumFaces; ++i) { for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
const aiFace& f = mesh.mFaces[i]; const aiFace& f = mesh.mFaces[i];
if (f.mNumIndices < 3) { if (f.mNumIndices < 3) {
continue; continue;
} }
for (unsigned int j = 0; j < 3; ++j) { for (unsigned int j = 0; j < 3; ++j) {
ai_assert(f.mIndices[j] <= 0xffff); ai_assert(f.mIndices[j] <= 0xffff);
writer.PutI2(static_cast<uint16_t>(f.mIndices[j])); writer.PutI2(static_cast<uint16_t>(f.mIndices[j]));
} }
// Edge visibility flag // Edge visibility flag
writer.PutI2(0x0); writer.PutI2(0x0);
} }
// TODO: write smoothing groups (CHUNK_SMOOLIST) // TODO: write smoothing groups (CHUNK_SMOOLIST)
WriteFaceMaterialChunk(mesh); WriteFaceMaterialChunk(mesh);
} }
// Transformation matrix by which the mesh vertices have been pre-transformed with. // Transformation matrix by which the mesh vertices have been pre-transformed with.
{ {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRMATRIX); ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRMATRIX);
for (unsigned int r = 0; r < 4; ++r) { for (unsigned int r = 0; r < 4; ++r) {
for (unsigned int c = 0; c < 3; ++c) { for (unsigned int c = 0; c < 3; ++c) {
writer.PutF4(trafo[r][c]); writer.PutF4(trafo[r][c]);
} }
} }
} }
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteFaceMaterialChunk(const aiMesh& mesh) void Discreet3DSExporter::WriteFaceMaterialChunk(const aiMesh& mesh)
{ {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACEMAT); ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACEMAT);
const std::string& name = GetMaterialName(*scene->mMaterials[mesh.mMaterialIndex], mesh.mMaterialIndex); const std::string& name = GetMaterialName(*scene->mMaterials[mesh.mMaterialIndex], mesh.mMaterialIndex);
WriteString(name); WriteString(name);
// Because assimp splits meshes by material, only a single // Because assimp splits meshes by material, only a single
// FACEMAT chunk needs to be written // FACEMAT chunk needs to be written
ai_assert(mesh.mNumFaces <= 0xffff); ai_assert(mesh.mNumFaces <= 0xffff);
const uint16_t count = static_cast<uint16_t>(mesh.mNumFaces); const uint16_t count = static_cast<uint16_t>(mesh.mNumFaces);
writer.PutU2(count); writer.PutU2(count);
for (unsigned int i = 0; i < mesh.mNumFaces; ++i) { for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
writer.PutU2(static_cast<uint16_t>(i)); writer.PutU2(static_cast<uint16_t>(i));
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteString(const std::string& s) { void Discreet3DSExporter::WriteString(const std::string& s) {
for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) { for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
writer.PutI1(*it); writer.PutI1(*it);
} }
writer.PutI1('\0'); writer.PutI1('\0');
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteString(const aiString& s) { void Discreet3DSExporter::WriteString(const aiString& s) {
for (std::size_t i = 0; i < s.length; ++i) { for (std::size_t i = 0; i < s.length; ++i) {
writer.PutI1(s.data[i]); writer.PutI1(s.data[i]);
} }
writer.PutI1('\0'); writer.PutI1('\0');
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteColor(const aiColor3D& color) { void Discreet3DSExporter::WriteColor(const aiColor3D& color) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_RGBF); ChunkWriter chunk(writer, Discreet3DS::CHUNK_RGBF);
writer.PutF4(color.r); writer.PutF4(color.r);
writer.PutF4(color.g); writer.PutF4(color.g);
writer.PutF4(color.b); writer.PutF4(color.b);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WritePercentChunk(float f) { void Discreet3DSExporter::WritePercentChunk(float f) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_PERCENTF); ChunkWriter chunk(writer, Discreet3DS::CHUNK_PERCENTF);
writer.PutF4(f); writer.PutF4(f);
} }

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -64,32 +64,32 @@ namespace Assimp
class Discreet3DSExporter class Discreet3DSExporter
{ {
public: public:
Discreet3DSExporter(boost::shared_ptr<IOStream> outfile, const aiScene* pScene); Discreet3DSExporter(boost::shared_ptr<IOStream> outfile, const aiScene* pScene);
private: private:
void WriteMeshes(); void WriteMeshes();
void WriteMaterials(); void WriteMaterials();
void WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags); void WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags);
void WriteFaceMaterialChunk(const aiMesh& mesh); void WriteFaceMaterialChunk(const aiMesh& mesh);
int WriteHierarchy(const aiNode& node, int level, int sibling_level); int WriteHierarchy(const aiNode& node, int level, int sibling_level);
void WriteString(const std::string& s); void WriteString(const std::string& s);
void WriteString(const aiString& s); void WriteString(const aiString& s);
void WriteColor(const aiColor3D& color); void WriteColor(const aiColor3D& color);
void WritePercentChunk(float f); void WritePercentChunk(float f);
private: private:
const aiScene* const scene; const aiScene* const scene;
StreamWriterLE writer; StreamWriterLE writer;
std::map<const aiNode*, aiMatrix4x4> trafos; std::map<const aiNode*, aiMatrix4x4> trafos;
typedef std::multimap<const aiNode*, unsigned int> MeshesByNodeMap; typedef std::multimap<const aiNode*, unsigned int> MeshesByNodeMap;
MeshesByNodeMap meshes; MeshesByNodeMap meshes;
}; };

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -53,8 +53,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "./../include/assimp/anim.h" #include "./../include/assimp/anim.h"
#include <stdio.h> //sprintf #include <stdio.h> //sprintf
namespace Assimp { namespace Assimp {
namespace D3DS { namespace D3DS {
#include "./../include/assimp/Compiler/pushpack1.h" #include "./../include/assimp/Compiler/pushpack1.h"
@ -65,253 +65,253 @@ namespace D3DS {
class Discreet3DS class Discreet3DS
{ {
private: private:
inline Discreet3DS() {} inline Discreet3DS() {}
public: public:
//! data structure for a single chunk in a .3ds file //! data structure for a single chunk in a .3ds file
struct Chunk struct Chunk
{ {
uint16_t Flag; uint16_t Flag;
uint32_t Size; uint32_t Size;
} PACK_STRUCT; } PACK_STRUCT;
//! Used for shading field in material3ds structure //! Used for shading field in material3ds structure
//! From AutoDesk 3ds SDK //! From AutoDesk 3ds SDK
typedef enum typedef enum
{ {
// translated to gouraud shading with wireframe active // translated to gouraud shading with wireframe active
Wire = 0x0, Wire = 0x0,
// if this material is set, no vertex normals will // if this material is set, no vertex normals will
// be calculated for the model. Face normals + gouraud // be calculated for the model. Face normals + gouraud
Flat = 0x1, Flat = 0x1,
// standard gouraud shading // standard gouraud shading
Gouraud = 0x2, Gouraud = 0x2,
// phong shading // phong shading
Phong = 0x3, Phong = 0x3,
// cooktorrance or anistropic phong shading ... // cooktorrance or anistropic phong shading ...
// the exact meaning is unknown, if you know it // the exact meaning is unknown, if you know it
// feel free to tell me ;-) // feel free to tell me ;-)
Metal = 0x4, Metal = 0x4,
// required by the ASE loader // required by the ASE loader
Blinn = 0x5 Blinn = 0x5
} shadetype3ds; } shadetype3ds;
// Flags for animated keys // Flags for animated keys
enum enum
{ {
KEY_USE_TENS = 0x1, KEY_USE_TENS = 0x1,
KEY_USE_CONT = 0x2, KEY_USE_CONT = 0x2,
KEY_USE_BIAS = 0x4, KEY_USE_BIAS = 0x4,
KEY_USE_EASE_TO = 0x8, KEY_USE_EASE_TO = 0x8,
KEY_USE_EASE_FROM = 0x10 KEY_USE_EASE_FROM = 0x10
} ; } ;
enum enum
{ {
// ******************************************************************** // ********************************************************************
// Basic chunks which can be found everywhere in the file // Basic chunks which can be found everywhere in the file
CHUNK_VERSION = 0x0002, CHUNK_VERSION = 0x0002,
CHUNK_RGBF = 0x0010, // float4 R; float4 G; float4 B CHUNK_RGBF = 0x0010, // float4 R; float4 G; float4 B
CHUNK_RGBB = 0x0011, // int1 R; int1 G; int B CHUNK_RGBB = 0x0011, // int1 R; int1 G; int B
// Linear color values (gamma = 2.2?) // Linear color values (gamma = 2.2?)
CHUNK_LINRGBF = 0x0013, // float4 R; float4 G; float4 B CHUNK_LINRGBF = 0x0013, // float4 R; float4 G; float4 B
CHUNK_LINRGBB = 0x0012, // int1 R; int1 G; int B CHUNK_LINRGBB = 0x0012, // int1 R; int1 G; int B
CHUNK_PERCENTW = 0x0030, // int2 percentage CHUNK_PERCENTW = 0x0030, // int2 percentage
CHUNK_PERCENTF = 0x0031, // float4 percentage CHUNK_PERCENTF = 0x0031, // float4 percentage
// ******************************************************************** // ********************************************************************
// Prj master chunk // Prj master chunk
CHUNK_PRJ = 0xC23D, CHUNK_PRJ = 0xC23D,
// MDLI master chunk // MDLI master chunk
CHUNK_MLI = 0x3DAA, CHUNK_MLI = 0x3DAA,
// Primary main chunk of the .3ds file // Primary main chunk of the .3ds file
CHUNK_MAIN = 0x4D4D, CHUNK_MAIN = 0x4D4D,
// Mesh main chunk // Mesh main chunk
CHUNK_OBJMESH = 0x3D3D, CHUNK_OBJMESH = 0x3D3D,
// Specifies the background color of the .3ds file // Specifies the background color of the .3ds file
// This is passed through the material system for // This is passed through the material system for
// viewing purposes. // viewing purposes.
CHUNK_BKGCOLOR = 0x1200, CHUNK_BKGCOLOR = 0x1200,
// Specifies the ambient base color of the scene. // Specifies the ambient base color of the scene.
// This is added to all materials in the file // This is added to all materials in the file
CHUNK_AMBCOLOR = 0x2100, CHUNK_AMBCOLOR = 0x2100,
// Specifies the background image for the whole scene // Specifies the background image for the whole scene
// This value is passed through the material system // This value is passed through the material system
// to the viewer // to the viewer
CHUNK_BIT_MAP = 0x1100, CHUNK_BIT_MAP = 0x1100,
CHUNK_BIT_MAP_EXISTS = 0x1101, CHUNK_BIT_MAP_EXISTS = 0x1101,
// ******************************************************************** // ********************************************************************
// Viewport related stuff. Ignored // Viewport related stuff. Ignored
CHUNK_DEFAULT_VIEW = 0x3000, CHUNK_DEFAULT_VIEW = 0x3000,
CHUNK_VIEW_TOP = 0x3010, CHUNK_VIEW_TOP = 0x3010,
CHUNK_VIEW_BOTTOM = 0x3020, CHUNK_VIEW_BOTTOM = 0x3020,
CHUNK_VIEW_LEFT = 0x3030, CHUNK_VIEW_LEFT = 0x3030,
CHUNK_VIEW_RIGHT = 0x3040, CHUNK_VIEW_RIGHT = 0x3040,
CHUNK_VIEW_FRONT = 0x3050, CHUNK_VIEW_FRONT = 0x3050,
CHUNK_VIEW_BACK = 0x3060, CHUNK_VIEW_BACK = 0x3060,
CHUNK_VIEW_USER = 0x3070, CHUNK_VIEW_USER = 0x3070,
CHUNK_VIEW_CAMERA = 0x3080, CHUNK_VIEW_CAMERA = 0x3080,
// ******************************************************************** // ********************************************************************
// Mesh chunks // Mesh chunks
CHUNK_OBJBLOCK = 0x4000, CHUNK_OBJBLOCK = 0x4000,
CHUNK_TRIMESH = 0x4100, CHUNK_TRIMESH = 0x4100,
CHUNK_VERTLIST = 0x4110, CHUNK_VERTLIST = 0x4110,
CHUNK_VERTFLAGS = 0x4111, CHUNK_VERTFLAGS = 0x4111,
CHUNK_FACELIST = 0x4120, CHUNK_FACELIST = 0x4120,
CHUNK_FACEMAT = 0x4130, CHUNK_FACEMAT = 0x4130,
CHUNK_MAPLIST = 0x4140, CHUNK_MAPLIST = 0x4140,
CHUNK_SMOOLIST = 0x4150, CHUNK_SMOOLIST = 0x4150,
CHUNK_TRMATRIX = 0x4160, CHUNK_TRMATRIX = 0x4160,
CHUNK_MESHCOLOR = 0x4165, CHUNK_MESHCOLOR = 0x4165,
CHUNK_TXTINFO = 0x4170, CHUNK_TXTINFO = 0x4170,
CHUNK_LIGHT = 0x4600, CHUNK_LIGHT = 0x4600,
CHUNK_CAMERA = 0x4700, CHUNK_CAMERA = 0x4700,
CHUNK_HIERARCHY = 0x4F00, CHUNK_HIERARCHY = 0x4F00,
// Specifies the global scaling factor. This is applied // Specifies the global scaling factor. This is applied
// to the root node's transformation matrix // to the root node's transformation matrix
CHUNK_MASTER_SCALE = 0x0100, CHUNK_MASTER_SCALE = 0x0100,
// ******************************************************************** // ********************************************************************
// Material chunks // Material chunks
CHUNK_MAT_MATERIAL = 0xAFFF, CHUNK_MAT_MATERIAL = 0xAFFF,
// asciiz containing the name of the material // asciiz containing the name of the material
CHUNK_MAT_MATNAME = 0xA000, CHUNK_MAT_MATNAME = 0xA000,
CHUNK_MAT_AMBIENT = 0xA010, // followed by color chunk CHUNK_MAT_AMBIENT = 0xA010, // followed by color chunk
CHUNK_MAT_DIFFUSE = 0xA020, // followed by color chunk CHUNK_MAT_DIFFUSE = 0xA020, // followed by color chunk
CHUNK_MAT_SPECULAR = 0xA030, // followed by color chunk CHUNK_MAT_SPECULAR = 0xA030, // followed by color chunk
// Specifies the shininess of the material // Specifies the shininess of the material
// followed by percentage chunk // followed by percentage chunk
CHUNK_MAT_SHININESS = 0xA040, CHUNK_MAT_SHININESS = 0xA040,
CHUNK_MAT_SHININESS_PERCENT = 0xA041 , CHUNK_MAT_SHININESS_PERCENT = 0xA041 ,
// Specifies the shading mode to be used // Specifies the shading mode to be used
// followed by a short // followed by a short
CHUNK_MAT_SHADING = 0xA100, CHUNK_MAT_SHADING = 0xA100,
// NOTE: Emissive color (self illumination) seems not // NOTE: Emissive color (self illumination) seems not
// to be a color but a single value, type is unknown. // to be a color but a single value, type is unknown.
// Make the parser accept both of them. // Make the parser accept both of them.
// followed by percentage chunk (?) // followed by percentage chunk (?)
CHUNK_MAT_SELF_ILLUM = 0xA080, CHUNK_MAT_SELF_ILLUM = 0xA080,
// Always followed by percentage chunk (?) // Always followed by percentage chunk (?)
CHUNK_MAT_SELF_ILPCT = 0xA084, CHUNK_MAT_SELF_ILPCT = 0xA084,
// Always followed by percentage chunk // Always followed by percentage chunk
CHUNK_MAT_TRANSPARENCY = 0xA050, CHUNK_MAT_TRANSPARENCY = 0xA050,
// Diffuse texture channel 0 // Diffuse texture channel 0
CHUNK_MAT_TEXTURE = 0xA200, CHUNK_MAT_TEXTURE = 0xA200,
// Contains opacity information for each texel // Contains opacity information for each texel
CHUNK_MAT_OPACMAP = 0xA210, CHUNK_MAT_OPACMAP = 0xA210,
// Contains a reflection map to be used to reflect // Contains a reflection map to be used to reflect
// the environment. This is partially supported. // the environment. This is partially supported.
CHUNK_MAT_REFLMAP = 0xA220, CHUNK_MAT_REFLMAP = 0xA220,
// Self Illumination map (emissive colors) // Self Illumination map (emissive colors)
CHUNK_MAT_SELFIMAP = 0xA33d, CHUNK_MAT_SELFIMAP = 0xA33d,
// Bumpmap. Not specified whether it is a heightmap // Bumpmap. Not specified whether it is a heightmap
// or a normal map. Assme it is a heightmap since // or a normal map. Assme it is a heightmap since
// artist normally prefer this format. // artist normally prefer this format.
CHUNK_MAT_BUMPMAP = 0xA230, CHUNK_MAT_BUMPMAP = 0xA230,
// Specular map. Seems to influence the specular color // Specular map. Seems to influence the specular color
CHUNK_MAT_SPECMAP = 0xA204, CHUNK_MAT_SPECMAP = 0xA204,
// Holds shininess data. // Holds shininess data.
CHUNK_MAT_MAT_SHINMAP = 0xA33C, CHUNK_MAT_MAT_SHINMAP = 0xA33C,
// Scaling in U/V direction. // Scaling in U/V direction.
// (need to gen separate UV coordinate set // (need to gen separate UV coordinate set
// and do this by hand) // and do this by hand)
CHUNK_MAT_MAP_USCALE = 0xA354, CHUNK_MAT_MAP_USCALE = 0xA354,
CHUNK_MAT_MAP_VSCALE = 0xA356, CHUNK_MAT_MAP_VSCALE = 0xA356,
// Translation in U/V direction. // Translation in U/V direction.
// (need to gen separate UV coordinate set // (need to gen separate UV coordinate set
// and do this by hand) // and do this by hand)
CHUNK_MAT_MAP_UOFFSET = 0xA358, CHUNK_MAT_MAP_UOFFSET = 0xA358,
CHUNK_MAT_MAP_VOFFSET = 0xA35a, CHUNK_MAT_MAP_VOFFSET = 0xA35a,
// UV-coordinates rotation around the z-axis // UV-coordinates rotation around the z-axis
// Assumed to be in radians. // Assumed to be in radians.
CHUNK_MAT_MAP_ANG = 0xA35C, CHUNK_MAT_MAP_ANG = 0xA35C,
// Tiling flags for 3DS files // Tiling flags for 3DS files
CHUNK_MAT_MAP_TILING = 0xa351, CHUNK_MAT_MAP_TILING = 0xa351,
// Specifies the file name of a texture // Specifies the file name of a texture
CHUNK_MAPFILE = 0xA300, CHUNK_MAPFILE = 0xA300,
// Specifies whether a materail requires two-sided rendering // Specifies whether a materail requires two-sided rendering
CHUNK_MAT_TWO_SIDE = 0xA081, CHUNK_MAT_TWO_SIDE = 0xA081,
// ******************************************************************** // ********************************************************************
// Main keyframer chunk. Contains translation/rotation/scaling data // Main keyframer chunk. Contains translation/rotation/scaling data
CHUNK_KEYFRAMER = 0xB000, CHUNK_KEYFRAMER = 0xB000,
// Supported sub chunks // Supported sub chunks
CHUNK_TRACKINFO = 0xB002, CHUNK_TRACKINFO = 0xB002,
CHUNK_TRACKOBJNAME = 0xB010, CHUNK_TRACKOBJNAME = 0xB010,
CHUNK_TRACKDUMMYOBJNAME = 0xB011, CHUNK_TRACKDUMMYOBJNAME = 0xB011,
CHUNK_TRACKPIVOT = 0xB013, CHUNK_TRACKPIVOT = 0xB013,
CHUNK_TRACKPOS = 0xB020, CHUNK_TRACKPOS = 0xB020,
CHUNK_TRACKROTATE = 0xB021, CHUNK_TRACKROTATE = 0xB021,
CHUNK_TRACKSCALE = 0xB022, CHUNK_TRACKSCALE = 0xB022,
// ******************************************************************** // ********************************************************************
// Keyframes for various other stuff in the file // Keyframes for various other stuff in the file
// Partially ignored // Partially ignored
CHUNK_AMBIENTKEY = 0xB001, CHUNK_AMBIENTKEY = 0xB001,
CHUNK_TRACKMORPH = 0xB026, CHUNK_TRACKMORPH = 0xB026,
CHUNK_TRACKHIDE = 0xB029, CHUNK_TRACKHIDE = 0xB029,
CHUNK_OBJNUMBER = 0xB030, CHUNK_OBJNUMBER = 0xB030,
CHUNK_TRACKCAMERA = 0xB003, CHUNK_TRACKCAMERA = 0xB003,
CHUNK_TRACKFOV = 0xB023, CHUNK_TRACKFOV = 0xB023,
CHUNK_TRACKROLL = 0xB024, CHUNK_TRACKROLL = 0xB024,
CHUNK_TRACKCAMTGT = 0xB004, CHUNK_TRACKCAMTGT = 0xB004,
CHUNK_TRACKLIGHT = 0xB005, CHUNK_TRACKLIGHT = 0xB005,
CHUNK_TRACKLIGTGT = 0xB006, CHUNK_TRACKLIGTGT = 0xB006,
CHUNK_TRACKSPOTL = 0xB007, CHUNK_TRACKSPOTL = 0xB007,
CHUNK_FRAMES = 0xB008, CHUNK_FRAMES = 0xB008,
// ******************************************************************** // ********************************************************************
// light sub-chunks // light sub-chunks
CHUNK_DL_OFF = 0x4620, CHUNK_DL_OFF = 0x4620,
CHUNK_DL_OUTER_RANGE = 0x465A, CHUNK_DL_OUTER_RANGE = 0x465A,
CHUNK_DL_INNER_RANGE = 0x4659, CHUNK_DL_INNER_RANGE = 0x4659,
CHUNK_DL_MULTIPLIER = 0x465B, CHUNK_DL_MULTIPLIER = 0x465B,
CHUNK_DL_EXCLUDE = 0x4654, CHUNK_DL_EXCLUDE = 0x4654,
CHUNK_DL_ATTENUATE = 0x4625, CHUNK_DL_ATTENUATE = 0x4625,
CHUNK_DL_SPOTLIGHT = 0x4610, CHUNK_DL_SPOTLIGHT = 0x4610,
// camera sub-chunks // camera sub-chunks
CHUNK_CAM_RANGES = 0x4720 CHUNK_CAM_RANGES = 0x4720
}; };
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -324,38 +324,39 @@ struct Face : public FaceWithSmoothingGroup
/** Helper structure representing a texture */ /** Helper structure representing a texture */
struct Texture struct Texture
{ {
//! Default constructor //! Default constructor
Texture() Texture()
: mOffsetU (0.0f) : mOffsetU (0.0f)
, mOffsetV (0.0f) , mOffsetV (0.0f)
, mScaleU (1.0f) , mScaleU (1.0f)
, mScaleV (1.0f) , mScaleV (1.0f)
, mRotation (0.0f) , mRotation (0.0f)
, mMapMode (aiTextureMapMode_Wrap) , mMapMode (aiTextureMapMode_Wrap)
, iUVSrc (0) , bPrivate()
{ , iUVSrc (0)
mTextureBlend = get_qnan(); {
} mTextureBlend = get_qnan();
}
//! Specifies the blend factor for the texture //! Specifies the blend factor for the texture
float mTextureBlend; float mTextureBlend;
//! Specifies the filename of the texture //! Specifies the filename of the texture
std::string mMapName; std::string mMapName;
//! Specifies texture coordinate offsets/scaling/rotations //! Specifies texture coordinate offsets/scaling/rotations
float mOffsetU; float mOffsetU;
float mOffsetV; float mOffsetV;
float mScaleU; float mScaleU;
float mScaleV; float mScaleV;
float mRotation; float mRotation;
//! Specifies the mapping mode to be used for the texture //! Specifies the mapping mode to be used for the texture
aiTextureMapMode mMapMode; aiTextureMapMode mMapMode;
//! Used internally //! Used internally
bool bPrivate; bool bPrivate;
int iUVSrc; int iUVSrc;
}; };
#include "./../include/assimp/Compiler/poppack1.h" #include "./../include/assimp/Compiler/poppack1.h"
@ -364,91 +365,91 @@ struct Texture
/** Helper structure representing a 3ds material */ /** Helper structure representing a 3ds material */
struct Material struct Material
{ {
//! Default constructor. Builds a default name for the material //! Default constructor. Builds a default name for the material
Material() Material()
: :
mDiffuse (0.6f,0.6f,0.6f), // FIX ... we won't want object to be black mDiffuse (0.6f,0.6f,0.6f), // FIX ... we won't want object to be black
mSpecularExponent (0.0f), mSpecularExponent (0.0f),
mShininessStrength (1.0f), mShininessStrength (1.0f),
mShading(Discreet3DS::Gouraud), mShading(Discreet3DS::Gouraud),
mTransparency (1.0f), mTransparency (1.0f),
mBumpHeight (1.0f), mBumpHeight (1.0f),
mTwoSided (false) mTwoSided (false)
{ {
static int iCnt = 0; static int iCnt = 0;
char szTemp[128]; char szTemp[128];
sprintf(szTemp,"UNNAMED_%i",iCnt++); sprintf(szTemp,"UNNAMED_%i",iCnt++);
mName = szTemp; mName = szTemp;
} }
//! Name of the material //! Name of the material
std::string mName; std::string mName;
//! Diffuse color of the material //! Diffuse color of the material
aiColor3D mDiffuse; aiColor3D mDiffuse;
//! Specular exponent //! Specular exponent
float mSpecularExponent; float mSpecularExponent;
//! Shininess strength, in percent //! Shininess strength, in percent
float mShininessStrength; float mShininessStrength;
//! Specular color of the material //! Specular color of the material
aiColor3D mSpecular; aiColor3D mSpecular;
//! Ambient color of the material //! Ambient color of the material
aiColor3D mAmbient; aiColor3D mAmbient;
//! Shading type to be used //! Shading type to be used
Discreet3DS::shadetype3ds mShading; Discreet3DS::shadetype3ds mShading;
//! Opacity of the material //! Opacity of the material
float mTransparency; float mTransparency;
//! Diffuse texture channel //! Diffuse texture channel
Texture sTexDiffuse; Texture sTexDiffuse;
//! Opacity texture channel //! Opacity texture channel
Texture sTexOpacity; Texture sTexOpacity;
//! Specular texture channel //! Specular texture channel
Texture sTexSpecular; Texture sTexSpecular;
//! Reflective texture channel //! Reflective texture channel
Texture sTexReflective; Texture sTexReflective;
//! Bump texture channel //! Bump texture channel
Texture sTexBump; Texture sTexBump;
//! Emissive texture channel //! Emissive texture channel
Texture sTexEmissive; Texture sTexEmissive;
//! Shininess texture channel //! Shininess texture channel
Texture sTexShininess; Texture sTexShininess;
//! Scaling factor for the bump values //! Scaling factor for the bump values
float mBumpHeight; float mBumpHeight;
//! Emissive color //! Emissive color
aiColor3D mEmissive; aiColor3D mEmissive;
//! Ambient texture channel //! Ambient texture channel
//! (used by the ASE format) //! (used by the ASE format)
Texture sTexAmbient; Texture sTexAmbient;
//! True if the material must be rendered from two sides //! True if the material must be rendered from two sides
bool mTwoSided; bool mTwoSided;
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure to represent a 3ds file mesh */ /** Helper structure to represent a 3ds file mesh */
struct Mesh : public MeshWithSmoothingGroups<D3DS::Face> struct Mesh : public MeshWithSmoothingGroups<D3DS::Face>
{ {
//! Default constructor //! Default constructor
Mesh() Mesh()
{ {
static int iCnt = 0; static int iCnt = 0;
// Generate a default name for the mesh // Generate a default name for the mesh
char szTemp[128]; char szTemp[128];
::sprintf(szTemp,"UNNAMED_%i",iCnt++); ::sprintf(szTemp,"UNNAMED_%i",iCnt++);
mName = szTemp; mName = szTemp;
} }
//! Name of the mesh //! Name of the mesh
std::string mName; std::string mName;
//! Texture coordinates //! Texture coordinates
std::vector<aiVector3D> mTexCoords; std::vector<aiVector3D> mTexCoords;
//! Face materials //! Face materials
std::vector<unsigned int> mFaceMaterials; std::vector<unsigned int> mFaceMaterials;
//! Local transformation matrix //! Local transformation matrix
aiMatrix4x4 mMat; aiMatrix4x4 mMat;
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -456,25 +457,25 @@ struct Mesh : public MeshWithSmoothingGroups<D3DS::Face>
C-API, so it would be difficult to make them a template. */ C-API, so it would be difficult to make them a template. */
struct aiFloatKey struct aiFloatKey
{ {
double mTime; ///< The time of this key double mTime; ///< The time of this key
float mValue; ///< The value of this key float mValue; ///< The value of this key
#ifdef __cplusplus #ifdef __cplusplus
// time is not compared // time is not compared
bool operator == (const aiFloatKey& o) const bool operator == (const aiFloatKey& o) const
{return o.mValue == this->mValue;} {return o.mValue == this->mValue;}
bool operator != (const aiFloatKey& o) const bool operator != (const aiFloatKey& o) const
{return o.mValue != this->mValue;} {return o.mValue != this->mValue;}
// Only time is compared. This operator is defined // Only time is compared. This operator is defined
// for use with std::sort // for use with std::sort
bool operator < (const aiFloatKey& o) const bool operator < (const aiFloatKey& o) const
{return mTime < o.mTime;} {return mTime < o.mTime;}
bool operator > (const aiFloatKey& o) const bool operator > (const aiFloatKey& o) const
{return mTime > o.mTime;} {return mTime > o.mTime;}
#endif #endif
}; };
@ -483,104 +484,104 @@ struct aiFloatKey
/** Helper structure to represent a 3ds file node */ /** Helper structure to represent a 3ds file node */
struct Node struct Node
{ {
Node() Node()
: mParent()
, mInstanceNumber()
, mHierarchyPos (0)
, mHierarchyIndex (0)
, mInstanceCount (1)
{
static int iCnt = 0;
: mHierarchyPos (0) // Generate a default name for the node
, mHierarchyIndex (0) char szTemp[128];
, mInstanceCount (1) ::sprintf(szTemp,"UNNAMED_%i",iCnt++);
mName = szTemp;
{ aRotationKeys.reserve (20);
static int iCnt = 0; aPositionKeys.reserve (20);
aScalingKeys.reserve (20);
}
// Generate a default name for the node ~Node()
char szTemp[128]; {
::sprintf(szTemp,"UNNAMED_%i",iCnt++); for (unsigned int i = 0; i < mChildren.size();++i)
mName = szTemp; delete mChildren[i];
}
aRotationKeys.reserve (20); //! Pointer to the parent node
aPositionKeys.reserve (20); Node* mParent;
aScalingKeys.reserve (20);
}
~Node() //! Holds all child nodes
{ std::vector<Node*> mChildren;
for (unsigned int i = 0; i < mChildren.size();++i)
delete mChildren[i];
}
//! Pointer to the parent node //! Name of the node
Node* mParent; std::string mName;
//! Holds all child nodes //! InstanceNumber of the node
std::vector<Node*> mChildren; int32_t mInstanceNumber;
//! Name of the node //! Dummy nodes: real name to be combined with the $$$DUMMY
std::string mName; std::string mDummyName;
//! InstanceNumber of the node //! Position of the node in the hierarchy (tree depth)
int32_t mInstanceNumber; int16_t mHierarchyPos;
//! Dummy nodes: real name to be combined with the $$$DUMMY //! Index of the node
std::string mDummyName; int16_t mHierarchyIndex;
//! Position of the node in the hierarchy (tree depth) //! Rotation keys loaded from the file
int16_t mHierarchyPos; std::vector<aiQuatKey> aRotationKeys;
//! Index of the node //! Position keys loaded from the file
int16_t mHierarchyIndex; std::vector<aiVectorKey> aPositionKeys;
//! Rotation keys loaded from the file //! Scaling keys loaded from the file
std::vector<aiQuatKey> aRotationKeys; std::vector<aiVectorKey> aScalingKeys;
//! Position keys loaded from the file
std::vector<aiVectorKey> aPositionKeys;
//! Scaling keys loaded from the file
std::vector<aiVectorKey> aScalingKeys;
// For target lights (spot lights and directional lights): // For target lights (spot lights and directional lights):
// The position of the target // The position of the target
std::vector< aiVectorKey > aTargetPositionKeys; std::vector< aiVectorKey > aTargetPositionKeys;
// For cameras: the camera roll angle // For cameras: the camera roll angle
std::vector< aiFloatKey > aCameraRollKeys; std::vector< aiFloatKey > aCameraRollKeys;
//! Pivot position loaded from the file //! Pivot position loaded from the file
aiVector3D vPivot; aiVector3D vPivot;
//instance count, will be kept only for the first node //instance count, will be kept only for the first node
int32_t mInstanceCount; int32_t mInstanceCount;
//! Add a child node, setup the right parent node for it //! Add a child node, setup the right parent node for it
//! \param pc Node to be 'adopted' //! \param pc Node to be 'adopted'
inline Node& push_back(Node* pc) inline Node& push_back(Node* pc)
{ {
mChildren.push_back(pc); mChildren.push_back(pc);
pc->mParent = this; pc->mParent = this;
return *this; return *this;
} }
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure analogue to aiScene */ /** Helper structure analogue to aiScene */
struct Scene struct Scene
{ {
//! List of all materials loaded //! List of all materials loaded
//! NOTE: 3ds references materials globally //! NOTE: 3ds references materials globally
std::vector<Material> mMaterials; std::vector<Material> mMaterials;
//! List of all meshes loaded //! List of all meshes loaded
std::vector<Mesh> mMeshes; std::vector<Mesh> mMeshes;
//! List of all cameras loaded //! List of all cameras loaded
std::vector<aiCamera*> mCameras; std::vector<aiCamera*> mCameras;
//! List of all lights loaded //! List of all lights loaded
std::vector<aiLight*> mLights; std::vector<aiLight*> mLights;
//! Pointer to the root node of the scene //! Pointer to the root node of the scene
// --- moved to main class // --- moved to main class
// Node* pcRootNode; // Node* pcRootNode;
}; };

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -55,7 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiNode; struct aiNode;
namespace Assimp { namespace Assimp {
using namespace D3DS; using namespace D3DS;
@ -67,212 +67,212 @@ class Discreet3DSImporter : public BaseImporter
{ {
public: public:
Discreet3DSImporter(); Discreet3DSImporter();
~Discreet3DSImporter(); ~Discreet3DSImporter();
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. * See BaseImporter::CanRead() for details.
*/ */
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const; bool checkSig) const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Called prior to ReadFile(). /** Called prior to ReadFile().
* The function is a request to the importer to update its configuration * The function is a request to the importer to update its configuration
* basing on the Importer's configuration property list. * basing on the Importer's configuration property list.
*/ */
void SetupProperties(const Importer* pImp); void SetupProperties(const Importer* pImp);
protected: protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Return importer meta information. /** Return importer meta information.
* See #BaseImporter::GetInfo for the details * See #BaseImporter::GetInfo for the details
*/ */
const aiImporterDesc* GetInfo () const; const aiImporterDesc* GetInfo () const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Imports the given file into the given scene structure. /** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details * See BaseImporter::InternReadFile() for details
*/ */
void InternReadFile( const std::string& pFile, aiScene* pScene, void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler); IOSystem* pIOHandler);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Converts a temporary material to the outer representation /** Converts a temporary material to the outer representation
*/ */
void ConvertMaterial(D3DS::Material& p_cMat, void ConvertMaterial(D3DS::Material& p_cMat,
aiMaterial& p_pcOut); aiMaterial& p_pcOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Read a chunk /** Read a chunk
* *
* @param pcOut Receives the current chunk * @param pcOut Receives the current chunk
*/ */
void ReadChunk(Discreet3DS::Chunk* pcOut); void ReadChunk(Discreet3DS::Chunk* pcOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Parse a percentage chunk. mCurrent will point to the next /** Parse a percentage chunk. mCurrent will point to the next
* chunk behind afterwards. If no percentage chunk is found * chunk behind afterwards. If no percentage chunk is found
* QNAN is returned. * QNAN is returned.
*/ */
float ParsePercentageChunk(); float ParsePercentageChunk();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Parse a color chunk. mCurrent will point to the next /** Parse a color chunk. mCurrent will point to the next
* chunk behind afterwards. If no color chunk is found * chunk behind afterwards. If no color chunk is found
* QNAN is returned in all members. * QNAN is returned in all members.
*/ */
void ParseColorChunk(aiColor3D* p_pcOut, void ParseColorChunk(aiColor3D* p_pcOut,
bool p_bAcceptPercent = true); bool p_bAcceptPercent = true);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Skip a chunk in the file /** Skip a chunk in the file
*/ */
void SkipChunk(); void SkipChunk();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Generate the nodegraph /** Generate the nodegraph
*/ */
void GenerateNodeGraph(aiScene* pcOut); void GenerateNodeGraph(aiScene* pcOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Parse a main top-level chunk in the file /** Parse a main top-level chunk in the file
*/ */
void ParseMainChunk(); void ParseMainChunk();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Parse a top-level chunk in the file /** Parse a top-level chunk in the file
*/ */
void ParseChunk(const char* name, unsigned int num); void ParseChunk(const char* name, unsigned int num);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Parse a top-level editor chunk in the file /** Parse a top-level editor chunk in the file
*/ */
void ParseEditorChunk(); void ParseEditorChunk();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Parse a top-level object chunk in the file /** Parse a top-level object chunk in the file
*/ */
void ParseObjectChunk(); void ParseObjectChunk();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Parse a material chunk in the file /** Parse a material chunk in the file
*/ */
void ParseMaterialChunk(); void ParseMaterialChunk();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Parse a mesh chunk in the file /** Parse a mesh chunk in the file
*/ */
void ParseMeshChunk(); void ParseMeshChunk();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Parse a light chunk in the file /** Parse a light chunk in the file
*/ */
void ParseLightChunk(); void ParseLightChunk();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Parse a camera chunk in the file /** Parse a camera chunk in the file
*/ */
void ParseCameraChunk(); void ParseCameraChunk();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Parse a face list chunk in the file /** Parse a face list chunk in the file
*/ */
void ParseFaceChunk(); void ParseFaceChunk();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Parse a keyframe chunk in the file /** Parse a keyframe chunk in the file
*/ */
void ParseKeyframeChunk(); void ParseKeyframeChunk();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Parse a hierarchy chunk in the file /** Parse a hierarchy chunk in the file
*/ */
void ParseHierarchyChunk(uint16_t parent); void ParseHierarchyChunk(uint16_t parent);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Parse a texture chunk in the file /** Parse a texture chunk in the file
*/ */
void ParseTextureChunk(D3DS::Texture* pcOut); void ParseTextureChunk(D3DS::Texture* pcOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Convert the meshes in the file /** Convert the meshes in the file
*/ */
void ConvertMeshes(aiScene* pcOut); void ConvertMeshes(aiScene* pcOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Replace the default material in the scene /** Replace the default material in the scene
*/ */
void ReplaceDefaultMaterial(); void ReplaceDefaultMaterial();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Convert the whole scene /** Convert the whole scene
*/ */
void ConvertScene(aiScene* pcOut); void ConvertScene(aiScene* pcOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** generate unique vertices for a mesh /** generate unique vertices for a mesh
*/ */
void MakeUnique(D3DS::Mesh& sMesh); void MakeUnique(D3DS::Mesh& sMesh);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Add a node to the node graph /** Add a node to the node graph
*/ */
void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn, void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn,
aiMatrix4x4& absTrafo); aiMatrix4x4& absTrafo);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Search for a node in the graph. /** Search for a node in the graph.
* Called recursively * Called recursively
*/ */
void InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCurrent); void InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCurrent);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Apply the master scaling factor to the mesh /** Apply the master scaling factor to the mesh
*/ */
void ApplyMasterScale(aiScene* pScene); void ApplyMasterScale(aiScene* pScene);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Clamp all indices in the file to a valid range /** Clamp all indices in the file to a valid range
*/ */
void CheckIndices(D3DS::Mesh& sMesh); void CheckIndices(D3DS::Mesh& sMesh);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Skip the TCB info in a track key /** Skip the TCB info in a track key
*/ */
void SkipTCBInfo(); void SkipTCBInfo();
protected: protected:
/** Stream to read from */ /** Stream to read from */
StreamReaderLE* stream; StreamReaderLE* stream;
/** Last touched node index */ /** Last touched node index */
short mLastNodeIndex; short mLastNodeIndex;
/** Current node, root node */ /** Current node, root node */
D3DS::Node* mCurrentNode, *mRootNode; D3DS::Node* mCurrentNode, *mRootNode;
/** Scene under construction */ /** Scene under construction */
D3DS::Scene* mScene; D3DS::Scene* mScene;
/** Ambient base color of the scene */ /** Ambient base color of the scene */
aiColor3D mClrAmbient; aiColor3D mClrAmbient;
/** Master scaling factor of the scene */ /** Master scaling factor of the scene */
float mMasterScale; float mMasterScale;
/** Path to the background image of the scene */ /** Path to the background image of the scene */
std::string mBackgroundImage; std::string mBackgroundImage;
bool bHasBG; bool bHasBG;
/** true if PRJ file */ /** true if PRJ file */
bool bIsPrj; bool bIsPrj;
}; };
} // end of namespace Assimp } // end of namespace Assimp

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -55,7 +55,7 @@ struct aiMaterial;
struct aiLight; struct aiLight;
namespace Assimp { namespace Assimp {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** AC3D (*.ac) importer class /** AC3D (*.ac) importer class
@ -63,209 +63,210 @@ namespace Assimp {
class AC3DImporter : public BaseImporter class AC3DImporter : public BaseImporter
{ {
public: public:
AC3DImporter(); AC3DImporter();
~AC3DImporter(); ~AC3DImporter();
// Represents an AC3D material // Represents an AC3D material
struct Material struct Material
{ {
Material() Material()
: rgb (0.6f,0.6f,0.6f) : rgb (0.6f,0.6f,0.6f)
, spec (1.f,1.f,1.f) , spec (1.f,1.f,1.f)
, shin (0.f) , shin (0.f)
, trans (0.f) , trans (0.f)
{} {}
// base color of the material // base color of the material
aiColor3D rgb; aiColor3D rgb;
// ambient color of the material // ambient color of the material
aiColor3D amb; aiColor3D amb;
// emissive color of the material // emissive color of the material
aiColor3D emis; aiColor3D emis;
// specular color of the material // specular color of the material
aiColor3D spec; aiColor3D spec;
// shininess exponent // shininess exponent
float shin; float shin;
// transparency. 0 == opaque // transparency. 0 == opaque
float trans; float trans;
// name of the material. optional. // name of the material. optional.
std::string name; std::string name;
}; };
// Represents an AC3D surface // Represents an AC3D surface
struct Surface struct Surface
{ {
Surface() Surface()
: mat (0) : mat (0)
, flags (0) , flags (0)
{} {}
unsigned int mat,flags; unsigned int mat,flags;
typedef std::pair<unsigned int, aiVector2D > SurfaceEntry; typedef std::pair<unsigned int, aiVector2D > SurfaceEntry;
std::vector< SurfaceEntry > entries; std::vector< SurfaceEntry > entries;
}; };
// Represents an AC3D object // Represents an AC3D object
struct Object struct Object
{ {
Object() Object()
: type (World) : type (World)
, name( "" ) , name( "" )
, children() , children()
, texture( "" ) , texture( "" )
, texRepeat( 1.f, 1.f ) , texRepeat( 1.f, 1.f )
, texOffset( 0.0f, 0.0f ) , texOffset( 0.0f, 0.0f )
, rotation() , rotation()
, translation() , translation()
, vertices() , vertices()
, surfaces() , surfaces()
, numRefs (0) , numRefs (0)
, subDiv (0) , subDiv (0)
{} , crease()
{}
// Type description // Type description
enum Type enum Type
{ {
World = 0x0, World = 0x0,
Poly = 0x1, Poly = 0x1,
Group = 0x2, Group = 0x2,
Light = 0x4 Light = 0x4
} type; } type;
// name of the object // name of the object
std::string name; std::string name;
// object children // object children
std::vector<Object> children; std::vector<Object> children;
// texture to be assigned to all surfaces of the object // texture to be assigned to all surfaces of the object
std::string texture; std::string texture;
// texture repat factors (scaling for all coordinates) // texture repat factors (scaling for all coordinates)
aiVector2D texRepeat, texOffset; aiVector2D texRepeat, texOffset;
// rotation matrix // rotation matrix
aiMatrix3x3 rotation; aiMatrix3x3 rotation;
// translation vector // translation vector
aiVector3D translation; aiVector3D translation;
// vertices // vertices
std::vector<aiVector3D> vertices; std::vector<aiVector3D> vertices;
// surfaces // surfaces
std::vector<Surface> surfaces; std::vector<Surface> surfaces;
// number of indices (= num verts in verbose format) // number of indices (= num verts in verbose format)
unsigned int numRefs; unsigned int numRefs;
// number of subdivisions to be performed on the // number of subdivisions to be performed on the
// imported data // imported data
unsigned int subDiv; unsigned int subDiv;
// max angle limit for smoothing // max angle limit for smoothing
float crease; float crease;
}; };
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. * See BaseImporter::CanRead() for details.
*/ */
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const; bool checkSig) const;
protected: protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Return importer meta information. /** Return importer meta information.
* See #BaseImporter::GetInfo for the details */ * See #BaseImporter::GetInfo for the details */
const aiImporterDesc* GetInfo () const; const aiImporterDesc* GetInfo () const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Imports the given file into the given scene structure. /** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details*/ * See BaseImporter::InternReadFile() for details*/
void InternReadFile( const std::string& pFile, aiScene* pScene, void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler); IOSystem* pIOHandler);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Called prior to ReadFile(). /** Called prior to ReadFile().
* The function is a request to the importer to update its configuration * The function is a request to the importer to update its configuration
* basing on the Importer's configuration property list.*/ * basing on the Importer's configuration property list.*/
void SetupProperties(const Importer* pImp); void SetupProperties(const Importer* pImp);
private: private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Get the next line from the file. /** Get the next line from the file.
* @return false if the end of the file was reached*/ * @return false if the end of the file was reached*/
bool GetNextLine(); bool GetNextLine();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Load the object section. This method is called recursively to /** Load the object section. This method is called recursively to
* load subobjects, the method returns after a 'kids 0' was * load subobjects, the method returns after a 'kids 0' was
* encountered. * encountered.
* @objects List of output objects*/ * @objects List of output objects*/
void LoadObjectSection(std::vector<Object>& objects); void LoadObjectSection(std::vector<Object>& objects);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Convert all objects into meshes and nodes. /** Convert all objects into meshes and nodes.
* @param object Current object to work on * @param object Current object to work on
* @param meshes Pointer to the list of output meshes * @param meshes Pointer to the list of output meshes
* @param outMaterials List of output materials * @param outMaterials List of output materials
* @param materials Material list * @param materials Material list
* @param Scenegraph node for the object */ * @param Scenegraph node for the object */
aiNode* ConvertObjectSection(Object& object, aiNode* ConvertObjectSection(Object& object,
std::vector<aiMesh*>& meshes, std::vector<aiMesh*>& meshes,
std::vector<aiMaterial*>& outMaterials, std::vector<aiMaterial*>& outMaterials,
const std::vector<Material>& materials, const std::vector<Material>& materials,
aiNode* parent = NULL); aiNode* parent = NULL);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Convert a material /** Convert a material
* @param object Current object * @param object Current object
* @param matSrc Source material description * @param matSrc Source material description
* @param matDest Destination material to be filled */ * @param matDest Destination material to be filled */
void ConvertMaterial(const Object& object, void ConvertMaterial(const Object& object,
const Material& matSrc, const Material& matSrc,
aiMaterial& matDest); aiMaterial& matDest);
private: private:
// points to the next data line // points to the next data line
const char* buffer; const char* buffer;
// Configuration option: if enabled, up to two meshes // Configuration option: if enabled, up to two meshes
// are generated per material: those faces who have // are generated per material: those faces who have
// their bf cull flags set are separated. // their bf cull flags set are separated.
bool configSplitBFCull; bool configSplitBFCull;
// Configuration switch: subdivision surfaces are only // Configuration switch: subdivision surfaces are only
// evaluated if the value is true. // evaluated if the value is true.
bool configEvalSubdivision; bool configEvalSubdivision;
// counts how many objects we have in the tree. // counts how many objects we have in the tree.
// basing on this information we can find a // basing on this information we can find a
// good estimate how many meshes we'll have in the final scene. // good estimate how many meshes we'll have in the final scene.
unsigned int mNumMeshes; unsigned int mNumMeshes;
// current list of light sources // current list of light sources
std::vector<aiLight*>* mLights; std::vector<aiLight*>* mLights;
// name counters // name counters
unsigned int lights, groups, polys, worlds; unsigned int lights, groups, polys, worlds;
}; };
} // end of namespace Assimp } // end of namespace Assimp

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -57,147 +57,147 @@ namespace Assimp {
/** Importer class for the 3DS ASE ASCII format. /** Importer class for the 3DS ASE ASCII format.
* *
*/ */
class ASEImporter : public BaseImporter { class ASEImporter : public BaseImporter {
public: public:
ASEImporter(); ASEImporter();
~ASEImporter(); ~ASEImporter();
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. * See BaseImporter::CanRead() for details.
*/ */
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const; bool checkSig) const;
protected: protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Return importer meta information. /** Return importer meta information.
* See #BaseImporter::GetInfo for the details * See #BaseImporter::GetInfo for the details
*/ */
const aiImporterDesc* GetInfo () const; const aiImporterDesc* GetInfo () const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Imports the given file into the given scene structure. /** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details * See BaseImporter::InternReadFile() for details
*/ */
void InternReadFile( const std::string& pFile, aiScene* pScene, void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler); IOSystem* pIOHandler);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Called prior to ReadFile(). /** Called prior to ReadFile().
* The function is a request to the importer to update its configuration * The function is a request to the importer to update its configuration
* basing on the Importer's configuration property list. * basing on the Importer's configuration property list.
*/ */
void SetupProperties(const Importer* pImp); void SetupProperties(const Importer* pImp);
private: private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Generate normal vectors basing on smoothing groups /** Generate normal vectors basing on smoothing groups
* (in some cases the normal are already contained in the file) * (in some cases the normal are already contained in the file)
* \param mesh Mesh to work on * \param mesh Mesh to work on
* \return false if the normals have been recomputed * \return false if the normals have been recomputed
*/ */
bool GenerateNormals(ASE::Mesh& mesh); bool GenerateNormals(ASE::Mesh& mesh);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Create valid vertex/normal/UV/color/face lists. /** Create valid vertex/normal/UV/color/face lists.
* All elements are unique, faces have only one set of indices * All elements are unique, faces have only one set of indices
* after this step occurs. * after this step occurs.
* \param mesh Mesh to work on * \param mesh Mesh to work on
*/ */
void BuildUniqueRepresentation(ASE::Mesh& mesh); void BuildUniqueRepresentation(ASE::Mesh& mesh);
/** Create one-material-per-mesh meshes ;-) /** Create one-material-per-mesh meshes ;-)
* \param mesh Mesh to work with * \param mesh Mesh to work with
* \param Receives the list of all created meshes * \param Receives the list of all created meshes
*/ */
void ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOut); void ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Convert a material to a aiMaterial object /** Convert a material to a aiMaterial object
* \param mat Input material * \param mat Input material
*/ */
void ConvertMaterial(ASE::Material& mat); void ConvertMaterial(ASE::Material& mat);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Setup the final material indices for each mesh /** Setup the final material indices for each mesh
*/ */
void BuildMaterialIndices(); void BuildMaterialIndices();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Build the node graph /** Build the node graph
*/ */
void BuildNodes(std::vector<ASE::BaseNode*>& nodes); void BuildNodes(std::vector<ASE::BaseNode*>& nodes);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Build output cameras /** Build output cameras
*/ */
void BuildCameras(); void BuildCameras();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Build output lights /** Build output lights
*/ */
void BuildLights(); void BuildLights();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Build output animations /** Build output animations
*/ */
void BuildAnimations(const std::vector<ASE::BaseNode*>& nodes); void BuildAnimations(const std::vector<ASE::BaseNode*>& nodes);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Add sub nodes to a node /** Add sub nodes to a node
* \param pcParent parent node to be filled * \param pcParent parent node to be filled
* \param szName Name of the parent node * \param szName Name of the parent node
* \param matrix Current transform * \param matrix Current transform
*/ */
void AddNodes(const std::vector<ASE::BaseNode*>& nodes, void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
aiNode* pcParent,const char* szName); aiNode* pcParent,const char* szName);
void AddNodes(const std::vector<ASE::BaseNode*>& nodes, void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
aiNode* pcParent,const char* szName, aiNode* pcParent,const char* szName,
const aiMatrix4x4& matrix); const aiMatrix4x4& matrix);
void AddMeshes(const ASE::BaseNode* snode,aiNode* node); void AddMeshes(const ASE::BaseNode* snode,aiNode* node);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Generate a default material and add it to the parser's list /** Generate a default material and add it to the parser's list
* Called if no material has been found in the file (rare for ASE, * Called if no material has been found in the file (rare for ASE,
* but not impossible) * but not impossible)
*/ */
void GenerateDefaultMaterial(); void GenerateDefaultMaterial();
protected: protected:
/** Parser instance */ /** Parser instance */
ASE::Parser* mParser; ASE::Parser* mParser;
/** Buffer to hold the loaded file */ /** Buffer to hold the loaded file */
char* mBuffer; char* mBuffer;
/** Scene to be filled */ /** Scene to be filled */
aiScene* pcScene; aiScene* pcScene;
/** Config options: Recompute the normals in every case - WA /** Config options: Recompute the normals in every case - WA
for 3DS Max broken ASE normal export */ for 3DS Max broken ASE normal export */
bool configRecomputeNormals; bool configRecomputeNormals;
bool noSkeletonMesh; bool noSkeletonMesh;
}; };
} // end of namespace Assimp } // end of namespace Assimp

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -61,7 +61,7 @@ struct aiCamera;
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER #ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
namespace Assimp { namespace Assimp {
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
/** Importer class for 3D Studio r3 and r4 3DS files /** Importer class for 3D Studio r3 and r4 3DS files

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
@ -59,39 +59,39 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
# include <boost/thread/thread.hpp> # include <boost/thread/thread.hpp>
# include <boost/thread/mutex.hpp> # include <boost/thread/mutex.hpp>
#endif #endif
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
using namespace Assimp; using namespace Assimp;
namespace Assimp namespace Assimp
{ {
// underlying structure for aiPropertyStore // underlying structure for aiPropertyStore
typedef BatchLoader::PropertyMap PropertyMap; typedef BatchLoader::PropertyMap PropertyMap;
/** Stores the LogStream objects for all active C log streams */ /** Stores the LogStream objects for all active C log streams */
struct mpred { struct mpred {
bool operator () (const aiLogStream& s0, const aiLogStream& s1) const { bool operator () (const aiLogStream& s0, const aiLogStream& s1) const {
return s0.callback<s1.callback&&s0.user<s1.user; return s0.callback<s1.callback&&s0.user<s1.user;
} }
}; };
typedef std::map<aiLogStream, Assimp::LogStream*, mpred> LogStreamMap; typedef std::map<aiLogStream, Assimp::LogStream*, mpred> LogStreamMap;
/** Stores the LogStream objects allocated by #aiGetPredefinedLogStream */ /** Stores the LogStream objects allocated by #aiGetPredefinedLogStream */
typedef std::list<Assimp::LogStream*> PredefLogStreamMap; typedef std::list<Assimp::LogStream*> PredefLogStreamMap;
/** Local storage of all active log streams */ /** Local storage of all active log streams */
static LogStreamMap gActiveLogStreams; static LogStreamMap gActiveLogStreams;
/** Local storage of LogStreams allocated by #aiGetPredefinedLogStream */ /** Local storage of LogStreams allocated by #aiGetPredefinedLogStream */
static PredefLogStreamMap gPredefinedStreams; static PredefLogStreamMap gPredefinedStreams;
/** Error message of the last failed import process */ /** Error message of the last failed import process */
static std::string gLastErrorString; static std::string gLastErrorString;
/** Verbose logging active or not? */ /** Verbose logging active or not? */
static aiBool gVerboseLogging = false; static aiBool gVerboseLogging = false;
/** will return all registered importers. */ /** will return all registered importers. */
void GetImporterInstanceList(std::vector< BaseImporter* >& out); void GetImporterInstanceList(std::vector< BaseImporter* >& out);
@ -110,331 +110,331 @@ static boost::mutex gLogStreamMutex;
class LogToCallbackRedirector : public LogStream class LogToCallbackRedirector : public LogStream
{ {
public: public:
LogToCallbackRedirector(const aiLogStream& s) LogToCallbackRedirector(const aiLogStream& s)
: stream (s) { : stream (s) {
ai_assert(NULL != s.callback); ai_assert(NULL != s.callback);
} }
~LogToCallbackRedirector() { ~LogToCallbackRedirector() {
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
boost::mutex::scoped_lock lock(gLogStreamMutex); boost::mutex::scoped_lock lock(gLogStreamMutex);
#endif #endif
// (HACK) Check whether the 'stream.user' pointer points to a // (HACK) Check whether the 'stream.user' pointer points to a
// custom LogStream allocated by #aiGetPredefinedLogStream. // custom LogStream allocated by #aiGetPredefinedLogStream.
// In this case, we need to delete it, too. Of course, this // In this case, we need to delete it, too. Of course, this
// might cause strange problems, but the chance is quite low. // might cause strange problems, but the chance is quite low.
PredefLogStreamMap::iterator it = std::find(gPredefinedStreams.begin(), PredefLogStreamMap::iterator it = std::find(gPredefinedStreams.begin(),
gPredefinedStreams.end(), (Assimp::LogStream*)stream.user); gPredefinedStreams.end(), (Assimp::LogStream*)stream.user);
if (it != gPredefinedStreams.end()) { if (it != gPredefinedStreams.end()) {
delete *it; delete *it;
gPredefinedStreams.erase(it); gPredefinedStreams.erase(it);
} }
} }
/** @copydoc LogStream::write */ /** @copydoc LogStream::write */
void write(const char* message) { void write(const char* message) {
stream.callback(message,stream.user); stream.callback(message,stream.user);
} }
private: private:
aiLogStream stream; aiLogStream stream;
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ReportSceneNotFoundError() void ReportSceneNotFoundError()
{ {
DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. " DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. "
"The C-API does not accept scenes produced by the C++ API and vice versa"); "The C-API does not accept scenes produced by the C++ API and vice versa");
assert(false); assert(false);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads the given file and returns its content. // Reads the given file and returns its content.
const aiScene* aiImportFile( const char* pFile, unsigned int pFlags) const aiScene* aiImportFile( const char* pFile, unsigned int pFlags)
{ {
return aiImportFileEx(pFile,pFlags,NULL); return aiImportFileEx(pFile,pFlags,NULL);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, aiFileIO* pFS) const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, aiFileIO* pFS)
{ {
return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL); return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags, const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags,
aiFileIO* pFS, aiFileIO* pFS,
const aiPropertyStore* props) const aiPropertyStore* props)
{ {
ai_assert(NULL != pFile); ai_assert(NULL != pFile);
const aiScene* scene = NULL; const aiScene* scene = NULL;
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
// create an Importer for this file // create an Importer for this file
Assimp::Importer* imp = new Assimp::Importer(); Assimp::Importer* imp = new Assimp::Importer();
// copy properties // copy properties
if(props) { if(props) {
const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props); const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props);
ImporterPimpl* pimpl = imp->Pimpl(); ImporterPimpl* pimpl = imp->Pimpl();
pimpl->mIntProperties = pp->ints; pimpl->mIntProperties = pp->ints;
pimpl->mFloatProperties = pp->floats; pimpl->mFloatProperties = pp->floats;
pimpl->mStringProperties = pp->strings; pimpl->mStringProperties = pp->strings;
pimpl->mMatrixProperties = pp->matrices; pimpl->mMatrixProperties = pp->matrices;
} }
// setup a custom IO system if necessary // setup a custom IO system if necessary
if (pFS) { if (pFS) {
imp->SetIOHandler( new CIOSystemWrapper (pFS) ); imp->SetIOHandler( new CIOSystemWrapper (pFS) );
} }
// and have it read the file // and have it read the file
scene = imp->ReadFile( pFile, pFlags); scene = imp->ReadFile( pFile, pFlags);
// if succeeded, store the importer in the scene and keep it alive // if succeeded, store the importer in the scene and keep it alive
if( scene) { if( scene) {
ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) ); ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
priv->mOrigImporter = imp; priv->mOrigImporter = imp;
} }
else { else {
// if failed, extract error code and destroy the import // if failed, extract error code and destroy the import
gLastErrorString = imp->GetErrorString(); gLastErrorString = imp->GetErrorString();
delete imp; delete imp;
} }
// return imported data. If the import failed the pointer is NULL anyways // return imported data. If the import failed the pointer is NULL anyways
ASSIMP_END_EXCEPTION_REGION(const aiScene*); ASSIMP_END_EXCEPTION_REGION(const aiScene*);
return scene; return scene;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const aiScene* aiImportFileFromMemory( const aiScene* aiImportFileFromMemory(
const char* pBuffer, const char* pBuffer,
unsigned int pLength, unsigned int pLength,
unsigned int pFlags, unsigned int pFlags,
const char* pHint) const char* pHint)
{ {
return aiImportFileFromMemoryWithProperties(pBuffer, pLength, pFlags, pHint, NULL); return aiImportFileFromMemoryWithProperties(pBuffer, pLength, pFlags, pHint, NULL);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const aiScene* aiImportFileFromMemoryWithProperties( const aiScene* aiImportFileFromMemoryWithProperties(
const char* pBuffer, const char* pBuffer,
unsigned int pLength, unsigned int pLength,
unsigned int pFlags, unsigned int pFlags,
const char* pHint, const char* pHint,
const aiPropertyStore* props) const aiPropertyStore* props)
{ {
ai_assert(NULL != pBuffer && 0 != pLength); ai_assert(NULL != pBuffer && 0 != pLength);
const aiScene* scene = NULL; const aiScene* scene = NULL;
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
// create an Importer for this file // create an Importer for this file
Assimp::Importer* imp = new Assimp::Importer(); Assimp::Importer* imp = new Assimp::Importer();
// copy properties // copy properties
if(props) { if(props) {
const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props); const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props);
ImporterPimpl* pimpl = imp->Pimpl(); ImporterPimpl* pimpl = imp->Pimpl();
pimpl->mIntProperties = pp->ints; pimpl->mIntProperties = pp->ints;
pimpl->mFloatProperties = pp->floats; pimpl->mFloatProperties = pp->floats;
pimpl->mStringProperties = pp->strings; pimpl->mStringProperties = pp->strings;
pimpl->mMatrixProperties = pp->matrices; pimpl->mMatrixProperties = pp->matrices;
} }
// and have it read the file from the memory buffer // and have it read the file from the memory buffer
scene = imp->ReadFileFromMemory( pBuffer, pLength, pFlags,pHint); scene = imp->ReadFileFromMemory( pBuffer, pLength, pFlags,pHint);
// if succeeded, store the importer in the scene and keep it alive // if succeeded, store the importer in the scene and keep it alive
if( scene) { if( scene) {
ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) ); ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
priv->mOrigImporter = imp; priv->mOrigImporter = imp;
} }
else { else {
// if failed, extract error code and destroy the import // if failed, extract error code and destroy the import
gLastErrorString = imp->GetErrorString(); gLastErrorString = imp->GetErrorString();
delete imp; delete imp;
} }
// return imported data. If the import failed the pointer is NULL anyways // return imported data. If the import failed the pointer is NULL anyways
ASSIMP_END_EXCEPTION_REGION(const aiScene*); ASSIMP_END_EXCEPTION_REGION(const aiScene*);
return scene; return scene;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Releases all resources associated with the given import process. // Releases all resources associated with the given import process.
void aiReleaseImport( const aiScene* pScene) void aiReleaseImport( const aiScene* pScene)
{ {
if (!pScene) { if (!pScene) {
return; return;
} }
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
// find the importer associated with this data // find the importer associated with this data
const ScenePrivateData* priv = ScenePriv(pScene); const ScenePrivateData* priv = ScenePriv(pScene);
if( !priv || !priv->mOrigImporter) { if( !priv || !priv->mOrigImporter) {
delete pScene; delete pScene;
} }
else { else {
// deleting the Importer also deletes the scene // deleting the Importer also deletes the scene
// Note: the reason that this is not written as 'delete priv->mOrigImporter' // Note: the reason that this is not written as 'delete priv->mOrigImporter'
// is a suspected bug in gcc 4.4+ (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52339) // is a suspected bug in gcc 4.4+ (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52339)
Importer* importer = priv->mOrigImporter; Importer* importer = priv->mOrigImporter;
delete importer; delete importer;
} }
ASSIMP_END_EXCEPTION_REGION(void); ASSIMP_END_EXCEPTION_REGION(void);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API const aiScene* aiApplyPostProcessing(const aiScene* pScene, ASSIMP_API const aiScene* aiApplyPostProcessing(const aiScene* pScene,
unsigned int pFlags) unsigned int pFlags)
{ {
const aiScene* sc = NULL; const aiScene* sc = NULL;
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
// find the importer associated with this data // find the importer associated with this data
const ScenePrivateData* priv = ScenePriv(pScene); const ScenePrivateData* priv = ScenePriv(pScene);
if( !priv || !priv->mOrigImporter) { if( !priv || !priv->mOrigImporter) {
ReportSceneNotFoundError(); ReportSceneNotFoundError();
return NULL; return NULL;
} }
sc = priv->mOrigImporter->ApplyPostProcessing(pFlags); sc = priv->mOrigImporter->ApplyPostProcessing(pFlags);
if (!sc) { if (!sc) {
aiReleaseImport(pScene); aiReleaseImport(pScene);
return NULL; return NULL;
} }
ASSIMP_END_EXCEPTION_REGION(const aiScene*); ASSIMP_END_EXCEPTION_REGION(const aiScene*);
return sc; return sc;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void CallbackToLogRedirector (const char* msg, char* dt) void CallbackToLogRedirector (const char* msg, char* dt)
{ {
ai_assert(NULL != msg && NULL != dt); ai_assert(NULL != msg && NULL != dt);
LogStream* s = (LogStream*)dt; LogStream* s = (LogStream*)dt;
s->write(msg); s->write(msg);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream,const char* file) ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream,const char* file)
{ {
aiLogStream sout; aiLogStream sout;
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
LogStream* stream = LogStream::createDefaultStream(pStream,file); LogStream* stream = LogStream::createDefaultStream(pStream,file);
if (!stream) { if (!stream) {
sout.callback = NULL; sout.callback = NULL;
sout.user = NULL; sout.user = NULL;
} }
else { else {
sout.callback = &CallbackToLogRedirector; sout.callback = &CallbackToLogRedirector;
sout.user = (char*)stream; sout.user = (char*)stream;
} }
gPredefinedStreams.push_back(stream); gPredefinedStreams.push_back(stream);
ASSIMP_END_EXCEPTION_REGION(aiLogStream); ASSIMP_END_EXCEPTION_REGION(aiLogStream);
return sout; return sout;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API void aiAttachLogStream( const aiLogStream* stream ) ASSIMP_API void aiAttachLogStream( const aiLogStream* stream )
{ {
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
boost::mutex::scoped_lock lock(gLogStreamMutex); boost::mutex::scoped_lock lock(gLogStreamMutex);
#endif #endif
LogStream* lg = new LogToCallbackRedirector(*stream); LogStream* lg = new LogToCallbackRedirector(*stream);
gActiveLogStreams[*stream] = lg; gActiveLogStreams[*stream] = lg;
if (DefaultLogger::isNullLogger()) { if (DefaultLogger::isNullLogger()) {
DefaultLogger::create(NULL,(gVerboseLogging == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL)); DefaultLogger::create(NULL,(gVerboseLogging == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
} }
DefaultLogger::get()->attachStream(lg); DefaultLogger::get()->attachStream(lg);
ASSIMP_END_EXCEPTION_REGION(void); ASSIMP_END_EXCEPTION_REGION(void);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API aiReturn aiDetachLogStream( const aiLogStream* stream) ASSIMP_API aiReturn aiDetachLogStream( const aiLogStream* stream)
{ {
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
boost::mutex::scoped_lock lock(gLogStreamMutex); boost::mutex::scoped_lock lock(gLogStreamMutex);
#endif #endif
// find the logstream associated with this data // find the logstream associated with this data
LogStreamMap::iterator it = gActiveLogStreams.find( *stream); LogStreamMap::iterator it = gActiveLogStreams.find( *stream);
// it should be there... else the user is playing fools with us // it should be there... else the user is playing fools with us
if( it == gActiveLogStreams.end()) { if( it == gActiveLogStreams.end()) {
return AI_FAILURE; return AI_FAILURE;
} }
DefaultLogger::get()->detatchStream( it->second ); DefaultLogger::get()->detatchStream( it->second );
delete it->second; delete it->second;
gActiveLogStreams.erase( it); gActiveLogStreams.erase( it);
if (gActiveLogStreams.empty()) { if (gActiveLogStreams.empty()) {
DefaultLogger::kill(); DefaultLogger::kill();
} }
ASSIMP_END_EXCEPTION_REGION(aiReturn); ASSIMP_END_EXCEPTION_REGION(aiReturn);
return AI_SUCCESS; return AI_SUCCESS;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API void aiDetachAllLogStreams(void) ASSIMP_API void aiDetachAllLogStreams(void)
{ {
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
boost::mutex::scoped_lock lock(gLogStreamMutex); boost::mutex::scoped_lock lock(gLogStreamMutex);
#endif #endif
for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) { for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) {
DefaultLogger::get()->detatchStream( it->second ); DefaultLogger::get()->detatchStream( it->second );
delete it->second; delete it->second;
} }
gActiveLogStreams.clear(); gActiveLogStreams.clear();
DefaultLogger::kill(); DefaultLogger::kill();
ASSIMP_END_EXCEPTION_REGION(void); ASSIMP_END_EXCEPTION_REGION(void);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API void aiEnableVerboseLogging(aiBool d) ASSIMP_API void aiEnableVerboseLogging(aiBool d)
{ {
if (!DefaultLogger::isNullLogger()) { if (!DefaultLogger::isNullLogger()) {
DefaultLogger::get()->setLogSeverity((d == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL)); DefaultLogger::get()->setLogSeverity((d == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
} }
gVerboseLogging = d; gVerboseLogging = d;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns the error text of the last failed import process. // Returns the error text of the last failed import process.
const char* aiGetErrorString() const char* aiGetErrorString()
{ {
return gLastErrorString.c_str(); return gLastErrorString.c_str();
} }
// ----------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------
// Return the description of a importer given its index // Return the description of a importer given its index
const aiImporterDesc* aiGetImportFormatDescription( size_t pIndex) const aiImporterDesc* aiGetImportFormatDescription( size_t pIndex)
{ {
return Importer().GetImporterInfo(pIndex); return Importer().GetImporterInfo(pIndex);
} }
// ----------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------
// Return the number of importers // Return the number of importers
size_t aiGetImportFormatCount(void) size_t aiGetImportFormatCount(void)
{ {
return Importer().GetImporterCount(); return Importer().GetImporterCount();
} }
@ -442,195 +442,195 @@ size_t aiGetImportFormatCount(void)
// Returns the error text of the last failed import process. // Returns the error text of the last failed import process.
aiBool aiIsExtensionSupported(const char* szExtension) aiBool aiIsExtensionSupported(const char* szExtension)
{ {
ai_assert(NULL != szExtension); ai_assert(NULL != szExtension);
aiBool candoit=AI_FALSE; aiBool candoit=AI_FALSE;
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
// FIXME: no need to create a temporary Importer instance just for that .. // FIXME: no need to create a temporary Importer instance just for that ..
Assimp::Importer tmp; Assimp::Importer tmp;
candoit = tmp.IsExtensionSupported(std::string(szExtension)) ? AI_TRUE : AI_FALSE; candoit = tmp.IsExtensionSupported(std::string(szExtension)) ? AI_TRUE : AI_FALSE;
ASSIMP_END_EXCEPTION_REGION(aiBool); ASSIMP_END_EXCEPTION_REGION(aiBool);
return candoit; return candoit;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Get a list of all file extensions supported by ASSIMP // Get a list of all file extensions supported by ASSIMP
void aiGetExtensionList(aiString* szOut) void aiGetExtensionList(aiString* szOut)
{ {
ai_assert(NULL != szOut); ai_assert(NULL != szOut);
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
// FIXME: no need to create a temporary Importer instance just for that .. // FIXME: no need to create a temporary Importer instance just for that ..
Assimp::Importer tmp; Assimp::Importer tmp;
tmp.GetExtensionList(*szOut); tmp.GetExtensionList(*szOut);
ASSIMP_END_EXCEPTION_REGION(void); ASSIMP_END_EXCEPTION_REGION(void);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Get the memory requirements for a particular import. // Get the memory requirements for a particular import.
void aiGetMemoryRequirements(const C_STRUCT aiScene* pIn, void aiGetMemoryRequirements(const C_STRUCT aiScene* pIn,
C_STRUCT aiMemoryInfo* in) C_STRUCT aiMemoryInfo* in)
{ {
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
// find the importer associated with this data // find the importer associated with this data
const ScenePrivateData* priv = ScenePriv(pIn); const ScenePrivateData* priv = ScenePriv(pIn);
if( !priv || !priv->mOrigImporter) { if( !priv || !priv->mOrigImporter) {
ReportSceneNotFoundError(); ReportSceneNotFoundError();
return; return;
} }
return priv->mOrigImporter->GetMemoryRequirements(*in); return priv->mOrigImporter->GetMemoryRequirements(*in);
ASSIMP_END_EXCEPTION_REGION(void); ASSIMP_END_EXCEPTION_REGION(void);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API aiPropertyStore* aiCreatePropertyStore(void) ASSIMP_API aiPropertyStore* aiCreatePropertyStore(void)
{ {
return reinterpret_cast<aiPropertyStore*>( new PropertyMap() ); return reinterpret_cast<aiPropertyStore*>( new PropertyMap() );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API void aiReleasePropertyStore(aiPropertyStore* p) ASSIMP_API void aiReleasePropertyStore(aiPropertyStore* p)
{ {
delete reinterpret_cast<PropertyMap*>(p); delete reinterpret_cast<PropertyMap*>(p);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Importer::SetPropertyInteger // Importer::SetPropertyInteger
ASSIMP_API void aiSetImportPropertyInteger(aiPropertyStore* p, const char* szName, int value) ASSIMP_API void aiSetImportPropertyInteger(aiPropertyStore* p, const char* szName, int value)
{ {
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
PropertyMap* pp = reinterpret_cast<PropertyMap*>(p); PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
SetGenericProperty<int>(pp->ints,szName,value); SetGenericProperty<int>(pp->ints,szName,value);
ASSIMP_END_EXCEPTION_REGION(void); ASSIMP_END_EXCEPTION_REGION(void);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Importer::SetPropertyFloat // Importer::SetPropertyFloat
ASSIMP_API void aiSetImportPropertyFloat(aiPropertyStore* p, const char* szName, float value) ASSIMP_API void aiSetImportPropertyFloat(aiPropertyStore* p, const char* szName, float value)
{ {
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
PropertyMap* pp = reinterpret_cast<PropertyMap*>(p); PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
SetGenericProperty<float>(pp->floats,szName,value); SetGenericProperty<float>(pp->floats,szName,value);
ASSIMP_END_EXCEPTION_REGION(void); ASSIMP_END_EXCEPTION_REGION(void);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Importer::SetPropertyString // Importer::SetPropertyString
ASSIMP_API void aiSetImportPropertyString(aiPropertyStore* p, const char* szName, ASSIMP_API void aiSetImportPropertyString(aiPropertyStore* p, const char* szName,
const C_STRUCT aiString* st) const C_STRUCT aiString* st)
{ {
if (!st) { if (!st) {
return; return;
} }
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
PropertyMap* pp = reinterpret_cast<PropertyMap*>(p); PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
SetGenericProperty<std::string>(pp->strings,szName,std::string(st->C_Str())); SetGenericProperty<std::string>(pp->strings,szName,std::string(st->C_Str()));
ASSIMP_END_EXCEPTION_REGION(void); ASSIMP_END_EXCEPTION_REGION(void);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Importer::SetPropertyMatrix // Importer::SetPropertyMatrix
ASSIMP_API void aiSetImportPropertyMatrix(aiPropertyStore* p, const char* szName, ASSIMP_API void aiSetImportPropertyMatrix(aiPropertyStore* p, const char* szName,
const C_STRUCT aiMatrix4x4* mat) const C_STRUCT aiMatrix4x4* mat)
{ {
if (!mat) { if (!mat) {
return; return;
} }
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
PropertyMap* pp = reinterpret_cast<PropertyMap*>(p); PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
SetGenericProperty<aiMatrix4x4>(pp->matrices,szName,*mat); SetGenericProperty<aiMatrix4x4>(pp->matrices,szName,*mat);
ASSIMP_END_EXCEPTION_REGION(void); ASSIMP_END_EXCEPTION_REGION(void);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Rotation matrix to quaternion // Rotation matrix to quaternion
ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion* quat,const aiMatrix3x3* mat) ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion* quat,const aiMatrix3x3* mat)
{ {
ai_assert(NULL != quat && NULL != mat); ai_assert(NULL != quat && NULL != mat);
*quat = aiQuaternion(*mat); *quat = aiQuaternion(*mat);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Matrix decomposition // Matrix decomposition
ASSIMP_API void aiDecomposeMatrix(const aiMatrix4x4* mat,aiVector3D* scaling, ASSIMP_API void aiDecomposeMatrix(const aiMatrix4x4* mat,aiVector3D* scaling,
aiQuaternion* rotation, aiQuaternion* rotation,
aiVector3D* position) aiVector3D* position)
{ {
ai_assert(NULL != rotation && NULL != position && NULL != scaling && NULL != mat); ai_assert(NULL != rotation && NULL != position && NULL != scaling && NULL != mat);
mat->Decompose(*scaling,*rotation,*position); mat->Decompose(*scaling,*rotation,*position);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Matrix transpose // Matrix transpose
ASSIMP_API void aiTransposeMatrix3(aiMatrix3x3* mat) ASSIMP_API void aiTransposeMatrix3(aiMatrix3x3* mat)
{ {
ai_assert(NULL != mat); ai_assert(NULL != mat);
mat->Transpose(); mat->Transpose();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API void aiTransposeMatrix4(aiMatrix4x4* mat) ASSIMP_API void aiTransposeMatrix4(aiMatrix4x4* mat)
{ {
ai_assert(NULL != mat); ai_assert(NULL != mat);
mat->Transpose(); mat->Transpose();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Vector transformation // Vector transformation
ASSIMP_API void aiTransformVecByMatrix3(aiVector3D* vec, ASSIMP_API void aiTransformVecByMatrix3(aiVector3D* vec,
const aiMatrix3x3* mat) const aiMatrix3x3* mat)
{ {
ai_assert(NULL != mat && NULL != vec); ai_assert(NULL != mat && NULL != vec);
*vec *= (*mat); *vec *= (*mat);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API void aiTransformVecByMatrix4(aiVector3D* vec, ASSIMP_API void aiTransformVecByMatrix4(aiVector3D* vec,
const aiMatrix4x4* mat) const aiMatrix4x4* mat)
{ {
ai_assert(NULL != mat && NULL != vec); ai_assert(NULL != mat && NULL != vec);
*vec *= (*mat); *vec *= (*mat);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Matrix multiplication // Matrix multiplication
ASSIMP_API void aiMultiplyMatrix4( ASSIMP_API void aiMultiplyMatrix4(
aiMatrix4x4* dst, aiMatrix4x4* dst,
const aiMatrix4x4* src) const aiMatrix4x4* src)
{ {
ai_assert(NULL != dst && NULL != src); ai_assert(NULL != dst && NULL != src);
*dst = (*dst) * (*src); *dst = (*dst) * (*src);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API void aiMultiplyMatrix3( ASSIMP_API void aiMultiplyMatrix3(
aiMatrix3x3* dst, aiMatrix3x3* dst,
const aiMatrix3x3* src) const aiMatrix3x3* src)
{ {
ai_assert(NULL != dst && NULL != src); ai_assert(NULL != dst && NULL != src);
*dst = (*dst) * (*src); *dst = (*dst) * (*src);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Matrix identity // Matrix identity
ASSIMP_API void aiIdentityMatrix3( ASSIMP_API void aiIdentityMatrix3(
aiMatrix3x3* mat) aiMatrix3x3* mat)
{ {
ai_assert(NULL != mat); ai_assert(NULL != mat);
*mat = aiMatrix3x3(); *mat = aiMatrix3x3();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API void aiIdentityMatrix4( ASSIMP_API void aiIdentityMatrix4(
aiMatrix4x4* mat) aiMatrix4x4* mat)
{ {
ai_assert(NULL != mat); ai_assert(NULL != mat);
*mat = aiMatrix4x4(); *mat = aiMatrix4x4();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
@ -54,76 +54,76 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API size_t aiGetExportFormatCount(void) ASSIMP_API size_t aiGetExportFormatCount(void)
{ {
return Exporter().GetExportFormatCount(); return Exporter().GetExportFormatCount();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t pIndex) ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t pIndex)
{ {
// Note: this is valid as the index always pertains to a builtin exporter, // Note: this is valid as the index always pertains to a builtin exporter,
// for which the returned structure is guaranteed to be of static storage duration. // for which the returned structure is guaranteed to be of static storage duration.
return Exporter().GetExportFormatDescription(pIndex); return Exporter().GetExportFormatDescription(pIndex);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API void aiCopyScene(const aiScene* pIn, aiScene** pOut) ASSIMP_API void aiCopyScene(const aiScene* pIn, aiScene** pOut)
{ {
if (!pOut || !pIn) { if (!pOut || !pIn) {
return; return;
} }
SceneCombiner::CopyScene(pOut,pIn,true); SceneCombiner::CopyScene(pOut,pIn,true);
ScenePriv(*pOut)->mIsCopy = true; ScenePriv(*pOut)->mIsCopy = true;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API void aiFreeScene(const C_STRUCT aiScene* pIn) ASSIMP_API void aiFreeScene(const C_STRUCT aiScene* pIn)
{ {
// note: aiReleaseImport() is also able to delete scene copies, but in addition // note: aiReleaseImport() is also able to delete scene copies, but in addition
// it also handles scenes with import metadata. // it also handles scenes with import metadata.
delete pIn; delete pIn;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API aiReturn aiExportScene( const aiScene* pScene, const char* pFormatId, const char* pFileName, unsigned int pPreprocessing ) ASSIMP_API aiReturn aiExportScene( const aiScene* pScene, const char* pFormatId, const char* pFileName, unsigned int pPreprocessing )
{ {
return ::aiExportSceneEx(pScene,pFormatId,pFileName,NULL,pPreprocessing); return ::aiExportSceneEx(pScene,pFormatId,pFileName,NULL,pPreprocessing);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API aiReturn aiExportSceneEx( const aiScene* pScene, const char* pFormatId, const char* pFileName, aiFileIO* pIO, unsigned int pPreprocessing ) ASSIMP_API aiReturn aiExportSceneEx( const aiScene* pScene, const char* pFormatId, const char* pFileName, aiFileIO* pIO, unsigned int pPreprocessing )
{ {
Exporter exp; Exporter exp;
if (pIO) { if (pIO) {
exp.SetIOHandler(new CIOSystemWrapper(pIO)); exp.SetIOHandler(new CIOSystemWrapper(pIO));
} }
return exp.Export(pScene,pFormatId,pFileName,pPreprocessing); return exp.Export(pScene,pFormatId,pFileName,pPreprocessing);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API const C_STRUCT aiExportDataBlob* aiExportSceneToBlob( const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing ) ASSIMP_API const C_STRUCT aiExportDataBlob* aiExportSceneToBlob( const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing )
{ {
Exporter exp; Exporter exp;
if (!exp.ExportToBlob(pScene,pFormatId,pPreprocessing)) { if (!exp.ExportToBlob(pScene,pFormatId,pPreprocessing)) {
return NULL; return NULL;
} }
const aiExportDataBlob* blob = exp.GetOrphanedBlob(); const aiExportDataBlob* blob = exp.GetOrphanedBlob();
ai_assert(blob); ai_assert(blob);
return blob; return blob;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API C_STRUCT void aiReleaseExportBlob( const aiExportDataBlob* pData ) ASSIMP_API C_STRUCT void aiReleaseExportBlob( const aiExportDataBlob* pData )
{ {
delete pData; delete pData;
} }
#endif // !ASSIMP_BUILD_NO_EXPORT #endif // !ASSIMP_BUILD_NO_EXPORT

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,8 @@
/* /*
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -61,69 +60,69 @@ namespace Assimp{
class B3DImporter : public BaseImporter{ class B3DImporter : public BaseImporter{
public: public:
virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const; virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
protected: protected:
virtual const aiImporterDesc* GetInfo () const; virtual const aiImporterDesc* GetInfo () const;
virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
private: private:
int ReadByte(); int ReadByte();
int ReadInt(); int ReadInt();
float ReadFloat(); float ReadFloat();
aiVector2D ReadVec2(); aiVector2D ReadVec2();
aiVector3D ReadVec3(); aiVector3D ReadVec3();
aiQuaternion ReadQuat(); aiQuaternion ReadQuat();
std::string ReadString(); std::string ReadString();
std::string ReadChunk(); std::string ReadChunk();
void ExitChunk(); void ExitChunk();
unsigned ChunkSize(); unsigned ChunkSize();
template<class T> template<class T>
T *to_array( const std::vector<T> &v ); T *to_array( const std::vector<T> &v );
struct Vertex{ struct Vertex{
aiVector3D vertex; aiVector3D vertex;
aiVector3D normal; aiVector3D normal;
aiVector3D texcoords; aiVector3D texcoords;
unsigned char bones[4]; unsigned char bones[4];
float weights[4]; float weights[4];
}; };
AI_WONT_RETURN void Oops() AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void Oops() AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Fail( std::string str ) AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void Fail( std::string str ) AI_WONT_RETURN_SUFFIX;
void ReadTEXS(); void ReadTEXS();
void ReadBRUS(); void ReadBRUS();
void ReadVRTS(); void ReadVRTS();
void ReadTRIS( int v0 ); void ReadTRIS( int v0 );
void ReadMESH(); void ReadMESH();
void ReadBONE( int id ); void ReadBONE( int id );
void ReadKEYS( aiNodeAnim *nodeAnim ); void ReadKEYS( aiNodeAnim *nodeAnim );
void ReadANIM(); void ReadANIM();
aiNode *ReadNODE( aiNode *parent ); aiNode *ReadNODE( aiNode *parent );
void ReadBB3D( aiScene *scene ); void ReadBB3D( aiScene *scene );
unsigned _pos; unsigned _pos;
// unsigned _size; // unsigned _size;
std::vector<unsigned char> _buf; std::vector<unsigned char> _buf;
std::vector<unsigned> _stack; std::vector<unsigned> _stack;
std::vector<std::string> _textures; std::vector<std::string> _textures;
std::vector<aiMaterial*> _materials; std::vector<aiMaterial*> _materials;
int _vflags,_tcsets,_tcsize; int _vflags,_tcsets,_tcsize;
std::vector<Vertex> _vertices; std::vector<Vertex> _vertices;
std::vector<aiNode*> _nodes; std::vector<aiNode*> _nodes;
std::vector<aiMesh*> _meshes; std::vector<aiMesh*> _meshes;
std::vector<aiNodeAnim*> _nodeAnims; std::vector<aiNodeAnim*> _nodeAnims;
std::vector<aiAnimation*> _animations; std::vector<aiAnimation*> _animations;
}; };
} }

View File

@ -4,7 +4,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
@ -55,22 +55,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
static const aiImporterDesc desc = { static const aiImporterDesc desc = {
"BVH Importer (MoCap)", "BVH Importer (MoCap)",
"", "",
"", "",
"", "",
aiImporterFlags_SupportTextFlavour, aiImporterFlags_SupportTextFlavour,
0, 0,
0, 0,
0, 0,
0, 0,
"bvh" "bvh"
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
BVHLoader::BVHLoader() BVHLoader::BVHLoader()
: noSkeletonMesh() : mLine(),
mAnimTickDuration(),
mAnimNumFrames(),
noSkeletonMesh()
{} {}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -82,458 +85,458 @@ BVHLoader::~BVHLoader()
// 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 BVHLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const bool BVHLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const
{ {
// check file extension // check file extension
const std::string extension = GetExtension(pFile); const std::string extension = GetExtension(pFile);
if( extension == "bvh") if( extension == "bvh")
return true; return true;
if ((!extension.length() || cs) && pIOHandler) { if ((!extension.length() || cs) && pIOHandler) {
const char* tokens[] = {"HIERARCHY"}; const char* tokens[] = {"HIERARCHY"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
} }
return false; return false;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BVHLoader::SetupProperties(const Importer* pImp) void BVHLoader::SetupProperties(const Importer* pImp)
{ {
noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0; noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Loader meta information // Loader meta information
const aiImporterDesc* BVHLoader::GetInfo () const const aiImporterDesc* BVHLoader::GetInfo () const
{ {
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void BVHLoader::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) void BVHLoader::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
{ {
mFileName = pFile; mFileName = pFile;
// read file into memory // read file into memory
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile)); boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
if( file.get() == NULL) if( file.get() == NULL)
throw DeadlyImportError( "Failed to open file " + pFile + "."); throw DeadlyImportError( "Failed to open file " + pFile + ".");
size_t fileSize = file->FileSize(); size_t fileSize = file->FileSize();
if( fileSize == 0) if( fileSize == 0)
throw DeadlyImportError( "File is too small."); throw DeadlyImportError( "File is too small.");
mBuffer.resize( fileSize); mBuffer.resize( fileSize);
file->Read( &mBuffer.front(), 1, fileSize); file->Read( &mBuffer.front(), 1, fileSize);
// start reading // start reading
mReader = mBuffer.begin(); mReader = mBuffer.begin();
mLine = 1; mLine = 1;
ReadStructure( pScene); ReadStructure( pScene);
if (!noSkeletonMesh) { if (!noSkeletonMesh) {
// build a dummy mesh for the skeleton so that we see something at least // build a dummy mesh for the skeleton so that we see something at least
SkeletonMeshBuilder meshBuilder( pScene); SkeletonMeshBuilder meshBuilder( pScene);
} }
// construct an animation from all the motion data we read // construct an animation from all the motion data we read
CreateAnimation( pScene); CreateAnimation( pScene);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads the file // Reads the file
void BVHLoader::ReadStructure( aiScene* pScene) void BVHLoader::ReadStructure( aiScene* pScene)
{ {
// first comes hierarchy // first comes hierarchy
std::string header = GetNextToken(); std::string header = GetNextToken();
if( header != "HIERARCHY") if( header != "HIERARCHY")
ThrowException( "Expected header string \"HIERARCHY\"."); ThrowException( "Expected header string \"HIERARCHY\".");
ReadHierarchy( pScene); ReadHierarchy( pScene);
// then comes the motion data // then comes the motion data
std::string motion = GetNextToken(); std::string motion = GetNextToken();
if( motion != "MOTION") if( motion != "MOTION")
ThrowException( "Expected beginning of motion data \"MOTION\"."); ThrowException( "Expected beginning of motion data \"MOTION\".");
ReadMotion( pScene); ReadMotion( pScene);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads the hierarchy // Reads the hierarchy
void BVHLoader::ReadHierarchy( aiScene* pScene) void BVHLoader::ReadHierarchy( aiScene* pScene)
{ {
std::string root = GetNextToken(); std::string root = GetNextToken();
if( root != "ROOT") if( root != "ROOT")
ThrowException( "Expected root node \"ROOT\"."); ThrowException( "Expected root node \"ROOT\".");
// Go read the hierarchy from here // Go read the hierarchy from here
pScene->mRootNode = ReadNode(); pScene->mRootNode = ReadNode();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads a node and recursively its childs and returns the created node; // Reads a node and recursively its childs and returns the created node;
aiNode* BVHLoader::ReadNode() aiNode* BVHLoader::ReadNode()
{ {
// first token is name // first token is name
std::string nodeName = GetNextToken(); std::string nodeName = GetNextToken();
if( nodeName.empty() || nodeName == "{") if( nodeName.empty() || nodeName == "{")
ThrowException( boost::str( boost::format( "Expected node name, but found \"%s\".") % nodeName)); ThrowException( boost::str( boost::format( "Expected node name, but found \"%s\".") % nodeName));
// then an opening brace should follow // then an opening brace should follow
std::string openBrace = GetNextToken(); std::string openBrace = GetNextToken();
if( openBrace != "{") if( openBrace != "{")
ThrowException( boost::str( boost::format( "Expected opening brace \"{\", but found \"%s\".") % openBrace)); ThrowException( boost::str( boost::format( "Expected opening brace \"{\", but found \"%s\".") % openBrace));
// Create a node // Create a node
aiNode* node = new aiNode( nodeName); aiNode* node = new aiNode( nodeName);
std::vector<aiNode*> childNodes; std::vector<aiNode*> childNodes;
// and create an bone entry for it // and create an bone entry for it
mNodes.push_back( Node( node)); mNodes.push_back( Node( node));
Node& internNode = mNodes.back(); Node& internNode = mNodes.back();
// now read the node's contents // now read the node's contents
while( 1) while( 1)
{ {
std::string token = GetNextToken(); std::string token = GetNextToken();
// node offset to parent node // node offset to parent node
if( token == "OFFSET") if( token == "OFFSET")
ReadNodeOffset( node); ReadNodeOffset( node);
else if( token == "CHANNELS") else if( token == "CHANNELS")
ReadNodeChannels( internNode); ReadNodeChannels( internNode);
else if( token == "JOINT") else if( token == "JOINT")
{ {
// child node follows // child node follows
aiNode* child = ReadNode(); aiNode* child = ReadNode();
child->mParent = node; child->mParent = node;
childNodes.push_back( child); childNodes.push_back( child);
} }
else if( token == "End") else if( token == "End")
{ {
// The real symbol is "End Site". Second part comes in a separate token // The real symbol is "End Site". Second part comes in a separate token
std::string siteToken = GetNextToken(); std::string siteToken = GetNextToken();
if( siteToken != "Site") if( siteToken != "Site")
ThrowException( boost::str( boost::format( "Expected \"End Site\" keyword, but found \"%s %s\".") % token % siteToken)); ThrowException( boost::str( boost::format( "Expected \"End Site\" keyword, but found \"%s %s\".") % token % siteToken));
aiNode* child = ReadEndSite( nodeName); aiNode* child = ReadEndSite( nodeName);
child->mParent = node; child->mParent = node;
childNodes.push_back( child); childNodes.push_back( child);
} }
else if( token == "}") else if( token == "}")
{ {
// we're done with that part of the hierarchy // we're done with that part of the hierarchy
break; break;
} else } else
{ {
// everything else is a parse error // everything else is a parse error
ThrowException( boost::str( boost::format( "Unknown keyword \"%s\".") % token)); ThrowException( boost::str( boost::format( "Unknown keyword \"%s\".") % token));
} }
} }
// add the child nodes if there are any // add the child nodes if there are any
if( childNodes.size() > 0) if( childNodes.size() > 0)
{ {
node->mNumChildren = childNodes.size(); node->mNumChildren = childNodes.size();
node->mChildren = new aiNode*[node->mNumChildren]; node->mChildren = new aiNode*[node->mNumChildren];
std::copy( childNodes.begin(), childNodes.end(), node->mChildren); std::copy( childNodes.begin(), childNodes.end(), node->mChildren);
} }
// and return the sub-hierarchy we built here // and return the sub-hierarchy we built here
return node; return node;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads an end node and returns the created node. // Reads an end node and returns the created node.
aiNode* BVHLoader::ReadEndSite( const std::string& pParentName) aiNode* BVHLoader::ReadEndSite( const std::string& pParentName)
{ {
// check opening brace // check opening brace
std::string openBrace = GetNextToken(); std::string openBrace = GetNextToken();
if( openBrace != "{") if( openBrace != "{")
ThrowException( boost::str( boost::format( "Expected opening brace \"{\", but found \"%s\".") % openBrace)); ThrowException( boost::str( boost::format( "Expected opening brace \"{\", but found \"%s\".") % openBrace));
// Create a node // Create a node
aiNode* node = new aiNode( "EndSite_" + pParentName); aiNode* node = new aiNode( "EndSite_" + pParentName);
// now read the node's contents. Only possible entry is "OFFSET" // now read the node's contents. Only possible entry is "OFFSET"
while( 1) while( 1)
{ {
std::string token = GetNextToken(); std::string token = GetNextToken();
// end node's offset // end node's offset
if( token == "OFFSET") if( token == "OFFSET")
{ {
ReadNodeOffset( node); ReadNodeOffset( node);
} }
else if( token == "}") else if( token == "}")
{ {
// we're done with the end node // we're done with the end node
break; break;
} else } else
{ {
// everything else is a parse error // everything else is a parse error
ThrowException( boost::str( boost::format( "Unknown keyword \"%s\".") % token)); ThrowException( boost::str( boost::format( "Unknown keyword \"%s\".") % token));
} }
} }
// and return the sub-hierarchy we built here // and return the sub-hierarchy we built here
return node; return node;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads a node offset for the given node // Reads a node offset for the given node
void BVHLoader::ReadNodeOffset( aiNode* pNode) void BVHLoader::ReadNodeOffset( aiNode* pNode)
{ {
// Offset consists of three floats to read // Offset consists of three floats to read
aiVector3D offset; aiVector3D offset;
offset.x = GetNextTokenAsFloat(); offset.x = GetNextTokenAsFloat();
offset.y = GetNextTokenAsFloat(); offset.y = GetNextTokenAsFloat();
offset.z = GetNextTokenAsFloat(); offset.z = GetNextTokenAsFloat();
// build a transformation matrix from it // build a transformation matrix from it
pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x, 0.0f, 1.0f, 0.0f, offset.y, pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x, 0.0f, 1.0f, 0.0f, offset.y,
0.0f, 0.0f, 1.0f, offset.z, 0.0f, 0.0f, 0.0f, 1.0f); 0.0f, 0.0f, 1.0f, offset.z, 0.0f, 0.0f, 0.0f, 1.0f);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads the animation channels for the given node // Reads the animation channels for the given node
void BVHLoader::ReadNodeChannels( BVHLoader::Node& pNode) void BVHLoader::ReadNodeChannels( BVHLoader::Node& pNode)
{ {
// number of channels. Use the float reader because we're lazy // number of channels. Use the float reader because we're lazy
float numChannelsFloat = GetNextTokenAsFloat(); float numChannelsFloat = GetNextTokenAsFloat();
unsigned int numChannels = (unsigned int) numChannelsFloat; unsigned int numChannels = (unsigned int) numChannelsFloat;
for( unsigned int a = 0; a < numChannels; a++) for( unsigned int a = 0; a < numChannels; a++)
{ {
std::string channelToken = GetNextToken(); std::string channelToken = GetNextToken();
if( channelToken == "Xposition") if( channelToken == "Xposition")
pNode.mChannels.push_back( Channel_PositionX); pNode.mChannels.push_back( Channel_PositionX);
else if( channelToken == "Yposition") else if( channelToken == "Yposition")
pNode.mChannels.push_back( Channel_PositionY); pNode.mChannels.push_back( Channel_PositionY);
else if( channelToken == "Zposition") else if( channelToken == "Zposition")
pNode.mChannels.push_back( Channel_PositionZ); pNode.mChannels.push_back( Channel_PositionZ);
else if( channelToken == "Xrotation") else if( channelToken == "Xrotation")
pNode.mChannels.push_back( Channel_RotationX); pNode.mChannels.push_back( Channel_RotationX);
else if( channelToken == "Yrotation") else if( channelToken == "Yrotation")
pNode.mChannels.push_back( Channel_RotationY); pNode.mChannels.push_back( Channel_RotationY);
else if( channelToken == "Zrotation") else if( channelToken == "Zrotation")
pNode.mChannels.push_back( Channel_RotationZ); pNode.mChannels.push_back( Channel_RotationZ);
else else
ThrowException( boost::str( boost::format( "Invalid channel specifier \"%s\".") % channelToken)); ThrowException( boost::str( boost::format( "Invalid channel specifier \"%s\".") % channelToken));
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads the motion data // Reads the motion data
void BVHLoader::ReadMotion( aiScene* /*pScene*/) void BVHLoader::ReadMotion( aiScene* /*pScene*/)
{ {
// Read number of frames // Read number of frames
std::string tokenFrames = GetNextToken(); std::string tokenFrames = GetNextToken();
if( tokenFrames != "Frames:") if( tokenFrames != "Frames:")
ThrowException( boost::str( boost::format( "Expected frame count \"Frames:\", but found \"%s\".") % tokenFrames)); ThrowException( boost::str( boost::format( "Expected frame count \"Frames:\", but found \"%s\".") % tokenFrames));
float numFramesFloat = GetNextTokenAsFloat(); float numFramesFloat = GetNextTokenAsFloat();
mAnimNumFrames = (unsigned int) numFramesFloat; mAnimNumFrames = (unsigned int) numFramesFloat;
// Read frame duration // Read frame duration
std::string tokenDuration1 = GetNextToken(); std::string tokenDuration1 = GetNextToken();
std::string tokenDuration2 = GetNextToken(); std::string tokenDuration2 = GetNextToken();
if( tokenDuration1 != "Frame" || tokenDuration2 != "Time:") if( tokenDuration1 != "Frame" || tokenDuration2 != "Time:")
ThrowException( boost::str( boost::format( "Expected frame duration \"Frame Time:\", but found \"%s %s\".") % tokenDuration1 % tokenDuration2)); ThrowException( boost::str( boost::format( "Expected frame duration \"Frame Time:\", but found \"%s %s\".") % tokenDuration1 % tokenDuration2));
mAnimTickDuration = GetNextTokenAsFloat(); mAnimTickDuration = GetNextTokenAsFloat();
// resize value vectors for each node // resize value vectors for each node
for( std::vector<Node>::iterator it = mNodes.begin(); it != mNodes.end(); ++it) for( std::vector<Node>::iterator it = mNodes.begin(); it != mNodes.end(); ++it)
it->mChannelValues.reserve( it->mChannels.size() * mAnimNumFrames); it->mChannelValues.reserve( it->mChannels.size() * mAnimNumFrames);
// now read all the data and store it in the corresponding node's value vector // now read all the data and store it in the corresponding node's value vector
for( unsigned int frame = 0; frame < mAnimNumFrames; ++frame) for( unsigned int frame = 0; frame < mAnimNumFrames; ++frame)
{ {
// on each line read the values for all nodes // on each line read the values for all nodes
for( std::vector<Node>::iterator it = mNodes.begin(); it != mNodes.end(); ++it) for( std::vector<Node>::iterator it = mNodes.begin(); it != mNodes.end(); ++it)
{ {
// get as many values as the node has channels // get as many values as the node has channels
for( unsigned int c = 0; c < it->mChannels.size(); ++c) for( unsigned int c = 0; c < it->mChannels.size(); ++c)
it->mChannelValues.push_back( GetNextTokenAsFloat()); it->mChannelValues.push_back( GetNextTokenAsFloat());
} }
// after one frame worth of values for all nodes there should be a newline, but we better don't rely on it // after one frame worth of values for all nodes there should be a newline, but we better don't rely on it
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Retrieves the next token // Retrieves the next token
std::string BVHLoader::GetNextToken() std::string BVHLoader::GetNextToken()
{ {
// skip any preceeding whitespace // skip any preceeding whitespace
while( mReader != mBuffer.end()) while( mReader != mBuffer.end())
{ {
if( !isspace( *mReader)) if( !isspace( *mReader))
break; break;
// count lines // count lines
if( *mReader == '\n') if( *mReader == '\n')
mLine++; mLine++;
++mReader; ++mReader;
} }
// collect all chars till the next whitespace. BVH is easy in respect to that. // collect all chars till the next whitespace. BVH is easy in respect to that.
std::string token; std::string token;
while( mReader != mBuffer.end()) while( mReader != mBuffer.end())
{ {
if( isspace( *mReader)) if( isspace( *mReader))
break; break;
token.push_back( *mReader); token.push_back( *mReader);
++mReader; ++mReader;
// little extra logic to make sure braces are counted correctly // little extra logic to make sure braces are counted correctly
if( token == "{" || token == "}") if( token == "{" || token == "}")
break; break;
} }
// empty token means end of file, which is just fine // empty token means end of file, which is just fine
return token; return token;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Reads the next token as a float // Reads the next token as a float
float BVHLoader::GetNextTokenAsFloat() float BVHLoader::GetNextTokenAsFloat()
{ {
std::string token = GetNextToken(); std::string token = GetNextToken();
if( token.empty()) if( token.empty())
ThrowException( "Unexpected end of file while trying to read a float"); ThrowException( "Unexpected end of file while trying to read a float");
// check if the float is valid by testing if the atof() function consumed every char of the token // check if the float is valid by testing if the atof() function consumed every char of the token
const char* ctoken = token.c_str(); const char* ctoken = token.c_str();
float result = 0.0f; float result = 0.0f;
ctoken = fast_atoreal_move<float>( ctoken, result); ctoken = fast_atoreal_move<float>( ctoken, result);
if( ctoken != token.c_str() + token.length()) if( ctoken != token.c_str() + token.length())
ThrowException( boost::str( boost::format( "Expected a floating point number, but found \"%s\".") % token)); ThrowException( boost::str( boost::format( "Expected a floating point number, but found \"%s\".") % token));
return result; return result;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Aborts the file reading with an exception // Aborts the file reading with an exception
AI_WONT_RETURN void BVHLoader::ThrowException( const std::string& pError) AI_WONT_RETURN void BVHLoader::ThrowException( const std::string& pError)
{ {
throw DeadlyImportError( boost::str( boost::format( "%s:%d - %s") % mFileName % mLine % pError)); throw DeadlyImportError( boost::str( boost::format( "%s:%d - %s") % mFileName % mLine % pError));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructs an animation for the motion data and stores it in the given scene // Constructs an animation for the motion data and stores it in the given scene
void BVHLoader::CreateAnimation( aiScene* pScene) void BVHLoader::CreateAnimation( aiScene* pScene)
{ {
// create the animation // create the animation
pScene->mNumAnimations = 1; pScene->mNumAnimations = 1;
pScene->mAnimations = new aiAnimation*[1]; pScene->mAnimations = new aiAnimation*[1];
aiAnimation* anim = new aiAnimation; aiAnimation* anim = new aiAnimation;
pScene->mAnimations[0] = anim; pScene->mAnimations[0] = anim;
// put down the basic parameters // put down the basic parameters
anim->mName.Set( "Motion"); anim->mName.Set( "Motion");
anim->mTicksPerSecond = 1.0 / double( mAnimTickDuration); anim->mTicksPerSecond = 1.0 / double( mAnimTickDuration);
anim->mDuration = double( mAnimNumFrames - 1); anim->mDuration = double( mAnimNumFrames - 1);
// now generate the tracks for all nodes // now generate the tracks for all nodes
anim->mNumChannels = mNodes.size(); anim->mNumChannels = mNodes.size();
anim->mChannels = new aiNodeAnim*[anim->mNumChannels]; anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
// FIX: set the array elements to NULL to ensure proper deletion if an exception is thrown // FIX: set the array elements to NULL to ensure proper deletion if an exception is thrown
for (unsigned int i = 0; i < anim->mNumChannels;++i) for (unsigned int i = 0; i < anim->mNumChannels;++i)
anim->mChannels[i] = NULL; anim->mChannels[i] = NULL;
for( unsigned int a = 0; a < anim->mNumChannels; a++) for( unsigned int a = 0; a < anim->mNumChannels; a++)
{ {
const Node& node = mNodes[a]; const Node& node = mNodes[a];
const std::string nodeName = std::string( node.mNode->mName.data ); const std::string nodeName = std::string( node.mNode->mName.data );
aiNodeAnim* nodeAnim = new aiNodeAnim; aiNodeAnim* nodeAnim = new aiNodeAnim;
anim->mChannels[a] = nodeAnim; anim->mChannels[a] = nodeAnim;
nodeAnim->mNodeName.Set( nodeName); nodeAnim->mNodeName.Set( nodeName);
// translational part, if given // translational part, if given
if( node.mChannels.size() == 6) if( node.mChannels.size() == 6)
{ {
nodeAnim->mNumPositionKeys = mAnimNumFrames; nodeAnim->mNumPositionKeys = mAnimNumFrames;
nodeAnim->mPositionKeys = new aiVectorKey[mAnimNumFrames]; nodeAnim->mPositionKeys = new aiVectorKey[mAnimNumFrames];
aiVectorKey* poskey = nodeAnim->mPositionKeys; aiVectorKey* poskey = nodeAnim->mPositionKeys;
for( unsigned int fr = 0; fr < mAnimNumFrames; ++fr) for( unsigned int fr = 0; fr < mAnimNumFrames; ++fr)
{ {
poskey->mTime = double( fr); poskey->mTime = double( fr);
// Now compute all translations in the right order // Now compute all translations in the right order
for( unsigned int channel = 0; channel < 3; ++channel) for( unsigned int channel = 0; channel < 3; ++channel)
{ {
switch( node.mChannels[channel]) switch( node.mChannels[channel])
{ {
case Channel_PositionX: poskey->mValue.x = node.mChannelValues[fr * node.mChannels.size() + channel]; break; case Channel_PositionX: poskey->mValue.x = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
case Channel_PositionY: poskey->mValue.y = node.mChannelValues[fr * node.mChannels.size() + channel]; break; case Channel_PositionY: poskey->mValue.y = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
case Channel_PositionZ: poskey->mValue.z = node.mChannelValues[fr * node.mChannels.size() + channel]; break; case Channel_PositionZ: poskey->mValue.z = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName ); default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName );
} }
} }
++poskey; ++poskey;
} }
} else } else
{ {
// if no translation part is given, put a default sequence // if no translation part is given, put a default sequence
aiVector3D nodePos( node.mNode->mTransformation.a4, node.mNode->mTransformation.b4, node.mNode->mTransformation.c4); aiVector3D nodePos( node.mNode->mTransformation.a4, node.mNode->mTransformation.b4, node.mNode->mTransformation.c4);
nodeAnim->mNumPositionKeys = 1; nodeAnim->mNumPositionKeys = 1;
nodeAnim->mPositionKeys = new aiVectorKey[1]; nodeAnim->mPositionKeys = new aiVectorKey[1];
nodeAnim->mPositionKeys[0].mTime = 0.0; nodeAnim->mPositionKeys[0].mTime = 0.0;
nodeAnim->mPositionKeys[0].mValue = nodePos; nodeAnim->mPositionKeys[0].mValue = nodePos;
} }
// rotation part. Always present. First find value offsets // rotation part. Always present. First find value offsets
{ {
unsigned int rotOffset = 0; unsigned int rotOffset = 0;
if( node.mChannels.size() == 6) if( node.mChannels.size() == 6)
{ {
// Offset all further calculations // Offset all further calculations
rotOffset = 3; rotOffset = 3;
} }
// Then create the number of rotation keys // Then create the number of rotation keys
nodeAnim->mNumRotationKeys = mAnimNumFrames; nodeAnim->mNumRotationKeys = mAnimNumFrames;
nodeAnim->mRotationKeys = new aiQuatKey[mAnimNumFrames]; nodeAnim->mRotationKeys = new aiQuatKey[mAnimNumFrames];
aiQuatKey* rotkey = nodeAnim->mRotationKeys; aiQuatKey* rotkey = nodeAnim->mRotationKeys;
for( unsigned int fr = 0; fr < mAnimNumFrames; ++fr) for( unsigned int fr = 0; fr < mAnimNumFrames; ++fr)
{ {
aiMatrix4x4 temp; aiMatrix4x4 temp;
aiMatrix3x3 rotMatrix; aiMatrix3x3 rotMatrix;
for( unsigned int channel = 0; channel < 3; ++channel) for( unsigned int channel = 0; channel < 3; ++channel)
{ {
// translate ZXY euler angels into a quaternion // translate ZXY euler angels into a quaternion
const float angle = node.mChannelValues[fr * node.mChannels.size() + rotOffset + channel] * float( AI_MATH_PI) / 180.0f; const float angle = node.mChannelValues[fr * node.mChannels.size() + rotOffset + channel] * float( AI_MATH_PI) / 180.0f;
// Compute rotation transformations in the right order // Compute rotation transformations in the right order
switch (node.mChannels[rotOffset+channel]) switch (node.mChannels[rotOffset+channel])
{ {
case Channel_RotationX: aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp); break; case Channel_RotationX: aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
case Channel_RotationY: aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp); break; case Channel_RotationY: aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
case Channel_RotationZ: aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp); break; case Channel_RotationZ: aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName ); default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName );
} }
} }
rotkey->mTime = double( fr); rotkey->mTime = double( fr);
rotkey->mValue = aiQuaternion( rotMatrix); rotkey->mValue = aiQuaternion( rotMatrix);
++rotkey; ++rotkey;
} }
} }
// scaling part. Always just a default track // scaling part. Always just a default track
{ {
nodeAnim->mNumScalingKeys = 1; nodeAnim->mNumScalingKeys = 1;
nodeAnim->mScalingKeys = new aiVectorKey[1]; nodeAnim->mScalingKeys = new aiVectorKey[1];
nodeAnim->mScalingKeys[0].mTime = 0.0; nodeAnim->mScalingKeys[0].mTime = 0.0;
nodeAnim->mScalingKeys[0].mValue.Set( 1.0f, 1.0f, 1.0f); nodeAnim->mScalingKeys[0].mValue.Set( 1.0f, 1.0f, 1.0f);
} }
} }
} }
#endif // !! ASSIMP_BUILD_NO_BVH_IMPORTER #endif // !! ASSIMP_BUILD_NO_BVH_IMPORTER

View File

@ -4,7 +4,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -64,106 +64,106 @@ namespace Assimp
class BVHLoader : public BaseImporter class BVHLoader : public BaseImporter
{ {
/** Possible animation channels for which the motion data holds the values */ /** Possible animation channels for which the motion data holds the values */
enum ChannelType enum ChannelType
{ {
Channel_PositionX, Channel_PositionX,
Channel_PositionY, Channel_PositionY,
Channel_PositionZ, Channel_PositionZ,
Channel_RotationX, Channel_RotationX,
Channel_RotationY, Channel_RotationY,
Channel_RotationZ Channel_RotationZ
}; };
/** Collected list of node. Will be bones of the dummy mesh some day, addressed by their array index */ /** Collected list of node. Will be bones of the dummy mesh some day, addressed by their array index */
struct Node struct Node
{ {
const aiNode* mNode; const aiNode* mNode;
std::vector<ChannelType> mChannels; std::vector<ChannelType> mChannels;
std::vector<float> mChannelValues; // motion data values for that node. Of size NumChannels * NumFrames std::vector<float> mChannelValues; // motion data values for that node. Of size NumChannels * NumFrames
Node() { } Node() { }
Node( const aiNode* pNode) : mNode( pNode) { } Node( const aiNode* pNode) : mNode( pNode) { }
}; };
public: public:
BVHLoader(); BVHLoader();
~BVHLoader(); ~BVHLoader();
public: public:
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. */ * See BaseImporter::CanRead() for details. */
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const; bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const;
void SetupProperties(const Importer* pImp); void SetupProperties(const Importer* pImp);
const aiImporterDesc* GetInfo () const; const aiImporterDesc* GetInfo () const;
protected: protected:
/** Imports the given file into the given scene structure. /** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details * See BaseImporter::InternReadFile() for details
*/ */
void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
protected: protected:
/** Reads the file */ /** Reads the file */
void ReadStructure( aiScene* pScene); void ReadStructure( aiScene* pScene);
/** Reads the hierarchy */ /** Reads the hierarchy */
void ReadHierarchy( aiScene* pScene); void ReadHierarchy( aiScene* pScene);
/** Reads a node and recursively its childs and returns the created node. */ /** Reads a node and recursively its childs and returns the created node. */
aiNode* ReadNode(); aiNode* ReadNode();
/** Reads an end node and returns the created node. */ /** Reads an end node and returns the created node. */
aiNode* ReadEndSite( const std::string& pParentName); aiNode* ReadEndSite( const std::string& pParentName);
/** Reads a node offset for the given node */ /** Reads a node offset for the given node */
void ReadNodeOffset( aiNode* pNode); void ReadNodeOffset( aiNode* pNode);
/** Reads the animation channels into the given node */ /** Reads the animation channels into the given node */
void ReadNodeChannels( BVHLoader::Node& pNode); void ReadNodeChannels( BVHLoader::Node& pNode);
/** Reads the motion data */ /** Reads the motion data */
void ReadMotion( aiScene* pScene); void ReadMotion( aiScene* pScene);
/** Retrieves the next token */ /** Retrieves the next token */
std::string GetNextToken(); std::string GetNextToken();
/** Reads the next token as a float */ /** Reads the next token as a float */
float GetNextTokenAsFloat(); float GetNextTokenAsFloat();
/** Aborts the file reading with an exception */ /** Aborts the file reading with an exception */
AI_WONT_RETURN void ThrowException( const std::string& pError) AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void ThrowException( const std::string& pError) AI_WONT_RETURN_SUFFIX;
/** Constructs an animation for the motion data and stores it in the given scene */ /** Constructs an animation for the motion data and stores it in the given scene */
void CreateAnimation( aiScene* pScene); void CreateAnimation( aiScene* pScene);
protected: protected:
/** Filename, for a verbose error message */ /** Filename, for a verbose error message */
std::string mFileName; std::string mFileName;
/** Buffer to hold the loaded file */ /** Buffer to hold the loaded file */
std::vector<char> mBuffer; std::vector<char> mBuffer;
/** Next char to read from the buffer */ /** Next char to read from the buffer */
std::vector<char>::const_iterator mReader; std::vector<char>::const_iterator mReader;
/** Current line, for error messages */ /** Current line, for error messages */
unsigned int mLine; unsigned int mLine;
/** Collected list of nodes. Will be bones of the dummy mesh some day, addressed by their array index. /** Collected list of nodes. Will be bones of the dummy mesh some day, addressed by their array index.
* Also contain the motion data for the node's channels * Also contain the motion data for the node's channels
*/ */
std::vector<Node> mNodes; std::vector<Node> mNodes;
/** basic Animation parameters */ /** basic Animation parameters */
float mAnimTickDuration; float mAnimTickDuration;
unsigned int mAnimNumFrames; unsigned int mAnimNumFrames;
bool noSkeletonMesh; bool noSkeletonMesh;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
@ -65,233 +65,241 @@ using namespace Assimp;
BaseImporter::BaseImporter() BaseImporter::BaseImporter()
: progress() : progress()
{ {
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
BaseImporter::~BaseImporter() BaseImporter::~BaseImporter()
{ {
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file and returns the imported data. // Imports the given file and returns the imported data.
aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, IOSystem* pIOHandler) aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, IOSystem* pIOHandler)
{ {
progress = pImp->GetProgressHandler(); progress = pImp->GetProgressHandler();
ai_assert(progress); ai_assert(progress);
// Gather configuration properties for this run // Gather configuration properties for this run
SetupProperties( pImp ); SetupProperties( pImp );
// Construct a file system filter to improve our success ratio at reading external files // Construct a file system filter to improve our success ratio at reading external files
FileSystemFilter filter(pFile,pIOHandler); FileSystemFilter filter(pFile,pIOHandler);
// create a scene object to hold the data // create a scene object to hold the data
ScopeGuard<aiScene> sc(new aiScene()); ScopeGuard<aiScene> sc(new aiScene());
// dispatch importing // dispatch importing
try try
{ {
InternReadFile( pFile, sc, &filter); InternReadFile( pFile, sc, &filter);
} catch( const std::exception& err ) { } catch( const std::exception& err ) {
// extract error description // extract error description
mErrorText = err.what(); mErrorText = err.what();
DefaultLogger::get()->error(mErrorText); DefaultLogger::get()->error(mErrorText);
return NULL; return NULL;
} }
// return what we gathered from the import. // return what we gathered from the import.
sc.dismiss(); sc.dismiss();
return sc; return sc;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BaseImporter::SetupProperties(const Importer* /*pImp*/) void BaseImporter::SetupProperties(const Importer* /*pImp*/)
{ {
// the default implementation does nothing // the default implementation does nothing
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BaseImporter::GetExtensionList(std::set<std::string>& extensions) void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
{ {
const aiImporterDesc* desc = GetInfo(); const aiImporterDesc* desc = GetInfo();
ai_assert(desc != NULL); ai_assert(desc != NULL);
const char* ext = desc->mFileExtensions; const char* ext = desc->mFileExtensions;
ai_assert(ext != NULL); ai_assert(ext != NULL);
const char* last = ext; const char* last = ext;
do { do {
if (!*ext || *ext == ' ') { if (!*ext || *ext == ' ') {
extensions.insert(std::string(last,ext-last)); extensions.insert(std::string(last,ext-last));
ai_assert(ext-last > 0); ai_assert(ext-last > 0);
last = ext; last = ext;
while(*last == ' ') { while(*last == ' ') {
++last; ++last;
} }
} }
} }
while(*ext++); while(*ext++);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
/*static*/ bool BaseImporter::SearchFileHeaderForToken(IOSystem* pIOHandler, /*static*/ bool BaseImporter::SearchFileHeaderForToken(IOSystem* pIOHandler,
const std::string& pFile, const std::string& pFile,
const char** tokens, const char** tokens,
unsigned int numTokens, unsigned int numTokens,
unsigned int searchBytes /* = 200 */, unsigned int searchBytes /* = 200 */,
bool tokensSol /* false */) bool tokensSol /* false */)
{ {
ai_assert(NULL != tokens && 0 != numTokens && 0 != searchBytes); ai_assert(NULL != tokens && 0 != numTokens && 0 != searchBytes);
if (!pIOHandler) if (!pIOHandler)
return false; return false;
boost::scoped_ptr<IOStream> pStream (pIOHandler->Open(pFile)); boost::scoped_ptr<IOStream> pStream (pIOHandler->Open(pFile));
if (pStream.get() ) { if (pStream.get() ) {
// read 200 characters from the file // read 200 characters from the file
boost::scoped_array<char> _buffer (new char[searchBytes+1 /* for the '\0' */]); boost::scoped_array<char> _buffer (new char[searchBytes+1 /* for the '\0' */]);
char* buffer = _buffer.get(); char* buffer = _buffer.get();
if( NULL == buffer ) {
return false;
}
const size_t read = pStream->Read(buffer,1,searchBytes); const size_t read = pStream->Read(buffer,1,searchBytes);
if (!read) if( !read ) {
return false; return false;
}
for (size_t i = 0; i < read; ++i) for( size_t i = 0; i < read; ++i ) {
buffer[i] = ::tolower(buffer[i]); buffer[ i ] = ::tolower( buffer[ i ] );
}
// It is not a proper handling of unicode files here ... // It is not a proper handling of unicode files here ...
// ehm ... but it works in most cases. // ehm ... but it works in most cases.
char* cur = buffer,*cur2 = buffer,*end = &buffer[read]; char* cur = buffer,*cur2 = buffer,*end = &buffer[read];
while (cur != end) { while (cur != end) {
if (*cur) if( *cur ) {
*cur2++ = *cur; *cur2++ = *cur;
++cur; }
} ++cur;
*cur2 = '\0'; }
*cur2 = '\0';
for (unsigned int i = 0; i < numTokens;++i) { for (unsigned int i = 0; i < numTokens;++i) {
ai_assert(NULL != tokens[i]); ai_assert(NULL != tokens[i]);
const char* r = strstr(buffer,tokens[i]); const char* r = strstr(buffer,tokens[i]);
if (!r) if( !r ) {
continue; continue;
// We got a match, either we don't care where it is, or it happens to }
// be in the beginning of the file / line // We got a match, either we don't care where it is, or it happens to
if (!tokensSol || r == buffer || r[-1] == '\r' || r[-1] == '\n') { // be in the beginning of the file / line
DefaultLogger::get()->debug(std::string("Found positive match for header keyword: ") + tokens[i]); if (!tokensSol || r == buffer || r[-1] == '\r' || r[-1] == '\n') {
return true; DefaultLogger::get()->debug(std::string("Found positive match for header keyword: ") + tokens[i]);
} return true;
} }
} }
return false; }
return false;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Simple check for file extension // Simple check for file extension
/*static*/ bool BaseImporter::SimpleExtensionCheck (const std::string& pFile, /*static*/ bool BaseImporter::SimpleExtensionCheck (const std::string& pFile,
const char* ext0, const char* ext0,
const char* ext1, const char* ext1,
const char* ext2) const char* ext2)
{ {
std::string::size_type pos = pFile.find_last_of('.'); std::string::size_type pos = pFile.find_last_of('.');
// no file extension - can't read // no file extension - can't read
if( pos == std::string::npos) if( pos == std::string::npos)
return false; return false;
const char* ext_real = & pFile[ pos+1 ]; const char* ext_real = & pFile[ pos+1 ];
if( !ASSIMP_stricmp(ext_real,ext0) ) if( !ASSIMP_stricmp(ext_real,ext0) )
return true; return true;
// check for other, optional, file extensions // check for other, optional, file extensions
if (ext1 && !ASSIMP_stricmp(ext_real,ext1)) if (ext1 && !ASSIMP_stricmp(ext_real,ext1))
return true; return true;
if (ext2 && !ASSIMP_stricmp(ext_real,ext2)) if (ext2 && !ASSIMP_stricmp(ext_real,ext2))
return true; return true;
return false; return false;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Get file extension from path // Get file extension from path
/*static*/ std::string BaseImporter::GetExtension (const std::string& pFile) /*static*/ std::string BaseImporter::GetExtension (const std::string& pFile)
{ {
std::string::size_type pos = pFile.find_last_of('.'); std::string::size_type pos = pFile.find_last_of('.');
// no file extension at all // no file extension at all
if( pos == std::string::npos) if( pos == std::string::npos)
return ""; return "";
std::string ret = pFile.substr(pos+1); std::string ret = pFile.substr(pos+1);
std::transform(ret.begin(),ret.end(),ret.begin(),::tolower); // thanks to Andy Maloney for the hint std::transform(ret.begin(),ret.end(),ret.begin(),::tolower); // thanks to Andy Maloney for the hint
return ret; return ret;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Check for magic bytes at the beginning of the file. // Check for magic bytes at the beginning of the file.
/* static */ bool BaseImporter::CheckMagicToken(IOSystem* pIOHandler, const std::string& pFile, /* static */ bool BaseImporter::CheckMagicToken(IOSystem* pIOHandler, const std::string& pFile,
const void* _magic, unsigned int num, unsigned int offset, unsigned int size) const void* _magic, unsigned int num, unsigned int offset, unsigned int size)
{ {
ai_assert(size <= 16 && _magic); ai_assert(size <= 16 && _magic);
if (!pIOHandler) { if (!pIOHandler) {
return false; return false;
} }
union { union {
const char* magic; const char* magic;
const uint16_t* magic_u16; const uint16_t* magic_u16;
const uint32_t* magic_u32; const uint32_t* magic_u32;
}; };
magic = reinterpret_cast<const char*>(_magic); magic = reinterpret_cast<const char*>(_magic);
boost::scoped_ptr<IOStream> pStream (pIOHandler->Open(pFile)); boost::scoped_ptr<IOStream> pStream (pIOHandler->Open(pFile));
if (pStream.get() ) { if (pStream.get() ) {
// skip to offset // skip to offset
pStream->Seek(offset,aiOrigin_SET); pStream->Seek(offset,aiOrigin_SET);
// read 'size' characters from the file // read 'size' characters from the file
union { union {
char data[16]; char data[16];
uint16_t data_u16[8]; uint16_t data_u16[8];
uint32_t data_u32[4]; uint32_t data_u32[4];
}; };
if(size != pStream->Read(data,1,size)) { if(size != pStream->Read(data,1,size)) {
return false; return false;
} }
for (unsigned int i = 0; i < num; ++i) { for (unsigned int i = 0; i < num; ++i) {
// also check against big endian versions of tokens with size 2,4 // also check against big endian versions of tokens with size 2,4
// that's just for convinience, the chance that we cause conflicts // that's just for convinience, the chance that we cause conflicts
// is quite low and it can save some lines and prevent nasty bugs // is quite low and it can save some lines and prevent nasty bugs
if (2 == size) { if (2 == size) {
uint16_t rev = *magic_u16; uint16_t rev = *magic_u16;
ByteSwap::Swap(&rev); ByteSwap::Swap(&rev);
if (data_u16[0] == *magic_u16 || data_u16[0] == rev) { if (data_u16[0] == *magic_u16 || data_u16[0] == rev) {
return true; return true;
} }
} }
else if (4 == size) { else if (4 == size) {
uint32_t rev = *magic_u32; uint32_t rev = *magic_u32;
ByteSwap::Swap(&rev); ByteSwap::Swap(&rev);
if (data_u32[0] == *magic_u32 || data_u32[0] == rev) { if (data_u32[0] == *magic_u32 || data_u32[0] == rev) {
return true; return true;
} }
} }
else { else {
// any length ... just compare // any length ... just compare
if(!memcmp(magic,data,size)) { if(!memcmp(magic,data,size)) {
return true; return true;
} }
} }
magic += size; magic += size;
} }
} }
return false; return false;
} }
#include "../contrib/ConvertUTF/ConvertUTF.h" #include "../contrib/ConvertUTF/ConvertUTF.h"
@ -299,311 +307,307 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ReportResult(ConversionResult res) void ReportResult(ConversionResult res)
{ {
if(res == sourceExhausted) { if(res == sourceExhausted) {
DefaultLogger::get()->error("Source ends with incomplete character sequence, transformation to UTF-8 fails"); DefaultLogger::get()->error("Source ends with incomplete character sequence, transformation to UTF-8 fails");
} }
else if(res == sourceIllegal) { else if(res == sourceIllegal) {
DefaultLogger::get()->error("Source contains illegal character sequence, transformation to UTF-8 fails"); DefaultLogger::get()->error("Source contains illegal character sequence, transformation to UTF-8 fails");
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Convert to UTF8 data // Convert to UTF8 data
void BaseImporter::ConvertToUTF8(std::vector<char>& data) void BaseImporter::ConvertToUTF8(std::vector<char>& data)
{ {
ConversionResult result; ConversionResult result;
if(data.size() < 8) { if(data.size() < 8) {
throw DeadlyImportError("File is too small"); throw DeadlyImportError("File is too small");
} }
// UTF 8 with BOM // UTF 8 with BOM
if((uint8_t)data[0] == 0xEF && (uint8_t)data[1] == 0xBB && (uint8_t)data[2] == 0xBF) { if((uint8_t)data[0] == 0xEF && (uint8_t)data[1] == 0xBB && (uint8_t)data[2] == 0xBF) {
DefaultLogger::get()->debug("Found UTF-8 BOM ..."); DefaultLogger::get()->debug("Found UTF-8 BOM ...");
std::copy(data.begin()+3,data.end(),data.begin()); std::copy(data.begin()+3,data.end(),data.begin());
data.resize(data.size()-3); data.resize(data.size()-3);
return; return;
} }
// UTF 32 BE with BOM // UTF 32 BE with BOM
if(*((uint32_t*)&data.front()) == 0xFFFE0000) { if(*((uint32_t*)&data.front()) == 0xFFFE0000) {
// swap the endianess .. // swap the endianess ..
for(uint32_t* p = (uint32_t*)&data.front(), *end = (uint32_t*)&data.back(); p <= end; ++p) { for(uint32_t* p = (uint32_t*)&data.front(), *end = (uint32_t*)&data.back(); p <= end; ++p) {
AI_SWAP4P(p); AI_SWAP4P(p);
} }
} }
// UTF 32 LE with BOM // UTF 32 LE with BOM
if(*((uint32_t*)&data.front()) == 0x0000FFFE) { if(*((uint32_t*)&data.front()) == 0x0000FFFE) {
DefaultLogger::get()->debug("Found UTF-32 BOM ..."); DefaultLogger::get()->debug("Found UTF-32 BOM ...");
const uint32_t* sstart = (uint32_t*)&data.front()+1, *send = (uint32_t*)&data.back()+1; const uint32_t* sstart = (uint32_t*)&data.front()+1, *send = (uint32_t*)&data.back()+1;
char* dstart,*dend; char* dstart,*dend;
std::vector<char> output; std::vector<char> output;
do { do {
output.resize(output.size()?output.size()*3/2:data.size()/2); output.resize(output.size()?output.size()*3/2:data.size()/2);
dstart = &output.front(),dend = &output.back()+1; dstart = &output.front(),dend = &output.back()+1;
result = ConvertUTF32toUTF8((const UTF32**)&sstart,(const UTF32*)send,(UTF8**)&dstart,(UTF8*)dend,lenientConversion); result = ConvertUTF32toUTF8((const UTF32**)&sstart,(const UTF32*)send,(UTF8**)&dstart,(UTF8*)dend,lenientConversion);
} while(result == targetExhausted); } while(result == targetExhausted);
ReportResult(result); ReportResult(result);
// copy to output buffer. // copy to output buffer.
const size_t outlen = (size_t)(dstart-&output.front()); const size_t outlen = (size_t)(dstart-&output.front());
data.assign(output.begin(),output.begin()+outlen); data.assign(output.begin(),output.begin()+outlen);
return; return;
} }
// UTF 16 BE with BOM // UTF 16 BE with BOM
if(*((uint16_t*)&data.front()) == 0xFFFE) { if(*((uint16_t*)&data.front()) == 0xFFFE) {
// swap the endianess .. // swap the endianess ..
for(uint16_t* p = (uint16_t*)&data.front(), *end = (uint16_t*)&data.back(); p <= end; ++p) { for(uint16_t* p = (uint16_t*)&data.front(), *end = (uint16_t*)&data.back(); p <= end; ++p) {
ByteSwap::Swap2(p); ByteSwap::Swap2(p);
} }
} }
// UTF 16 LE with BOM // UTF 16 LE with BOM
if(*((uint16_t*)&data.front()) == 0xFEFF) { if(*((uint16_t*)&data.front()) == 0xFEFF) {
DefaultLogger::get()->debug("Found UTF-16 BOM ..."); DefaultLogger::get()->debug("Found UTF-16 BOM ...");
const uint16_t* sstart = (uint16_t*)&data.front()+1, *send = (uint16_t*)(&data.back()+1); const uint16_t* sstart = (uint16_t*)&data.front()+1, *send = (uint16_t*)(&data.back()+1);
char* dstart,*dend; char* dstart,*dend;
std::vector<char> output; std::vector<char> output;
do { do {
output.resize(output.size()?output.size()*3/2:data.size()*3/4); output.resize(output.size()?output.size()*3/2:data.size()*3/4);
dstart = &output.front(),dend = &output.back()+1; dstart = &output.front(),dend = &output.back()+1;
result = ConvertUTF16toUTF8((const UTF16**)&sstart,(const UTF16*)send,(UTF8**)&dstart,(UTF8*)dend,lenientConversion); result = ConvertUTF16toUTF8((const UTF16**)&sstart,(const UTF16*)send,(UTF8**)&dstart,(UTF8*)dend,lenientConversion);
} while(result == targetExhausted); } while(result == targetExhausted);
ReportResult(result); ReportResult(result);
// copy to output buffer. // copy to output buffer.
const size_t outlen = (size_t)(dstart-&output.front()); const size_t outlen = (size_t)(dstart-&output.front());
data.assign(output.begin(),output.begin()+outlen); data.assign(output.begin(),output.begin()+outlen);
return; return;
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Convert to UTF8 data to ISO-8859-1 // Convert to UTF8 data to ISO-8859-1
void BaseImporter::ConvertUTF8toISO8859_1(std::string& data) void BaseImporter::ConvertUTF8toISO8859_1(std::string& data)
{ {
size_t size = data.size(); size_t size = data.size();
size_t i = 0, j = 0; size_t i = 0, j = 0;
while(i < size) { while(i < size) {
if ((unsigned char) data[i] < (size_t) 0x80) { if ((unsigned char) data[i] < (size_t) 0x80) {
data[j] = data[i]; data[j] = data[i];
} else if(i < size - 1) { } else if(i < size - 1) {
if((unsigned char) data[i] == 0xC2) { if((unsigned char) data[i] == 0xC2) {
data[j] = data[++i]; data[j] = data[++i];
} else if((unsigned char) data[i] == 0xC3) { } else if((unsigned char) data[i] == 0xC3) {
data[j] = ((unsigned char) data[++i] + 0x40); data[j] = ((unsigned char) data[++i] + 0x40);
} else { } else {
std::stringstream stream; std::stringstream stream;
stream << "UTF8 code " << std::hex << data[i] << data[i + 1] << " can not be converted into ISA-8859-1."; stream << "UTF8 code " << std::hex << data[i] << data[i + 1] << " can not be converted into ISA-8859-1.";
DefaultLogger::get()->error(stream.str()); DefaultLogger::get()->error(stream.str());
data[j++] = data[i++]; data[j++] = data[i++];
data[j] = data[i]; data[j] = data[i];
} }
} else { } else {
DefaultLogger::get()->error("UTF8 code but only one character remaining"); DefaultLogger::get()->error("UTF8 code but only one character remaining");
data[j] = data[i]; data[j] = data[i];
} }
i++; j++; i++; j++;
} }
data.resize(j); data.resize(j);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BaseImporter::TextFileToBuffer(IOStream* stream, void BaseImporter::TextFileToBuffer(IOStream* stream,
std::vector<char>& data) std::vector<char>& data)
{ {
ai_assert(NULL != stream); ai_assert(NULL != stream);
const size_t fileSize = stream->FileSize(); const size_t fileSize = stream->FileSize();
if(!fileSize) { if(!fileSize) {
throw DeadlyImportError("File is empty"); throw DeadlyImportError("File is empty");
} }
data.reserve(fileSize+1); data.reserve(fileSize+1);
data.resize(fileSize); data.resize(fileSize);
if(fileSize != stream->Read( &data[0], 1, fileSize)) { if(fileSize != stream->Read( &data[0], 1, fileSize)) {
throw DeadlyImportError("File read error"); throw DeadlyImportError("File read error");
} }
ConvertToUTF8(data); ConvertToUTF8(data);
// append a binary zero to simplify string parsing // append a binary zero to simplify string parsing
data.push_back(0); data.push_back(0);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
namespace Assimp namespace Assimp
{ {
// Represents an import request // Represents an import request
struct LoadRequest struct LoadRequest
{ {
LoadRequest(const std::string& _file, unsigned int _flags,const BatchLoader::PropertyMap* _map, unsigned int _id) LoadRequest(const std::string& _file, unsigned int _flags,const BatchLoader::PropertyMap* _map, unsigned int _id)
: file(_file), flags(_flags), refCnt(1),scene(NULL), loaded(false), id(_id) : file(_file), flags(_flags), refCnt(1),scene(NULL), loaded(false), id(_id)
{ {
if (_map) if (_map)
map = *_map; map = *_map;
} }
const std::string file; const std::string file;
unsigned int flags; unsigned int flags;
unsigned int refCnt; unsigned int refCnt;
aiScene* scene; aiScene* scene;
bool loaded; bool loaded;
BatchLoader::PropertyMap map; BatchLoader::PropertyMap map;
unsigned int id; unsigned int id;
bool operator== (const std::string& f) { bool operator== (const std::string& f) {
return file == f; return file == f;
} }
}; };
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// BatchLoader::pimpl data structure // BatchLoader::pimpl data structure
struct Assimp::BatchData struct Assimp::BatchData
{ {
BatchData() BatchData()
: pIOSystem() : pIOSystem()
, pImporter() , pImporter()
, next_id(0xffff) , next_id(0xffff)
{} {}
// IO system to be used for all imports // IO system to be used for all imports
IOSystem* pIOSystem; IOSystem* pIOSystem;
// Importer used to load all meshes // Importer used to load all meshes
Importer* pImporter; Importer* pImporter;
// List of all imports // List of all imports
std::list<LoadRequest> requests; std::list<LoadRequest> requests;
// Base path // Base path
std::string pathBase; std::string pathBase;
// Id for next item // Id for next item
unsigned int next_id; unsigned int next_id;
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
BatchLoader::BatchLoader(IOSystem* pIO) BatchLoader::BatchLoader(IOSystem* pIO)
{ {
ai_assert(NULL != pIO); ai_assert(NULL != pIO);
data = new BatchData(); data = new BatchData();
data->pIOSystem = pIO; data->pIOSystem = pIO;
data->pImporter = new Importer(); data->pImporter = new Importer();
data->pImporter->SetIOHandler(data->pIOSystem); data->pImporter->SetIOHandler(data->pIOSystem);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
BatchLoader::~BatchLoader() BatchLoader::~BatchLoader()
{ {
// delete all scenes wthat have not been polled by the user // delete all scenes wthat have not been polled by the user
for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) { for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) {
delete (*it).scene; delete (*it).scene;
} }
data->pImporter->SetIOHandler(NULL); /* get pointer back into our posession */ data->pImporter->SetIOHandler(NULL); /* get pointer back into our posession */
delete data->pImporter; delete data->pImporter;
delete data; delete data;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
unsigned int BatchLoader::AddLoadRequest (const std::string& file, unsigned int BatchLoader::AddLoadRequest (const std::string& file,
unsigned int steps /*= 0*/, const PropertyMap* map /*= NULL*/) unsigned int steps /*= 0*/, const PropertyMap* map /*= NULL*/)
{ {
ai_assert(!file.empty()); ai_assert(!file.empty());
// check whether we have this loading request already // check whether we have this loading request already
std::list<LoadRequest>::iterator it; std::list<LoadRequest>::iterator it;
for (it = data->requests.begin();it != data->requests.end(); ++it) { for (it = data->requests.begin();it != data->requests.end(); ++it) {
// Call IOSystem's path comparison function here // Call IOSystem's path comparison function here
if (data->pIOSystem->ComparePaths((*it).file,file)) { if (data->pIOSystem->ComparePaths((*it).file,file)) {
if (map) { if (map) {
if (!((*it).map == *map)) if (!((*it).map == *map))
continue; continue;
} }
else if (!(*it).map.empty()) else if (!(*it).map.empty())
continue; continue;
(*it).refCnt++; (*it).refCnt++;
return (*it).id; return (*it).id;
} }
} }
// no, we don't have it. So add it to the queue ... // no, we don't have it. So add it to the queue ...
data->requests.push_back(LoadRequest(file,steps,map,data->next_id)); data->requests.push_back(LoadRequest(file,steps,map,data->next_id));
return data->next_id++; return data->next_id++;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiScene* BatchLoader::GetImport (unsigned int which) aiScene* BatchLoader::GetImport (unsigned int which)
{ {
for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) { for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) {
if ((*it).id == which && (*it).loaded) { if ((*it).id == which && (*it).loaded) {
aiScene* sc = (*it).scene; aiScene* sc = (*it).scene;
if (!(--(*it).refCnt)) { if (!(--(*it).refCnt)) {
data->requests.erase(it); data->requests.erase(it);
} }
return sc; return sc;
} }
} }
return NULL; return NULL;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BatchLoader::LoadAll() void BatchLoader::LoadAll()
{ {
// no threaded implementation for the moment // no threaded implementation for the moment
for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) { for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) {
// force validation in debug builds // force validation in debug builds
unsigned int pp = (*it).flags; unsigned int pp = (*it).flags;
#ifdef ASSIMP_BUILD_DEBUG #ifdef ASSIMP_BUILD_DEBUG
pp |= aiProcess_ValidateDataStructure; pp |= aiProcess_ValidateDataStructure;
#endif #endif
// setup config properties if necessary // setup config properties if necessary
ImporterPimpl* pimpl = data->pImporter->Pimpl(); ImporterPimpl* pimpl = data->pImporter->Pimpl();
pimpl->mFloatProperties = (*it).map.floats; pimpl->mFloatProperties = (*it).map.floats;
pimpl->mIntProperties = (*it).map.ints; pimpl->mIntProperties = (*it).map.ints;
pimpl->mStringProperties = (*it).map.strings; pimpl->mStringProperties = (*it).map.strings;
pimpl->mMatrixProperties = (*it).map.matrices; pimpl->mMatrixProperties = (*it).map.matrices;
if (!DefaultLogger::isNullLogger()) if (!DefaultLogger::isNullLogger())
{ {
DefaultLogger::get()->info("%%% BEGIN EXTERNAL FILE %%%"); DefaultLogger::get()->info("%%% BEGIN EXTERNAL FILE %%%");
DefaultLogger::get()->info("File: " + (*it).file); DefaultLogger::get()->info("File: " + (*it).file);
} }
data->pImporter->ReadFile((*it).file,pp); data->pImporter->ReadFile((*it).file,pp);
(*it).scene = data->pImporter->GetOrphanedScene(); (*it).scene = data->pImporter->GetOrphanedScene();
(*it).loaded = true; (*it).loaded = true;
DefaultLogger::get()->info("%%% END EXTERNAL FILE %%%"); DefaultLogger::get()->info("%%% END EXTERNAL FILE %%%");
} }
} }

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiScene; struct aiScene;
namespace Assimp { namespace Assimp {
class Importer; class Importer;
class IOSystem; class IOSystem;
@ -64,32 +64,32 @@ class IOStream;
// utility to do char4 to uint32 in a portable manner // utility to do char4 to uint32 in a portable manner
#define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \ #define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \
(string[1] << 16) + (string[2] << 8) + string[3])) (string[1] << 16) + (string[2] << 8) + string[3]))
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <typename T> template <typename T>
struct ScopeGuard struct ScopeGuard
{ {
ScopeGuard(T* obj) : obj(obj), mdismiss() {} ScopeGuard(T* obj) : obj(obj), mdismiss() {}
~ScopeGuard () throw() { ~ScopeGuard () throw() {
if (!mdismiss) { if (!mdismiss) {
delete obj; delete obj;
} }
obj = NULL; obj = NULL;
} }
T* dismiss() { T* dismiss() {
mdismiss=true; mdismiss=true;
return obj; return obj;
} }
operator T*() { operator T*() {
return obj; return obj;
} }
T* operator -> () { T* operator -> () {
return obj; return obj;
} }
private: private:
// no copying allowed. // no copying allowed.
@ -97,8 +97,8 @@ private:
ScopeGuard( const ScopeGuard & ); ScopeGuard( const ScopeGuard & );
ScopeGuard &operator = ( const ScopeGuard & ); ScopeGuard &operator = ( const ScopeGuard & );
T* obj; T* obj;
bool mdismiss; bool mdismiss;
}; };
@ -115,257 +115,257 @@ private:
*/ */
class ASSIMP_API BaseImporter class ASSIMP_API BaseImporter
{ {
friend class Importer; friend class Importer;
public: public:
/** Constructor to be privately used by #Importer */ /** Constructor to be privately used by #Importer */
BaseImporter(); BaseImporter();
/** Destructor, private as well */ /** Destructor, private as well */
virtual ~BaseImporter(); virtual ~BaseImporter();
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.
* *
* The implementation should be as quick as possible. A check for * The implementation should be as quick as possible. A check for
* the file extension is enough. If no suitable loader is found with * the file extension is enough. If no suitable loader is found with
* this strategy, CanRead() is called again, the 'checkSig' parameter * this strategy, CanRead() is called again, the 'checkSig' parameter
* set to true this time. Now the implementation is expected to * set to true this time. Now the implementation is expected to
* perform a full check of the file structure, possibly searching the * perform a full check of the file structure, possibly searching the
* first bytes of the file for magic identifiers or keywords. * first bytes of the file for magic identifiers or keywords.
* *
* @param pFile Path and file name of the file to be examined. * @param pFile Path and file name of the file to be examined.
* @param pIOHandler The IO handler to use for accessing any file. * @param pIOHandler The IO handler to use for accessing any file.
* @param checkSig Set to true if this method is called a second time. * @param checkSig Set to true if this method is called a second time.
* This time, the implementation may take more time to examine the * This time, the implementation may take more time to examine the
* contents of the file to be loaded for magic bytes, keywords, etc * contents of the file to be loaded for magic bytes, keywords, etc
* to be able to load files with unknown/not existent file extensions. * to be able to load files with unknown/not existent file extensions.
* @return true if the class can read this file, false if not. * @return true if the class can read this file, false if not.
*/ */
virtual bool CanRead( virtual bool CanRead(
const std::string& pFile, const std::string& pFile,
IOSystem* pIOHandler, IOSystem* pIOHandler,
bool checkSig bool checkSig
) const = 0; ) const = 0;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Imports the given file and returns the imported data. /** Imports the given file and returns the imported data.
* If the import succeeds, ownership of the data is transferred to * If the import succeeds, ownership of the data is transferred to
* the caller. If the import fails, NULL is returned. The function * the caller. If the import fails, NULL is returned. The function
* takes care that any partially constructed data is destroyed * takes care that any partially constructed data is destroyed
* beforehand. * beforehand.
* *
* @param pImp #Importer object hosting this loader. * @param pImp #Importer object hosting this loader.
* @param pFile Path of the file to be imported. * @param pFile Path of the file to be imported.
* @param pIOHandler IO-Handler used to open this and possible other files. * @param pIOHandler IO-Handler used to open this and possible other files.
* @return The imported data or NULL if failed. If it failed a * @return The imported data or NULL if failed. If it failed a
* human-readable error description can be retrieved by calling * human-readable error description can be retrieved by calling
* GetErrorText() * GetErrorText()
* *
* @note This function is not intended to be overridden. Implement * @note This function is not intended to be overridden. Implement
* InternReadFile() to do the import. If an exception is thrown somewhere * InternReadFile() to do the import. If an exception is thrown somewhere
* in InternReadFile(), this function will catch it and transform it into * in InternReadFile(), this function will catch it and transform it into
* a suitable response to the caller. * a suitable response to the caller.
*/ */
aiScene* ReadFile( aiScene* ReadFile(
const Importer* pImp, const Importer* pImp,
const std::string& pFile, const std::string& pFile,
IOSystem* pIOHandler IOSystem* pIOHandler
); );
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns the error description of the last error that occured. /** Returns the error description of the last error that occured.
* @return A description of the last error that occured. An empty * @return A description of the last error that occured. An empty
* string if there was no error. * string if there was no error.
*/ */
const std::string& GetErrorText() const { const std::string& GetErrorText() const {
return mErrorText; return mErrorText;
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Called prior to ReadFile(). /** Called prior to ReadFile().
* The function is a request to the importer to update its configuration * The function is a request to the importer to update its configuration
* basing on the Importer's configuration property list. * basing on the Importer's configuration property list.
* @param pImp Importer instance * @param pImp Importer instance
*/ */
virtual void SetupProperties( virtual void SetupProperties(
const Importer* pImp const Importer* pImp
); );
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Called by #Importer::GetImporterInfo to get a description of /** Called by #Importer::GetImporterInfo to get a description of
* some loader features. Importers must provide this information. */ * some loader features. Importers must provide this information. */
virtual const aiImporterDesc* GetInfo() const = 0; virtual const aiImporterDesc* GetInfo() const = 0;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Called by #Importer::GetExtensionList for each loaded importer. /** Called by #Importer::GetExtensionList for each loaded importer.
* Take the extension list contained in the structure returned by * Take the extension list contained in the structure returned by
* #GetInfo and insert all file extensions into the given set. * #GetInfo and insert all file extensions into the given set.
* @param extension set to collect file extensions in*/ * @param extension set to collect file extensions in*/
void GetExtensionList(std::set<std::string>& extensions); void GetExtensionList(std::set<std::string>& extensions);
protected: protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Imports the given file into the given scene structure. The /** Imports the given file into the given scene structure. The
* function is expected to throw an ImportErrorException if there is * function is expected to throw an ImportErrorException if there is
* an error. If it terminates normally, the data in aiScene is * an error. If it terminates normally, the data in aiScene is
* expected to be correct. Override this function to implement the * expected to be correct. Override this function to implement the
* actual importing. * actual importing.
* <br> * <br>
* The output scene must meet the following requirements:<br> * The output scene must meet the following requirements:<br>
* <ul> * <ul>
* <li>At least a root node must be there, even if its only purpose * <li>At least a root node must be there, even if its only purpose
* is to reference one mesh.</li> * is to reference one mesh.</li>
* <li>aiMesh::mPrimitiveTypes may be 0. The types of primitives * <li>aiMesh::mPrimitiveTypes may be 0. The types of primitives
* in the mesh are determined automatically in this case.</li> * in the mesh are determined automatically in this case.</li>
* <li>the vertex data is stored in a pseudo-indexed "verbose" format. * <li>the vertex data is stored in a pseudo-indexed "verbose" format.
* In fact this means that every vertex that is referenced by * In fact this means that every vertex that is referenced by
* a face is unique. Or the other way round: a vertex index may * a face is unique. Or the other way round: a vertex index may
* not occur twice in a single aiMesh.</li> * not occur twice in a single aiMesh.</li>
* <li>aiAnimation::mDuration may be -1. Assimp determines the length * <li>aiAnimation::mDuration may be -1. Assimp determines the length
* of the animation automatically in this case as the length of * of the animation automatically in this case as the length of
* the longest animation channel.</li> * the longest animation channel.</li>
* <li>aiMesh::mBitangents may be NULL if tangents and normals are * <li>aiMesh::mBitangents may be NULL if tangents and normals are
* given. In this case bitangents are computed as the cross product * given. In this case bitangents are computed as the cross product
* between normal and tangent.</li> * between normal and tangent.</li>
* <li>There needn't be a material. If none is there a default material * <li>There needn't be a material. If none is there a default material
* is generated. However, it is recommended practice for loaders * is generated. However, it is recommended practice for loaders
* to generate a default material for yourself that matches the * to generate a default material for yourself that matches the
* default material setting for the file format better than Assimp's * default material setting for the file format better than Assimp's
* generic default material. Note that default materials *should* * generic default material. Note that default materials *should*
* be named AI_DEFAULT_MATERIAL_NAME if they're just color-shaded * be named AI_DEFAULT_MATERIAL_NAME if they're just color-shaded
* or AI_DEFAULT_TEXTURED_MATERIAL_NAME if they define a (dummy) * or AI_DEFAULT_TEXTURED_MATERIAL_NAME if they define a (dummy)
* texture. </li> * texture. </li>
* </ul> * </ul>
* If the AI_SCENE_FLAGS_INCOMPLETE-Flag is <b>not</b> set:<ul> * If the AI_SCENE_FLAGS_INCOMPLETE-Flag is <b>not</b> set:<ul>
* <li> at least one mesh must be there</li> * <li> at least one mesh must be there</li>
* <li> there may be no meshes with 0 vertices or faces</li> * <li> there may be no meshes with 0 vertices or faces</li>
* </ul> * </ul>
* This won't be checked (except by the validation step): Assimp will * This won't be checked (except by the validation step): Assimp will
* crash if one of the conditions is not met! * crash if one of the conditions is not met!
* *
* @param pFile Path of the file to be imported. * @param pFile Path of the file to be imported.
* @param pScene The scene object to hold the imported data. * @param pScene The scene object to hold the imported data.
* NULL is not a valid parameter. * NULL is not a valid parameter.
* @param pIOHandler The IO handler to use for any file access. * @param pIOHandler The IO handler to use for any file access.
* NULL is not a valid parameter. */ * NULL is not a valid parameter. */
virtual void InternReadFile( virtual void InternReadFile(
const std::string& pFile, const std::string& pFile,
aiScene* pScene, aiScene* pScene,
IOSystem* pIOHandler IOSystem* pIOHandler
) = 0; ) = 0;
public: // static utilities public: // static utilities
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** A utility for CanRead(). /** A utility for CanRead().
* *
* The function searches the header of a file for a specific token * The function searches the header of a file for a specific token
* and returns true if this token is found. This works for text * and returns true if this token is found. This works for text
* files only. There is a rudimentary handling of UNICODE files. * files only. There is a rudimentary handling of UNICODE files.
* The comparison is case independent. * The comparison is case independent.
* *
* @param pIOSystem IO System to work with * @param pIOSystem IO System to work with
* @param file File name of the file * @param file File name of the file
* @param tokens List of tokens to search for * @param tokens List of tokens to search for
* @param numTokens Size of the token array * @param numTokens Size of the token array
* @param searchBytes Number of bytes to be searched for the tokens. * @param searchBytes Number of bytes to be searched for the tokens.
*/ */
static bool SearchFileHeaderForToken( static bool SearchFileHeaderForToken(
IOSystem* pIOSystem, IOSystem* pIOSystem,
const std::string& file, const std::string& file,
const char** tokens, const char** tokens,
unsigned int numTokens, unsigned int numTokens,
unsigned int searchBytes = 200, unsigned int searchBytes = 200,
bool tokensSol = false); bool tokensSol = false);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** @brief Check whether a file has a specific file extension /** @brief Check whether a file has a specific file extension
* @param pFile Input file * @param pFile Input file
* @param ext0 Extension to check for. Lowercase characters only, no dot! * @param ext0 Extension to check for. Lowercase characters only, no dot!
* @param ext1 Optional second extension * @param ext1 Optional second extension
* @param ext2 Optional third extension * @param ext2 Optional third extension
* @note Case-insensitive * @note Case-insensitive
*/ */
static bool SimpleExtensionCheck ( static bool SimpleExtensionCheck (
const std::string& pFile, const std::string& pFile,
const char* ext0, const char* ext0,
const char* ext1 = NULL, const char* ext1 = NULL,
const char* ext2 = NULL); const char* ext2 = NULL);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** @brief Extract file extension from a string /** @brief Extract file extension from a string
* @param pFile Input file * @param pFile Input file
* @return Extension without trailing dot, all lowercase * @return Extension without trailing dot, all lowercase
*/ */
static std::string GetExtension ( static std::string GetExtension (
const std::string& pFile); const std::string& pFile);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** @brief Check whether a file starts with one or more magic tokens /** @brief Check whether a file starts with one or more magic tokens
* @param pFile Input file * @param pFile Input file
* @param pIOHandler IO system to be used * @param pIOHandler IO system to be used
* @param magic n magic tokens * @param magic n magic tokens
* @params num Size of magic * @params num Size of magic
* @param offset Offset from file start where tokens are located * @param offset Offset from file start where tokens are located
* @param Size of one token, in bytes. Maximally 16 bytes. * @param Size of one token, in bytes. Maximally 16 bytes.
* @return true if one of the given tokens was found * @return true if one of the given tokens was found
* *
* @note For convinence, the check is also performed for the * @note For convinence, the check is also performed for the
* byte-swapped variant of all tokens (big endian). Only for * byte-swapped variant of all tokens (big endian). Only for
* tokens of size 2,4. * tokens of size 2,4.
*/ */
static bool CheckMagicToken( static bool CheckMagicToken(
IOSystem* pIOHandler, IOSystem* pIOHandler,
const std::string& pFile, const std::string& pFile,
const void* magic, const void* magic,
unsigned int num, unsigned int num,
unsigned int offset = 0, unsigned int offset = 0,
unsigned int size = 4); unsigned int size = 4);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** An utility for all text file loaders. It converts a file to our /** An utility for all text file loaders. It converts a file to our
* UTF8 character set. Errors are reported, but ignored. * UTF8 character set. Errors are reported, but ignored.
* *
* @param data File buffer to be converted to UTF8 data. The buffer * @param data File buffer to be converted to UTF8 data. The buffer
* is resized as appropriate. */ * is resized as appropriate. */
static void ConvertToUTF8( static void ConvertToUTF8(
std::vector<char>& data); std::vector<char>& data);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** An utility for all text file loaders. It converts a file from our /** An utility for all text file loaders. It converts a file from our
* UTF8 character set back to ISO-8859-1. Errors are reported, but ignored. * UTF8 character set back to ISO-8859-1. Errors are reported, but ignored.
* *
* @param data File buffer to be converted from UTF8 to ISO-8859-1. The buffer * @param data File buffer to be converted from UTF8 to ISO-8859-1. The buffer
* is resized as appropriate. */ * is resized as appropriate. */
static void ConvertUTF8toISO8859_1( static void ConvertUTF8toISO8859_1(
std::string& data); std::string& data);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Utility for text file loaders which copies the contents of the /** Utility for text file loaders which copies the contents of the
* file into a memory buffer and converts it to our UTF8 * file into a memory buffer and converts it to our UTF8
* representation. * representation.
* @param stream Stream to read from. * @param stream Stream to read from.
* @param data Output buffer to be resized and filled with the * @param data Output buffer to be resized and filled with the
* converted text file data. The buffer is terminated with * converted text file data. The buffer is terminated with
* a binary 0. */ * a binary 0. */
static void TextFileToBuffer( static void TextFileToBuffer(
IOStream* stream, IOStream* stream,
std::vector<char>& data); std::vector<char>& data);
protected: protected:
/** Error description in case there was one. */ /** Error description in case there was one. */
std::string mErrorText; std::string mErrorText;
/** Currently set progress handler */ /** Currently set progress handler */
ProgressHandler* progress; ProgressHandler* progress;
}; };

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
@ -61,45 +61,45 @@ BaseProcess::BaseProcess()
// Destructor, private as well // Destructor, private as well
BaseProcess::~BaseProcess() BaseProcess::~BaseProcess()
{ {
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BaseProcess::ExecuteOnScene( Importer* pImp) void BaseProcess::ExecuteOnScene( Importer* pImp)
{ {
ai_assert(NULL != pImp && NULL != pImp->Pimpl()->mScene); ai_assert(NULL != pImp && NULL != pImp->Pimpl()->mScene);
progress = pImp->GetProgressHandler(); progress = pImp->GetProgressHandler();
ai_assert(progress); ai_assert(progress);
SetupProperties( pImp ); SetupProperties( pImp );
// catch exceptions thrown inside the PostProcess-Step // catch exceptions thrown inside the PostProcess-Step
try try
{ {
Execute(pImp->Pimpl()->mScene); Execute(pImp->Pimpl()->mScene);
} catch( const std::exception& err ) { } catch( const std::exception& err ) {
// extract error description // extract error description
pImp->Pimpl()->mErrorString = err.what(); pImp->Pimpl()->mErrorString = err.what();
DefaultLogger::get()->error(pImp->Pimpl()->mErrorString); DefaultLogger::get()->error(pImp->Pimpl()->mErrorString);
// and kill the partially imported data // and kill the partially imported data
delete pImp->Pimpl()->mScene; delete pImp->Pimpl()->mScene;
pImp->Pimpl()->mScene = NULL; pImp->Pimpl()->mScene = NULL;
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BaseProcess::SetupProperties(const Importer* /*pImp*/) void BaseProcess::SetupProperties(const Importer* /*pImp*/)
{ {
// the default implementation does nothing // the default implementation does nothing
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool BaseProcess::RequireVerboseFormat() const bool BaseProcess::RequireVerboseFormat() const
{ {
return true; return true;
} }

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -49,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiScene; struct aiScene;
namespace Assimp { namespace Assimp {
class Importer; class Importer;
@ -64,121 +64,121 @@ class SharedPostProcessInfo
{ {
public: public:
struct Base struct Base
{ {
virtual ~Base() virtual ~Base()
{} {}
}; };
//! Represents data that is allocated on the heap, thus needs to be deleted //! Represents data that is allocated on the heap, thus needs to be deleted
template <typename T> template <typename T>
struct THeapData : public Base struct THeapData : public Base
{ {
THeapData(T* in) THeapData(T* in)
: data (in) : data (in)
{} {}
~THeapData() ~THeapData()
{ {
delete data; delete data;
} }
T* data; T* data;
}; };
//! Represents static, by-value data not allocated on the heap //! Represents static, by-value data not allocated on the heap
template <typename T> template <typename T>
struct TStaticData : public Base struct TStaticData : public Base
{ {
TStaticData(T in) TStaticData(T in)
: data (in) : data (in)
{} {}
~TStaticData() ~TStaticData()
{} {}
T data; T data;
}; };
// some typedefs for cleaner code // some typedefs for cleaner code
typedef unsigned int KeyType; typedef unsigned int KeyType;
typedef std::map<KeyType, Base*> PropertyMap; typedef std::map<KeyType, Base*> PropertyMap;
public: public:
//! Destructor //! Destructor
~SharedPostProcessInfo() ~SharedPostProcessInfo()
{ {
Clean(); Clean();
} }
//! Remove all stored properties from the table //! Remove all stored properties from the table
void Clean() void Clean()
{ {
// invoke the virtual destructor for all stored properties // invoke the virtual destructor for all stored properties
for (PropertyMap::iterator it = pmap.begin(), end = pmap.end(); for (PropertyMap::iterator it = pmap.begin(), end = pmap.end();
it != end; ++it) it != end; ++it)
{ {
delete (*it).second; delete (*it).second;
} }
pmap.clear(); pmap.clear();
} }
//! Add a heap property to the list //! Add a heap property to the list
template <typename T> template <typename T>
void AddProperty( const char* name, T* in ){ void AddProperty( const char* name, T* in ){
AddProperty(name,(Base*)new THeapData<T>(in)); AddProperty(name,(Base*)new THeapData<T>(in));
} }
//! Add a static by-value property to the list //! Add a static by-value property to the list
template <typename T> template <typename T>
void AddProperty( const char* name, T in ){ void AddProperty( const char* name, T in ){
AddProperty(name,(Base*)new TStaticData<T>(in)); AddProperty(name,(Base*)new TStaticData<T>(in));
} }
//! Get a heap property //! Get a heap property
template <typename T> template <typename T>
bool GetProperty( const char* name, T*& out ) const bool GetProperty( const char* name, T*& out ) const
{ {
THeapData<T>* t = (THeapData<T>*)GetPropertyInternal(name); THeapData<T>* t = (THeapData<T>*)GetPropertyInternal(name);
if(!t) if(!t)
{ {
out = NULL; out = NULL;
return false; return false;
} }
out = t->data; out = t->data;
return true; return true;
} }
//! Get a static, by-value property //! Get a static, by-value property
template <typename T> template <typename T>
bool GetProperty( const char* name, T& out ) const bool GetProperty( const char* name, T& out ) const
{ {
TStaticData<T>* t = (TStaticData<T>*)GetPropertyInternal(name); TStaticData<T>* t = (TStaticData<T>*)GetPropertyInternal(name);
if(!t)return false; if(!t)return false;
out = t->data; out = t->data;
return true; return true;
} }
//! Remove a property of a specific type //! Remove a property of a specific type
void RemoveProperty( const char* name) { void RemoveProperty( const char* name) {
SetGenericPropertyPtr<Base>(pmap,name,NULL); SetGenericPropertyPtr<Base>(pmap,name,NULL);
} }
private: private:
void AddProperty( const char* name, Base* data) { void AddProperty( const char* name, Base* data) {
SetGenericPropertyPtr<Base>(pmap,name,data); SetGenericPropertyPtr<Base>(pmap,name,data);
} }
Base* GetPropertyInternal( const char* name) const { Base* GetPropertyInternal( const char* name) const {
return GetGenericProperty<Base*>(pmap,name,NULL); return GetGenericProperty<Base*>(pmap,name,NULL);
} }
private: private:
//! Map of all stored properties //! Map of all stored properties
PropertyMap pmap; PropertyMap pmap;
}; };
#if 0 #if 0
@ -190,10 +190,10 @@ private:
*/ */
struct PPDependencyTable struct PPDependencyTable
{ {
unsigned int execute_me_before_these; unsigned int execute_me_before_these;
unsigned int execute_me_after_these; unsigned int execute_me_after_these;
unsigned int only_if_these_are_not_specified; unsigned int only_if_these_are_not_specified;
unsigned int mutually_exclusive_with; unsigned int mutually_exclusive_with;
}; };
#endif #endif
@ -213,79 +213,79 @@ private:
*/ */
class ASSIMP_API_WINONLY BaseProcess class ASSIMP_API_WINONLY BaseProcess
{ {
friend class Importer; friend class Importer;
public: public:
/** Constructor to be privately used by Importer */ /** Constructor to be privately used by Importer */
BaseProcess(); BaseProcess();
/** Destructor, private as well */ /** Destructor, private as well */
virtual ~BaseProcess(); virtual ~BaseProcess();
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the processing step is present in the given flag. /** Returns whether the processing step is present in the given flag.
* @param pFlags The processing flags the importer was called with. A * @param pFlags The processing flags the importer was called with. A
* bitwise combination of #aiPostProcessSteps. * bitwise combination of #aiPostProcessSteps.
* @return true if the process is present in this flag fields, * @return true if the process is present in this flag fields,
* false if not. * false if not.
*/ */
virtual bool IsActive( unsigned int pFlags) const = 0; virtual bool IsActive( unsigned int pFlags) const = 0;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Check whether this step expects its input vertex data to be /** Check whether this step expects its input vertex data to be
* in verbose format. */ * in verbose format. */
virtual bool RequireVerboseFormat() const; virtual bool RequireVerboseFormat() const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Executes the post processing step on the given imported data. /** Executes the post processing step on the given imported data.
* The function deletes the scene if the postprocess step fails ( * The function deletes the scene if the postprocess step fails (
* the object pointer will be set to NULL). * the object pointer will be set to NULL).
* @param pImp Importer instance (pImp->mScene must be valid) * @param pImp Importer instance (pImp->mScene must be valid)
*/ */
void ExecuteOnScene( Importer* pImp); void ExecuteOnScene( Importer* pImp);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Called prior to ExecuteOnScene(). /** Called prior to ExecuteOnScene().
* The function is a request to the process to update its configuration * The function is a request to the process to update its configuration
* basing on the Importer's configuration property list. * basing on the Importer's configuration property list.
*/ */
virtual void SetupProperties(const Importer* pImp); virtual void SetupProperties(const Importer* pImp);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Executes the post processing step on the given imported data. /** Executes the post processing step on the given imported data.
* A process should throw an ImportErrorException* if it fails. * A process should throw an ImportErrorException* if it fails.
* This method must be implemented by deriving classes. * This method must be implemented by deriving classes.
* @param pScene The imported data to work at. * @param pScene The imported data to work at.
*/ */
virtual void Execute( aiScene* pScene) = 0; virtual void Execute( aiScene* pScene) = 0;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Assign a new SharedPostProcessInfo to the step. This object /** Assign a new SharedPostProcessInfo to the step. This object
* allows multiple postprocess steps to share data. * allows multiple postprocess steps to share data.
* @param sh May be NULL * @param sh May be NULL
*/ */
inline void SetSharedData(SharedPostProcessInfo* sh) { inline void SetSharedData(SharedPostProcessInfo* sh) {
shared = sh; shared = sh;
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Get the shared data that is assigned to the step. /** Get the shared data that is assigned to the step.
*/ */
inline SharedPostProcessInfo* GetSharedData() { inline SharedPostProcessInfo* GetSharedData() {
return shared; return shared;
} }
protected: protected:
/** See the doc of #SharedPostProcessInfo for more details */ /** See the doc of #SharedPostProcessInfo for more details */
SharedPostProcessInfo* shared; SharedPostProcessInfo* shared;
/** Currently active progress handler */ /** Currently active progress handler */
ProgressHandler* progress; ProgressHandler* progress;
}; };

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
@ -53,95 +53,95 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
void Bitmap::Save(aiTexture* texture, IOStream* file) { void Bitmap::Save(aiTexture* texture, IOStream* file) {
if(file != NULL) { if(file != NULL) {
Header header; Header header;
DIB dib; DIB dib;
dib.size = DIB::dib_size; dib.size = DIB::dib_size;
dib.width = texture->mWidth; dib.width = texture->mWidth;
dib.height = texture->mHeight; dib.height = texture->mHeight;
dib.planes = 1; dib.planes = 1;
dib.bits_per_pixel = 8 * mBytesPerPixel; dib.bits_per_pixel = 8 * mBytesPerPixel;
dib.compression = 0; dib.compression = 0;
dib.image_size = (((dib.width * mBytesPerPixel) + 3) & 0x0000FFFC) * dib.height; dib.image_size = (((dib.width * mBytesPerPixel) + 3) & 0x0000FFFC) * dib.height;
dib.x_resolution = 0; dib.x_resolution = 0;
dib.y_resolution = 0; dib.y_resolution = 0;
dib.nb_colors = 0; dib.nb_colors = 0;
dib.nb_important_colors = 0; dib.nb_important_colors = 0;
header.type = 0x4D42; // 'BM' header.type = 0x4D42; // 'BM'
header.offset = Header::header_size + DIB::dib_size; header.offset = Header::header_size + DIB::dib_size;
header.size = header.offset + dib.image_size; header.size = header.offset + dib.image_size;
header.reserved1 = 0; header.reserved1 = 0;
header.reserved2 = 0; header.reserved2 = 0;
WriteHeader(header, file); WriteHeader(header, file);
WriteDIB(dib, file); WriteDIB(dib, file);
WriteData(texture, file); WriteData(texture, file);
} }
} }
template<typename T> template<typename T>
inline std::size_t Copy(uint8_t* data, T& field) { inline std::size_t Copy(uint8_t* data, T& field) {
std::memcpy(data, &AI_BE(field), sizeof(field)); return sizeof(field); std::memcpy(data, &AI_BE(field), sizeof(field)); return sizeof(field);
} }
void Bitmap::WriteHeader(Header& header, IOStream* file) { void Bitmap::WriteHeader(Header& header, IOStream* file) {
uint8_t data[Header::header_size]; uint8_t data[Header::header_size];
std::size_t offset = 0; std::size_t offset = 0;
offset += Copy(&data[offset], header.type); offset += Copy(&data[offset], header.type);
offset += Copy(&data[offset], header.size); offset += Copy(&data[offset], header.size);
offset += Copy(&data[offset], header.reserved1); offset += Copy(&data[offset], header.reserved1);
offset += Copy(&data[offset], header.reserved2); offset += Copy(&data[offset], header.reserved2);
offset += Copy(&data[offset], header.offset); offset += Copy(&data[offset], header.offset);
file->Write(data, Header::header_size, 1); file->Write(data, Header::header_size, 1);
} }
void Bitmap::WriteDIB(DIB& dib, IOStream* file) { void Bitmap::WriteDIB(DIB& dib, IOStream* file) {
uint8_t data[DIB::dib_size]; uint8_t data[DIB::dib_size];
std::size_t offset = 0; std::size_t offset = 0;
offset += Copy(&data[offset], dib.size); offset += Copy(&data[offset], dib.size);
offset += Copy(&data[offset], dib.width); offset += Copy(&data[offset], dib.width);
offset += Copy(&data[offset], dib.height); offset += Copy(&data[offset], dib.height);
offset += Copy(&data[offset], dib.planes); offset += Copy(&data[offset], dib.planes);
offset += Copy(&data[offset], dib.bits_per_pixel); offset += Copy(&data[offset], dib.bits_per_pixel);
offset += Copy(&data[offset], dib.compression); offset += Copy(&data[offset], dib.compression);
offset += Copy(&data[offset], dib.image_size); offset += Copy(&data[offset], dib.image_size);
offset += Copy(&data[offset], dib.x_resolution); offset += Copy(&data[offset], dib.x_resolution);
offset += Copy(&data[offset], dib.y_resolution); offset += Copy(&data[offset], dib.y_resolution);
offset += Copy(&data[offset], dib.nb_colors); offset += Copy(&data[offset], dib.nb_colors);
offset += Copy(&data[offset], dib.nb_important_colors); offset += Copy(&data[offset], dib.nb_important_colors);
file->Write(data, DIB::dib_size, 1); file->Write(data, DIB::dib_size, 1);
} }
void Bitmap::WriteData(aiTexture* texture, IOStream* file) { void Bitmap::WriteData(aiTexture* texture, IOStream* file) {
static const std::size_t padding_offset = 4; static const std::size_t padding_offset = 4;
static const uint8_t padding_data[padding_offset] = {0x0, 0x0, 0x0, 0x0}; static const uint8_t padding_data[padding_offset] = {0x0, 0x0, 0x0, 0x0};
unsigned int padding = (padding_offset - ((mBytesPerPixel * texture->mWidth) % padding_offset)) % padding_offset; unsigned int padding = (padding_offset - ((mBytesPerPixel * texture->mWidth) % padding_offset)) % padding_offset;
uint8_t pixel[mBytesPerPixel]; uint8_t pixel[mBytesPerPixel];
for(std::size_t i = 0; i < texture->mHeight; ++i) { for(std::size_t i = 0; i < texture->mHeight; ++i) {
for(std::size_t j = 0; j < texture->mWidth; ++j) { for(std::size_t j = 0; j < texture->mWidth; ++j) {
const aiTexel& texel = texture->pcData[(texture->mHeight - i - 1) * texture->mWidth + j]; // Bitmap files are stored in bottom-up format const aiTexel& texel = texture->pcData[(texture->mHeight - i - 1) * texture->mWidth + j]; // Bitmap files are stored in bottom-up format
pixel[0] = texel.r; pixel[0] = texel.r;
pixel[1] = texel.g; pixel[1] = texel.g;
pixel[2] = texel.b; pixel[2] = texel.b;
pixel[3] = texel.a; pixel[3] = texel.a;
file->Write(pixel, mBytesPerPixel, 1); file->Write(pixel, mBytesPerPixel, 1);
} }
file->Write(padding_data, padding, 1); file->Write(padding_data, padding, 1);
} }
} }
} }

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
@ -57,85 +57,85 @@ namespace Assimp {
class IOStream; class IOStream;
class Bitmap { class Bitmap {
protected: protected:
struct Header { struct Header {
uint16_t type; uint16_t type;
uint32_t size; uint32_t size;
uint16_t reserved1; uint16_t reserved1;
uint16_t reserved2; uint16_t reserved2;
uint32_t offset; uint32_t offset;
// We define the struct size because sizeof(Header) might return a wrong result because of structure padding. // We define the struct size because sizeof(Header) might return a wrong result because of structure padding.
// Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field). // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field).
static const std::size_t header_size = static const std::size_t header_size =
sizeof(uint16_t) + // type sizeof(uint16_t) + // type
sizeof(uint32_t) + // size sizeof(uint32_t) + // size
sizeof(uint16_t) + // reserved1 sizeof(uint16_t) + // reserved1
sizeof(uint16_t) + // reserved2 sizeof(uint16_t) + // reserved2
sizeof(uint32_t); // offset sizeof(uint32_t); // offset
}; };
struct DIB { struct DIB {
uint32_t size; uint32_t size;
int32_t width; int32_t width;
int32_t height; int32_t height;
uint16_t planes; uint16_t planes;
uint16_t bits_per_pixel; uint16_t bits_per_pixel;
uint32_t compression; uint32_t compression;
uint32_t image_size; uint32_t image_size;
int32_t x_resolution; int32_t x_resolution;
int32_t y_resolution; int32_t y_resolution;
uint32_t nb_colors; uint32_t nb_colors;
uint32_t nb_important_colors; uint32_t nb_important_colors;
// We define the struct size because sizeof(DIB) might return a wrong result because of structure padding. // We define the struct size because sizeof(DIB) might return a wrong result because of structure padding.
// Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field). // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field).
static const std::size_t dib_size = static const std::size_t dib_size =
sizeof(uint32_t) + // size sizeof(uint32_t) + // size
sizeof(int32_t) + // width sizeof(int32_t) + // width
sizeof(int32_t) + // height sizeof(int32_t) + // height
sizeof(uint16_t) + // planes sizeof(uint16_t) + // planes
sizeof(uint16_t) + // bits_per_pixel sizeof(uint16_t) + // bits_per_pixel
sizeof(uint32_t) + // compression sizeof(uint32_t) + // compression
sizeof(uint32_t) + // image_size sizeof(uint32_t) + // image_size
sizeof(int32_t) + // x_resolution sizeof(int32_t) + // x_resolution
sizeof(int32_t) + // y_resolution sizeof(int32_t) + // y_resolution
sizeof(uint32_t) + // nb_colors sizeof(uint32_t) + // nb_colors
sizeof(uint32_t); // nb_important_colors sizeof(uint32_t); // nb_important_colors
}; };
static const std::size_t mBytesPerPixel = 4; static const std::size_t mBytesPerPixel = 4;
public: public:
static void Save(aiTexture* texture, IOStream* file); static void Save(aiTexture* texture, IOStream* file);
protected: protected:
static void WriteHeader(Header& header, IOStream* file); static void WriteHeader(Header& header, IOStream* file);
static void WriteDIB(DIB& dib, IOStream* file); static void WriteDIB(DIB& dib, IOStream* file);
static void WriteData(aiTexture* texture, IOStream* file); static void WriteData(aiTexture* texture, IOStream* file);
}; };

View File

@ -52,7 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp namespace Assimp
{ {
template< > const std::string LogFunctions< BlenderBMeshConverter >::log_prefix = "BLEND_BMESH: "; template< > const std::string LogFunctions< BlenderBMeshConverter >::log_prefix = "BLEND_BMESH: ";
} }
using namespace Assimp; using namespace Assimp;
@ -61,142 +61,142 @@ using namespace Assimp::Formatter;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
BlenderBMeshConverter::BlenderBMeshConverter( const Mesh* mesh ): BlenderBMeshConverter::BlenderBMeshConverter( const Mesh* mesh ):
BMesh( mesh ), BMesh( mesh ),
triMesh( NULL ) triMesh( NULL )
{ {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
BlenderBMeshConverter::~BlenderBMeshConverter( ) BlenderBMeshConverter::~BlenderBMeshConverter( )
{ {
DestroyTriMesh( ); DestroyTriMesh( );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool BlenderBMeshConverter::ContainsBMesh( ) const bool BlenderBMeshConverter::ContainsBMesh( ) const
{ {
// TODO - Should probably do some additional verification here // TODO - Should probably do some additional verification here
return BMesh->totpoly && BMesh->totloop && BMesh->totvert; return BMesh->totpoly && BMesh->totloop && BMesh->totvert;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const Mesh* BlenderBMeshConverter::TriangulateBMesh( ) const Mesh* BlenderBMeshConverter::TriangulateBMesh( )
{ {
AssertValidMesh( ); AssertValidMesh( );
AssertValidSizes( ); AssertValidSizes( );
PrepareTriMesh( ); PrepareTriMesh( );
for ( int i = 0; i < BMesh->totpoly; ++i ) for ( int i = 0; i < BMesh->totpoly; ++i )
{ {
const MPoly& poly = BMesh->mpoly[ i ]; const MPoly& poly = BMesh->mpoly[ i ];
ConvertPolyToFaces( poly ); ConvertPolyToFaces( poly );
} }
return triMesh; return triMesh;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::AssertValidMesh( ) void BlenderBMeshConverter::AssertValidMesh( )
{ {
if ( !ContainsBMesh( ) ) if ( !ContainsBMesh( ) )
{ {
ThrowException( "BlenderBMeshConverter requires a BMesh with \"polygons\" - please call BlenderBMeshConverter::ContainsBMesh to check this first" ); ThrowException( "BlenderBMeshConverter requires a BMesh with \"polygons\" - please call BlenderBMeshConverter::ContainsBMesh to check this first" );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::AssertValidSizes( ) void BlenderBMeshConverter::AssertValidSizes( )
{ {
if ( BMesh->totpoly != static_cast<int>( BMesh->mpoly.size( ) ) ) if ( BMesh->totpoly != static_cast<int>( BMesh->mpoly.size( ) ) )
{ {
ThrowException( "BMesh poly array has incorrect size" ); ThrowException( "BMesh poly array has incorrect size" );
} }
if ( BMesh->totloop != static_cast<int>( BMesh->mloop.size( ) ) ) if ( BMesh->totloop != static_cast<int>( BMesh->mloop.size( ) ) )
{ {
ThrowException( "BMesh loop array has incorrect size" ); ThrowException( "BMesh loop array has incorrect size" );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::PrepareTriMesh( ) void BlenderBMeshConverter::PrepareTriMesh( )
{ {
if ( triMesh ) if ( triMesh )
{ {
DestroyTriMesh( ); DestroyTriMesh( );
} }
triMesh = new Mesh( *BMesh ); triMesh = new Mesh( *BMesh );
triMesh->totface = 0; triMesh->totface = 0;
triMesh->mface.clear( ); triMesh->mface.clear( );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::DestroyTriMesh( ) void BlenderBMeshConverter::DestroyTriMesh( )
{ {
delete triMesh; delete triMesh;
triMesh = NULL; triMesh = NULL;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::ConvertPolyToFaces( const MPoly& poly ) void BlenderBMeshConverter::ConvertPolyToFaces( const MPoly& poly )
{ {
const MLoop* polyLoop = &BMesh->mloop[ poly.loopstart ]; const MLoop* polyLoop = &BMesh->mloop[ poly.loopstart ];
if ( poly.totloop == 3 || poly.totloop == 4 ) if ( poly.totloop == 3 || poly.totloop == 4 )
{ {
AddFace( polyLoop[ 0 ].v, polyLoop[ 1 ].v, polyLoop[ 2 ].v, poly.totloop == 4 ? polyLoop[ 3 ].v : 0 ); AddFace( polyLoop[ 0 ].v, polyLoop[ 1 ].v, polyLoop[ 2 ].v, poly.totloop == 4 ? polyLoop[ 3 ].v : 0 );
// UVs are optional, so only convert when present. // UVs are optional, so only convert when present.
if ( BMesh->mloopuv.size() ) if ( BMesh->mloopuv.size() )
{ {
if ( (poly.loopstart + poly.totloop ) > static_cast<int>( BMesh->mloopuv.size() ) ) if ( (poly.loopstart + poly.totloop ) > static_cast<int>( BMesh->mloopuv.size() ) )
{ {
ThrowException( "BMesh uv loop array has incorrect size" ); ThrowException( "BMesh uv loop array has incorrect size" );
} }
const MLoopUV* loopUV = &BMesh->mloopuv[ poly.loopstart ]; const MLoopUV* loopUV = &BMesh->mloopuv[ poly.loopstart ];
AddTFace( loopUV[ 0 ].uv, loopUV[ 1 ].uv, loopUV[ 2 ].uv, poly.totloop == 4 ? loopUV[ 3 ].uv : 0 ); AddTFace( loopUV[ 0 ].uv, loopUV[ 1 ].uv, loopUV[ 2 ].uv, poly.totloop == 4 ? loopUV[ 3 ].uv : 0 );
} }
} }
else if ( poly.totloop > 4 ) else if ( poly.totloop > 4 )
{ {
#if ASSIMP_BLEND_WITH_GLU_TESSELLATE #if ASSIMP_BLEND_WITH_GLU_TESSELLATE
BlenderTessellatorGL tessGL( *this ); BlenderTessellatorGL tessGL( *this );
tessGL.Tessellate( polyLoop, poly.totloop, triMesh->mvert ); tessGL.Tessellate( polyLoop, poly.totloop, triMesh->mvert );
#elif ASSIMP_BLEND_WITH_POLY_2_TRI #elif ASSIMP_BLEND_WITH_POLY_2_TRI
BlenderTessellatorP2T tessP2T( *this ); BlenderTessellatorP2T tessP2T( *this );
tessP2T.Tessellate( polyLoop, poly.totloop, triMesh->mvert ); tessP2T.Tessellate( polyLoop, poly.totloop, triMesh->mvert );
#endif #endif
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::AddFace( int v1, int v2, int v3, int v4 ) void BlenderBMeshConverter::AddFace( int v1, int v2, int v3, int v4 )
{ {
MFace face; MFace face;
face.v1 = v1; face.v1 = v1;
face.v2 = v2; face.v2 = v2;
face.v3 = v3; face.v3 = v3;
face.v4 = v4; face.v4 = v4;
// TODO - Work out how materials work // TODO - Work out how materials work
face.mat_nr = 0; face.mat_nr = 0;
triMesh->mface.push_back( face ); triMesh->mface.push_back( face );
triMesh->totface = triMesh->mface.size( ); triMesh->totface = triMesh->mface.size( );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::AddTFace( const float* uv1, const float *uv2, const float *uv3, const float* uv4 ) void BlenderBMeshConverter::AddTFace( const float* uv1, const float *uv2, const float *uv3, const float* uv4 )
{ {
MTFace mtface; MTFace mtface;
memcpy( &mtface.uv[ 0 ], uv1, sizeof(float) * 2 ); memcpy( &mtface.uv[ 0 ], uv1, sizeof(float) * 2 );
memcpy( &mtface.uv[ 1 ], uv2, sizeof(float) * 2 ); memcpy( &mtface.uv[ 1 ], uv2, sizeof(float) * 2 );
memcpy( &mtface.uv[ 2 ], uv3, sizeof(float) * 2 ); memcpy( &mtface.uv[ 2 ], uv3, sizeof(float) * 2 );
if ( uv4 ) if ( uv4 )
{ {
memcpy( &mtface.uv[ 3 ], uv4, sizeof(float) * 2 ); memcpy( &mtface.uv[ 3 ], uv4, sizeof(float) * 2 );
} }
triMesh->mtface.push_back( mtface ); triMesh->mtface.push_back( mtface );
} }
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER #endif // ASSIMP_BUILD_NO_BLEND_IMPORTER

View File

@ -48,46 +48,46 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp namespace Assimp
{ {
// TinyFormatter.h // TinyFormatter.h
namespace Formatter namespace Formatter
{ {
template < typename T,typename TR, typename A > class basic_formatter; template < typename T,typename TR, typename A > class basic_formatter;
typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format; typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format;
} }
// BlenderScene.h // BlenderScene.h
namespace Blender namespace Blender
{ {
struct Mesh; struct Mesh;
struct MPoly; struct MPoly;
struct MLoop; struct MLoop;
} }
class BlenderBMeshConverter: public LogFunctions< BlenderBMeshConverter > class BlenderBMeshConverter: public LogFunctions< BlenderBMeshConverter >
{ {
public: public:
BlenderBMeshConverter( const Blender::Mesh* mesh ); BlenderBMeshConverter( const Blender::Mesh* mesh );
~BlenderBMeshConverter( ); ~BlenderBMeshConverter( );
bool ContainsBMesh( ) const; bool ContainsBMesh( ) const;
const Blender::Mesh* TriangulateBMesh( ); const Blender::Mesh* TriangulateBMesh( );
private: private:
void AssertValidMesh( ); void AssertValidMesh( );
void AssertValidSizes( ); void AssertValidSizes( );
void PrepareTriMesh( ); void PrepareTriMesh( );
void DestroyTriMesh( ); void DestroyTriMesh( );
void ConvertPolyToFaces( const Blender::MPoly& poly ); void ConvertPolyToFaces( const Blender::MPoly& poly );
void AddFace( int v1, int v2, int v3, int v4 = 0 ); void AddFace( int v1, int v2, int v3, int v4 = 0 );
void AddTFace( const float* uv1, const float* uv2, const float *uv3, const float* uv4 = 0 ); void AddTFace( const float* uv1, const float* uv2, const float *uv3, const float* uv4 = 0 );
const Blender::Mesh* BMesh; const Blender::Mesh* BMesh;
Blender::Mesh* triMesh; Blender::Mesh* triMesh;
friend class BlenderTessellatorGL; friend class BlenderTessellatorGL;
friend class BlenderTessellatorP2T; friend class BlenderTessellatorP2T;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -56,168 +56,168 @@ using namespace Assimp::Formatter;
#define for_each BOOST_FOREACH #define for_each BOOST_FOREACH
bool match4(StreamReaderAny& stream, const char* string) { bool match4(StreamReaderAny& stream, const char* string) {
char tmp[] = { char tmp[] = {
(stream).GetI1(), (stream).GetI1(),
(stream).GetI1(), (stream).GetI1(),
(stream).GetI1(), (stream).GetI1(),
(stream).GetI1() (stream).GetI1()
}; };
return (tmp[0]==string[0] && tmp[1]==string[1] && tmp[2]==string[2] && tmp[3]==string[3]); return (tmp[0]==string[0] && tmp[1]==string[1] && tmp[2]==string[2] && tmp[3]==string[3]);
} }
struct Type { struct Type {
size_t size; size_t size;
std::string name; std::string name;
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void DNAParser :: Parse () void DNAParser :: Parse ()
{ {
StreamReaderAny& stream = *db.reader.get(); StreamReaderAny& stream = *db.reader.get();
DNA& dna = db.dna; DNA& dna = db.dna;
if(!match4(stream,"SDNA")) { if(!match4(stream,"SDNA")) {
throw DeadlyImportError("BlenderDNA: Expected SDNA chunk"); throw DeadlyImportError("BlenderDNA: Expected SDNA chunk");
} }
// name dictionary // name dictionary
if(!match4(stream,"NAME")) { if(!match4(stream,"NAME")) {
throw DeadlyImportError("BlenderDNA: Expected NAME field"); throw DeadlyImportError("BlenderDNA: Expected NAME field");
} }
std::vector<std::string> names (stream.GetI4()); std::vector<std::string> names (stream.GetI4());
for_each(std::string& s, names) { for_each(std::string& s, names) {
while (char c = stream.GetI1()) { while (char c = stream.GetI1()) {
s += c; s += c;
} }
} }
// type dictionary // type dictionary
for (;stream.GetCurrentPos() & 0x3; stream.GetI1()); for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
if(!match4(stream,"TYPE")) { if(!match4(stream,"TYPE")) {
throw DeadlyImportError("BlenderDNA: Expected TYPE field"); throw DeadlyImportError("BlenderDNA: Expected TYPE field");
} }
std::vector<Type> types (stream.GetI4()); std::vector<Type> types (stream.GetI4());
for_each(Type& s, types) { for_each(Type& s, types) {
while (char c = stream.GetI1()) { while (char c = stream.GetI1()) {
s.name += c; s.name += c;
} }
} }
// type length dictionary // type length dictionary
for (;stream.GetCurrentPos() & 0x3; stream.GetI1()); for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
if(!match4(stream,"TLEN")) { if(!match4(stream,"TLEN")) {
throw DeadlyImportError("BlenderDNA: Expected TLEN field"); throw DeadlyImportError("BlenderDNA: Expected TLEN field");
} }
for_each(Type& s, types) { for_each(Type& s, types) {
s.size = stream.GetI2(); s.size = stream.GetI2();
} }
// structures dictionary // structures dictionary
for (;stream.GetCurrentPos() & 0x3; stream.GetI1()); for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
if(!match4(stream,"STRC")) { if(!match4(stream,"STRC")) {
throw DeadlyImportError("BlenderDNA: Expected STRC field"); throw DeadlyImportError("BlenderDNA: Expected STRC field");
} }
size_t end = stream.GetI4(), fields = 0; size_t end = stream.GetI4(), fields = 0;
dna.structures.reserve(end); dna.structures.reserve(end);
for(size_t i = 0; i != end; ++i) { for(size_t i = 0; i != end; ++i) {
uint16_t n = stream.GetI2(); uint16_t n = stream.GetI2();
if (n >= types.size()) { if (n >= types.size()) {
throw DeadlyImportError((format(), throw DeadlyImportError((format(),
"BlenderDNA: Invalid type index in structure name" ,n, "BlenderDNA: Invalid type index in structure name" ,n,
" (there are only ", types.size(), " entries)" " (there are only ", types.size(), " entries)"
)); ));
} }
// maintain separate indexes // maintain separate indexes
dna.indices[types[n].name] = dna.structures.size(); dna.indices[types[n].name] = dna.structures.size();
dna.structures.push_back(Structure()); dna.structures.push_back(Structure());
Structure& s = dna.structures.back(); Structure& s = dna.structures.back();
s.name = types[n].name; s.name = types[n].name;
//s.index = dna.structures.size()-1; //s.index = dna.structures.size()-1;
n = stream.GetI2(); n = stream.GetI2();
s.fields.reserve(n); s.fields.reserve(n);
size_t offset = 0; size_t offset = 0;
for (size_t m = 0; m < n; ++m, ++fields) { for (size_t m = 0; m < n; ++m, ++fields) {
uint16_t j = stream.GetI2(); uint16_t j = stream.GetI2();
if (j >= types.size()) { if (j >= types.size()) {
throw DeadlyImportError((format(), throw DeadlyImportError((format(),
"BlenderDNA: Invalid type index in structure field ", j, "BlenderDNA: Invalid type index in structure field ", j,
" (there are only ", types.size(), " entries)" " (there are only ", types.size(), " entries)"
)); ));
} }
s.fields.push_back(Field()); s.fields.push_back(Field());
Field& f = s.fields.back(); Field& f = s.fields.back();
f.offset = offset; f.offset = offset;
f.type = types[j].name; f.type = types[j].name;
f.size = types[j].size; f.size = types[j].size;
j = stream.GetI2(); j = stream.GetI2();
if (j >= names.size()) { if (j >= names.size()) {
throw DeadlyImportError((format(), throw DeadlyImportError((format(),
"BlenderDNA: Invalid name index in structure field ", j, "BlenderDNA: Invalid name index in structure field ", j,
" (there are only ", names.size(), " entries)" " (there are only ", names.size(), " entries)"
)); ));
} }
f.name = names[j]; f.name = names[j];
f.flags = 0u; f.flags = 0u;
// pointers always specify the size of the pointee instead of their own. // pointers always specify the size of the pointee instead of their own.
// The pointer asterisk remains a property of the lookup name. // The pointer asterisk remains a property of the lookup name.
if (f.name[0] == '*') { if (f.name[0] == '*') {
f.size = db.i64bit ? 8 : 4; f.size = db.i64bit ? 8 : 4;
f.flags |= FieldFlag_Pointer; f.flags |= FieldFlag_Pointer;
} }
// arrays, however, specify the size of a single element so we // arrays, however, specify the size of a single element so we
// need to parse the (possibly multi-dimensional) array declaration // need to parse the (possibly multi-dimensional) array declaration
// in order to obtain the actual size of the array in the file. // in order to obtain the actual size of the array in the file.
// Also we need to alter the lookup name to include no array // Also we need to alter the lookup name to include no array
// brackets anymore or size fixup won't work (if our size does // brackets anymore or size fixup won't work (if our size does
// not match the size read from the DNA). // not match the size read from the DNA).
if (*f.name.rbegin() == ']') { if (*f.name.rbegin() == ']') {
const std::string::size_type rb = f.name.find('['); const std::string::size_type rb = f.name.find('[');
if (rb == std::string::npos) { if (rb == std::string::npos) {
throw DeadlyImportError((format(), throw DeadlyImportError((format(),
"BlenderDNA: Encountered invalid array declaration ", "BlenderDNA: Encountered invalid array declaration ",
f.name f.name
)); ));
} }
f.flags |= FieldFlag_Array; f.flags |= FieldFlag_Array;
DNA::ExtractArraySize(f.name,f.array_sizes); DNA::ExtractArraySize(f.name,f.array_sizes);
f.name = f.name.substr(0,rb); f.name = f.name.substr(0,rb);
f.size *= f.array_sizes[0] * f.array_sizes[1]; f.size *= f.array_sizes[0] * f.array_sizes[1];
} }
// maintain separate indexes // maintain separate indexes
s.indices[f.name] = s.fields.size()-1; s.indices[f.name] = s.fields.size()-1;
offset += f.size; offset += f.size;
} }
s.size = offset; s.size = offset;
} }
DefaultLogger::get()->debug((format(),"BlenderDNA: Got ",dna.structures.size(), DefaultLogger::get()->debug((format(),"BlenderDNA: Got ",dna.structures.size(),
" structures with totally ",fields," fields")); " structures with totally ",fields," fields"));
#ifdef ASSIMP_BUILD_BLENDER_DEBUG #ifdef ASSIMP_BUILD_BLENDER_DEBUG
dna.DumpToFile(); dna.DumpToFile();
#endif #endif
dna.AddPrimitiveStructures(); dna.AddPrimitiveStructures();
dna.RegisterConverters(); dna.RegisterConverters();
} }
@ -227,144 +227,144 @@ void DNAParser :: Parse ()
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void DNA :: DumpToFile() void DNA :: DumpToFile()
{ {
// we dont't bother using the VFS here for this is only for debugging. // we dont't bother using the VFS here for this is only for debugging.
// (and all your bases are belong to us). // (and all your bases are belong to us).
std::ofstream f("dna.txt"); std::ofstream f("dna.txt");
if (f.fail()) { if (f.fail()) {
DefaultLogger::get()->error("Could not dump dna to dna.txt"); DefaultLogger::get()->error("Could not dump dna to dna.txt");
return; return;
} }
f << "Field format: type name offset size" << "\n"; f << "Field format: type name offset size" << "\n";
f << "Structure format: name size" << "\n"; f << "Structure format: name size" << "\n";
for_each(const Structure& s, structures) { for_each(const Structure& s, structures) {
f << s.name << " " << s.size << "\n\n"; f << s.name << " " << s.size << "\n\n";
for_each(const Field& ff, s.fields) { for_each(const Field& ff, s.fields) {
f << "\t" << ff.type << " " << ff.name << " " << ff.offset << " " << ff.size << std::endl; f << "\t" << ff.type << " " << ff.name << " " << ff.offset << " " << ff.size << std::endl;
} }
f << std::endl; f << std::endl;
} }
DefaultLogger::get()->info("BlenderDNA: Dumped dna to dna.txt"); DefaultLogger::get()->info("BlenderDNA: Dumped dna to dna.txt");
} }
#endif #endif
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
/*static*/ void DNA :: ExtractArraySize( /*static*/ void DNA :: ExtractArraySize(
const std::string& out, const std::string& out,
size_t array_sizes[2] size_t array_sizes[2]
) )
{ {
array_sizes[0] = array_sizes[1] = 1; array_sizes[0] = array_sizes[1] = 1;
std::string::size_type pos = out.find('['); std::string::size_type pos = out.find('[');
if (pos++ == std::string::npos) { if (pos++ == std::string::npos) {
return; return;
} }
array_sizes[0] = strtoul10(&out[pos]); array_sizes[0] = strtoul10(&out[pos]);
pos = out.find('[',pos); pos = out.find('[',pos);
if (pos++ == std::string::npos) { if (pos++ == std::string::npos) {
return; return;
} }
array_sizes[1] = strtoul10(&out[pos]); array_sizes[1] = strtoul10(&out[pos]);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
boost::shared_ptr< ElemBase > DNA :: ConvertBlobToStructure( boost::shared_ptr< ElemBase > DNA :: ConvertBlobToStructure(
const Structure& structure, const Structure& structure,
const FileDatabase& db const FileDatabase& db
) const ) const
{ {
std::map<std::string, FactoryPair >::const_iterator it = converters.find(structure.name); std::map<std::string, FactoryPair >::const_iterator it = converters.find(structure.name);
if (it == converters.end()) { if (it == converters.end()) {
return boost::shared_ptr< ElemBase >(); return boost::shared_ptr< ElemBase >();
} }
boost::shared_ptr< ElemBase > ret = (structure.*((*it).second.first))(); boost::shared_ptr< ElemBase > ret = (structure.*((*it).second.first))();
(structure.*((*it).second.second))(ret,db); (structure.*((*it).second.second))(ret,db);
return ret; return ret;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
DNA::FactoryPair DNA :: GetBlobToStructureConverter( DNA::FactoryPair DNA :: GetBlobToStructureConverter(
const Structure& structure, const Structure& structure,
const FileDatabase& /*db*/ const FileDatabase& /*db*/
) const ) const
{ {
std::map<std::string, FactoryPair>::const_iterator it = converters.find(structure.name); std::map<std::string, FactoryPair>::const_iterator it = converters.find(structure.name);
return it == converters.end() ? FactoryPair() : (*it).second; return it == converters.end() ? FactoryPair() : (*it).second;
} }
// basing on http://www.blender.org/development/architecture/notes-on-sdna/ // basing on http://www.blender.org/development/architecture/notes-on-sdna/
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void DNA :: AddPrimitiveStructures() void DNA :: AddPrimitiveStructures()
{ {
// NOTE: these are just dummies. Their presence enforces // NOTE: these are just dummies. Their presence enforces
// Structure::Convert<target_type> to be called on these // Structure::Convert<target_type> to be called on these
// empty structures. These converters are special // empty structures. These converters are special
// overloads which scan the name of the structure and // overloads which scan the name of the structure and
// perform the required data type conversion if one // perform the required data type conversion if one
// of these special names is found in the structure // of these special names is found in the structure
// in question. // in question.
indices["int"] = structures.size(); indices["int"] = structures.size();
structures.push_back( Structure() ); structures.push_back( Structure() );
structures.back().name = "int"; structures.back().name = "int";
structures.back().size = 4; structures.back().size = 4;
indices["short"] = structures.size(); indices["short"] = structures.size();
structures.push_back( Structure() ); structures.push_back( Structure() );
structures.back().name = "short"; structures.back().name = "short";
structures.back().size = 2; structures.back().size = 2;
indices["char"] = structures.size(); indices["char"] = structures.size();
structures.push_back( Structure() ); structures.push_back( Structure() );
structures.back().name = "char"; structures.back().name = "char";
structures.back().size = 1; structures.back().size = 1;
indices["float"] = structures.size(); indices["float"] = structures.size();
structures.push_back( Structure() ); structures.push_back( Structure() );
structures.back().name = "float"; structures.back().name = "float";
structures.back().size = 4; structures.back().size = 4;
indices["double"] = structures.size(); indices["double"] = structures.size();
structures.push_back( Structure() ); structures.push_back( Structure() );
structures.back().name = "double"; structures.back().name = "double";
structures.back().size = 8; structures.back().size = 8;
// no long, seemingly. // no long, seemingly.
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void SectionParser :: Next() void SectionParser :: Next()
{ {
stream.SetCurrentPos(current.start + current.size); stream.SetCurrentPos(current.start + current.size);
const char tmp[] = { const char tmp[] = {
stream.GetI1(), stream.GetI1(),
stream.GetI1(), stream.GetI1(),
stream.GetI1(), stream.GetI1(),
stream.GetI1() stream.GetI1()
}; };
current.id = std::string(tmp,tmp[3]?4:tmp[2]?3:tmp[1]?2:1); current.id = std::string(tmp,tmp[3]?4:tmp[2]?3:tmp[1]?2:1);
current.size = stream.GetI4(); current.size = stream.GetI4();
current.address.val = ptr64 ? stream.GetU8() : stream.GetU4(); current.address.val = ptr64 ? stream.GetU8() : stream.GetU4();
current.dna_index = stream.GetI4(); current.dna_index = stream.GetI4();
current.num = stream.GetI4(); current.num = stream.GetI4();
current.start = stream.GetCurrentPos(); current.start = stream.GetCurrentPos();
if (stream.GetRemainingSizeToLimit() < current.size) { if (stream.GetRemainingSizeToLimit() < current.size) {
throw DeadlyImportError("BLEND: invalid size of file block"); throw DeadlyImportError("BLEND: invalid size of file block");
} }
#ifdef ASSIMP_BUILD_BLENDER_DEBUG #ifdef ASSIMP_BUILD_BLENDER_DEBUG
DefaultLogger::get()->debug(current.id); DefaultLogger::get()->debug(current.id);
#endif #endif
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -60,142 +60,142 @@ struct aiTexture;
namespace Assimp { namespace Assimp {
namespace Blender { namespace Blender {
// -------------------------------------------------------------------- // --------------------------------------------------------------------
/** Mini smart-array to avoid pulling in even more boost stuff. usable with vector and deque */ /** Mini smart-array to avoid pulling in even more boost stuff. usable with vector and deque */
// -------------------------------------------------------------------- // --------------------------------------------------------------------
template <template <typename,typename> class TCLASS, typename T> template <template <typename,typename> class TCLASS, typename T>
struct TempArray { struct TempArray {
typedef TCLASS< T*,std::allocator<T*> > mywrap; typedef TCLASS< T*,std::allocator<T*> > mywrap;
TempArray() { TempArray() {
} }
~TempArray () { ~TempArray () {
for_each(T* elem, arr) { for_each(T* elem, arr) {
delete elem; delete elem;
} }
} }
void dismiss() { void dismiss() {
arr.clear(); arr.clear();
} }
mywrap* operator -> () { mywrap* operator -> () {
return &arr; return &arr;
} }
operator mywrap& () { operator mywrap& () {
return arr; return arr;
} }
operator const mywrap& () const { operator const mywrap& () const {
return arr; return arr;
} }
mywrap& get () { mywrap& get () {
return arr; return arr;
} }
const mywrap& get () const { const mywrap& get () const {
return arr; return arr;
} }
T* operator[] (size_t idx) const { T* operator[] (size_t idx) const {
return arr[idx]; return arr[idx];
} }
T*& operator[] (size_t idx) { T*& operator[] (size_t idx) {
return arr[idx]; return arr[idx];
} }
private: private:
// no copy semantics // no copy semantics
void operator= (const TempArray&) { void operator= (const TempArray&) {
} }
TempArray(const TempArray& arr) { TempArray(const TempArray& arr) {
} }
private: private:
mywrap arr; mywrap arr;
}; };
#ifdef _MSC_VER #ifdef _MSC_VER
# pragma warning(disable:4351) # pragma warning(disable:4351)
#endif #endif
struct ObjectCompare { struct ObjectCompare {
bool operator() (const Object* left, const Object* right) const { bool operator() (const Object* left, const Object* right) const {
return strcmp(left->id.name, right->id.name) == -1; return strcmp(left->id.name, right->id.name) == -1;
} }
}; };
// When keeping objects in sets, sort them by their name. // When keeping objects in sets, sort them by their name.
typedef std::set<const Object*, ObjectCompare> ObjectSet; typedef std::set<const Object*, ObjectCompare> ObjectSet;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
/** ConversionData acts as intermediate storage location for /** ConversionData acts as intermediate storage location for
* the various ConvertXXX routines in BlenderImporter.*/ * the various ConvertXXX routines in BlenderImporter.*/
// -------------------------------------------------------------------- // --------------------------------------------------------------------
struct ConversionData struct ConversionData
{ {
ConversionData(const FileDatabase& db) ConversionData(const FileDatabase& db)
: sentinel_cnt() : sentinel_cnt()
, next_texture() , next_texture()
, db(db) , db(db)
{} {}
struct ObjectCompare { struct ObjectCompare {
bool operator() (const Object* left, const Object* right) const { bool operator() (const Object* left, const Object* right) const {
return strcmp(left->id.name, right->id.name) == -1; return strcmp(left->id.name, right->id.name) == -1;
} }
}; };
ObjectSet objects; ObjectSet objects;
TempArray <std::vector, aiMesh> meshes; TempArray <std::vector, aiMesh> meshes;
TempArray <std::vector, aiCamera> cameras; TempArray <std::vector, aiCamera> cameras;
TempArray <std::vector, aiLight> lights; TempArray <std::vector, aiLight> lights;
TempArray <std::vector, aiMaterial> materials; TempArray <std::vector, aiMaterial> materials;
TempArray <std::vector, aiTexture> textures; TempArray <std::vector, aiTexture> textures;
// set of all materials referenced by at least one mesh in the scene // set of all materials referenced by at least one mesh in the scene
std::deque< boost::shared_ptr< Material > > materials_raw; std::deque< boost::shared_ptr< Material > > materials_raw;
// counter to name sentinel textures inserted as substitutes for procedural textures. // counter to name sentinel textures inserted as substitutes for procedural textures.
unsigned int sentinel_cnt; unsigned int sentinel_cnt;
// next texture ID for each texture type, respectively // next texture ID for each texture type, respectively
unsigned int next_texture[aiTextureType_UNKNOWN+1]; unsigned int next_texture[aiTextureType_UNKNOWN+1];
// original file data // original file data
const FileDatabase& db; const FileDatabase& db;
}; };
#ifdef _MSC_VER #ifdef _MSC_VER
# pragma warning(default:4351) # pragma warning(default:4351)
#endif #endif
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
inline const char* GetTextureTypeDisplayString(Tex::Type t) inline const char* GetTextureTypeDisplayString(Tex::Type t)
{ {
switch (t) { switch (t) {
case Tex::Type_CLOUDS : return "Clouds"; case Tex::Type_CLOUDS : return "Clouds";
case Tex::Type_WOOD : return "Wood"; case Tex::Type_WOOD : return "Wood";
case Tex::Type_MARBLE : return "Marble"; case Tex::Type_MARBLE : return "Marble";
case Tex::Type_MAGIC : return "Magic"; case Tex::Type_MAGIC : return "Magic";
case Tex::Type_BLEND : return "Blend"; case Tex::Type_BLEND : return "Blend";
case Tex::Type_STUCCI : return "Stucci"; case Tex::Type_STUCCI : return "Stucci";
case Tex::Type_NOISE : return "Noise"; case Tex::Type_NOISE : return "Noise";
case Tex::Type_PLUGIN : return "Plugin"; case Tex::Type_PLUGIN : return "Plugin";
case Tex::Type_MUSGRAVE : return "Musgrave"; case Tex::Type_MUSGRAVE : return "Musgrave";
case Tex::Type_VORONOI : return "Voronoi"; case Tex::Type_VORONOI : return "Voronoi";
case Tex::Type_DISTNOISE : return "DistortedNoise"; case Tex::Type_DISTNOISE : return "DistortedNoise";
case Tex::Type_ENVMAP : return "EnvMap"; case Tex::Type_ENVMAP : return "EnvMap";
case Tex::Type_IMAGE : return "Image"; case Tex::Type_IMAGE : return "Image";
default: default:
break; break;
} }
return "<Unknown>"; return "<Unknown>";
} }
} // ! Blender } // ! Blender

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -54,43 +54,43 @@ struct aiLight;
struct aiCamera; struct aiCamera;
struct aiMaterial; struct aiMaterial;
namespace Assimp { namespace Assimp {
// TinyFormatter.h // TinyFormatter.h
namespace Formatter { namespace Formatter {
template <typename T,typename TR, typename A> class basic_formatter; template <typename T,typename TR, typename A> class basic_formatter;
typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format; typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
} }
// BlenderDNA.h // BlenderDNA.h
namespace Blender { namespace Blender {
class FileDatabase; class FileDatabase;
struct ElemBase; struct ElemBase;
} }
// BlenderScene.h // BlenderScene.h
namespace Blender { namespace Blender {
struct Scene; struct Scene;
struct Object; struct Object;
struct Mesh; struct Mesh;
struct Camera; struct Camera;
struct Lamp; struct Lamp;
struct MTex; struct MTex;
struct Image; struct Image;
struct Material; struct Material;
} }
// BlenderIntermediate.h // BlenderIntermediate.h
namespace Blender { namespace Blender {
struct ConversionData; struct ConversionData;
template <template <typename,typename> class TCLASS, typename T> struct TempArray; template <template <typename,typename> class TCLASS, typename T> struct TempArray;
} }
// BlenderModifier.h // BlenderModifier.h
namespace Blender { namespace Blender {
class BlenderModifierShowcase; class BlenderModifierShowcase;
class BlenderModifier; class BlenderModifier;
} }
@ -102,127 +102,127 @@ namespace Assimp {
class BlenderImporter : public BaseImporter, public LogFunctions<BlenderImporter> class BlenderImporter : public BaseImporter, public LogFunctions<BlenderImporter>
{ {
public: public:
BlenderImporter(); BlenderImporter();
~BlenderImporter(); ~BlenderImporter();
public: public:
// -------------------- // --------------------
bool CanRead( const std::string& pFile, bool CanRead( const std::string& pFile,
IOSystem* pIOHandler, IOSystem* pIOHandler,
bool checkSig bool checkSig
) const; ) const;
protected: protected:
// -------------------- // --------------------
const aiImporterDesc* GetInfo () const; const aiImporterDesc* GetInfo () const;
// -------------------- // --------------------
void GetExtensionList(std::set<std::string>& app); void GetExtensionList(std::set<std::string>& app);
// -------------------- // --------------------
void SetupProperties(const Importer* pImp); void SetupProperties(const Importer* pImp);
// -------------------- // --------------------
void InternReadFile( const std::string& pFile, void InternReadFile( const std::string& pFile,
aiScene* pScene, aiScene* pScene,
IOSystem* pIOHandler IOSystem* pIOHandler
); );
// -------------------- // --------------------
void ParseBlendFile(Blender::FileDatabase& out, void ParseBlendFile(Blender::FileDatabase& out,
boost::shared_ptr<IOStream> stream boost::shared_ptr<IOStream> stream
); );
// -------------------- // --------------------
void ExtractScene(Blender::Scene& out, void ExtractScene(Blender::Scene& out,
const Blender::FileDatabase& file const Blender::FileDatabase& file
); );
// -------------------- // --------------------
void ConvertBlendFile(aiScene* out, void ConvertBlendFile(aiScene* out,
const Blender::Scene& in, const Blender::Scene& in,
const Blender::FileDatabase& file const Blender::FileDatabase& file
); );
private: private:
// -------------------- // --------------------
aiNode* ConvertNode(const Blender::Scene& in, aiNode* ConvertNode(const Blender::Scene& in,
const Blender::Object* obj, const Blender::Object* obj,
Blender::ConversionData& conv_info, Blender::ConversionData& conv_info,
const aiMatrix4x4& parentTransform const aiMatrix4x4& parentTransform
); );
// -------------------- // --------------------
void ConvertMesh(const Blender::Scene& in, void ConvertMesh(const Blender::Scene& in,
const Blender::Object* obj, const Blender::Object* obj,
const Blender::Mesh* mesh, const Blender::Mesh* mesh,
Blender::ConversionData& conv_data, Blender::ConversionData& conv_data,
Blender::TempArray<std::vector,aiMesh>& temp Blender::TempArray<std::vector,aiMesh>& temp
); );
// -------------------- // --------------------
aiLight* ConvertLight(const Blender::Scene& in, aiLight* ConvertLight(const Blender::Scene& in,
const Blender::Object* obj, const Blender::Object* obj,
const Blender::Lamp* mesh, const Blender::Lamp* mesh,
Blender::ConversionData& conv_data Blender::ConversionData& conv_data
); );
// -------------------- // --------------------
aiCamera* ConvertCamera(const Blender::Scene& in, aiCamera* ConvertCamera(const Blender::Scene& in,
const Blender::Object* obj, const Blender::Object* obj,
const Blender::Camera* mesh, const Blender::Camera* mesh,
Blender::ConversionData& conv_data Blender::ConversionData& conv_data
); );
// -------------------- // --------------------
void BuildMaterials( void BuildMaterials(
Blender::ConversionData& conv_data Blender::ConversionData& conv_data
) ; ) ;
// -------------------- // --------------------
void ResolveTexture( void ResolveTexture(
aiMaterial* out, aiMaterial* out,
const Blender::Material* mat, const Blender::Material* mat,
const Blender::MTex* tex, const Blender::MTex* tex,
Blender::ConversionData& conv_data Blender::ConversionData& conv_data
); );
// -------------------- // --------------------
void ResolveImage( void ResolveImage(
aiMaterial* out, aiMaterial* out,
const Blender::Material* mat, const Blender::Material* mat,
const Blender::MTex* tex, const Blender::MTex* tex,
const Blender::Image* img, const Blender::Image* img,
Blender::ConversionData& conv_data Blender::ConversionData& conv_data
); );
void AddSentinelTexture( void AddSentinelTexture(
aiMaterial* out, aiMaterial* out,
const Blender::Material* mat, const Blender::Material* mat,
const Blender::MTex* tex, const Blender::MTex* tex,
Blender::ConversionData& conv_data Blender::ConversionData& conv_data
); );
private: // static stuff, mostly logging and error reporting. private: // static stuff, mostly logging and error reporting.
// -------------------- // --------------------
static void CheckActualType(const Blender::ElemBase* dt, static void CheckActualType(const Blender::ElemBase* dt,
const char* check const char* check
); );
// -------------------- // --------------------
static void NotSupportedObjectType(const Blender::Object* obj, static void NotSupportedObjectType(const Blender::Object* obj,
const char* type const char* type
); );
private: private:
Blender::BlenderModifierShowcase* modifier_cache; Blender::BlenderModifierShowcase* modifier_cache;
}; // !class BlenderImporter }; // !class BlenderImporter

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -58,120 +58,120 @@ using namespace Assimp;
using namespace Assimp::Blender; using namespace Assimp::Blender;
template <typename T> BlenderModifier* god() { template <typename T> BlenderModifier* god() {
return new T(); return new T();
} }
// add all available modifiers here // add all available modifiers here
typedef BlenderModifier* (*fpCreateModifier)(); typedef BlenderModifier* (*fpCreateModifier)();
static const fpCreateModifier creators[] = { static const fpCreateModifier creators[] = {
&god<BlenderModifier_Mirror>, &god<BlenderModifier_Mirror>,
&god<BlenderModifier_Subdivision>, &god<BlenderModifier_Subdivision>,
NULL // sentinel NULL // sentinel
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// just testing out some new macros to simplify logging // just testing out some new macros to simplify logging
#define ASSIMP_LOG_WARN_F(string,...)\ #define ASSIMP_LOG_WARN_F(string,...)\
DefaultLogger::get()->warn((Formatter::format(string),__VA_ARGS__)) DefaultLogger::get()->warn((Formatter::format(string),__VA_ARGS__))
#define ASSIMP_LOG_ERROR_F(string,...)\ #define ASSIMP_LOG_ERROR_F(string,...)\
DefaultLogger::get()->error((Formatter::format(string),__VA_ARGS__)) DefaultLogger::get()->error((Formatter::format(string),__VA_ARGS__))
#define ASSIMP_LOG_DEBUG_F(string,...)\ #define ASSIMP_LOG_DEBUG_F(string,...)\
DefaultLogger::get()->debug((Formatter::format(string),__VA_ARGS__)) DefaultLogger::get()->debug((Formatter::format(string),__VA_ARGS__))
#define ASSIMP_LOG_INFO_F(string,...)\ #define ASSIMP_LOG_INFO_F(string,...)\
DefaultLogger::get()->info((Formatter::format(string),__VA_ARGS__)) DefaultLogger::get()->info((Formatter::format(string),__VA_ARGS__))
#define ASSIMP_LOG_WARN(string)\ #define ASSIMP_LOG_WARN(string)\
DefaultLogger::get()->warn(string) DefaultLogger::get()->warn(string)
#define ASSIMP_LOG_ERROR(string)\ #define ASSIMP_LOG_ERROR(string)\
DefaultLogger::get()->error(string) DefaultLogger::get()->error(string)
#define ASSIMP_LOG_DEBUG(string)\ #define ASSIMP_LOG_DEBUG(string)\
DefaultLogger::get()->debug(string) DefaultLogger::get()->debug(string)
#define ASSIMP_LOG_INFO(string)\ #define ASSIMP_LOG_INFO(string)\
DefaultLogger::get()->info(string) DefaultLogger::get()->info(string)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
struct SharedModifierData : ElemBase struct SharedModifierData : ElemBase
{ {
ModifierData modifier; ModifierData modifier;
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_data, const Scene& in, const Object& orig_object ) void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_data, const Scene& in, const Object& orig_object )
{ {
size_t cnt = 0u, ful = 0u; size_t cnt = 0u, ful = 0u;
// NOTE: this cast is potentially unsafe by design, so we need to perform type checks before // NOTE: this cast is potentially unsafe by design, so we need to perform type checks before
// we're allowed to dereference the pointers without risking to crash. We might still be // we're allowed to dereference the pointers without risking to crash. We might still be
// invoking UB btw - we're assuming that the ModifierData member of the respective modifier // invoking UB btw - we're assuming that the ModifierData member of the respective modifier
// structures is at offset sizeof(vftable) with no padding. // structures is at offset sizeof(vftable) with no padding.
const SharedModifierData* cur = boost::static_pointer_cast<const SharedModifierData> ( orig_object.modifiers.first.get() ); const SharedModifierData* cur = boost::static_pointer_cast<const SharedModifierData> ( orig_object.modifiers.first.get() );
for (; cur; cur = boost::static_pointer_cast<const SharedModifierData> ( cur->modifier.next.get() ), ++ful) { for (; cur; cur = boost::static_pointer_cast<const SharedModifierData> ( cur->modifier.next.get() ), ++ful) {
ai_assert(cur->dna_type); ai_assert(cur->dna_type);
const Structure* s = conv_data.db.dna.Get( cur->dna_type ); const Structure* s = conv_data.db.dna.Get( cur->dna_type );
if (!s) { if (!s) {
ASSIMP_LOG_WARN_F("BlendModifier: could not resolve DNA name: ",cur->dna_type); ASSIMP_LOG_WARN_F("BlendModifier: could not resolve DNA name: ",cur->dna_type);
continue; continue;
} }
// this is a common trait of all XXXMirrorData structures in BlenderDNA // this is a common trait of all XXXMirrorData structures in BlenderDNA
const Field* f = s->Get("modifier"); const Field* f = s->Get("modifier");
if (!f || f->offset != 0) { if (!f || f->offset != 0) {
ASSIMP_LOG_WARN("BlendModifier: expected a `modifier` member at offset 0"); ASSIMP_LOG_WARN("BlendModifier: expected a `modifier` member at offset 0");
continue; continue;
} }
s = conv_data.db.dna.Get( f->type ); s = conv_data.db.dna.Get( f->type );
if (!s || s->name != "ModifierData") { if (!s || s->name != "ModifierData") {
ASSIMP_LOG_WARN("BlendModifier: expected a ModifierData structure as first member"); ASSIMP_LOG_WARN("BlendModifier: expected a ModifierData structure as first member");
continue; continue;
} }
// now, we can be sure that we should be fine to dereference *cur* as // now, we can be sure that we should be fine to dereference *cur* as
// ModifierData (with the above note). // ModifierData (with the above note).
const ModifierData& dat = cur->modifier; const ModifierData& dat = cur->modifier;
const fpCreateModifier* curgod = creators; const fpCreateModifier* curgod = creators;
std::vector< BlenderModifier* >::iterator curmod = cached_modifiers->begin(), endmod = cached_modifiers->end(); std::vector< BlenderModifier* >::iterator curmod = cached_modifiers->begin(), endmod = cached_modifiers->end();
for (;*curgod;++curgod,++curmod) { // allocate modifiers on the fly for (;*curgod;++curgod,++curmod) { // allocate modifiers on the fly
if (curmod == endmod) { if (curmod == endmod) {
cached_modifiers->push_back((*curgod)()); cached_modifiers->push_back((*curgod)());
endmod = cached_modifiers->end(); endmod = cached_modifiers->end();
curmod = endmod-1; curmod = endmod-1;
} }
BlenderModifier* const modifier = *curmod; BlenderModifier* const modifier = *curmod;
if(modifier->IsActive(dat)) { if(modifier->IsActive(dat)) {
modifier->DoIt(out,conv_data,*boost::static_pointer_cast<const ElemBase>(cur),in,orig_object); modifier->DoIt(out,conv_data,*boost::static_pointer_cast<const ElemBase>(cur),in,orig_object);
cnt++; cnt++;
curgod = NULL; curgod = NULL;
break; break;
} }
} }
if (curgod) { if (curgod) {
ASSIMP_LOG_WARN_F("Couldn't find a handler for modifier: ",dat.name); ASSIMP_LOG_WARN_F("Couldn't find a handler for modifier: ",dat.name);
} }
} }
// Even though we managed to resolve some or all of the modifiers on this // Even though we managed to resolve some or all of the modifiers on this
// object, we still can't say whether our modifier implementations were // object, we still can't say whether our modifier implementations were
// able to fully do their job. // able to fully do their job.
if (ful) { if (ful) {
ASSIMP_LOG_DEBUG_F("BlendModifier: found handlers for ",cnt," of ",ful," modifiers on `",orig_object.id.name, ASSIMP_LOG_DEBUG_F("BlendModifier: found handlers for ",cnt," of ",ful," modifiers on `",orig_object.id.name,
"`, check log messages above for errors"); "`, check log messages above for errors");
} }
} }
@ -179,102 +179,102 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_d
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool BlenderModifier_Mirror :: IsActive (const ModifierData& modin) bool BlenderModifier_Mirror :: IsActive (const ModifierData& modin)
{ {
return modin.type == ModifierData::eModifierType_Mirror; return modin.type == ModifierData::eModifierType_Mirror;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier, void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier,
const Scene& /*in*/, const Scene& /*in*/,
const Object& orig_object ) const Object& orig_object )
{ {
// hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers() // hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
const MirrorModifierData& mir = static_cast<const MirrorModifierData&>(orig_modifier); const MirrorModifierData& mir = static_cast<const MirrorModifierData&>(orig_modifier);
ai_assert(mir.modifier.type == ModifierData::eModifierType_Mirror); ai_assert(mir.modifier.type == ModifierData::eModifierType_Mirror);
conv_data.meshes->reserve(conv_data.meshes->size() + out.mNumMeshes); conv_data.meshes->reserve(conv_data.meshes->size() + out.mNumMeshes);
// XXX not entirely correct, mirroring on two axes results in 4 distinct objects in blender ... // XXX not entirely correct, mirroring on two axes results in 4 distinct objects in blender ...
// take all input meshes and clone them // take all input meshes and clone them
for (unsigned int i = 0; i < out.mNumMeshes; ++i) { for (unsigned int i = 0; i < out.mNumMeshes; ++i) {
aiMesh* mesh; aiMesh* mesh;
SceneCombiner::Copy(&mesh,conv_data.meshes[out.mMeshes[i]]); SceneCombiner::Copy(&mesh,conv_data.meshes[out.mMeshes[i]]);
const float xs = mir.flag & MirrorModifierData::Flags_AXIS_X ? -1.f : 1.f; const float xs = mir.flag & MirrorModifierData::Flags_AXIS_X ? -1.f : 1.f;
const float ys = mir.flag & MirrorModifierData::Flags_AXIS_Y ? -1.f : 1.f; const float ys = mir.flag & MirrorModifierData::Flags_AXIS_Y ? -1.f : 1.f;
const float zs = mir.flag & MirrorModifierData::Flags_AXIS_Z ? -1.f : 1.f; const float zs = mir.flag & MirrorModifierData::Flags_AXIS_Z ? -1.f : 1.f;
if (mir.mirror_ob) { if (mir.mirror_ob) {
const aiVector3D center( mir.mirror_ob->obmat[3][0],mir.mirror_ob->obmat[3][1],mir.mirror_ob->obmat[3][2] ); const aiVector3D center( mir.mirror_ob->obmat[3][0],mir.mirror_ob->obmat[3][1],mir.mirror_ob->obmat[3][2] );
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
aiVector3D& v = mesh->mVertices[i]; aiVector3D& v = mesh->mVertices[i];
v.x = center.x + xs*(center.x - v.x); v.x = center.x + xs*(center.x - v.x);
v.y = center.y + ys*(center.y - v.y); v.y = center.y + ys*(center.y - v.y);
v.z = center.z + zs*(center.z - v.z); v.z = center.z + zs*(center.z - v.z);
} }
} }
else { else {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
aiVector3D& v = mesh->mVertices[i]; aiVector3D& v = mesh->mVertices[i];
v.x *= xs;v.y *= ys;v.z *= zs; v.x *= xs;v.y *= ys;v.z *= zs;
} }
} }
if (mesh->mNormals) { if (mesh->mNormals) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
aiVector3D& v = mesh->mNormals[i]; aiVector3D& v = mesh->mNormals[i];
v.x *= xs;v.y *= ys;v.z *= zs; v.x *= xs;v.y *= ys;v.z *= zs;
} }
} }
if (mesh->mTangents) { if (mesh->mTangents) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
aiVector3D& v = mesh->mTangents[i]; aiVector3D& v = mesh->mTangents[i];
v.x *= xs;v.y *= ys;v.z *= zs; v.x *= xs;v.y *= ys;v.z *= zs;
} }
} }
if (mesh->mBitangents) { if (mesh->mBitangents) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
aiVector3D& v = mesh->mBitangents[i]; aiVector3D& v = mesh->mBitangents[i];
v.x *= xs;v.y *= ys;v.z *= zs; v.x *= xs;v.y *= ys;v.z *= zs;
} }
} }
const float us = mir.flag & MirrorModifierData::Flags_MIRROR_U ? -1.f : 1.f; const float us = mir.flag & MirrorModifierData::Flags_MIRROR_U ? -1.f : 1.f;
const float vs = mir.flag & MirrorModifierData::Flags_MIRROR_V ? -1.f : 1.f; const float vs = mir.flag & MirrorModifierData::Flags_MIRROR_V ? -1.f : 1.f;
for (unsigned int n = 0; mesh->HasTextureCoords(n); ++n) { for (unsigned int n = 0; mesh->HasTextureCoords(n); ++n) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
aiVector3D& v = mesh->mTextureCoords[n][i]; aiVector3D& v = mesh->mTextureCoords[n][i];
v.x *= us;v.y *= vs; v.x *= us;v.y *= vs;
} }
} }
// Only reverse the winding order if an odd number of axes were mirrored. // Only reverse the winding order if an odd number of axes were mirrored.
if (xs * ys * zs < 0) { if (xs * ys * zs < 0) {
for( unsigned int i = 0; i < mesh->mNumFaces; i++) { for( unsigned int i = 0; i < mesh->mNumFaces; i++) {
aiFace& face = mesh->mFaces[i]; aiFace& face = mesh->mFaces[i];
for( unsigned int fi = 0; fi < face.mNumIndices / 2; ++fi) for( unsigned int fi = 0; fi < face.mNumIndices / 2; ++fi)
std::swap( face.mIndices[fi], face.mIndices[face.mNumIndices - 1 - fi]); std::swap( face.mIndices[fi], face.mIndices[face.mNumIndices - 1 - fi]);
} }
} }
conv_data.meshes->push_back(mesh); conv_data.meshes->push_back(mesh);
} }
unsigned int* nind = new unsigned int[out.mNumMeshes*2]; unsigned int* nind = new unsigned int[out.mNumMeshes*2];
std::copy(out.mMeshes,out.mMeshes+out.mNumMeshes,nind); std::copy(out.mMeshes,out.mMeshes+out.mNumMeshes,nind);
std::transform(out.mMeshes,out.mMeshes+out.mNumMeshes,nind+out.mNumMeshes, std::transform(out.mMeshes,out.mMeshes+out.mNumMeshes,nind+out.mNumMeshes,
std::bind1st(std::plus< unsigned int >(),out.mNumMeshes)); std::bind1st(std::plus< unsigned int >(),out.mNumMeshes));
delete[] out.mMeshes; delete[] out.mMeshes;
out.mMeshes = nind; out.mMeshes = nind;
out.mNumMeshes *= 2; out.mNumMeshes *= 2;
ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Mirror` modifier to `", ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Mirror` modifier to `",
orig_object.id.name,"`"); orig_object.id.name,"`");
} }
@ -283,46 +283,46 @@ void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, co
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool BlenderModifier_Subdivision :: IsActive (const ModifierData& modin) bool BlenderModifier_Subdivision :: IsActive (const ModifierData& modin)
{ {
return modin.type == ModifierData::eModifierType_Subsurf; return modin.type == ModifierData::eModifierType_Subsurf;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier, void BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier,
const Scene& /*in*/, const Scene& /*in*/,
const Object& orig_object ) const Object& orig_object )
{ {
// hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers() // hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
const SubsurfModifierData& mir = static_cast<const SubsurfModifierData&>(orig_modifier); const SubsurfModifierData& mir = static_cast<const SubsurfModifierData&>(orig_modifier);
ai_assert(mir.modifier.type == ModifierData::eModifierType_Subsurf); ai_assert(mir.modifier.type == ModifierData::eModifierType_Subsurf);
Subdivider::Algorithm algo; Subdivider::Algorithm algo;
switch (mir.subdivType) switch (mir.subdivType)
{ {
case SubsurfModifierData::TYPE_CatmullClarke: case SubsurfModifierData::TYPE_CatmullClarke:
algo = Subdivider::CATMULL_CLARKE; algo = Subdivider::CATMULL_CLARKE;
break; break;
case SubsurfModifierData::TYPE_Simple: case SubsurfModifierData::TYPE_Simple:
ASSIMP_LOG_WARN("BlendModifier: The `SIMPLE` subdivision algorithm is not currently implemented, using Catmull-Clarke"); ASSIMP_LOG_WARN("BlendModifier: The `SIMPLE` subdivision algorithm is not currently implemented, using Catmull-Clarke");
algo = Subdivider::CATMULL_CLARKE; algo = Subdivider::CATMULL_CLARKE;
break; break;
default: default:
ASSIMP_LOG_WARN_F("BlendModifier: Unrecognized subdivision algorithm: ",mir.subdivType); ASSIMP_LOG_WARN_F("BlendModifier: Unrecognized subdivision algorithm: ",mir.subdivType);
return; return;
}; };
boost::scoped_ptr<Subdivider> subd(Subdivider::Create(algo)); boost::scoped_ptr<Subdivider> subd(Subdivider::Create(algo));
ai_assert(subd); ai_assert(subd);
aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes]; aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes];
boost::scoped_array<aiMesh*> tempmeshes(new aiMesh*[out.mNumMeshes]()); boost::scoped_array<aiMesh*> tempmeshes(new aiMesh*[out.mNumMeshes]());
subd->Subdivide(meshes,out.mNumMeshes,tempmeshes.get(),std::max( mir.renderLevels, mir.levels ),true); subd->Subdivide(meshes,out.mNumMeshes,tempmeshes.get(),std::max( mir.renderLevels, mir.levels ),true);
std::copy(tempmeshes.get(),tempmeshes.get()+out.mNumMeshes,meshes); std::copy(tempmeshes.get(),tempmeshes.get()+out.mNumMeshes,meshes);
ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Subdivision` modifier to `", ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Subdivision` modifier to `",
orig_object.id.name,"`"); orig_object.id.name,"`");
} }
#endif #endif

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderIntermediate.h" #include "BlenderIntermediate.h"
#include "TinyFormatter.h" #include "TinyFormatter.h"
namespace Assimp { namespace Assimp {
namespace Blender { namespace Blender {
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
/** Dummy base class for all blender modifiers. Modifiers are reused between imports, so /** Dummy base class for all blender modifiers. Modifiers are reused between imports, so
@ -57,30 +57,30 @@ class BlenderModifier
{ {
public: public:
virtual ~BlenderModifier() { virtual ~BlenderModifier() {
} }
public: public:
// -------------------- // --------------------
/** Check if *this* modifier is active, given a ModifierData& block.*/ /** Check if *this* modifier is active, given a ModifierData& block.*/
virtual bool IsActive( const ModifierData& /*modin*/) { virtual bool IsActive( const ModifierData& /*modin*/) {
return false; return false;
} }
// -------------------- // --------------------
/** Apply the modifier to a given output node. The original data used /** Apply the modifier to a given output node. The original data used
* to construct the node is given as well. Not called unless IsActive() * to construct the node is given as well. Not called unless IsActive()
* was called and gave positive response. */ * was called and gave positive response. */
virtual void DoIt(aiNode& /*out*/, virtual void DoIt(aiNode& /*out*/,
ConversionData& /*conv_data*/, ConversionData& /*conv_data*/,
const ElemBase& orig_modifier, const ElemBase& orig_modifier,
const Scene& /*in*/, const Scene& /*in*/,
const Object& /*orig_object*/ const Object& /*orig_object*/
) { ) {
DefaultLogger::get()->warn((Formatter::format("This modifier is not supported, skipping: "),orig_modifier.dna_type)); DefaultLogger::get()->warn((Formatter::format("This modifier is not supported, skipping: "),orig_modifier.dna_type));
return; return;
} }
}; };
@ -91,17 +91,17 @@ class BlenderModifierShowcase
{ {
public: public:
// -------------------- // --------------------
/** Apply all requested modifiers provided we support them. */ /** Apply all requested modifiers provided we support them. */
void ApplyModifiers(aiNode& out, void ApplyModifiers(aiNode& out,
ConversionData& conv_data, ConversionData& conv_data,
const Scene& in, const Scene& in,
const Object& orig_object const Object& orig_object
); );
private: private:
TempArray< std::vector,BlenderModifier > cached_modifiers; TempArray< std::vector,BlenderModifier > cached_modifiers;
}; };
@ -119,16 +119,16 @@ class BlenderModifier_Mirror : public BlenderModifier
{ {
public: public:
// -------------------- // --------------------
virtual bool IsActive( const ModifierData& modin); virtual bool IsActive( const ModifierData& modin);
// -------------------- // --------------------
virtual void DoIt(aiNode& out, virtual void DoIt(aiNode& out,
ConversionData& conv_data, ConversionData& conv_data,
const ElemBase& orig_modifier, const ElemBase& orig_modifier,
const Scene& in, const Scene& in,
const Object& orig_object const Object& orig_object
) ; ) ;
}; };
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
@ -138,16 +138,16 @@ class BlenderModifier_Subdivision : public BlenderModifier
{ {
public: public:
// -------------------- // --------------------
virtual bool IsActive( const ModifierData& modin); virtual bool IsActive( const ModifierData& modin);
// -------------------- // --------------------
virtual void DoIt(aiNode& out, virtual void DoIt(aiNode& out,
ConversionData& conv_data, ConversionData& conv_data,
const ElemBase& orig_modifier, const ElemBase& orig_modifier,
const Scene& in, const Scene& in,
const Object& orig_object const Object& orig_object
) ; ) ;
}; };

View File

@ -76,7 +76,7 @@ template <> void Structure :: Convert<Object> (
ReadFieldPtr<ErrorPolicy_Fail>(dest.data,"*data",db); ReadFieldPtr<ErrorPolicy_Fail>(dest.data,"*data",db);
ReadField<ErrorPolicy_Igno>(dest.modifiers,"modifiers",db); ReadField<ErrorPolicy_Igno>(dest.modifiers,"modifiers",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -90,7 +90,7 @@ template <> void Structure :: Convert<Group> (
ReadField<ErrorPolicy_Igno>(dest.layer,"layer",db); ReadField<ErrorPolicy_Igno>(dest.layer,"layer",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.gobject,"*gobject",db); ReadFieldPtr<ErrorPolicy_Igno>(dest.gobject,"*gobject",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -129,7 +129,7 @@ template <> void Structure :: Convert<MTex> (
ReadField<ErrorPolicy_Igno>(dest.hardfac,"hardfac",db); ReadField<ErrorPolicy_Igno>(dest.hardfac,"hardfac",db);
ReadField<ErrorPolicy_Igno>(dest.norfac,"norfac",db); ReadField<ErrorPolicy_Igno>(dest.norfac,"norfac",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -146,7 +146,7 @@ template <> void Structure :: Convert<TFace> (
ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db); ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db);
ReadField<ErrorPolicy_Igno>(dest.unwrap,"unwrap",db); ReadField<ErrorPolicy_Igno>(dest.unwrap,"unwrap",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -162,7 +162,7 @@ template <> void Structure :: Convert<SubsurfModifierData> (
ReadField<ErrorPolicy_Igno>(dest.renderLevels,"renderLevels",db); ReadField<ErrorPolicy_Igno>(dest.renderLevels,"renderLevels",db);
ReadField<ErrorPolicy_Igno>(dest.flags,"flags",db); ReadField<ErrorPolicy_Igno>(dest.flags,"flags",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -179,7 +179,7 @@ template <> void Structure :: Convert<MFace> (
ReadField<ErrorPolicy_Fail>(dest.mat_nr,"mat_nr",db); ReadField<ErrorPolicy_Fail>(dest.mat_nr,"mat_nr",db);
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db); ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -207,7 +207,7 @@ template <> void Structure :: Convert<Lamp> (
ReadField<ErrorPolicy_Igno>((int&)dest.falloff_type,"falloff_type",db); ReadField<ErrorPolicy_Igno>((int&)dest.falloff_type,"falloff_type",db);
ReadField<ErrorPolicy_Igno>(dest.sun_brightness,"sun_brightness",db); ReadField<ErrorPolicy_Igno>(dest.sun_brightness,"sun_brightness",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -220,7 +220,7 @@ template <> void Structure :: Convert<MDeformWeight> (
ReadField<ErrorPolicy_Fail>(dest.def_nr,"def_nr",db); ReadField<ErrorPolicy_Fail>(dest.def_nr,"def_nr",db);
ReadField<ErrorPolicy_Fail>(dest.weight,"weight",db); ReadField<ErrorPolicy_Fail>(dest.weight,"weight",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -234,7 +234,7 @@ template <> void Structure :: Convert<PackedFile> (
ReadField<ErrorPolicy_Warn>(dest.seek,"seek",db); ReadField<ErrorPolicy_Warn>(dest.seek,"seek",db);
ReadFieldPtr<ErrorPolicy_Warn>(dest.data,"*data",db); ReadFieldPtr<ErrorPolicy_Warn>(dest.data,"*data",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -243,36 +243,36 @@ template <> void Structure :: Convert<Base> (
const FileDatabase& db const FileDatabase& db
) const ) const
{ {
// note: as per https://github.com/assimp/assimp/issues/128, // note: as per https://github.com/assimp/assimp/issues/128,
// reading the Object linked list recursively is prone to stack overflow. // reading the Object linked list recursively is prone to stack overflow.
// This structure converter is therefore an hand-written exception that // This structure converter is therefore an hand-written exception that
// does it iteratively. // does it iteratively.
const int initial_pos = db.reader->GetCurrentPos(); const int initial_pos = db.reader->GetCurrentPos();
std::pair<Base*, int> todo = std::make_pair(&dest, initial_pos); std::pair<Base*, int> todo = std::make_pair(&dest, initial_pos);
for ( ;; ) { for ( ;; ) {
Base& cur_dest = *todo.first; Base& cur_dest = *todo.first;
db.reader->SetCurrentPos(todo.second); db.reader->SetCurrentPos(todo.second);
// we know that this is a double-linked, circular list which we never // we know that this is a double-linked, circular list which we never
// traverse backwards, so don't bother resolving the back links. // traverse backwards, so don't bother resolving the back links.
cur_dest.prev = NULL; cur_dest.prev = NULL;
ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.object,"*object",db); ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.object,"*object",db);
// the return value of ReadFieldPtr indicates whether the object // the return value of ReadFieldPtr indicates whether the object
// was already cached. In this case, we don't need to resolve // was already cached. In this case, we don't need to resolve
// it again. // it again.
if(!ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.next,"*next",db, true) && cur_dest.next) { if(!ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.next,"*next",db, true) && cur_dest.next) {
todo = std::make_pair(&*cur_dest.next, db.reader->GetCurrentPos()); todo = std::make_pair(&*cur_dest.next, db.reader->GetCurrentPos());
continue; continue;
} }
break; break;
} }
db.reader->SetCurrentPos(initial_pos + size); db.reader->SetCurrentPos(initial_pos + size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -288,7 +288,7 @@ template <> void Structure :: Convert<MTFace> (
ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db); ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db);
ReadField<ErrorPolicy_Igno>(dest.unwrap,"unwrap",db); ReadField<ErrorPolicy_Igno>(dest.unwrap,"unwrap",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -324,7 +324,7 @@ template <> void Structure :: Convert<Material> (
ReadField<ErrorPolicy_Warn>(dest.spec_shader,"spec_shader",db); ReadField<ErrorPolicy_Warn>(dest.spec_shader,"spec_shader",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.mtex,"*mtex",db); ReadFieldPtr<ErrorPolicy_Igno>(dest.mtex,"*mtex",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -345,7 +345,7 @@ template <> void Structure :: Convert<MTexPoly> (
ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db); ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db);
ReadField<ErrorPolicy_Igno>(dest.pad,"pad",db); ReadField<ErrorPolicy_Igno>(dest.pad,"pad",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -379,7 +379,7 @@ template <> void Structure :: Convert<Mesh> (
ReadFieldPtr<ErrorPolicy_Igno>(dest.mcol,"*mcol",db); ReadFieldPtr<ErrorPolicy_Igno>(dest.mcol,"*mcol",db);
ReadFieldPtr<ErrorPolicy_Fail>(dest.mat,"**mat",db); ReadFieldPtr<ErrorPolicy_Fail>(dest.mat,"**mat",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -392,7 +392,7 @@ template <> void Structure :: Convert<MDeformVert> (
ReadFieldPtr<ErrorPolicy_Warn>(dest.dw,"*dw",db); ReadFieldPtr<ErrorPolicy_Warn>(dest.dw,"*dw",db);
ReadField<ErrorPolicy_Igno>(dest.totweight,"totweight",db); ReadField<ErrorPolicy_Igno>(dest.totweight,"totweight",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -404,7 +404,7 @@ template <> void Structure :: Convert<World> (
ReadField<ErrorPolicy_Fail>(dest.id,"id",db); ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -419,7 +419,7 @@ template <> void Structure :: Convert<MLoopCol> (
ReadField<ErrorPolicy_Igno>(dest.b,"b",db); ReadField<ErrorPolicy_Igno>(dest.b,"b",db);
ReadField<ErrorPolicy_Igno>(dest.a,"a",db); ReadField<ErrorPolicy_Igno>(dest.a,"a",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -435,7 +435,7 @@ template <> void Structure :: Convert<MVert> (
ReadField<ErrorPolicy_Warn>(dest.mat_nr,"mat_nr",db); ReadField<ErrorPolicy_Warn>(dest.mat_nr,"mat_nr",db);
ReadField<ErrorPolicy_Igno>(dest.bweight,"bweight",db); ReadField<ErrorPolicy_Igno>(dest.bweight,"bweight",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -451,7 +451,7 @@ template <> void Structure :: Convert<MEdge> (
ReadField<ErrorPolicy_Igno>(dest.bweight,"bweight",db); ReadField<ErrorPolicy_Igno>(dest.bweight,"bweight",db);
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db); ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -464,7 +464,7 @@ template <> void Structure :: Convert<MLoopUV> (
ReadFieldArray<ErrorPolicy_Igno>(dest.uv,"uv",db); ReadFieldArray<ErrorPolicy_Igno>(dest.uv,"uv",db);
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db); ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -478,7 +478,7 @@ template <> void Structure :: Convert<GroupObject> (
ReadFieldPtr<ErrorPolicy_Fail>(dest.next,"*next",db); ReadFieldPtr<ErrorPolicy_Fail>(dest.next,"*next",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.ob,"*ob",db); ReadFieldPtr<ErrorPolicy_Igno>(dest.ob,"*ob",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -491,7 +491,7 @@ template <> void Structure :: Convert<ListBase> (
ReadFieldPtr<ErrorPolicy_Igno>(dest.first,"*first",db); ReadFieldPtr<ErrorPolicy_Igno>(dest.first,"*first",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.last,"*last",db); ReadFieldPtr<ErrorPolicy_Igno>(dest.last,"*last",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -504,7 +504,7 @@ template <> void Structure :: Convert<MLoop> (
ReadField<ErrorPolicy_Igno>(dest.v,"v",db); ReadField<ErrorPolicy_Igno>(dest.v,"v",db);
ReadField<ErrorPolicy_Igno>(dest.e,"e",db); ReadField<ErrorPolicy_Igno>(dest.e,"e",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -520,7 +520,7 @@ template <> void Structure :: Convert<ModifierData> (
ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db); ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db);
ReadFieldArray<ErrorPolicy_Igno>(dest.name,"name",db); ReadFieldArray<ErrorPolicy_Igno>(dest.name,"name",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -533,7 +533,7 @@ template <> void Structure :: Convert<ID> (
ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db); ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db);
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db); ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -548,7 +548,7 @@ template <> void Structure :: Convert<MCol> (
ReadField<ErrorPolicy_Fail>(dest.b,"b",db); ReadField<ErrorPolicy_Fail>(dest.b,"b",db);
ReadField<ErrorPolicy_Fail>(dest.a,"a",db); ReadField<ErrorPolicy_Fail>(dest.a,"a",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -563,7 +563,7 @@ template <> void Structure :: Convert<MPoly> (
ReadField<ErrorPolicy_Igno>(dest.mat_nr,"mat_nr",db); ReadField<ErrorPolicy_Igno>(dest.mat_nr,"mat_nr",db);
ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db); ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -579,7 +579,7 @@ template <> void Structure :: Convert<Scene> (
ReadFieldPtr<ErrorPolicy_Warn>(dest.basact,"*basact",db); ReadFieldPtr<ErrorPolicy_Warn>(dest.basact,"*basact",db);
ReadField<ErrorPolicy_Igno>(dest.base,"base",db); ReadField<ErrorPolicy_Igno>(dest.base,"base",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -594,7 +594,7 @@ template <> void Structure :: Convert<Library> (
ReadFieldArray<ErrorPolicy_Fail>(dest.filename,"filename",db); ReadFieldArray<ErrorPolicy_Fail>(dest.filename,"filename",db);
ReadFieldPtr<ErrorPolicy_Warn>(dest.parent,"*parent",db); ReadFieldPtr<ErrorPolicy_Warn>(dest.parent,"*parent",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -607,7 +607,7 @@ template <> void Structure :: Convert<Tex> (
ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db); ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
ReadFieldPtr<ErrorPolicy_Warn>(dest.ima,"*ima",db); ReadFieldPtr<ErrorPolicy_Warn>(dest.ima,"*ima",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -622,7 +622,7 @@ template <> void Structure :: Convert<Camera> (
ReadField<ErrorPolicy_Warn>((int&)dest.flag,"flag",db); ReadField<ErrorPolicy_Warn>((int&)dest.flag,"flag",db);
ReadField<ErrorPolicy_Warn>(dest.angle,"angle",db); ReadField<ErrorPolicy_Warn>(dest.angle,"angle",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -638,7 +638,7 @@ template <> void Structure :: Convert<MirrorModifierData> (
ReadField<ErrorPolicy_Igno>(dest.tolerance,"tolerance",db); ReadField<ErrorPolicy_Igno>(dest.tolerance,"tolerance",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.mirror_ob,"*mirror_ob",db); ReadFieldPtr<ErrorPolicy_Igno>(dest.mirror_ob,"*mirror_ob",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -671,7 +671,7 @@ template <> void Structure :: Convert<Image> (
ReadField<ErrorPolicy_Igno>(dest.gen_y,"gen_y",db); ReadField<ErrorPolicy_Igno>(dest.gen_y,"gen_y",db);
ReadField<ErrorPolicy_Igno>(dest.gen_type,"gen_type",db); ReadField<ErrorPolicy_Igno>(dest.gen_type,"gen_type",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -46,8 +46,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderDNA.h" #include "BlenderDNA.h"
namespace Assimp { namespace Assimp {
namespace Blender { namespace Blender {
// Minor parts of this file are extracts from blender data structures, // Minor parts of this file are extracts from blender data structures,
// declared in the ./source/blender/makesdna directory. // declared in the ./source/blender/makesdna directory.
@ -65,7 +65,7 @@ namespace Assimp {
// //
// * Structures may include the primitive types char, int, short, // * Structures may include the primitive types char, int, short,
// float, double. Signedness specifiers are not allowed on // float, double. Signedness specifiers are not allowed on
// integers. Enum types are allowed, but they must have been // integers. Enum types are allowed, but they must have been
// defined in this header. // defined in this header.
// //
// * Structures may aggregate other structures, unless not defined // * Structures may aggregate other structures, unless not defined
@ -103,15 +103,15 @@ struct Image;
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct ID : ElemBase { struct ID : ElemBase {
char name[24] WARN; char name[24] WARN;
short flag; short flag;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct ListBase : ElemBase { struct ListBase : ElemBase {
boost::shared_ptr<ElemBase> first; boost::shared_ptr<ElemBase> first;
boost::shared_ptr<ElemBase> last; boost::shared_ptr<ElemBase> last;
}; };
@ -119,37 +119,37 @@ struct ListBase : ElemBase {
struct PackedFile : ElemBase { struct PackedFile : ElemBase {
int size WARN; int size WARN;
int seek WARN; int seek WARN;
boost::shared_ptr< FileOffset > data WARN; boost::shared_ptr< FileOffset > data WARN;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct GroupObject : ElemBase { struct GroupObject : ElemBase {
boost::shared_ptr<GroupObject> prev,next FAIL; boost::shared_ptr<GroupObject> prev,next FAIL;
boost::shared_ptr<Object> ob; boost::shared_ptr<Object> ob;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Group : ElemBase { struct Group : ElemBase {
ID id FAIL; ID id FAIL;
int layer; int layer;
boost::shared_ptr<GroupObject> gobject; boost::shared_ptr<GroupObject> gobject;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct World : ElemBase { struct World : ElemBase {
ID id FAIL; ID id FAIL;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MVert : ElemBase { struct MVert : ElemBase {
float co[3] FAIL; float co[3] FAIL;
float no[3] FAIL; float no[3] FAIL;
char flag; char flag;
int mat_nr WARN; int mat_nr WARN;
int bweight; int bweight;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@ -161,68 +161,68 @@ struct MEdge : ElemBase {
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MLoop : ElemBase { struct MLoop : ElemBase {
int v, e; int v, e;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MLoopUV : ElemBase { struct MLoopUV : ElemBase {
float uv[2]; float uv[2];
int flag; int flag;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
// Note that red and blue are not swapped, as with MCol // Note that red and blue are not swapped, as with MCol
struct MLoopCol : ElemBase { struct MLoopCol : ElemBase {
char r, g, b, a; char r, g, b, a;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MPoly : ElemBase { struct MPoly : ElemBase {
int loopstart; int loopstart;
int totloop; int totloop;
short mat_nr; short mat_nr;
char flag; char flag;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MTexPoly : ElemBase { struct MTexPoly : ElemBase {
Image* tpage; Image* tpage;
char flag, transp; char flag, transp;
short mode, tile, pad; short mode, tile, pad;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MCol : ElemBase { struct MCol : ElemBase {
char r,g,b,a FAIL; char r,g,b,a FAIL;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MFace : ElemBase { struct MFace : ElemBase {
int v1,v2,v3,v4 FAIL; int v1,v2,v3,v4 FAIL;
int mat_nr FAIL; int mat_nr FAIL;
char flag; char flag;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct TFace : ElemBase { struct TFace : ElemBase {
float uv[4][2] FAIL; float uv[4][2] FAIL;
int col[4] FAIL; int col[4] FAIL;
char flag; char flag;
short mode; short mode;
short tile; short tile;
short unwrap; short unwrap;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MTFace : ElemBase { struct MTFace : ElemBase {
float uv[4][2] FAIL; float uv[4][2] FAIL;
char flag; char flag;
short mode; short mode;
short tile; short tile;
short unwrap; short unwrap;
// boost::shared_ptr<Image> tpage; // boost::shared_ptr<Image> tpage;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@ -234,124 +234,124 @@ struct MDeformWeight : ElemBase {
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MDeformVert : ElemBase { struct MDeformVert : ElemBase {
vector<MDeformWeight> dw WARN; vector<MDeformWeight> dw WARN;
int totweight; int totweight;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Material : ElemBase { struct Material : ElemBase {
ID id FAIL; ID id FAIL;
float r,g,b WARN; float r,g,b WARN;
float specr,specg,specb WARN; float specr,specg,specb WARN;
short har; short har;
float ambr,ambg,ambb WARN; float ambr,ambg,ambb WARN;
float mirr,mirg,mirb; float mirr,mirg,mirb;
float emit WARN; float emit WARN;
float alpha WARN; float alpha WARN;
float ref; float ref;
float translucency; float translucency;
float roughness; float roughness;
float darkness; float darkness;
float refrac; float refrac;
boost::shared_ptr<Group> group; boost::shared_ptr<Group> group;
short diff_shader WARN; short diff_shader WARN;
short spec_shader WARN; short spec_shader WARN;
boost::shared_ptr<MTex> mtex[18]; boost::shared_ptr<MTex> mtex[18];
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Mesh : ElemBase { struct Mesh : ElemBase {
ID id FAIL; ID id FAIL;
int totface FAIL; int totface FAIL;
int totedge FAIL; int totedge FAIL;
int totvert FAIL; int totvert FAIL;
int totloop; int totloop;
int totpoly; int totpoly;
short subdiv; short subdiv;
short subdivr; short subdivr;
short subsurftype; short subsurftype;
short smoothresh; short smoothresh;
vector<MFace> mface FAIL; vector<MFace> mface FAIL;
vector<MTFace> mtface; vector<MTFace> mtface;
vector<TFace> tface; vector<TFace> tface;
vector<MVert> mvert FAIL; vector<MVert> mvert FAIL;
vector<MEdge> medge WARN; vector<MEdge> medge WARN;
vector<MLoop> mloop; vector<MLoop> mloop;
vector<MLoopUV> mloopuv; vector<MLoopUV> mloopuv;
vector<MLoopCol> mloopcol; vector<MLoopCol> mloopcol;
vector<MPoly> mpoly; vector<MPoly> mpoly;
vector<MTexPoly> mtpoly; vector<MTexPoly> mtpoly;
vector<MDeformVert> dvert; vector<MDeformVert> dvert;
vector<MCol> mcol; vector<MCol> mcol;
vector< boost::shared_ptr<Material> > mat FAIL; vector< boost::shared_ptr<Material> > mat FAIL;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Library : ElemBase { struct Library : ElemBase {
ID id FAIL; ID id FAIL;
char name[240] WARN; char name[240] WARN;
char filename[240] FAIL; char filename[240] FAIL;
boost::shared_ptr<Library> parent WARN; boost::shared_ptr<Library> parent WARN;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Camera : ElemBase { struct Camera : ElemBase {
enum Type { enum Type {
Type_PERSP = 0 Type_PERSP = 0
,Type_ORTHO = 1 ,Type_ORTHO = 1
}; };
ID id FAIL; ID id FAIL;
// struct AnimData *adt; // struct AnimData *adt;
Type type,flag WARN; Type type,flag WARN;
float angle WARN; float angle WARN;
//float passepartalpha, angle; //float passepartalpha, angle;
//float clipsta, clipend; //float clipsta, clipend;
//float lens, ortho_scale, drawsize; //float lens, ortho_scale, drawsize;
//float shiftx, shifty; //float shiftx, shifty;
//float YF_dofdist, YF_aperture; //float YF_dofdist, YF_aperture;
//short YF_bkhtype, YF_bkhbias; //short YF_bkhtype, YF_bkhbias;
//float YF_bkhrot; //float YF_bkhrot;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Lamp : ElemBase { struct Lamp : ElemBase {
enum FalloffType { enum FalloffType {
FalloffType_Constant = 0x0 FalloffType_Constant = 0x0
,FalloffType_InvLinear = 0x1 ,FalloffType_InvLinear = 0x1
,FalloffType_InvSquare = 0x2 ,FalloffType_InvSquare = 0x2
//,FalloffType_Curve = 0x3 //,FalloffType_Curve = 0x3
//,FalloffType_Sliders = 0x4 //,FalloffType_Sliders = 0x4
}; };
enum Type { enum Type {
Type_Local = 0x0 Type_Local = 0x0
,Type_Sun = 0x1 ,Type_Sun = 0x1
,Type_Spot = 0x2 ,Type_Spot = 0x2
,Type_Hemi = 0x3 ,Type_Hemi = 0x3
,Type_Area = 0x4 ,Type_Area = 0x4
//,Type_YFPhoton = 0x5 //,Type_YFPhoton = 0x5
}; };
ID id FAIL; ID id FAIL;
//AnimData *adt; //AnimData *adt;
Type type FAIL; Type type FAIL;
short flags; short flags;
//int mode; //int mode;
@ -374,33 +374,33 @@ struct Lamp : ElemBase {
//short ray_samp, ray_sampy, ray_sampz; //short ray_samp, ray_sampy, ray_sampz;
//short ray_samp_type; //short ray_samp_type;
//short area_shape; //short area_shape;
//float area_size, area_sizey, area_sizez; //float area_size, area_sizey, area_sizez;
//float adapt_thresh; //float adapt_thresh;
//short ray_samp_method; //short ray_samp_method;
//short texact, shadhalostep; //short texact, shadhalostep;
//short sun_effect_type; //short sun_effect_type;
//short skyblendtype; //short skyblendtype;
//float horizon_brightness; //float horizon_brightness;
//float spread; //float spread;
float sun_brightness; float sun_brightness;
//float sun_size; //float sun_size;
//float backscattered_light; //float backscattered_light;
//float sun_intensity; //float sun_intensity;
//float atm_turbidity; //float atm_turbidity;
//float atm_inscattering_factor; //float atm_inscattering_factor;
//float atm_extinction_factor; //float atm_extinction_factor;
//float atm_distance_factor; //float atm_distance_factor;
//float skyblendfac; //float skyblendfac;
//float sky_exposure; //float sky_exposure;
//short sky_colorspace; //short sky_colorspace;
// int YF_numphotons, YF_numsearch; // int YF_numphotons, YF_numsearch;
// short YF_phdepth, YF_useqmc, YF_bufsize, YF_pad; // short YF_phdepth, YF_useqmc, YF_bufsize, YF_pad;
// float YF_causticblur, YF_ltradius; // float YF_causticblur, YF_ltradius;
// float YF_glowint, YF_glowofs; // float YF_glowint, YF_glowofs;
// short YF_glowtype, YF_pad2; // short YF_glowtype, YF_pad2;
//struct Ipo *ipo; //struct Ipo *ipo;
@ -412,7 +412,7 @@ struct Lamp : ElemBase {
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct ModifierData : ElemBase { struct ModifierData : ElemBase {
enum ModifierType { enum ModifierType {
eModifierType_None = 0, eModifierType_None = 0,
eModifierType_Subsurf, eModifierType_Subsurf,
eModifierType_Lattice, eModifierType_Lattice,
@ -446,314 +446,314 @@ struct ModifierData : ElemBase {
eModifierType_Surface, eModifierType_Surface,
eModifierType_Smoke, eModifierType_Smoke,
eModifierType_ShapeKey eModifierType_ShapeKey
}; };
boost::shared_ptr<ElemBase> next WARN; boost::shared_ptr<ElemBase> next WARN;
boost::shared_ptr<ElemBase> prev WARN; boost::shared_ptr<ElemBase> prev WARN;
int type, mode; int type, mode;
char name[32]; char name[32];
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct SubsurfModifierData : ElemBase { struct SubsurfModifierData : ElemBase {
enum Type { enum Type {
TYPE_CatmullClarke = 0x0, TYPE_CatmullClarke = 0x0,
TYPE_Simple = 0x1 TYPE_Simple = 0x1
}; };
enum Flags { enum Flags {
// some omitted // some omitted
FLAGS_SubsurfUV =1<<3 FLAGS_SubsurfUV =1<<3
}; };
ModifierData modifier FAIL; ModifierData modifier FAIL;
short subdivType WARN; short subdivType WARN;
short levels FAIL; short levels FAIL;
short renderLevels ; short renderLevels ;
short flags; short flags;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MirrorModifierData : ElemBase { struct MirrorModifierData : ElemBase {
enum Flags { enum Flags {
Flags_CLIPPING =1<<0, Flags_CLIPPING =1<<0,
Flags_MIRROR_U =1<<1, Flags_MIRROR_U =1<<1,
Flags_MIRROR_V =1<<2, Flags_MIRROR_V =1<<2,
Flags_AXIS_X =1<<3, Flags_AXIS_X =1<<3,
Flags_AXIS_Y =1<<4, Flags_AXIS_Y =1<<4,
Flags_AXIS_Z =1<<5, Flags_AXIS_Z =1<<5,
Flags_VGROUP =1<<6 Flags_VGROUP =1<<6
}; };
ModifierData modifier FAIL; ModifierData modifier FAIL;
short axis, flag; short axis, flag;
float tolerance; float tolerance;
boost::shared_ptr<Object> mirror_ob; boost::shared_ptr<Object> mirror_ob;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Object : ElemBase { struct Object : ElemBase {
ID id FAIL; ID id FAIL;
enum Type { enum Type {
Type_EMPTY = 0 Type_EMPTY = 0
,Type_MESH = 1 ,Type_MESH = 1
,Type_CURVE = 2 ,Type_CURVE = 2
,Type_SURF = 3 ,Type_SURF = 3
,Type_FONT = 4 ,Type_FONT = 4
,Type_MBALL = 5 ,Type_MBALL = 5
,Type_LAMP = 10 ,Type_LAMP = 10
,Type_CAMERA = 11 ,Type_CAMERA = 11
,Type_WAVE = 21 ,Type_WAVE = 21
,Type_LATTICE = 22 ,Type_LATTICE = 22
}; };
Type type FAIL; Type type FAIL;
float obmat[4][4] WARN; float obmat[4][4] WARN;
float parentinv[4][4] WARN; float parentinv[4][4] WARN;
char parsubstr[32] WARN; char parsubstr[32] WARN;
Object* parent WARN; Object* parent WARN;
boost::shared_ptr<Object> track WARN; boost::shared_ptr<Object> track WARN;
boost::shared_ptr<Object> proxy,proxy_from,proxy_group WARN; boost::shared_ptr<Object> proxy,proxy_from,proxy_group WARN;
boost::shared_ptr<Group> dup_group WARN; boost::shared_ptr<Group> dup_group WARN;
boost::shared_ptr<ElemBase> data FAIL; boost::shared_ptr<ElemBase> data FAIL;
ListBase modifiers; ListBase modifiers;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Base : ElemBase { struct Base : ElemBase {
Base* prev WARN; Base* prev WARN;
boost::shared_ptr<Base> next WARN; boost::shared_ptr<Base> next WARN;
boost::shared_ptr<Object> object WARN; boost::shared_ptr<Object> object WARN;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Scene : ElemBase { struct Scene : ElemBase {
ID id FAIL; ID id FAIL;
boost::shared_ptr<Object> camera WARN; boost::shared_ptr<Object> camera WARN;
boost::shared_ptr<World> world WARN; boost::shared_ptr<World> world WARN;
boost::shared_ptr<Base> basact WARN; boost::shared_ptr<Base> basact WARN;
ListBase base; ListBase base;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Image : ElemBase { struct Image : ElemBase {
ID id FAIL; ID id FAIL;
char name[240] WARN; char name[240] WARN;
//struct anim *anim; //struct anim *anim;
short ok, flag; short ok, flag;
short source, type, pad, pad1; short source, type, pad, pad1;
int lastframe; int lastframe;
short tpageflag, totbind; short tpageflag, totbind;
short xrep, yrep; short xrep, yrep;
short twsta, twend; short twsta, twend;
//unsigned int bindcode; //unsigned int bindcode;
//unsigned int *repbind; //unsigned int *repbind;
boost::shared_ptr<PackedFile> packedfile; boost::shared_ptr<PackedFile> packedfile;
//struct PreviewImage * preview; //struct PreviewImage * preview;
float lastupdate; float lastupdate;
int lastused; int lastused;
short animspeed; short animspeed;
short gen_x, gen_y, gen_type; short gen_x, gen_y, gen_type;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Tex : ElemBase { struct Tex : ElemBase {
// actually, the only texture type we support is Type_IMAGE // actually, the only texture type we support is Type_IMAGE
enum Type { enum Type {
Type_CLOUDS = 1 Type_CLOUDS = 1
,Type_WOOD = 2 ,Type_WOOD = 2
,Type_MARBLE = 3 ,Type_MARBLE = 3
,Type_MAGIC = 4 ,Type_MAGIC = 4
,Type_BLEND = 5 ,Type_BLEND = 5
,Type_STUCCI = 6 ,Type_STUCCI = 6
,Type_NOISE = 7 ,Type_NOISE = 7
,Type_IMAGE = 8 ,Type_IMAGE = 8
,Type_PLUGIN = 9 ,Type_PLUGIN = 9
,Type_ENVMAP = 10 ,Type_ENVMAP = 10
,Type_MUSGRAVE = 11 ,Type_MUSGRAVE = 11
,Type_VORONOI = 12 ,Type_VORONOI = 12
,Type_DISTNOISE = 13 ,Type_DISTNOISE = 13
,Type_POINTDENSITY = 14 ,Type_POINTDENSITY = 14
,Type_VOXELDATA = 15 ,Type_VOXELDATA = 15
}; };
enum ImageFlags { enum ImageFlags {
ImageFlags_INTERPOL = 1 ImageFlags_INTERPOL = 1
,ImageFlags_USEALPHA = 2 ,ImageFlags_USEALPHA = 2
,ImageFlags_MIPMAP = 4 ,ImageFlags_MIPMAP = 4
,ImageFlags_IMAROT = 16 ,ImageFlags_IMAROT = 16
,ImageFlags_CALCALPHA = 32 ,ImageFlags_CALCALPHA = 32
,ImageFlags_NORMALMAP = 2048 ,ImageFlags_NORMALMAP = 2048
,ImageFlags_GAUSS_MIP = 4096 ,ImageFlags_GAUSS_MIP = 4096
,ImageFlags_FILTER_MIN = 8192 ,ImageFlags_FILTER_MIN = 8192
,ImageFlags_DERIVATIVEMAP = 16384 ,ImageFlags_DERIVATIVEMAP = 16384
}; };
ID id FAIL; ID id FAIL;
// AnimData *adt; // AnimData *adt;
//float noisesize, turbul; //float noisesize, turbul;
//float bright, contrast, rfac, gfac, bfac; //float bright, contrast, rfac, gfac, bfac;
//float filtersize; //float filtersize;
//float mg_H, mg_lacunarity, mg_octaves, mg_offset, mg_gain; //float mg_H, mg_lacunarity, mg_octaves, mg_offset, mg_gain;
//float dist_amount, ns_outscale; //float dist_amount, ns_outscale;
//float vn_w1; //float vn_w1;
//float vn_w2; //float vn_w2;
//float vn_w3; //float vn_w3;
//float vn_w4; //float vn_w4;
//float vn_mexp; //float vn_mexp;
//short vn_distm, vn_coltype; //short vn_distm, vn_coltype;
//short noisedepth, noisetype; //short noisedepth, noisetype;
//short noisebasis, noisebasis2; //short noisebasis, noisebasis2;
//short flag; //short flag;
ImageFlags imaflag; ImageFlags imaflag;
Type type FAIL; Type type FAIL;
//short stype; //short stype;
//float cropxmin, cropymin, cropxmax, cropymax; //float cropxmin, cropymin, cropxmax, cropymax;
//int texfilter; //int texfilter;
//int afmax; //int afmax;
//short xrepeat, yrepeat; //short xrepeat, yrepeat;
//short extend; //short extend;
//short fie_ima; //short fie_ima;
//int len; //int len;
//int frames, offset, sfra; //int frames, offset, sfra;
//float checkerdist, nabla; //float checkerdist, nabla;
//float norfac; //float norfac;
//ImageUser iuser; //ImageUser iuser;
//bNodeTree *nodetree; //bNodeTree *nodetree;
//Ipo *ipo; //Ipo *ipo;
boost::shared_ptr<Image> ima WARN; boost::shared_ptr<Image> ima WARN;
//PluginTex *plugin; //PluginTex *plugin;
//ColorBand *coba; //ColorBand *coba;
//EnvMap *env; //EnvMap *env;
//PreviewImage * preview; //PreviewImage * preview;
//PointDensity *pd; //PointDensity *pd;
//VoxelData *vd; //VoxelData *vd;
//char use_nodes; //char use_nodes;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MTex : ElemBase { struct MTex : ElemBase {
enum Projection { enum Projection {
Proj_N = 0 Proj_N = 0
,Proj_X = 1 ,Proj_X = 1
,Proj_Y = 2 ,Proj_Y = 2
,Proj_Z = 3 ,Proj_Z = 3
}; };
enum Flag { enum Flag {
Flag_RGBTOINT = 0x1 Flag_RGBTOINT = 0x1
,Flag_STENCIL = 0x2 ,Flag_STENCIL = 0x2
,Flag_NEGATIVE = 0x4 ,Flag_NEGATIVE = 0x4
,Flag_ALPHAMIX = 0x8 ,Flag_ALPHAMIX = 0x8
,Flag_VIEWSPACE = 0x10 ,Flag_VIEWSPACE = 0x10
}; };
enum BlendType { enum BlendType {
BlendType_BLEND = 0 BlendType_BLEND = 0
,BlendType_MUL = 1 ,BlendType_MUL = 1
,BlendType_ADD = 2 ,BlendType_ADD = 2
,BlendType_SUB = 3 ,BlendType_SUB = 3
,BlendType_DIV = 4 ,BlendType_DIV = 4
,BlendType_DARK = 5 ,BlendType_DARK = 5
,BlendType_DIFF = 6 ,BlendType_DIFF = 6
,BlendType_LIGHT = 7 ,BlendType_LIGHT = 7
,BlendType_SCREEN = 8 ,BlendType_SCREEN = 8
,BlendType_OVERLAY = 9 ,BlendType_OVERLAY = 9
,BlendType_BLEND_HUE = 10 ,BlendType_BLEND_HUE = 10
,BlendType_BLEND_SAT = 11 ,BlendType_BLEND_SAT = 11
,BlendType_BLEND_VAL = 12 ,BlendType_BLEND_VAL = 12
,BlendType_BLEND_COLOR = 13 ,BlendType_BLEND_COLOR = 13
}; };
enum MapType { enum MapType {
MapType_COL = 1 MapType_COL = 1
,MapType_NORM = 2 ,MapType_NORM = 2
,MapType_COLSPEC = 4 ,MapType_COLSPEC = 4
,MapType_COLMIR = 8 ,MapType_COLMIR = 8
,MapType_REF = 16 ,MapType_REF = 16
,MapType_SPEC = 32 ,MapType_SPEC = 32
,MapType_EMIT = 64 ,MapType_EMIT = 64
,MapType_ALPHA = 128 ,MapType_ALPHA = 128
,MapType_HAR = 256 ,MapType_HAR = 256
,MapType_RAYMIRR = 512 ,MapType_RAYMIRR = 512
,MapType_TRANSLU = 1024 ,MapType_TRANSLU = 1024
,MapType_AMB = 2048 ,MapType_AMB = 2048
,MapType_DISPLACE = 4096 ,MapType_DISPLACE = 4096
,MapType_WARP = 8192 ,MapType_WARP = 8192
}; };
// short texco, maptoneg; // short texco, maptoneg;
MapType mapto; MapType mapto;
BlendType blendtype; BlendType blendtype;
boost::shared_ptr<Object> object; boost::shared_ptr<Object> object;
boost::shared_ptr<Tex> tex; boost::shared_ptr<Tex> tex;
char uvname[32]; char uvname[32];
Projection projx,projy,projz; Projection projx,projy,projz;
char mapping; char mapping;
float ofs[3], size[3], rot; float ofs[3], size[3], rot;
int texflag; int texflag;
short colormodel, pmapto, pmaptoneg; short colormodel, pmapto, pmaptoneg;
//short normapspace, which_output; //short normapspace, which_output;
//char brush_map_mode; //char brush_map_mode;
float r,g,b,k WARN; float r,g,b,k WARN;
//float def_var, rt; //float def_var, rt;
//float colfac, varfac; //float colfac, varfac;
float norfac; float norfac;
//float dispfac, warpfac; //float dispfac, warpfac;
float colspecfac, mirrfac, alphafac; float colspecfac, mirrfac, alphafac;
float difffac, specfac, emitfac, hardfac; float difffac, specfac, emitfac, hardfac;
//float raymirrfac, translfac, ambfac; //float raymirrfac, translfac, ambfac;
//float colemitfac, colreflfac, coltransfac; //float colemitfac, colreflfac, coltransfac;
//float densfac, scatterfac, reflfac; //float densfac, scatterfac, reflfac;
//float timefac, lengthfac, clumpfac; //float timefac, lengthfac, clumpfac;
//float kinkfac, roughfac, padensfac; //float kinkfac, roughfac, padensfac;
//float lifefac, sizefac, ivelfac, pvelfac; //float lifefac, sizefac, ivelfac, pvelfac;
//float shadowfac; //float shadowfac;
//float zenupfac, zendownfac, blendfac; //float zenupfac, zendownfac, blendfac;
}; };
} }
} }
#endif #endif

View File

@ -47,8 +47,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderDNA.h" #include "BlenderDNA.h"
#include "BlenderScene.h" #include "BlenderScene.h"
namespace Assimp { namespace Assimp {
namespace Blender { namespace Blender {
template <> void Structure :: Convert<Object> ( template <> void Structure :: Convert<Object> (
@ -250,7 +250,7 @@ template <> void Structure :: Convert<Image> (
; ;
} }
} }
#endif #endif

View File

@ -56,7 +56,7 @@ static const unsigned int BLEND_TESS_MAGIC = 0x83ed9ac3;
namspace Assimp namspace Assimp
{ {
template< > const std::string LogFunctions< BlenderTessellatorGL >::log_prefix = "BLEND_TESS_GL: "; template< > const std::string LogFunctions< BlenderTessellatorGL >::log_prefix = "BLEND_TESS_GL: ";
} }
using namespace Assimp; using namespace Assimp;
@ -68,7 +68,7 @@ using namespace Assimp::Blender;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
BlenderTessellatorGL::BlenderTessellatorGL( BlenderBMeshConverter& converter ): BlenderTessellatorGL::BlenderTessellatorGL( BlenderBMeshConverter& converter ):
converter( &converter ) converter( &converter )
{ {
} }
@ -80,167 +80,167 @@ BlenderTessellatorGL::~BlenderTessellatorGL( )
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices ) void BlenderTessellatorGL::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
{ {
AssertVertexCount( vertexCount ); AssertVertexCount( vertexCount );
std::vector< VertexGL > polyLoopGL; std::vector< VertexGL > polyLoopGL;
GenerateLoopVerts( polyLoopGL, polyLoop, vertexCount, vertices ); GenerateLoopVerts( polyLoopGL, polyLoop, vertexCount, vertices );
TessDataGL tessData; TessDataGL tessData;
Tesssellate( polyLoopGL, tessData ); Tesssellate( polyLoopGL, tessData );
TriangulateDrawCalls( tessData ); TriangulateDrawCalls( tessData );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::AssertVertexCount( int vertexCount ) void BlenderTessellatorGL::AssertVertexCount( int vertexCount )
{ {
if ( vertexCount <= 4 ) if ( vertexCount <= 4 )
{ {
ThrowException( "Expected more than 4 vertices for tessellation" ); ThrowException( "Expected more than 4 vertices for tessellation" );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::GenerateLoopVerts( std::vector< VertexGL >& polyLoopGL, const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices ) void BlenderTessellatorGL::GenerateLoopVerts( std::vector< VertexGL >& polyLoopGL, const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
{ {
for ( int i = 0; i < vertexCount; ++i ) for ( int i = 0; i < vertexCount; ++i )
{ {
const MLoop& loopItem = polyLoop[ i ]; const MLoop& loopItem = polyLoop[ i ];
const MVert& vertex = vertices[ loopItem.v ]; const MVert& vertex = vertices[ loopItem.v ];
polyLoopGL.push_back( VertexGL( vertex.co[ 0 ], vertex.co[ 1 ], vertex.co[ 2 ], loopItem.v, BLEND_TESS_MAGIC ) ); polyLoopGL.push_back( VertexGL( vertex.co[ 0 ], vertex.co[ 1 ], vertex.co[ 2 ], loopItem.v, BLEND_TESS_MAGIC ) );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::Tesssellate( std::vector< VertexGL >& polyLoopGL, TessDataGL& tessData ) void BlenderTessellatorGL::Tesssellate( std::vector< VertexGL >& polyLoopGL, TessDataGL& tessData )
{ {
GLUtesselator* tessellator = gluNewTess( ); GLUtesselator* tessellator = gluNewTess( );
gluTessCallback( tessellator, GLU_TESS_BEGIN_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateBegin ) ); gluTessCallback( tessellator, GLU_TESS_BEGIN_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateBegin ) );
gluTessCallback( tessellator, GLU_TESS_END_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEnd ) ); gluTessCallback( tessellator, GLU_TESS_END_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEnd ) );
gluTessCallback( tessellator, GLU_TESS_VERTEX_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateVertex ) ); gluTessCallback( tessellator, GLU_TESS_VERTEX_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateVertex ) );
gluTessCallback( tessellator, GLU_TESS_COMBINE_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateCombine ) ); gluTessCallback( tessellator, GLU_TESS_COMBINE_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateCombine ) );
gluTessCallback( tessellator, GLU_TESS_EDGE_FLAG_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEdgeFlag ) ); gluTessCallback( tessellator, GLU_TESS_EDGE_FLAG_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEdgeFlag ) );
gluTessCallback( tessellator, GLU_TESS_ERROR_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateError ) ); gluTessCallback( tessellator, GLU_TESS_ERROR_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateError ) );
gluTessProperty( tessellator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO ); gluTessProperty( tessellator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO );
gluTessBeginPolygon( tessellator, &tessData ); gluTessBeginPolygon( tessellator, &tessData );
gluTessBeginContour( tessellator ); gluTessBeginContour( tessellator );
for ( unsigned int i = 0; i < polyLoopGL.size( ); ++i ) for ( unsigned int i = 0; i < polyLoopGL.size( ); ++i )
{ {
gluTessVertex( tessellator, reinterpret_cast< GLdouble* >( &polyLoopGL[ i ] ), &polyLoopGL[ i ] ); gluTessVertex( tessellator, reinterpret_cast< GLdouble* >( &polyLoopGL[ i ] ), &polyLoopGL[ i ] );
} }
gluTessEndContour( tessellator ); gluTessEndContour( tessellator );
gluTessEndPolygon( tessellator ); gluTessEndPolygon( tessellator );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TriangulateDrawCalls( const TessDataGL& tessData ) void BlenderTessellatorGL::TriangulateDrawCalls( const TessDataGL& tessData )
{ {
// NOTE - Because we are supplying a callback to GLU_TESS_EDGE_FLAG_DATA we don't technically // NOTE - Because we are supplying a callback to GLU_TESS_EDGE_FLAG_DATA we don't technically
// need support for GL_TRIANGLE_STRIP and GL_TRIANGLE_FAN but we'll keep it here in case // need support for GL_TRIANGLE_STRIP and GL_TRIANGLE_FAN but we'll keep it here in case
// GLU tessellate changes or tristrips and fans are wanted. // GLU tessellate changes or tristrips and fans are wanted.
// See: http://www.opengl.org/sdk/docs/man2/xhtml/gluTessCallback.xml // See: http://www.opengl.org/sdk/docs/man2/xhtml/gluTessCallback.xml
for ( unsigned int i = 0; i < tessData.drawCalls.size( ); ++i ) for ( unsigned int i = 0; i < tessData.drawCalls.size( ); ++i )
{ {
const DrawCallGL& drawCallGL = tessData.drawCalls[ i ]; const DrawCallGL& drawCallGL = tessData.drawCalls[ i ];
const VertexGL* vertices = &tessData.vertices[ drawCallGL.baseVertex ]; const VertexGL* vertices = &tessData.vertices[ drawCallGL.baseVertex ];
if ( drawCallGL.drawMode == GL_TRIANGLES ) if ( drawCallGL.drawMode == GL_TRIANGLES )
{ {
MakeFacesFromTris( vertices, drawCallGL.vertexCount ); MakeFacesFromTris( vertices, drawCallGL.vertexCount );
} }
else if ( drawCallGL.drawMode == GL_TRIANGLE_STRIP ) else if ( drawCallGL.drawMode == GL_TRIANGLE_STRIP )
{ {
MakeFacesFromTriStrip( vertices, drawCallGL.vertexCount ); MakeFacesFromTriStrip( vertices, drawCallGL.vertexCount );
} }
else if ( drawCallGL.drawMode == GL_TRIANGLE_FAN ) else if ( drawCallGL.drawMode == GL_TRIANGLE_FAN )
{ {
MakeFacesFromTriFan( vertices, drawCallGL.vertexCount ); MakeFacesFromTriFan( vertices, drawCallGL.vertexCount );
} }
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::MakeFacesFromTris( const VertexGL* vertices, int vertexCount ) void BlenderTessellatorGL::MakeFacesFromTris( const VertexGL* vertices, int vertexCount )
{ {
int triangleCount = vertexCount / 3; int triangleCount = vertexCount / 3;
for ( int i = 0; i < triangleCount; ++i ) for ( int i = 0; i < triangleCount; ++i )
{ {
int vertexBase = i * 3; int vertexBase = i * 3;
converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index ); converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::MakeFacesFromTriStrip( const VertexGL* vertices, int vertexCount ) void BlenderTessellatorGL::MakeFacesFromTriStrip( const VertexGL* vertices, int vertexCount )
{ {
int triangleCount = vertexCount - 2; int triangleCount = vertexCount - 2;
for ( int i = 0; i < triangleCount; ++i ) for ( int i = 0; i < triangleCount; ++i )
{ {
int vertexBase = i; int vertexBase = i;
converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index ); converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::MakeFacesFromTriFan( const VertexGL* vertices, int vertexCount ) void BlenderTessellatorGL::MakeFacesFromTriFan( const VertexGL* vertices, int vertexCount )
{ {
int triangleCount = vertexCount - 2; int triangleCount = vertexCount - 2;
for ( int i = 0; i < triangleCount; ++i ) for ( int i = 0; i < triangleCount; ++i )
{ {
int vertexBase = i; int vertexBase = i;
converter->AddFace( vertices[ 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index ); converter->AddFace( vertices[ 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TessellateBegin( GLenum drawModeGL, void* userData ) void BlenderTessellatorGL::TessellateBegin( GLenum drawModeGL, void* userData )
{ {
TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData ); TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData );
tessData.drawCalls.push_back( DrawCallGL( drawModeGL, tessData.vertices.size( ) ) ); tessData.drawCalls.push_back( DrawCallGL( drawModeGL, tessData.vertices.size( ) ) );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TessellateEnd( void* ) void BlenderTessellatorGL::TessellateEnd( void* )
{ {
// Do nothing // Do nothing
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TessellateVertex( const void* vtxData, void* userData ) void BlenderTessellatorGL::TessellateVertex( const void* vtxData, void* userData )
{ {
TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData ); TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData );
const VertexGL& vertex = *reinterpret_cast< const VertexGL* >( vtxData ); const VertexGL& vertex = *reinterpret_cast< const VertexGL* >( vtxData );
if ( vertex.magic != BLEND_TESS_MAGIC ) if ( vertex.magic != BLEND_TESS_MAGIC )
{ {
ThrowException( "Point returned by GLU Tessellate was probably not one of ours. This indicates we need a new way to store vertex information" ); ThrowException( "Point returned by GLU Tessellate was probably not one of ours. This indicates we need a new way to store vertex information" );
} }
tessData.vertices.push_back( vertex ); tessData.vertices.push_back( vertex );
if ( tessData.drawCalls.size( ) == 0 ) if ( tessData.drawCalls.size( ) == 0 )
{ {
ThrowException( "\"Vertex\" callback received before \"Begin\"" ); ThrowException( "\"Vertex\" callback received before \"Begin\"" );
} }
++( tessData.drawCalls.back( ).vertexCount ); ++( tessData.drawCalls.back( ).vertexCount );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TessellateCombine( const GLdouble intersection[ 3 ], const GLdouble* [ 4 ], const GLfloat [ 4 ], GLdouble** out, void* userData ) void BlenderTessellatorGL::TessellateCombine( const GLdouble intersection[ 3 ], const GLdouble* [ 4 ], const GLfloat [ 4 ], GLdouble** out, void* userData )
{ {
ThrowException( "Intersected polygon loops are not yet supported" ); ThrowException( "Intersected polygon loops are not yet supported" );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TessellateEdgeFlag( GLboolean, void* ) void BlenderTessellatorGL::TessellateEdgeFlag( GLboolean, void* )
{ {
// Do nothing // Do nothing
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TessellateError( GLenum errorCode, void* ) void BlenderTessellatorGL::TessellateError( GLenum errorCode, void* )
{ {
ThrowException( reinterpret_cast< const char* >( gluErrorString( errorCode ) ) ); ThrowException( reinterpret_cast< const char* >( gluErrorString( errorCode ) ) );
} }
#endif // ASSIMP_BLEND_WITH_GLU_TESSELLATE #endif // ASSIMP_BLEND_WITH_GLU_TESSELLATE
@ -249,7 +249,7 @@ void BlenderTessellatorGL::TessellateError( GLenum errorCode, void* )
namespace Assimp namespace Assimp
{ {
template< > const std::string LogFunctions< BlenderTessellatorP2T >::log_prefix = "BLEND_TESS_P2T: "; template< > const std::string LogFunctions< BlenderTessellatorP2T >::log_prefix = "BLEND_TESS_P2T: ";
} }
using namespace Assimp; using namespace Assimp;
@ -257,7 +257,7 @@ using namespace Assimp::Blender;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
BlenderTessellatorP2T::BlenderTessellatorP2T( BlenderBMeshConverter& converter ): BlenderTessellatorP2T::BlenderTessellatorP2T( BlenderBMeshConverter& converter ):
converter( &converter ) converter( &converter )
{ {
} }
@ -269,178 +269,178 @@ BlenderTessellatorP2T::~BlenderTessellatorP2T( )
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices ) void BlenderTessellatorP2T::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
{ {
AssertVertexCount( vertexCount ); AssertVertexCount( vertexCount );
// NOTE - We have to hope that points in a Blender polygon are roughly on the same plane. // NOTE - We have to hope that points in a Blender polygon are roughly on the same plane.
// There may be some triangulation artifacts if they are wildly different. // There may be some triangulation artifacts if they are wildly different.
std::vector< PointP2T > points; std::vector< PointP2T > points;
Copy3DVertices( polyLoop, vertexCount, vertices, points ); Copy3DVertices( polyLoop, vertexCount, vertices, points );
PlaneP2T plane = FindLLSQPlane( points ); PlaneP2T plane = FindLLSQPlane( points );
aiMatrix4x4 transform = GeneratePointTransformMatrix( plane ); aiMatrix4x4 transform = GeneratePointTransformMatrix( plane );
TransformAndFlattenVectices( transform, points ); TransformAndFlattenVectices( transform, points );
std::vector< p2t::Point* > pointRefs; std::vector< p2t::Point* > pointRefs;
ReferencePoints( points, pointRefs ); ReferencePoints( points, pointRefs );
p2t::CDT cdt( pointRefs ); p2t::CDT cdt( pointRefs );
cdt.Triangulate( ); cdt.Triangulate( );
std::vector< p2t::Triangle* > triangles = cdt.GetTriangles( ); std::vector< p2t::Triangle* > triangles = cdt.GetTriangles( );
MakeFacesFromTriangles( triangles ); MakeFacesFromTriangles( triangles );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::AssertVertexCount( int vertexCount ) void BlenderTessellatorP2T::AssertVertexCount( int vertexCount )
{ {
if ( vertexCount <= 4 ) if ( vertexCount <= 4 )
{ {
ThrowException( "Expected more than 4 vertices for tessellation" ); ThrowException( "Expected more than 4 vertices for tessellation" );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::Copy3DVertices( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices, std::vector< PointP2T >& points ) const void BlenderTessellatorP2T::Copy3DVertices( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices, std::vector< PointP2T >& points ) const
{ {
points.resize( vertexCount ); points.resize( vertexCount );
for ( int i = 0; i < vertexCount; ++i ) for ( int i = 0; i < vertexCount; ++i )
{ {
const MLoop& loop = polyLoop[ i ]; const MLoop& loop = polyLoop[ i ];
const MVert& vert = vertices[ loop.v ]; const MVert& vert = vertices[ loop.v ];
PointP2T& point = points[ i ]; PointP2T& point = points[ i ];
point.point3D.Set( vert.co[ 0 ], vert.co[ 1 ], vert.co[ 2 ] ); point.point3D.Set( vert.co[ 0 ], vert.co[ 1 ], vert.co[ 2 ] );
point.index = loop.v; point.index = loop.v;
point.magic = BLEND_TESS_MAGIC; point.magic = BLEND_TESS_MAGIC;
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiMatrix4x4 BlenderTessellatorP2T::GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const aiMatrix4x4 BlenderTessellatorP2T::GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const
{ {
aiVector3D sideA( 1.0f, 0.0f, 0.0f ); aiVector3D sideA( 1.0f, 0.0f, 0.0f );
if ( std::fabs( plane.normal * sideA ) > 0.999f ) if ( std::fabs( plane.normal * sideA ) > 0.999f )
{ {
sideA = aiVector3D( 0.0f, 1.0f, 0.0f ); sideA = aiVector3D( 0.0f, 1.0f, 0.0f );
} }
aiVector3D sideB( plane.normal ^ sideA ); aiVector3D sideB( plane.normal ^ sideA );
sideB.Normalize( ); sideB.Normalize( );
sideA = sideB ^ plane.normal; sideA = sideB ^ plane.normal;
aiMatrix4x4 result; aiMatrix4x4 result;
result.a1 = sideA.x; result.a1 = sideA.x;
result.a2 = sideA.y; result.a2 = sideA.y;
result.a3 = sideA.z; result.a3 = sideA.z;
result.b1 = sideB.x; result.b1 = sideB.x;
result.b2 = sideB.y; result.b2 = sideB.y;
result.b3 = sideB.z; result.b3 = sideB.z;
result.c1 = plane.normal.x; result.c1 = plane.normal.x;
result.c2 = plane.normal.y; result.c2 = plane.normal.y;
result.c3 = plane.normal.z; result.c3 = plane.normal.z;
result.a4 = plane.centre.x; result.a4 = plane.centre.x;
result.b4 = plane.centre.y; result.b4 = plane.centre.y;
result.c4 = plane.centre.z; result.c4 = plane.centre.z;
result.Inverse( ); result.Inverse( );
return result; return result;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const void BlenderTessellatorP2T::TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const
{ {
for ( unsigned int i = 0; i < vertices.size( ); ++i ) for ( unsigned int i = 0; i < vertices.size( ); ++i )
{ {
PointP2T& point = vertices[ i ]; PointP2T& point = vertices[ i ];
point.point3D = transform * point.point3D; point.point3D = transform * point.point3D;
point.point2D.set( point.point3D.y, point.point3D.z ); point.point2D.set( point.point3D.y, point.point3D.z );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const void BlenderTessellatorP2T::ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const
{ {
pointRefs.resize( points.size( ) ); pointRefs.resize( points.size( ) );
for ( unsigned int i = 0; i < points.size( ); ++i ) for ( unsigned int i = 0; i < points.size( ); ++i )
{ {
pointRefs[ i ] = &points[ i ].point2D; pointRefs[ i ] = &points[ i ].point2D;
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Yes this is filthy... but we have no choice // Yes this is filthy... but we have no choice
#define OffsetOf( Class, Member ) ( static_cast< unsigned int >( \ #define OffsetOf( Class, Member ) ( static_cast< unsigned int >( \
reinterpret_cast<uint8_t*>(&( reinterpret_cast< Class* >( NULL )->*( &Class::Member ) )) - \ reinterpret_cast<uint8_t*>(&( reinterpret_cast< Class* >( NULL )->*( &Class::Member ) )) - \
static_cast<uint8_t*>(NULL) ) ) static_cast<uint8_t*>(NULL) ) )
inline PointP2T& BlenderTessellatorP2T::GetActualPointStructure( p2t::Point& point ) const inline PointP2T& BlenderTessellatorP2T::GetActualPointStructure( p2t::Point& point ) const
{ {
unsigned int pointOffset = OffsetOf( PointP2T, point2D ); unsigned int pointOffset = OffsetOf( PointP2T, point2D );
PointP2T& pointStruct = *reinterpret_cast< PointP2T* >( reinterpret_cast< char* >( &point ) - pointOffset ); PointP2T& pointStruct = *reinterpret_cast< PointP2T* >( reinterpret_cast< char* >( &point ) - pointOffset );
if ( pointStruct.magic != static_cast<int>( BLEND_TESS_MAGIC ) ) if ( pointStruct.magic != static_cast<int>( BLEND_TESS_MAGIC ) )
{ {
ThrowException( "Point returned by poly2tri was probably not one of ours. This indicates we need a new way to store vertex information" ); ThrowException( "Point returned by poly2tri was probably not one of ours. This indicates we need a new way to store vertex information" );
} }
return pointStruct; return pointStruct;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const void BlenderTessellatorP2T::MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const
{ {
for ( unsigned int i = 0; i < triangles.size( ); ++i ) for ( unsigned int i = 0; i < triangles.size( ); ++i )
{ {
p2t::Triangle& Triangle = *triangles[ i ]; p2t::Triangle& Triangle = *triangles[ i ];
PointP2T& pointA = GetActualPointStructure( *Triangle.GetPoint( 0 ) ); PointP2T& pointA = GetActualPointStructure( *Triangle.GetPoint( 0 ) );
PointP2T& pointB = GetActualPointStructure( *Triangle.GetPoint( 1 ) ); PointP2T& pointB = GetActualPointStructure( *Triangle.GetPoint( 1 ) );
PointP2T& pointC = GetActualPointStructure( *Triangle.GetPoint( 2 ) ); PointP2T& pointC = GetActualPointStructure( *Triangle.GetPoint( 2 ) );
converter->AddFace( pointA.index, pointB.index, pointC.index ); converter->AddFace( pointA.index, pointB.index, pointC.index );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
inline float p2tMax( float a, float b ) inline float p2tMax( float a, float b )
{ {
return a > b ? a : b; return a > b ? a : b;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html // Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
float BlenderTessellatorP2T::FindLargestMatrixElem( const aiMatrix3x3& mtx ) const float BlenderTessellatorP2T::FindLargestMatrixElem( const aiMatrix3x3& mtx ) const
{ {
float result = 0.0f; float result = 0.0f;
for ( int x = 0; x < 3; ++x ) for ( int x = 0; x < 3; ++x )
{ {
for ( int y = 0; y < 3; ++y ) for ( int y = 0; y < 3; ++y )
{ {
result = p2tMax( std::fabs( mtx[ x ][ y ] ), result ); result = p2tMax( std::fabs( mtx[ x ][ y ] ), result );
} }
} }
return result; return result;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Aparently Assimp doesn't have matrix scaling // Aparently Assimp doesn't have matrix scaling
aiMatrix3x3 BlenderTessellatorP2T::ScaleMatrix( const aiMatrix3x3& mtx, float scale ) const aiMatrix3x3 BlenderTessellatorP2T::ScaleMatrix( const aiMatrix3x3& mtx, float scale ) const
{ {
aiMatrix3x3 result; aiMatrix3x3 result;
for ( int x = 0; x < 3; ++x ) for ( int x = 0; x < 3; ++x )
{ {
for ( int y = 0; y < 3; ++y ) for ( int y = 0; y < 3; ++y )
{ {
result[ x ][ y ] = mtx[ x ][ y ] * scale; result[ x ][ y ] = mtx[ x ][ y ] * scale;
} }
} }
return result; return result;
} }
@ -448,70 +448,70 @@ aiMatrix3x3 BlenderTessellatorP2T::ScaleMatrix( const aiMatrix3x3& mtx, float sc
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html // Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
aiVector3D BlenderTessellatorP2T::GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const aiVector3D BlenderTessellatorP2T::GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const
{ {
float scale = FindLargestMatrixElem( mtx ); float scale = FindLargestMatrixElem( mtx );
aiMatrix3x3 mc = ScaleMatrix( mtx, 1.0f / scale ); aiMatrix3x3 mc = ScaleMatrix( mtx, 1.0f / scale );
mc = mc * mc * mc; mc = mc * mc * mc;
aiVector3D v( 1.0f ); aiVector3D v( 1.0f );
aiVector3D lastV = v; aiVector3D lastV = v;
for ( int i = 0; i < 100; ++i ) for ( int i = 0; i < 100; ++i )
{ {
v = mc * v; v = mc * v;
v.Normalize( ); v.Normalize( );
if ( ( v - lastV ).SquareLength( ) < 1e-16f ) if ( ( v - lastV ).SquareLength( ) < 1e-16f )
{ {
break; break;
} }
lastV = v; lastV = v;
} }
return v; return v;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html // Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
PlaneP2T BlenderTessellatorP2T::FindLLSQPlane( const std::vector< PointP2T >& points ) const PlaneP2T BlenderTessellatorP2T::FindLLSQPlane( const std::vector< PointP2T >& points ) const
{ {
PlaneP2T result; PlaneP2T result;
aiVector3D sum( 0.0f ); aiVector3D sum( 0.0f );
for ( unsigned int i = 0; i < points.size( ); ++i ) for ( unsigned int i = 0; i < points.size( ); ++i )
{ {
sum += points[ i ].point3D; sum += points[ i ].point3D;
} }
result.centre = sum * ( 1.0f / points.size( ) ); result.centre = sum * ( 1.0f / points.size( ) );
float sumXX = 0.0f; float sumXX = 0.0f;
float sumXY = 0.0f; float sumXY = 0.0f;
float sumXZ = 0.0f; float sumXZ = 0.0f;
float sumYY = 0.0f; float sumYY = 0.0f;
float sumYZ = 0.0f; float sumYZ = 0.0f;
float sumZZ = 0.0f; float sumZZ = 0.0f;
for ( unsigned int i = 0; i < points.size( ); ++i ) for ( unsigned int i = 0; i < points.size( ); ++i )
{ {
aiVector3D offset = points[ i ].point3D - result.centre; aiVector3D offset = points[ i ].point3D - result.centre;
sumXX += offset.x * offset.x; sumXX += offset.x * offset.x;
sumXY += offset.x * offset.y; sumXY += offset.x * offset.y;
sumXZ += offset.x * offset.z; sumXZ += offset.x * offset.z;
sumYY += offset.y * offset.y; sumYY += offset.y * offset.y;
sumYZ += offset.y * offset.z; sumYZ += offset.y * offset.z;
sumZZ += offset.z * offset.z; sumZZ += offset.z * offset.z;
} }
aiMatrix3x3 mtx( sumXX, sumXY, sumXZ, sumXY, sumYY, sumYZ, sumXZ, sumYZ, sumZZ ); aiMatrix3x3 mtx( sumXX, sumXY, sumXZ, sumXY, sumYY, sumYZ, sumXZ, sumYZ, sumZZ );
float det = mtx.Determinant( ); float det = mtx.Determinant( );
if ( det == 0.0f ) if ( det == 0.0f )
{ {
result.normal = aiVector3D( 0.0f ); result.normal = aiVector3D( 0.0f );
} }
else else
{ {
aiMatrix3x3 invMtx = mtx; aiMatrix3x3 invMtx = mtx;
invMtx.Inverse( ); invMtx.Inverse( );
result.normal = GetEigenVectorFromLargestEigenValue( invMtx ); result.normal = GetEigenVectorFromLargestEigenValue( invMtx );
} }
return result; return result;
} }
#endif // ASSIMP_BLEND_WITH_POLY_2_TRI #endif // ASSIMP_BLEND_WITH_POLY_2_TRI

View File

@ -50,11 +50,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// made configurable in CMake and potentially not wanted by most users // made configurable in CMake and potentially not wanted by most users
// as it requires a Gl environment. // as it requires a Gl environment.
#ifndef ASSIMP_BLEND_WITH_GLU_TESSELLATE #ifndef ASSIMP_BLEND_WITH_GLU_TESSELLATE
# define ASSIMP_BLEND_WITH_GLU_TESSELLATE 0 # define ASSIMP_BLEND_WITH_GLU_TESSELLATE 0
#endif #endif
#ifndef ASSIMP_BLEND_WITH_POLY_2_TRI #ifndef ASSIMP_BLEND_WITH_POLY_2_TRI
# define ASSIMP_BLEND_WITH_POLY_2_TRI 1 # define ASSIMP_BLEND_WITH_POLY_2_TRI 1
#endif #endif
#include "LogAux.h" #include "LogAux.h"
@ -68,74 +68,74 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp namespace Assimp
{ {
class BlenderBMeshConverter; class BlenderBMeshConverter;
// TinyFormatter.h // TinyFormatter.h
namespace Formatter namespace Formatter
{ {
template < typename T,typename TR, typename A > class basic_formatter; template < typename T,typename TR, typename A > class basic_formatter;
typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format; typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format;
} }
// BlenderScene.h // BlenderScene.h
namespace Blender namespace Blender
{ {
struct MLoop; struct MLoop;
struct MVert; struct MVert;
struct VertexGL struct VertexGL
{ {
GLdouble X; GLdouble X;
GLdouble Y; GLdouble Y;
GLdouble Z; GLdouble Z;
int index; int index;
int magic; int magic;
VertexGL( GLdouble X, GLdouble Y, GLdouble Z, int index, int magic ): X( X ), Y( Y ), Z( Z ), index( index ), magic( magic ) { } VertexGL( GLdouble X, GLdouble Y, GLdouble Z, int index, int magic ): X( X ), Y( Y ), Z( Z ), index( index ), magic( magic ) { }
}; };
struct DrawCallGL struct DrawCallGL
{ {
GLenum drawMode; GLenum drawMode;
int baseVertex; int baseVertex;
int vertexCount; int vertexCount;
DrawCallGL( GLenum drawMode, int baseVertex ): drawMode( drawMode ), baseVertex( baseVertex ), vertexCount( 0 ) { } DrawCallGL( GLenum drawMode, int baseVertex ): drawMode( drawMode ), baseVertex( baseVertex ), vertexCount( 0 ) { }
}; };
struct TessDataGL struct TessDataGL
{ {
std::vector< DrawCallGL > drawCalls; std::vector< DrawCallGL > drawCalls;
std::vector< VertexGL > vertices; std::vector< VertexGL > vertices;
}; };
} }
class BlenderTessellatorGL: public LogFunctions< BlenderTessellatorGL > class BlenderTessellatorGL: public LogFunctions< BlenderTessellatorGL >
{ {
public: public:
BlenderTessellatorGL( BlenderBMeshConverter& converter ); BlenderTessellatorGL( BlenderBMeshConverter& converter );
~BlenderTessellatorGL( ); ~BlenderTessellatorGL( );
void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices ); void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
private: private:
void AssertVertexCount( int vertexCount ); void AssertVertexCount( int vertexCount );
void GenerateLoopVerts( std::vector< Blender::VertexGL >& polyLoopGL, const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices ); void GenerateLoopVerts( std::vector< Blender::VertexGL >& polyLoopGL, const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
void Tesssellate( std::vector< Blender::VertexGL >& polyLoopGL, Blender::TessDataGL& tessData ); void Tesssellate( std::vector< Blender::VertexGL >& polyLoopGL, Blender::TessDataGL& tessData );
void TriangulateDrawCalls( const Blender::TessDataGL& tessData ); void TriangulateDrawCalls( const Blender::TessDataGL& tessData );
void MakeFacesFromTris( const Blender::VertexGL* vertices, int vertexCount ); void MakeFacesFromTris( const Blender::VertexGL* vertices, int vertexCount );
void MakeFacesFromTriStrip( const Blender::VertexGL* vertices, int vertexCount ); void MakeFacesFromTriStrip( const Blender::VertexGL* vertices, int vertexCount );
void MakeFacesFromTriFan( const Blender::VertexGL* vertices, int vertexCount ); void MakeFacesFromTriFan( const Blender::VertexGL* vertices, int vertexCount );
static void TessellateBegin( GLenum drawModeGL, void* userData ); static void TessellateBegin( GLenum drawModeGL, void* userData );
static void TessellateEnd( void* userData ); static void TessellateEnd( void* userData );
static void TessellateVertex( const void* vtxData, void* userData ); static void TessellateVertex( const void* vtxData, void* userData );
static void TessellateCombine( const GLdouble intersection[ 3 ], const GLdouble* [ 4 ], const GLfloat [ 4 ], GLdouble** out, void* userData ); static void TessellateCombine( const GLdouble intersection[ 3 ], const GLdouble* [ 4 ], const GLfloat [ 4 ], GLdouble** out, void* userData );
static void TessellateEdgeFlag( GLboolean edgeFlag, void* userData ); static void TessellateEdgeFlag( GLboolean edgeFlag, void* userData );
static void TessellateError( GLenum errorCode, void* userData ); static void TessellateError( GLenum errorCode, void* userData );
BlenderBMeshConverter* converter; BlenderBMeshConverter* converter;
}; };
} // end of namespace Assimp } // end of namespace Assimp
#endif // ASSIMP_BLEND_WITH_GLU_TESSELLATE #endif // ASSIMP_BLEND_WITH_GLU_TESSELLATE
@ -146,61 +146,61 @@ namespace Assimp
namespace Assimp namespace Assimp
{ {
class BlenderBMeshConverter; class BlenderBMeshConverter;
// TinyFormatter.h // TinyFormatter.h
namespace Formatter namespace Formatter
{ {
template < typename T,typename TR, typename A > class basic_formatter; template < typename T,typename TR, typename A > class basic_formatter;
typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format; typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format;
} }
// BlenderScene.h // BlenderScene.h
namespace Blender namespace Blender
{ {
struct MLoop; struct MLoop;
struct MVert; struct MVert;
struct PointP2T struct PointP2T
{ {
aiVector3D point3D; aiVector3D point3D;
p2t::Point point2D; p2t::Point point2D;
int magic; int magic;
int index; int index;
}; };
struct PlaneP2T struct PlaneP2T
{ {
aiVector3D centre; aiVector3D centre;
aiVector3D normal; aiVector3D normal;
}; };
} }
class BlenderTessellatorP2T: public LogFunctions< BlenderTessellatorP2T > class BlenderTessellatorP2T: public LogFunctions< BlenderTessellatorP2T >
{ {
public: public:
BlenderTessellatorP2T( BlenderBMeshConverter& converter ); BlenderTessellatorP2T( BlenderBMeshConverter& converter );
~BlenderTessellatorP2T( ); ~BlenderTessellatorP2T( );
void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices ); void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
private: private:
void AssertVertexCount( int vertexCount ); void AssertVertexCount( int vertexCount );
void Copy3DVertices( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices, std::vector< Blender::PointP2T >& targetVertices ) const; void Copy3DVertices( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices, std::vector< Blender::PointP2T >& targetVertices ) const;
aiMatrix4x4 GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const; aiMatrix4x4 GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const;
void TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const; void TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const;
void ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const; void ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const;
inline Blender::PointP2T& GetActualPointStructure( p2t::Point& point ) const; inline Blender::PointP2T& GetActualPointStructure( p2t::Point& point ) const;
void MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const; void MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const;
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html // Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
float FindLargestMatrixElem( const aiMatrix3x3& mtx ) const; float FindLargestMatrixElem( const aiMatrix3x3& mtx ) const;
aiMatrix3x3 ScaleMatrix( const aiMatrix3x3& mtx, float scale ) const; aiMatrix3x3 ScaleMatrix( const aiMatrix3x3& mtx, float scale ) const;
aiVector3D GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const; aiVector3D GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const;
Blender::PlaneP2T FindLLSQPlane( const std::vector< Blender::PointP2T >& points ) const; Blender::PlaneP2T FindLLSQPlane( const std::vector< Blender::PointP2T >& points ) const;
BlenderBMeshConverter* converter; BlenderBMeshConverter* converter;
}; };
} // end of namespace Assimp } // end of namespace Assimp
#endif // ASSIMP_BLEND_WITH_POLY_2_TRI #endif // ASSIMP_BLEND_WITH_POLY_2_TRI

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
@ -54,8 +54,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <set> #include <set>
#include <vector> #include <vector>
namespace Assimp { namespace Assimp {
class BlobIOSystem; class BlobIOSystem;
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
/** Redirect IOStream to a blob */ /** Redirect IOStream to a blob */
@ -64,144 +64,144 @@ class BlobIOStream : public IOStream
{ {
public: public:
BlobIOStream(BlobIOSystem* creator, const std::string& file, size_t initial = 4096) BlobIOStream(BlobIOSystem* creator, const std::string& file, size_t initial = 4096)
: buffer() : buffer()
, cur_size() , cur_size()
, file_size() , file_size()
, cursor() , cursor()
, initial(initial) , initial(initial)
, file(file) , file(file)
, creator(creator) , creator(creator)
{ {
} }
virtual ~BlobIOStream(); virtual ~BlobIOStream();
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
aiExportDataBlob* GetBlob() aiExportDataBlob* GetBlob()
{ {
aiExportDataBlob* blob = new aiExportDataBlob(); aiExportDataBlob* blob = new aiExportDataBlob();
blob->size = file_size; blob->size = file_size;
blob->data = buffer; blob->data = buffer;
buffer = NULL; buffer = NULL;
return blob; return blob;
} }
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
virtual size_t Read( void *, virtual size_t Read( void *,
size_t, size_t,
size_t ) size_t )
{ {
return 0; return 0;
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
virtual size_t Write(const void* pvBuffer, virtual size_t Write(const void* pvBuffer,
size_t pSize, size_t pSize,
size_t pCount) size_t pCount)
{ {
pSize *= pCount; pSize *= pCount;
if (cursor + pSize > cur_size) { if (cursor + pSize > cur_size) {
Grow(cursor + pSize); Grow(cursor + pSize);
} }
memcpy(buffer+cursor, pvBuffer, pSize); memcpy(buffer+cursor, pvBuffer, pSize);
cursor += pSize; cursor += pSize;
file_size = std::max(file_size,cursor); file_size = std::max(file_size,cursor);
return pCount; return pCount;
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
virtual aiReturn Seek(size_t pOffset, virtual aiReturn Seek(size_t pOffset,
aiOrigin pOrigin) aiOrigin pOrigin)
{ {
switch(pOrigin) switch(pOrigin)
{ {
case aiOrigin_CUR: case aiOrigin_CUR:
cursor += pOffset; cursor += pOffset;
break; break;
case aiOrigin_END: case aiOrigin_END:
cursor = file_size - pOffset; cursor = file_size - pOffset;
break; break;
case aiOrigin_SET: case aiOrigin_SET:
cursor = pOffset; cursor = pOffset;
break; break;
default: default:
return AI_FAILURE; return AI_FAILURE;
} }
if (cursor > file_size) { if (cursor > file_size) {
Grow(cursor); Grow(cursor);
} }
file_size = std::max(cursor,file_size); file_size = std::max(cursor,file_size);
return AI_SUCCESS; return AI_SUCCESS;
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
virtual size_t Tell() const virtual size_t Tell() const
{ {
return cursor; return cursor;
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
virtual size_t FileSize() const virtual size_t FileSize() const
{ {
return file_size; return file_size;
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
virtual void Flush() virtual void Flush()
{ {
// ignore // ignore
} }
private: private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
void Grow(size_t need = 0) void Grow(size_t need = 0)
{ {
// 1.5 and phi are very heap-friendly growth factors (the first // 1.5 and phi are very heap-friendly growth factors (the first
// allows for frequent re-use of heap blocks, the second // allows for frequent re-use of heap blocks, the second
// forms a fibonacci sequence with similar characteristics - // forms a fibonacci sequence with similar characteristics -
// since this heavily depends on the heap implementation // since this heavily depends on the heap implementation
// and other factors as well, i'll just go with 1.5 since // and other factors as well, i'll just go with 1.5 since
// it is quicker to compute). // it is quicker to compute).
size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) )); size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) ));
const uint8_t* const old = buffer; const uint8_t* const old = buffer;
buffer = new uint8_t[new_size]; buffer = new uint8_t[new_size];
if (old) { if (old) {
memcpy(buffer,old,cur_size); memcpy(buffer,old,cur_size);
delete[] old; delete[] old;
} }
cur_size = new_size; cur_size = new_size;
} }
private: private:
uint8_t* buffer; uint8_t* buffer;
size_t cur_size,file_size, cursor, initial; size_t cur_size,file_size, cursor, initial;
const std::string file; const std::string file;
BlobIOSystem* const creator; BlobIOSystem* const creator;
}; };
@ -213,122 +213,122 @@ private:
class BlobIOSystem : public IOSystem class BlobIOSystem : public IOSystem
{ {
friend class BlobIOStream; friend class BlobIOStream;
typedef std::pair<std::string, aiExportDataBlob*> BlobEntry; typedef std::pair<std::string, aiExportDataBlob*> BlobEntry;
public: public:
BlobIOSystem() BlobIOSystem()
{ {
} }
virtual ~BlobIOSystem() virtual ~BlobIOSystem()
{ {
BOOST_FOREACH(BlobEntry& blobby, blobs) { BOOST_FOREACH(BlobEntry& blobby, blobs) {
delete blobby.second; delete blobby.second;
} }
} }
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
const char* GetMagicFileName() const const char* GetMagicFileName() const
{ {
return AI_BLOBIO_MAGIC; return AI_BLOBIO_MAGIC;
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
aiExportDataBlob* GetBlobChain() aiExportDataBlob* GetBlobChain()
{ {
// one must be the master // one must be the master
aiExportDataBlob* master = NULL, *cur; aiExportDataBlob* master = NULL, *cur;
BOOST_FOREACH(const BlobEntry& blobby, blobs) { BOOST_FOREACH(const BlobEntry& blobby, blobs) {
if (blobby.first == AI_BLOBIO_MAGIC) { if (blobby.first == AI_BLOBIO_MAGIC) {
master = blobby.second; master = blobby.second;
break; break;
} }
} }
if (!master) { if (!master) {
DefaultLogger::get()->error("BlobIOSystem: no data written or master file was not closed properly."); DefaultLogger::get()->error("BlobIOSystem: no data written or master file was not closed properly.");
return NULL; return NULL;
} }
master->name.Set(""); master->name.Set("");
cur = master; cur = master;
BOOST_FOREACH(const BlobEntry& blobby, blobs) { BOOST_FOREACH(const BlobEntry& blobby, blobs) {
if (blobby.second == master) { if (blobby.second == master) {
continue; continue;
} }
cur->next = blobby.second; cur->next = blobby.second;
cur = cur->next; cur = cur->next;
// extract the file extension from the file written // extract the file extension from the file written
const std::string::size_type s = blobby.first.find_first_of('.'); const std::string::size_type s = blobby.first.find_first_of('.');
cur->name.Set(s == std::string::npos ? blobby.first : blobby.first.substr(s+1)); cur->name.Set(s == std::string::npos ? blobby.first : blobby.first.substr(s+1));
} }
// give up blob ownership // give up blob ownership
blobs.clear(); blobs.clear();
return master; return master;
} }
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
virtual bool Exists( const char* pFile) const { virtual bool Exists( const char* pFile) const {
return created.find(std::string(pFile)) != created.end(); return created.find(std::string(pFile)) != created.end();
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
virtual char getOsSeparator() const { virtual char getOsSeparator() const {
return '/'; return '/';
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
virtual IOStream* Open(const char* pFile, virtual IOStream* Open(const char* pFile,
const char* pMode) const char* pMode)
{ {
if (pMode[0] != 'w') { if (pMode[0] != 'w') {
return NULL; return NULL;
} }
created.insert(std::string(pFile)); created.insert(std::string(pFile));
return new BlobIOStream(this,std::string(pFile)); return new BlobIOStream(this,std::string(pFile));
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
virtual void Close( IOStream* pFile) virtual void Close( IOStream* pFile)
{ {
delete pFile; delete pFile;
} }
private: private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
void OnDestruct(const std::string& filename, BlobIOStream* child) void OnDestruct(const std::string& filename, BlobIOStream* child)
{ {
// we don't know in which the files are closed, so we // we don't know in which the files are closed, so we
// can't reliably say that the first must be the master // can't reliably say that the first must be the master
// file ... // file ...
blobs.push_back( BlobEntry(filename,child->GetBlob()) ); blobs.push_back( BlobEntry(filename,child->GetBlob()) );
} }
private: private:
std::set<std::string> created; std::set<std::string> created;
std::vector< BlobEntry > blobs; std::vector< BlobEntry > blobs;
}; };
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
BlobIOStream :: ~BlobIOStream() BlobIOStream :: ~BlobIOStream()
{ {
creator->OnDestruct(file,this); creator->OnDestruct(file,this);
delete[] buffer; delete[] buffer;
} }

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -51,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdlib.h> #include <stdlib.h>
#endif #endif
namespace Assimp { namespace Assimp {
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
/** Defines some useful byte order swap routines. /** Defines some useful byte order swap routines.
* *
@ -60,143 +60,143 @@ namespace Assimp {
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
class ByteSwap class ByteSwap
{ {
ByteSwap() {} ByteSwap() {}
public: public:
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** Swap two bytes of data /** Swap two bytes of data
* @param[inout] _szOut A void* to save the reintcasts for the caller. */ * @param[inout] _szOut A void* to save the reintcasts for the caller. */
static inline void Swap2(void* _szOut) static inline void Swap2(void* _szOut)
{ {
ai_assert(_szOut); ai_assert(_szOut);
#if _MSC_VER >= 1400 #if _MSC_VER >= 1400
uint16_t* const szOut = reinterpret_cast<uint16_t*>(_szOut); uint16_t* const szOut = reinterpret_cast<uint16_t*>(_szOut);
*szOut = _byteswap_ushort(*szOut); *szOut = _byteswap_ushort(*szOut);
#else #else
uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut); uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
std::swap(szOut[0],szOut[1]); std::swap(szOut[0],szOut[1]);
#endif #endif
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** Swap four bytes of data /** Swap four bytes of data
* @param[inout] _szOut A void* to save the reintcasts for the caller. */ * @param[inout] _szOut A void* to save the reintcasts for the caller. */
static inline void Swap4(void* _szOut) static inline void Swap4(void* _szOut)
{ {
ai_assert(_szOut); ai_assert(_szOut);
#if _MSC_VER >= 1400 #if _MSC_VER >= 1400
uint32_t* const szOut = reinterpret_cast<uint32_t*>(_szOut); uint32_t* const szOut = reinterpret_cast<uint32_t*>(_szOut);
*szOut = _byteswap_ulong(*szOut); *szOut = _byteswap_ulong(*szOut);
#else #else
uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut); uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
std::swap(szOut[0],szOut[3]); std::swap(szOut[0],szOut[3]);
std::swap(szOut[1],szOut[2]); std::swap(szOut[1],szOut[2]);
#endif #endif
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** Swap eight bytes of data /** Swap eight bytes of data
* @param[inout] _szOut A void* to save the reintcasts for the caller. */ * @param[inout] _szOut A void* to save the reintcasts for the caller. */
static inline void Swap8(void* _szOut) static inline void Swap8(void* _szOut)
{ {
ai_assert(_szOut); ai_assert(_szOut);
#if _MSC_VER >= 1400 #if _MSC_VER >= 1400
uint64_t* const szOut = reinterpret_cast<uint64_t*>(_szOut); uint64_t* const szOut = reinterpret_cast<uint64_t*>(_szOut);
*szOut = _byteswap_uint64(*szOut); *szOut = _byteswap_uint64(*szOut);
#else #else
uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut); uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
std::swap(szOut[0],szOut[7]); std::swap(szOut[0],szOut[7]);
std::swap(szOut[1],szOut[6]); std::swap(szOut[1],szOut[6]);
std::swap(szOut[2],szOut[5]); std::swap(szOut[2],szOut[5]);
std::swap(szOut[3],szOut[4]); std::swap(szOut[3],szOut[4]);
#endif #endif
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** ByteSwap a float. Not a joke. /** ByteSwap a float. Not a joke.
* @param[inout] fOut ehm. .. */ * @param[inout] fOut ehm. .. */
static inline void Swap(float* fOut) { static inline void Swap(float* fOut) {
Swap4(fOut); Swap4(fOut);
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** ByteSwap a double. Not a joke. /** ByteSwap a double. Not a joke.
* @param[inout] fOut ehm. .. */ * @param[inout] fOut ehm. .. */
static inline void Swap(double* fOut) { static inline void Swap(double* fOut) {
Swap8(fOut); Swap8(fOut);
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** ByteSwap an int16t. Not a joke. /** ByteSwap an int16t. Not a joke.
* @param[inout] fOut ehm. .. */ * @param[inout] fOut ehm. .. */
static inline void Swap(int16_t* fOut) { static inline void Swap(int16_t* fOut) {
Swap2(fOut); Swap2(fOut);
} }
static inline void Swap(uint16_t* fOut) { static inline void Swap(uint16_t* fOut) {
Swap2(fOut); Swap2(fOut);
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** ByteSwap an int32t. Not a joke. /** ByteSwap an int32t. Not a joke.
* @param[inout] fOut ehm. .. */ * @param[inout] fOut ehm. .. */
static inline void Swap(int32_t* fOut){ static inline void Swap(int32_t* fOut){
Swap4(fOut); Swap4(fOut);
} }
static inline void Swap(uint32_t* fOut){ static inline void Swap(uint32_t* fOut){
Swap4(fOut); Swap4(fOut);
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
/** ByteSwap an int64t. Not a joke. /** ByteSwap an int64t. Not a joke.
* @param[inout] fOut ehm. .. */ * @param[inout] fOut ehm. .. */
static inline void Swap(int64_t* fOut) { static inline void Swap(int64_t* fOut) {
Swap8(fOut); Swap8(fOut);
} }
static inline void Swap(uint64_t* fOut) { static inline void Swap(uint64_t* fOut) {
Swap8(fOut); Swap8(fOut);
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
//! Templatized ByteSwap //! Templatized ByteSwap
//! \returns param tOut as swapped //! \returns param tOut as swapped
template<typename Type> template<typename Type>
static inline Type Swapped(Type tOut) static inline Type Swapped(Type tOut)
{ {
return _swapper<Type,sizeof(Type)>()(tOut); return _swapper<Type,sizeof(Type)>()(tOut);
} }
private: private:
template <typename T, size_t size> struct _swapper; template <typename T, size_t size> struct _swapper;
}; };
template <typename T> struct ByteSwap::_swapper<T,2> { template <typename T> struct ByteSwap::_swapper<T,2> {
T operator() (T tOut) { T operator() (T tOut) {
Swap2(&tOut); Swap2(&tOut);
return tOut; return tOut;
} }
}; };
template <typename T> struct ByteSwap::_swapper<T,4> { template <typename T> struct ByteSwap::_swapper<T,4> {
T operator() (T tOut) { T operator() (T tOut) {
Swap4(&tOut); Swap4(&tOut);
return tOut; return tOut;
} }
}; };
template <typename T> struct ByteSwap::_swapper<T,8> { template <typename T> struct ByteSwap::_swapper<T,8> {
T operator() (T tOut) { T operator() (T tOut) {
Swap8(&tOut); Swap8(&tOut);
return tOut; return tOut;
} }
}; };
@ -204,39 +204,39 @@ template <typename T> struct ByteSwap::_swapper<T,8> {
// ByteSwap macros for BigEndian/LittleEndian support // ByteSwap macros for BigEndian/LittleEndian support
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
#if (defined AI_BUILD_BIG_ENDIAN) #if (defined AI_BUILD_BIG_ENDIAN)
# define AI_LE(t) (t) # define AI_LE(t) (t)
# define AI_BE(t) ByteSwap::Swapped(t) # define AI_BE(t) ByteSwap::Swapped(t)
# define AI_LSWAP2(p) # define AI_LSWAP2(p)
# define AI_LSWAP4(p) # define AI_LSWAP4(p)
# define AI_LSWAP8(p) # define AI_LSWAP8(p)
# define AI_LSWAP2P(p) # define AI_LSWAP2P(p)
# define AI_LSWAP4P(p) # define AI_LSWAP4P(p)
# define AI_LSWAP8P(p) # define AI_LSWAP8P(p)
# define LE_NCONST const # define LE_NCONST const
# define AI_SWAP2(p) ByteSwap::Swap2(&(p)) # define AI_SWAP2(p) ByteSwap::Swap2(&(p))
# define AI_SWAP4(p) ByteSwap::Swap4(&(p)) # define AI_SWAP4(p) ByteSwap::Swap4(&(p))
# define AI_SWAP8(p) ByteSwap::Swap8(&(p)) # define AI_SWAP8(p) ByteSwap::Swap8(&(p))
# define AI_SWAP2P(p) ByteSwap::Swap2((p)) # define AI_SWAP2P(p) ByteSwap::Swap2((p))
# define AI_SWAP4P(p) ByteSwap::Swap4((p)) # define AI_SWAP4P(p) ByteSwap::Swap4((p))
# define AI_SWAP8P(p) ByteSwap::Swap8((p)) # define AI_SWAP8P(p) ByteSwap::Swap8((p))
# define BE_NCONST # define BE_NCONST
#else #else
# define AI_BE(t) (t) # define AI_BE(t) (t)
# define AI_LE(t) ByteSwap::Swapped(t) # define AI_LE(t) ByteSwap::Swapped(t)
# define AI_SWAP2(p) # define AI_SWAP2(p)
# define AI_SWAP4(p) # define AI_SWAP4(p)
# define AI_SWAP8(p) # define AI_SWAP8(p)
# define AI_SWAP2P(p) # define AI_SWAP2P(p)
# define AI_SWAP4P(p) # define AI_SWAP4P(p)
# define AI_SWAP8P(p) # define AI_SWAP8P(p)
# define BE_NCONST const # define BE_NCONST const
# define AI_LSWAP2(p) ByteSwap::Swap2(&(p)) # define AI_LSWAP2(p) ByteSwap::Swap2(&(p))
# define AI_LSWAP4(p) ByteSwap::Swap4(&(p)) # define AI_LSWAP4(p) ByteSwap::Swap4(&(p))
# define AI_LSWAP8(p) ByteSwap::Swap8(&(p)) # define AI_LSWAP8(p) ByteSwap::Swap8(&(p))
# define AI_LSWAP2P(p) ByteSwap::Swap2((p)) # define AI_LSWAP2P(p) ByteSwap::Swap2((p))
# define AI_LSWAP4P(p) ByteSwap::Swap4((p)) # define AI_LSWAP4P(p) ByteSwap::Swap4((p))
# define AI_LSWAP8P(p) ByteSwap::Swap8((p)) # define AI_LSWAP8P(p) ByteSwap::Swap8((p))
# define LE_NCONST # define LE_NCONST
#endif #endif
@ -244,41 +244,41 @@ namespace Intern {
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
template <typename T, bool doit> template <typename T, bool doit>
struct ByteSwapper { struct ByteSwapper {
void operator() (T* inout) { void operator() (T* inout) {
ByteSwap::Swap(inout); ByteSwap::Swap(inout);
} }
}; };
template <typename T> template <typename T>
struct ByteSwapper<T,false> { struct ByteSwapper<T,false> {
void operator() (T*) { void operator() (T*) {
} }
}; };
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
template <bool SwapEndianess, typename T, bool RuntimeSwitch> template <bool SwapEndianess, typename T, bool RuntimeSwitch>
struct Getter { struct Getter {
void operator() (T* inout, bool le) { void operator() (T* inout, bool le) {
#ifdef AI_BUILD_BIG_ENDIAN #ifdef AI_BUILD_BIG_ENDIAN
le = le; le = le;
#else #else
le = !le; le = !le;
#endif #endif
if (le) { if (le) {
ByteSwapper<T,(sizeof(T)>1?true:false)> () (inout); ByteSwapper<T,(sizeof(T)>1?true:false)> () (inout);
} }
else ByteSwapper<T,false> () (inout); else ByteSwapper<T,false> () (inout);
} }
}; };
template <bool SwapEndianess, typename T> template <bool SwapEndianess, typename T>
struct Getter<SwapEndianess,T,false> { struct Getter<SwapEndianess,T,false> {
void operator() (T* inout, bool /*le*/) { void operator() (T* inout, bool /*le*/) {
// static branch // static branch
ByteSwapper<T,(SwapEndianess && sizeof(T)>1)> () (inout); ByteSwapper<T,(SwapEndianess && sizeof(T)>1)> () (inout);
} }
}; };
} // end Intern } // end Intern
} // end Assimp } // end Assimp

File diff suppressed because it is too large Load Diff

View File

@ -55,19 +55,19 @@ struct aiMaterial;
struct aiImporterDesc; struct aiImporterDesc;
namespace _melange_ { namespace _melange_ {
class BaseObject; // c4d_file.h class BaseObject; // c4d_file.h
class PolygonObject; class PolygonObject;
class BaseMaterial; class BaseMaterial;
class BaseShader; class BaseShader;
} }
namespace Assimp { namespace Assimp {
// TinyFormatter.h // TinyFormatter.h
namespace Formatter { namespace Formatter {
template <typename T,typename TR, typename A> class basic_formatter; template <typename T,typename TR, typename A> class basic_formatter;
typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format; typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
} }
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
/** Importer class to load Cinema4D files using the Melange library to be obtained from /** Importer class to load Cinema4D files using the Melange library to be obtained from
@ -79,42 +79,42 @@ class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter>
{ {
public: public:
C4DImporter(); C4DImporter();
~C4DImporter(); ~C4DImporter();
public: public:
// -------------------- // --------------------
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const; bool checkSig) const;
protected: protected:
// -------------------- // --------------------
const aiImporterDesc* GetInfo () const; const aiImporterDesc* GetInfo () const;
// -------------------- // --------------------
void SetupProperties(const Importer* pImp); void SetupProperties(const Importer* pImp);
// -------------------- // --------------------
void InternReadFile( const std::string& pFile, aiScene* pScene, void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler); IOSystem* pIOHandler);
private: private:
void ReadMaterials(_melange_::BaseMaterial* mat); void ReadMaterials(_melange_::BaseMaterial* mat);
void RecurseHierarchy(_melange_::BaseObject* object, aiNode* parent); void RecurseHierarchy(_melange_::BaseObject* object, aiNode* parent);
aiMesh* ReadMesh(_melange_::BaseObject* object); aiMesh* ReadMesh(_melange_::BaseObject* object);
unsigned int ResolveMaterial(_melange_::PolygonObject* obj); unsigned int ResolveMaterial(_melange_::PolygonObject* obj);
bool ReadShader(aiMaterial* out, _melange_::BaseShader* shader); bool ReadShader(aiMaterial* out, _melange_::BaseShader* shader);
std::vector<aiMesh*> meshes; std::vector<aiMesh*> meshes;
std::vector<aiMaterial*> materials; std::vector<aiMaterial*> materials;
typedef std::map<_melange_::BaseMaterial*, unsigned int> MaterialMap; typedef std::map<_melange_::BaseMaterial*, unsigned int> MaterialMap;
MaterialMap material_mapping; MaterialMap material_mapping;
}; // !class C4DImporter }; // !class C4DImporter

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
@ -48,61 +48,61 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../include/assimp/IOStream.hpp" #include "../include/assimp/IOStream.hpp"
#include "../include/assimp/IOSystem.hpp" #include "../include/assimp/IOSystem.hpp"
namespace Assimp { namespace Assimp {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Custom IOStream implementation for the C-API // Custom IOStream implementation for the C-API
class CIOStreamWrapper : public IOStream class CIOStreamWrapper : public IOStream
{ {
friend class CIOSystemWrapper; friend class CIOSystemWrapper;
public: public:
CIOStreamWrapper(aiFile* pFile) CIOStreamWrapper(aiFile* pFile)
: mFile(pFile) : mFile(pFile)
{} {}
// ................................................................... // ...................................................................
size_t Read(void* pvBuffer, size_t Read(void* pvBuffer,
size_t pSize, size_t pSize,
size_t pCount size_t pCount
){ ){
// need to typecast here as C has no void* // need to typecast here as C has no void*
return mFile->ReadProc(mFile,(char*)pvBuffer,pSize,pCount); return mFile->ReadProc(mFile,(char*)pvBuffer,pSize,pCount);
} }
// ................................................................... // ...................................................................
size_t Write(const void* pvBuffer, size_t Write(const void* pvBuffer,
size_t pSize, size_t pSize,
size_t pCount size_t pCount
){ ){
// need to typecast here as C has no void* // need to typecast here as C has no void*
return mFile->WriteProc(mFile,(const char*)pvBuffer,pSize,pCount); return mFile->WriteProc(mFile,(const char*)pvBuffer,pSize,pCount);
} }
// ................................................................... // ...................................................................
aiReturn Seek(size_t pOffset, aiReturn Seek(size_t pOffset,
aiOrigin pOrigin aiOrigin pOrigin
){ ){
return mFile->SeekProc(mFile,pOffset,pOrigin); return mFile->SeekProc(mFile,pOffset,pOrigin);
} }
// ................................................................... // ...................................................................
size_t Tell(void) const { size_t Tell(void) const {
return mFile->TellProc(mFile); return mFile->TellProc(mFile);
} }
// ................................................................... // ...................................................................
size_t FileSize() const { size_t FileSize() const {
return mFile->FileSizeProc(mFile); return mFile->FileSizeProc(mFile);
} }
// ................................................................... // ...................................................................
void Flush () { void Flush () {
return mFile->FlushProc(mFile); return mFile->FlushProc(mFile);
} }
private: private:
aiFile* mFile; aiFile* mFile;
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -110,48 +110,48 @@ private:
class CIOSystemWrapper : public IOSystem class CIOSystemWrapper : public IOSystem
{ {
public: public:
CIOSystemWrapper(aiFileIO* pFile) CIOSystemWrapper(aiFileIO* pFile)
: mFileSystem(pFile) : mFileSystem(pFile)
{} {}
// ................................................................... // ...................................................................
bool Exists( const char* pFile) const { bool Exists( const char* pFile) const {
aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,"rb"); aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,"rb");
if (p){ if (p){
mFileSystem->CloseProc(mFileSystem,p); mFileSystem->CloseProc(mFileSystem,p);
return true; return true;
} }
return false; return false;
} }
// ................................................................... // ...................................................................
char getOsSeparator() const { char getOsSeparator() const {
#ifndef _WIN32 #ifndef _WIN32
return '/'; return '/';
#else #else
return '\\'; return '\\';
#endif #endif
} }
// ................................................................... // ...................................................................
IOStream* Open(const char* pFile,const char* pMode = "rb") { IOStream* Open(const char* pFile,const char* pMode = "rb") {
aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,pMode); aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,pMode);
if (!p) { if (!p) {
return NULL; return NULL;
} }
return new CIOStreamWrapper(p); return new CIOStreamWrapper(p);
} }
// ................................................................... // ...................................................................
void Close( IOStream* pFile) { void Close( IOStream* pFile) {
if (!pFile) { if (!pFile) {
return; return;
} }
mFileSystem->CloseProc(mFileSystem,((CIOStreamWrapper*) pFile)->mFile); mFileSystem->CloseProc(mFileSystem,((CIOStreamWrapper*) pFile)->mFile);
delete pFile; delete pFile;
} }
private: private:
aiFileIO* mFileSystem; aiFileIO* mFileSystem;
}; };
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -49,21 +49,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiNode; struct aiNode;
namespace Assimp { namespace Assimp {
class LineSplitter; class LineSplitter;
// TinyFormatter.h // TinyFormatter.h
namespace Formatter { namespace Formatter {
template <typename T,typename TR, typename A> class basic_formatter; template <typename T,typename TR, typename A> class basic_formatter;
typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format; typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
} }
// COBScene.h // COBScene.h
namespace COB { namespace COB {
struct ChunkInfo; struct ChunkInfo;
struct Node; struct Node;
struct Scene; struct Scene;
} }
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
/** Importer class to load TrueSpace files (cob,scn) up to v6. /** Importer class to load TrueSpace files (cob,scn) up to v6.
@ -73,99 +73,99 @@ namespace Assimp {
class COBImporter : public BaseImporter class COBImporter : public BaseImporter
{ {
public: public:
COBImporter(); COBImporter();
~COBImporter(); ~COBImporter();
public: public:
// -------------------- // --------------------
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const; bool checkSig) const;
protected: protected:
// -------------------- // --------------------
const aiImporterDesc* GetInfo () const; const aiImporterDesc* GetInfo () const;
// -------------------- // --------------------
void SetupProperties(const Importer* pImp); void SetupProperties(const Importer* pImp);
// -------------------- // --------------------
void InternReadFile( const std::string& pFile, aiScene* pScene, void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler); IOSystem* pIOHandler);
private: private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Prepend 'COB: ' and throw msg.*/ /** Prepend 'COB: ' and throw msg.*/
AI_WONT_RETURN static void ThrowException(const std::string& msg) AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN static void ThrowException(const std::string& msg) AI_WONT_RETURN_SUFFIX;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** @brief Read from an ascii scene/object file /** @brief Read from an ascii scene/object file
* @param out Receives output data. * @param out Receives output data.
* @param stream Stream to read from. */ * @param stream Stream to read from. */
void ReadAsciiFile(COB::Scene& out, StreamReaderLE* stream); void ReadAsciiFile(COB::Scene& out, StreamReaderLE* stream);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** @brief Read from a binary scene/object file /** @brief Read from a binary scene/object file
* @param out Receives output data. * @param out Receives output data.
* @param stream Stream to read from. */ * @param stream Stream to read from. */
void ReadBinaryFile(COB::Scene& out, StreamReaderLE* stream); void ReadBinaryFile(COB::Scene& out, StreamReaderLE* stream);
private: private:
// Conversion to Assimp output format // Conversion to Assimp output format
aiNode* BuildNodes(const COB::Node& root,const COB::Scene& scin,aiScene* fill); aiNode* BuildNodes(const COB::Node& root,const COB::Scene& scin,aiScene* fill);
private: private:
// ASCII file support // ASCII file support
void UnsupportedChunk_Ascii(LineSplitter& splitter, const COB::ChunkInfo& nfo, const char* name); void UnsupportedChunk_Ascii(LineSplitter& splitter, const COB::ChunkInfo& nfo, const char* name);
void ReadChunkInfo_Ascii(COB::ChunkInfo& out, const LineSplitter& splitter); void ReadChunkInfo_Ascii(COB::ChunkInfo& out, const LineSplitter& splitter);
void ReadBasicNodeInfo_Ascii(COB::Node& msh, LineSplitter& splitter, const COB::ChunkInfo& nfo); void ReadBasicNodeInfo_Ascii(COB::Node& msh, LineSplitter& splitter, const COB::ChunkInfo& nfo);
template <typename T> void ReadFloat3Tuple_Ascii(T& fill, const char** in); template <typename T> void ReadFloat3Tuple_Ascii(T& fill, const char** in);
void ReadPolH_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo); void ReadPolH_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
void ReadBitM_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo); void ReadBitM_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
void ReadMat1_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo); void ReadMat1_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
void ReadGrou_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo); void ReadGrou_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
void ReadBone_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo); void ReadBone_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
void ReadCame_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo); void ReadCame_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
void ReadLght_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo); void ReadLght_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
void ReadUnit_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo); void ReadUnit_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
void ReadChan_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo); void ReadChan_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
// ASCII file logging stuff to add proper line numbers to messages // ASCII file logging stuff to add proper line numbers to messages
static void LogWarn_Ascii (const LineSplitter& splitter, const Formatter::format& message); static void LogWarn_Ascii (const LineSplitter& splitter, const Formatter::format& message);
static void LogError_Ascii(const LineSplitter& splitter, const Formatter::format& message); static void LogError_Ascii(const LineSplitter& splitter, const Formatter::format& message);
static void LogInfo_Ascii (const LineSplitter& splitter, const Formatter::format& message); static void LogInfo_Ascii (const LineSplitter& splitter, const Formatter::format& message);
static void LogDebug_Ascii(const LineSplitter& splitter, const Formatter::format& message); static void LogDebug_Ascii(const LineSplitter& splitter, const Formatter::format& message);
static void LogWarn_Ascii (const Formatter::format& message); static void LogWarn_Ascii (const Formatter::format& message);
static void LogError_Ascii (const Formatter::format& message); static void LogError_Ascii (const Formatter::format& message);
static void LogInfo_Ascii (const Formatter::format& message); static void LogInfo_Ascii (const Formatter::format& message);
static void LogDebug_Ascii (const Formatter::format& message); static void LogDebug_Ascii (const Formatter::format& message);
// Binary file support // Binary file support
void UnsupportedChunk_Binary(StreamReaderLE& reader, const COB::ChunkInfo& nfo, const char* name); void UnsupportedChunk_Binary(StreamReaderLE& reader, const COB::ChunkInfo& nfo, const char* name);
void ReadString_Binary(std::string& out, StreamReaderLE& reader); void ReadString_Binary(std::string& out, StreamReaderLE& reader);
void ReadBasicNodeInfo_Binary(COB::Node& msh, StreamReaderLE& reader, const COB::ChunkInfo& nfo); void ReadBasicNodeInfo_Binary(COB::Node& msh, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
void ReadPolH_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo); void ReadPolH_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
void ReadBitM_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo); void ReadBitM_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
void ReadMat1_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo); void ReadMat1_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
void ReadCame_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo); void ReadCame_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
void ReadLght_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo); void ReadLght_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
void ReadGrou_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo); void ReadGrou_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
void ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo); void ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
}; // !class COBImporter }; // !class COBImporter

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -50,208 +50,208 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h" #include "BaseImporter.h"
#include "./../include/assimp/material.h" #include "./../include/assimp/material.h"
namespace Assimp { namespace Assimp {
namespace COB { namespace COB {
// ------------------ // ------------------
/** Represents a single vertex index in a face */ /** Represents a single vertex index in a face */
struct VertexIndex struct VertexIndex
{ {
// intentionally uninitialized // intentionally uninitialized
unsigned int pos_idx,uv_idx; unsigned int pos_idx,uv_idx;
}; };
// ------------------ // ------------------
/** COB Face data structure */ /** COB Face data structure */
struct Face struct Face
{ {
// intentionally uninitialized // intentionally uninitialized
unsigned int material, flags; unsigned int material, flags;
std::vector<VertexIndex> indices; std::vector<VertexIndex> indices;
}; };
// ------------------ // ------------------
/** COB chunk header information */ /** COB chunk header information */
struct ChunkInfo struct ChunkInfo
{ {
enum {NO_SIZE=UINT_MAX}; enum {NO_SIZE=UINT_MAX};
ChunkInfo () ChunkInfo ()
: id (0) : id (0)
, parent_id (0) , parent_id (0)
, version (0) , version (0)
, size (NO_SIZE) , size (NO_SIZE)
{} {}
// Id of this chunk, unique within file // Id of this chunk, unique within file
unsigned int id; unsigned int id;
// and the corresponding parent // and the corresponding parent
unsigned int parent_id; unsigned int parent_id;
// version. v1.23 becomes 123 // version. v1.23 becomes 123
unsigned int version; unsigned int version;
// chunk size in bytes, only relevant for binary files // chunk size in bytes, only relevant for binary files
// NO_SIZE is also valid. // NO_SIZE is also valid.
unsigned int size; unsigned int size;
}; };
// ------------------ // ------------------
/** A node in the scenegraph */ /** A node in the scenegraph */
struct Node : public ChunkInfo struct Node : public ChunkInfo
{ {
enum Type { enum Type {
TYPE_MESH,TYPE_GROUP,TYPE_LIGHT,TYPE_CAMERA,TYPE_BONE TYPE_MESH,TYPE_GROUP,TYPE_LIGHT,TYPE_CAMERA,TYPE_BONE
}; };
virtual ~Node() {} virtual ~Node() {}
Node(Type type) : type(type), unit_scale(1.f){} Node(Type type) : type(type), unit_scale(1.f){}
Type type; Type type;
// used during resolving // used during resolving
typedef std::deque<const Node*> ChildList; typedef std::deque<const Node*> ChildList;
mutable ChildList temp_children; mutable ChildList temp_children;
// unique name // unique name
std::string name; std::string name;
// local mesh transformation // local mesh transformation
aiMatrix4x4 transform; aiMatrix4x4 transform;
// scaling for this node to get to the metric system // scaling for this node to get to the metric system
float unit_scale; float unit_scale;
}; };
// ------------------ // ------------------
/** COB Mesh data structure */ /** COB Mesh data structure */
struct Mesh : public Node struct Mesh : public Node
{ {
using ChunkInfo::operator=; using ChunkInfo::operator=;
enum DrawFlags { enum DrawFlags {
SOLID = 0x1, SOLID = 0x1,
TRANS = 0x2, TRANS = 0x2,
WIRED = 0x4, WIRED = 0x4,
BBOX = 0x8, BBOX = 0x8,
HIDE = 0x10 HIDE = 0x10
}; };
Mesh() Mesh()
: Node(TYPE_MESH) : Node(TYPE_MESH)
, draw_flags(SOLID) , draw_flags(SOLID)
{} {}
// vertex elements // vertex elements
std::vector<aiVector2D> texture_coords; std::vector<aiVector2D> texture_coords;
std::vector<aiVector3D> vertex_positions; std::vector<aiVector3D> vertex_positions;
// face data // face data
std::vector<Face> faces; std::vector<Face> faces;
// misc. drawing flags // misc. drawing flags
unsigned int draw_flags; unsigned int draw_flags;
// used during resolving // used during resolving
typedef std::deque<Face*> FaceRefList; typedef std::deque<Face*> FaceRefList;
typedef std::map< unsigned int,FaceRefList > TempMap; typedef std::map< unsigned int,FaceRefList > TempMap;
TempMap temp_map; TempMap temp_map;
}; };
// ------------------ // ------------------
/** COB Group data structure */ /** COB Group data structure */
struct Group : public Node struct Group : public Node
{ {
using ChunkInfo::operator=; using ChunkInfo::operator=;
Group() : Node(TYPE_GROUP) {} Group() : Node(TYPE_GROUP) {}
}; };
// ------------------ // ------------------
/** COB Bone data structure */ /** COB Bone data structure */
struct Bone : public Node struct Bone : public Node
{ {
using ChunkInfo::operator=; using ChunkInfo::operator=;
Bone() : Node(TYPE_BONE) {} Bone() : Node(TYPE_BONE) {}
}; };
// ------------------ // ------------------
/** COB Light data structure */ /** COB Light data structure */
struct Light : public Node struct Light : public Node
{ {
enum LightType { enum LightType {
SPOT,LOCAL,INFINITE SPOT,LOCAL,INFINITE
}; };
using ChunkInfo::operator=; using ChunkInfo::operator=;
Light() : Node(TYPE_LIGHT),angle(),inner_angle(),ltype(SPOT) {} Light() : Node(TYPE_LIGHT),angle(),inner_angle(),ltype(SPOT) {}
aiColor3D color; aiColor3D color;
float angle,inner_angle; float angle,inner_angle;
LightType ltype; LightType ltype;
}; };
// ------------------ // ------------------
/** COB Camera data structure */ /** COB Camera data structure */
struct Camera : public Node struct Camera : public Node
{ {
using ChunkInfo::operator=; using ChunkInfo::operator=;
Camera() : Node(TYPE_CAMERA) {} Camera() : Node(TYPE_CAMERA) {}
}; };
// ------------------ // ------------------
/** COB Texture data structure */ /** COB Texture data structure */
struct Texture struct Texture
{ {
std::string path; std::string path;
aiUVTransform transform; aiUVTransform transform;
}; };
// ------------------ // ------------------
/** COB Material data structure */ /** COB Material data structure */
struct Material : ChunkInfo struct Material : ChunkInfo
{ {
using ChunkInfo::operator=; using ChunkInfo::operator=;
enum Shader { enum Shader {
FLAT,PHONG,METAL FLAT,PHONG,METAL
}; };
enum AutoFacet { enum AutoFacet {
FACETED,AUTOFACETED,SMOOTH FACETED,AUTOFACETED,SMOOTH
}; };
Material() : alpha(),exp(),ior(),ka(),ks(1.f), Material() : alpha(),exp(),ior(),ka(),ks(1.f),
matnum(UINT_MAX), matnum(UINT_MAX),
shader(FLAT),autofacet(FACETED), shader(FLAT),autofacet(FACETED),
autofacet_angle() autofacet_angle()
{} {}
std::string type; std::string type;
aiColor3D rgb; aiColor3D rgb;
float alpha, exp, ior,ka,ks; float alpha, exp, ior,ka,ks;
unsigned int matnum; unsigned int matnum;
Shader shader; Shader shader;
AutoFacet autofacet; AutoFacet autofacet;
float autofacet_angle; float autofacet_angle;
boost::shared_ptr<Texture> tex_env,tex_bump,tex_color; boost::shared_ptr<Texture> tex_env,tex_bump,tex_color;
}; };
// ------------------ // ------------------
/** Embedded bitmap, for instance for the thumbnail image */ /** Embedded bitmap, for instance for the thumbnail image */
struct Bitmap : ChunkInfo struct Bitmap : ChunkInfo
{ {
Bitmap() : orig_size() {} Bitmap() : orig_size() {}
struct BitmapHeader struct BitmapHeader
{ {
}; };
BitmapHeader head; BitmapHeader head;
size_t orig_size; size_t orig_size;
std::vector<char> buff_zipped; std::vector<char> buff_zipped;
}; };
typedef std::deque< boost::shared_ptr<Node> > NodeList; typedef std::deque< boost::shared_ptr<Node> > NodeList;
@ -261,14 +261,14 @@ typedef std::vector< Material > MaterialList;
/** Represents a master COB scene, even if we loaded just a single COB file */ /** Represents a master COB scene, even if we loaded just a single COB file */
struct Scene struct Scene
{ {
NodeList nodes; NodeList nodes;
MaterialList materials; MaterialList materials;
// becomes *0 later // becomes *0 later
Bitmap thumbnail; Bitmap thumbnail;
}; };
} // end COB } // end COB
} // end Assimp } // end Assimp
#endif #endif

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
@ -62,16 +62,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
static const aiImporterDesc desc = { static const aiImporterDesc desc = {
"CharacterStudio Motion Importer (MoCap)", "CharacterStudio Motion Importer (MoCap)",
"", "",
"", "",
"", "",
aiImporterFlags_SupportTextFlavour, aiImporterFlags_SupportTextFlavour,
0, 0,
0, 0,
0, 0,
0, 0,
"csm" "csm"
}; };
@ -90,217 +90,217 @@ CSMImporter::~CSMImporter()
// 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 CSMImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const bool CSMImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{ {
// check file extension // check file extension
const std::string extension = GetExtension(pFile); const std::string extension = GetExtension(pFile);
if( extension == "csm") if( extension == "csm")
return true; return true;
if ((checkSig || !extension.length()) && pIOHandler) { if ((checkSig || !extension.length()) && pIOHandler) {
const char* tokens[] = {"$Filename"}; const char* tokens[] = {"$Filename"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
} }
return false; return false;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Build a string of all file extensions supported // Build a string of all file extensions supported
const aiImporterDesc* CSMImporter::GetInfo () const const aiImporterDesc* CSMImporter::GetInfo () const
{ {
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Setup configuration properties for the loader // Setup configuration properties for the loader
void CSMImporter::SetupProperties(const Importer* pImp) void CSMImporter::SetupProperties(const Importer* pImp)
{ {
noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0; noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void CSMImporter::InternReadFile( const std::string& pFile, void CSMImporter::InternReadFile( const std::string& pFile,
aiScene* pScene, IOSystem* pIOHandler) aiScene* pScene, IOSystem* pIOHandler)
{ {
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
// Check whether we can read from the file // Check whether we can read from the file
if( file.get() == NULL) { if( file.get() == NULL) {
throw DeadlyImportError( "Failed to open CSM file " + pFile + "."); throw DeadlyImportError( "Failed to open CSM file " + pFile + ".");
} }
// allocate storage and copy the contents of the file to a memory buffer // allocate storage and copy the contents of the file to a memory buffer
std::vector<char> mBuffer2; std::vector<char> mBuffer2;
TextFileToBuffer(file.get(),mBuffer2); TextFileToBuffer(file.get(),mBuffer2);
const char* buffer = &mBuffer2[0]; const char* buffer = &mBuffer2[0];
aiAnimation* anim = new aiAnimation(); aiAnimation* anim = new aiAnimation();
int first = 0, last = 0x00ffffff; int first = 0, last = 0x00ffffff;
// now process the file and look out for '$' sections // now process the file and look out for '$' sections
while (1) { while (1) {
SkipSpaces(&buffer); SkipSpaces(&buffer);
if ('\0' == *buffer) if ('\0' == *buffer)
break; break;
if ('$' == *buffer) { if ('$' == *buffer) {
++buffer; ++buffer;
if (TokenMatchI(buffer,"firstframe",10)) { if (TokenMatchI(buffer,"firstframe",10)) {
SkipSpaces(&buffer); SkipSpaces(&buffer);
first = strtol10(buffer,&buffer); first = strtol10(buffer,&buffer);
} }
else if (TokenMatchI(buffer,"lastframe",9)) { else if (TokenMatchI(buffer,"lastframe",9)) {
SkipSpaces(&buffer); SkipSpaces(&buffer);
last = strtol10(buffer,&buffer); last = strtol10(buffer,&buffer);
} }
else if (TokenMatchI(buffer,"rate",4)) { else if (TokenMatchI(buffer,"rate",4)) {
SkipSpaces(&buffer); SkipSpaces(&buffer);
float d; float d;
buffer = fast_atoreal_move<float>(buffer,d); buffer = fast_atoreal_move<float>(buffer,d);
anim->mTicksPerSecond = d; anim->mTicksPerSecond = d;
} }
else if (TokenMatchI(buffer,"order",5)) { else if (TokenMatchI(buffer,"order",5)) {
std::vector< aiNodeAnim* > anims_temp; std::vector< aiNodeAnim* > anims_temp;
anims_temp.reserve(30); anims_temp.reserve(30);
while (1) { while (1) {
SkipSpaces(&buffer); SkipSpaces(&buffer);
if (IsLineEnd(*buffer) && SkipSpacesAndLineEnd(&buffer) && *buffer == '$') if (IsLineEnd(*buffer) && SkipSpacesAndLineEnd(&buffer) && *buffer == '$')
break; // next section break; // next section
// Construct a new node animation channel and setup its name // Construct a new node animation channel and setup its name
anims_temp.push_back(new aiNodeAnim()); anims_temp.push_back(new aiNodeAnim());
aiNodeAnim* nda = anims_temp.back(); aiNodeAnim* nda = anims_temp.back();
char* ot = nda->mNodeName.data; char* ot = nda->mNodeName.data;
while (!IsSpaceOrNewLine(*buffer)) while (!IsSpaceOrNewLine(*buffer))
*ot++ = *buffer++; *ot++ = *buffer++;
*ot = '\0'; *ot = '\0';
nda->mNodeName.length = (size_t)(ot-nda->mNodeName.data); nda->mNodeName.length = (size_t)(ot-nda->mNodeName.data);
} }
anim->mNumChannels = anims_temp.size(); anim->mNumChannels = anims_temp.size();
if (!anim->mNumChannels) if (!anim->mNumChannels)
throw DeadlyImportError("CSM: Empty $order section"); throw DeadlyImportError("CSM: Empty $order section");
// copy over to the output animation // copy over to the output animation
anim->mChannels = new aiNodeAnim*[anim->mNumChannels]; anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
::memcpy(anim->mChannels,&anims_temp[0],sizeof(aiNodeAnim*)*anim->mNumChannels); ::memcpy(anim->mChannels,&anims_temp[0],sizeof(aiNodeAnim*)*anim->mNumChannels);
} }
else if (TokenMatchI(buffer,"points",6)) { else if (TokenMatchI(buffer,"points",6)) {
if (!anim->mNumChannels) if (!anim->mNumChannels)
throw DeadlyImportError("CSM: \'$order\' section is required to appear prior to \'$points\'"); throw DeadlyImportError("CSM: \'$order\' section is required to appear prior to \'$points\'");
// If we know how many frames we'll read, we can preallocate some storage // If we know how many frames we'll read, we can preallocate some storage
unsigned int alloc = 100; unsigned int alloc = 100;
if (last != 0x00ffffff) if (last != 0x00ffffff)
{ {
alloc = last-first; alloc = last-first;
alloc += alloc>>2u; // + 25% alloc += alloc>>2u; // + 25%
for (unsigned int i = 0; i < anim->mNumChannels;++i) for (unsigned int i = 0; i < anim->mNumChannels;++i)
anim->mChannels[i]->mPositionKeys = new aiVectorKey[alloc]; anim->mChannels[i]->mPositionKeys = new aiVectorKey[alloc];
} }
unsigned int filled = 0; unsigned int filled = 0;
// Now read all point data. // Now read all point data.
while (1) { while (1) {
SkipSpaces(&buffer); SkipSpaces(&buffer);
if (IsLineEnd(*buffer) && (!SkipSpacesAndLineEnd(&buffer) || *buffer == '$')) { if (IsLineEnd(*buffer) && (!SkipSpacesAndLineEnd(&buffer) || *buffer == '$')) {
break; // next section break; // next section
} }
// read frame // read frame
const int frame = ::strtoul10(buffer,&buffer); const int frame = ::strtoul10(buffer,&buffer);
last = std::max(frame,last); last = std::max(frame,last);
first = std::min(frame,last); first = std::min(frame,last);
for (unsigned int i = 0; i < anim->mNumChannels;++i) { for (unsigned int i = 0; i < anim->mNumChannels;++i) {
aiNodeAnim* s = anim->mChannels[i]; aiNodeAnim* s = anim->mChannels[i];
if (s->mNumPositionKeys == alloc) { /* need to reallocate? */ if (s->mNumPositionKeys == alloc) { /* need to reallocate? */
aiVectorKey* old = s->mPositionKeys; aiVectorKey* old = s->mPositionKeys;
s->mPositionKeys = new aiVectorKey[s->mNumPositionKeys = alloc*2]; s->mPositionKeys = new aiVectorKey[s->mNumPositionKeys = alloc*2];
::memcpy(s->mPositionKeys,old,sizeof(aiVectorKey)*alloc); ::memcpy(s->mPositionKeys,old,sizeof(aiVectorKey)*alloc);
delete[] old; delete[] old;
} }
// read x,y,z // read x,y,z
if(!SkipSpacesAndLineEnd(&buffer)) if(!SkipSpacesAndLineEnd(&buffer))
throw DeadlyImportError("CSM: Unexpected EOF occured reading sample x coord"); throw DeadlyImportError("CSM: Unexpected EOF occured reading sample x coord");
if (TokenMatchI(buffer, "DROPOUT", 7)) { if (TokenMatchI(buffer, "DROPOUT", 7)) {
// seems this is invalid marker data; at least the doc says it's possible // seems this is invalid marker data; at least the doc says it's possible
DefaultLogger::get()->warn("CSM: Encountered invalid marker data (DROPOUT)"); DefaultLogger::get()->warn("CSM: Encountered invalid marker data (DROPOUT)");
} }
else { else {
aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys; aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys;
sub->mTime = (double)frame; sub->mTime = (double)frame;
buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.x); buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.x);
if(!SkipSpacesAndLineEnd(&buffer)) if(!SkipSpacesAndLineEnd(&buffer))
throw DeadlyImportError("CSM: Unexpected EOF occured reading sample y coord"); throw DeadlyImportError("CSM: Unexpected EOF occured reading sample y coord");
buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.y); buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.y);
if(!SkipSpacesAndLineEnd(&buffer)) if(!SkipSpacesAndLineEnd(&buffer))
throw DeadlyImportError("CSM: Unexpected EOF occured reading sample z coord"); throw DeadlyImportError("CSM: Unexpected EOF occured reading sample z coord");
buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.z); buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.z);
++s->mNumPositionKeys; ++s->mNumPositionKeys;
} }
} }
// update allocation granularity // update allocation granularity
if (filled == alloc) if (filled == alloc)
alloc *= 2; alloc *= 2;
++filled; ++filled;
} }
// all channels must be complete in order to continue safely. // all channels must be complete in order to continue safely.
for (unsigned int i = 0; i < anim->mNumChannels;++i) { for (unsigned int i = 0; i < anim->mNumChannels;++i) {
if (!anim->mChannels[i]->mNumPositionKeys) if (!anim->mChannels[i]->mNumPositionKeys)
throw DeadlyImportError("CSM: Invalid marker track"); throw DeadlyImportError("CSM: Invalid marker track");
} }
} }
} }
else { else {
// advance to the next line // advance to the next line
SkipLine(&buffer); SkipLine(&buffer);
} }
} }
// Setup a proper animation duration // Setup a proper animation duration
anim->mDuration = last - std::min( first, 0 ); anim->mDuration = last - std::min( first, 0 );
// build a dummy root node with the tiny markers as children // build a dummy root node with the tiny markers as children
pScene->mRootNode = new aiNode(); pScene->mRootNode = new aiNode();
pScene->mRootNode->mName.Set("$CSM_DummyRoot"); pScene->mRootNode->mName.Set("$CSM_DummyRoot");
pScene->mRootNode->mNumChildren = anim->mNumChannels; pScene->mRootNode->mNumChildren = anim->mNumChannels;
pScene->mRootNode->mChildren = new aiNode* [anim->mNumChannels]; pScene->mRootNode->mChildren = new aiNode* [anim->mNumChannels];
for (unsigned int i = 0; i < anim->mNumChannels;++i) { for (unsigned int i = 0; i < anim->mNumChannels;++i) {
aiNodeAnim* na = anim->mChannels[i]; aiNodeAnim* na = anim->mChannels[i];
aiNode* nd = pScene->mRootNode->mChildren[i] = new aiNode(); aiNode* nd = pScene->mRootNode->mChildren[i] = new aiNode();
nd->mName = anim->mChannels[i]->mNodeName; nd->mName = anim->mChannels[i]->mNodeName;
nd->mParent = pScene->mRootNode; nd->mParent = pScene->mRootNode;
aiMatrix4x4::Translation(na->mPositionKeys[0].mValue, nd->mTransformation); aiMatrix4x4::Translation(na->mPositionKeys[0].mValue, nd->mTransformation);
} }
// Store the one and only animation in the scene // Store the one and only animation in the scene
pScene->mAnimations = new aiAnimation*[pScene->mNumAnimations=1]; pScene->mAnimations = new aiAnimation*[pScene->mNumAnimations=1];
pScene->mAnimations[0] = anim; pScene->mAnimations[0] = anim;
anim->mName.Set("$CSM_MasterAnim"); anim->mName.Set("$CSM_MasterAnim");
// mark the scene as incomplete and run SkeletonMeshBuilder on it // mark the scene as incomplete and run SkeletonMeshBuilder on it
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
if (!noSkeletonMesh) { if (!noSkeletonMesh) {
SkeletonMeshBuilder maker(pScene,pScene->mRootNode,true); SkeletonMeshBuilder maker(pScene,pScene->mRootNode,true);
} }
} }
#endif // !! ASSIMP_BUILD_NO_CSM_IMPORTER #endif // !! ASSIMP_BUILD_NO_CSM_IMPORTER

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h" #include "BaseImporter.h"
namespace Assimp { namespace Assimp {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Importer class to load MOCAPs in CharacterStudio Motion format. /** Importer class to load MOCAPs in CharacterStudio Motion format.
@ -60,30 +60,30 @@ namespace Assimp {
class CSMImporter : public BaseImporter class CSMImporter : public BaseImporter
{ {
public: public:
CSMImporter(); CSMImporter();
~CSMImporter(); ~CSMImporter();
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const; bool checkSig) const;
protected: protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
const aiImporterDesc* GetInfo () const; const aiImporterDesc* GetInfo () const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
void SetupProperties(const Importer* pImp); void SetupProperties(const Importer* pImp);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
void InternReadFile( const std::string& pFile, aiScene* pScene, void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler); IOSystem* pIOHandler);
private: private:
bool noSkeletonMesh; bool noSkeletonMesh;
}; // end of class CSMImporter }; // end of class CSMImporter
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
@ -56,21 +56,21 @@ using namespace Assimp;
CalcTangentsProcess::CalcTangentsProcess() CalcTangentsProcess::CalcTangentsProcess()
: configMaxAngle( AI_DEG_TO_RAD(45.f) ) : configMaxAngle( AI_DEG_TO_RAD(45.f) )
, configSourceUV( 0 ) { , configSourceUV( 0 ) {
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
CalcTangentsProcess::~CalcTangentsProcess() CalcTangentsProcess::~CalcTangentsProcess()
{ {
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
bool CalcTangentsProcess::IsActive( unsigned int pFlags) const bool CalcTangentsProcess::IsActive( unsigned int pFlags) const
{ {
return (pFlags & aiProcess_CalcTangentSpace) != 0; return (pFlags & aiProcess_CalcTangentSpace) != 0;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -79,12 +79,12 @@ void CalcTangentsProcess::SetupProperties(const Importer* pImp)
{ {
ai_assert( NULL != pImp ); ai_assert( NULL != pImp );
// get the current value of the property // get the current value of the property
configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE,45.f); configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE,45.f);
configMaxAngle = std::max(std::min(configMaxAngle,45.0f),0.0f); configMaxAngle = std::max(std::min(configMaxAngle,45.0f),0.0f);
configMaxAngle = AI_DEG_TO_RAD(configMaxAngle); configMaxAngle = AI_DEG_TO_RAD(configMaxAngle);
configSourceUV = pImp->GetPropertyInteger(AI_CONFIG_PP_CT_TEXTURE_CHANNEL_INDEX,0); configSourceUV = pImp->GetPropertyInteger(AI_CONFIG_PP_CT_TEXTURE_CHANNEL_INDEX,0);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -95,12 +95,12 @@ void CalcTangentsProcess::Execute( aiScene* pScene)
DefaultLogger::get()->debug("CalcTangentsProcess begin"); DefaultLogger::get()->debug("CalcTangentsProcess begin");
bool bHas = false; bool bHas = false;
for ( unsigned int a = 0; a < pScene->mNumMeshes; a++ ) { for ( unsigned int a = 0; a < pScene->mNumMeshes; a++ ) {
if(ProcessMesh( pScene->mMeshes[a],a))bHas = true; if(ProcessMesh( pScene->mMeshes[a],a))bHas = true;
} }
if ( bHas ) { if ( bHas ) {
DefaultLogger::get()->info("CalcTangentsProcess finished. Tangents have been calculated"); DefaultLogger::get()->info("CalcTangentsProcess finished. Tangents have been calculated");
} else { } else {
DefaultLogger::get()->debug("CalcTangentsProcess finished"); DefaultLogger::get()->debug("CalcTangentsProcess finished");
@ -111,106 +111,106 @@ void CalcTangentsProcess::Execute( aiScene* pScene)
// Calculates tangents and bitangents for the given mesh // Calculates tangents and bitangents for the given mesh
bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
{ {
// we assume that the mesh is still in the verbose vertex format where each face has its own set // we assume that the mesh is still in the verbose vertex format where each face has its own set
// of vertices and no vertices are shared between faces. Sadly I don't know any quick test to // of vertices and no vertices are shared between faces. Sadly I don't know any quick test to
// assert() it here. // assert() it here.
// assert( must be verbose, dammit); // assert( must be verbose, dammit);
if (pMesh->mTangents) // this implies that mBitangents is also there if (pMesh->mTangents) // this implies that mBitangents is also there
return false; return false;
// If the mesh consists of lines and/or points but not of // If the mesh consists of lines and/or points but not of
// triangles or higher-order polygons the normal vectors // triangles or higher-order polygons the normal vectors
// are undefined. // are undefined.
if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
{ {
DefaultLogger::get()->info("Tangents are undefined for line and point meshes"); DefaultLogger::get()->info("Tangents are undefined for line and point meshes");
return false; return false;
} }
// what we can check, though, is if the mesh has normals and texture coordinates. That's a requirement // what we can check, though, is if the mesh has normals and texture coordinates. That's a requirement
if( pMesh->mNormals == NULL) if( pMesh->mNormals == NULL)
{ {
DefaultLogger::get()->error("Failed to compute tangents; need normals"); DefaultLogger::get()->error("Failed to compute tangents; need normals");
return false; return false;
} }
if( configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV] ) if( configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV] )
{ {
DefaultLogger::get()->error((Formatter::format("Failed to compute tangents; need UV data in channel"),configSourceUV)); DefaultLogger::get()->error((Formatter::format("Failed to compute tangents; need UV data in channel"),configSourceUV));
return false; return false;
} }
const float angleEpsilon = 0.9999f; const float angleEpsilon = 0.9999f;
std::vector<bool> vertexDone( pMesh->mNumVertices, false); std::vector<bool> vertexDone( pMesh->mNumVertices, false);
const float qnan = get_qnan(); const float qnan = get_qnan();
// create space for the tangents and bitangents // create space for the tangents and bitangents
pMesh->mTangents = new aiVector3D[pMesh->mNumVertices]; pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices]; pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
const aiVector3D* meshPos = pMesh->mVertices; const aiVector3D* meshPos = pMesh->mVertices;
const aiVector3D* meshNorm = pMesh->mNormals; const aiVector3D* meshNorm = pMesh->mNormals;
const aiVector3D* meshTex = pMesh->mTextureCoords[configSourceUV]; const aiVector3D* meshTex = pMesh->mTextureCoords[configSourceUV];
aiVector3D* meshTang = pMesh->mTangents; aiVector3D* meshTang = pMesh->mTangents;
aiVector3D* meshBitang = pMesh->mBitangents; aiVector3D* meshBitang = pMesh->mBitangents;
// calculate the tangent and bitangent for every face // calculate the tangent and bitangent for every face
for( unsigned int a = 0; a < pMesh->mNumFaces; a++) for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
{ {
const aiFace& face = pMesh->mFaces[a]; const aiFace& face = pMesh->mFaces[a];
if (face.mNumIndices < 3) if (face.mNumIndices < 3)
{ {
// There are less than three indices, thus the tangent vector // There are less than three indices, thus the tangent vector
// is not defined. We are finished with these vertices now, // is not defined. We are finished with these vertices now,
// their tangent vectors are set to qnan. // their tangent vectors are set to qnan.
for (unsigned int i = 0; i < face.mNumIndices;++i) for (unsigned int i = 0; i < face.mNumIndices;++i)
{ {
unsigned int idx = face.mIndices[i]; unsigned int idx = face.mIndices[i];
vertexDone [idx] = true; vertexDone [idx] = true;
meshTang [idx] = aiVector3D(qnan); meshTang [idx] = aiVector3D(qnan);
meshBitang [idx] = aiVector3D(qnan); meshBitang [idx] = aiVector3D(qnan);
} }
continue; continue;
} }
// triangle or polygon... we always use only the first three indices. A polygon // triangle or polygon... we always use only the first three indices. A polygon
// is supposed to be planar anyways.... // is supposed to be planar anyways....
// FIXME: (thom) create correct calculation for multi-vertex polygons maybe? // FIXME: (thom) create correct calculation for multi-vertex polygons maybe?
const unsigned int p0 = face.mIndices[0], p1 = face.mIndices[1], p2 = face.mIndices[2]; const unsigned int p0 = face.mIndices[0], p1 = face.mIndices[1], p2 = face.mIndices[2];
// position differences p1->p2 and p1->p3 // position differences p1->p2 and p1->p3
aiVector3D v = meshPos[p1] - meshPos[p0], w = meshPos[p2] - meshPos[p0]; aiVector3D v = meshPos[p1] - meshPos[p0], w = meshPos[p2] - meshPos[p0];
// texture offset p1->p2 and p1->p3 // texture offset p1->p2 and p1->p3
float sx = meshTex[p1].x - meshTex[p0].x, sy = meshTex[p1].y - meshTex[p0].y; float sx = meshTex[p1].x - meshTex[p0].x, sy = meshTex[p1].y - meshTex[p0].y;
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 ( 0 == sx && 0 ==sy && 0 == tx && 0 == ty ) {
sx = 0.0; sy = 1.0; sx = 0.0; sy = 1.0;
tx = 1.0; ty = 0.0; tx = 1.0; ty = 0.0;
} }
// tangent points in the direction where to positive X axis of the texture coord's would point in model space // tangent points in the direction where to positive X axis of the texture coord's would point in model space
// bitangent's points along the positive Y axis of the texture coord's, respectively // bitangent's points along the positive Y axis of the texture coord's, respectively
aiVector3D tangent, bitangent; aiVector3D tangent, bitangent;
tangent.x = (w.x * sy - v.x * ty) * dirCorrection; tangent.x = (w.x * sy - v.x * ty) * dirCorrection;
tangent.y = (w.y * sy - v.y * ty) * dirCorrection; tangent.y = (w.y * sy - v.y * ty) * dirCorrection;
tangent.z = (w.z * sy - v.z * ty) * dirCorrection; tangent.z = (w.z * sy - v.z * ty) * dirCorrection;
bitangent.x = (w.x * sx - v.x * tx) * dirCorrection; bitangent.x = (w.x * sx - v.x * tx) * dirCorrection;
bitangent.y = (w.y * sx - v.y * tx) * dirCorrection; bitangent.y = (w.y * sx - v.y * tx) * dirCorrection;
bitangent.z = (w.z * sx - v.z * tx) * dirCorrection; bitangent.z = (w.z * sx - v.z * tx) * dirCorrection;
// store for every vertex of that face // store for every vertex of that face
for( unsigned int b = 0; b < face.mNumIndices; ++b ) { for( unsigned int b = 0; b < face.mNumIndices; ++b ) {
unsigned int p = face.mIndices[b]; unsigned int p = face.mIndices[b];
// project tangent and bitangent into the plane formed by the vertex' normal // project tangent and bitangent into the plane formed by the vertex' normal
aiVector3D localTangent = tangent - meshNorm[p] * (tangent * meshNorm[p]); aiVector3D localTangent = tangent - meshNorm[p] * (tangent * meshNorm[p]);
aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]); aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]);
localTangent.Normalize(); localBitangent.Normalize(); localTangent.Normalize(); localBitangent.Normalize();
// reconstruct tangent/bitangent according to normal and bitangent/tangent when it's infinite or NaN. // reconstruct tangent/bitangent according to normal and bitangent/tangent when it's infinite or NaN.
bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z); bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z);
@ -226,92 +226,92 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
} }
// and write it into the mesh. // and write it into the mesh.
meshTang[ p ] = localTangent; meshTang[ p ] = localTangent;
meshBitang[ p ] = localBitangent; meshBitang[ p ] = localBitangent;
} }
} }
// create a helper to quickly find locally close vertices among the vertex array // create a helper to quickly find locally close vertices among the vertex array
// FIX: check whether we can reuse the SpatialSort of a previous step // FIX: check whether we can reuse the SpatialSort of a previous step
SpatialSort* vertexFinder = NULL; SpatialSort* vertexFinder = NULL;
SpatialSort _vertexFinder; SpatialSort _vertexFinder;
float posEpsilon; float posEpsilon;
if (shared) if (shared)
{ {
std::vector<std::pair<SpatialSort,float> >* avf; std::vector<std::pair<SpatialSort,float> >* avf;
shared->GetProperty(AI_SPP_SPATIAL_SORT,avf); shared->GetProperty(AI_SPP_SPATIAL_SORT,avf);
if (avf) if (avf)
{ {
std::pair<SpatialSort,float>& blubb = avf->operator [] (meshIndex); std::pair<SpatialSort,float>& blubb = avf->operator [] (meshIndex);
vertexFinder = &blubb.first; vertexFinder = &blubb.first;
posEpsilon = blubb.second;; posEpsilon = blubb.second;;
} }
} }
if (!vertexFinder) if (!vertexFinder)
{ {
_vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D)); _vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D));
vertexFinder = &_vertexFinder; vertexFinder = &_vertexFinder;
posEpsilon = ComputePositionEpsilon(pMesh); posEpsilon = ComputePositionEpsilon(pMesh);
} }
std::vector<unsigned int> verticesFound; std::vector<unsigned int> verticesFound;
const float fLimit = cosf(configMaxAngle); const float fLimit = cosf(configMaxAngle);
std::vector<unsigned int> closeVertices; std::vector<unsigned int> closeVertices;
// in the second pass we now smooth out all tangents and bitangents at the same local position // in the second pass we now smooth out all tangents and bitangents at the same local position
// if they are not too far off. // if they are not too far off.
for( unsigned int a = 0; a < pMesh->mNumVertices; a++) for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
{ {
if( vertexDone[a]) if( vertexDone[a])
continue; continue;
const aiVector3D& origPos = pMesh->mVertices[a]; const aiVector3D& origPos = pMesh->mVertices[a];
const aiVector3D& origNorm = pMesh->mNormals[a]; const aiVector3D& origNorm = pMesh->mNormals[a];
const aiVector3D& origTang = pMesh->mTangents[a]; const aiVector3D& origTang = pMesh->mTangents[a];
const aiVector3D& origBitang = pMesh->mBitangents[a]; const aiVector3D& origBitang = pMesh->mBitangents[a];
closeVertices.resize( 0 ); closeVertices.resize( 0 );
// find all vertices close to that position // find all vertices close to that position
vertexFinder->FindPositions( origPos, posEpsilon, verticesFound); vertexFinder->FindPositions( origPos, posEpsilon, verticesFound);
closeVertices.reserve (verticesFound.size()+5); closeVertices.reserve (verticesFound.size()+5);
closeVertices.push_back( a); closeVertices.push_back( a);
// look among them for other vertices sharing the same normal and a close-enough tangent/bitangent // look among them for other vertices sharing the same normal and a close-enough tangent/bitangent
for( unsigned int b = 0; b < verticesFound.size(); b++) for( unsigned int b = 0; b < verticesFound.size(); b++)
{ {
unsigned int idx = verticesFound[b]; unsigned int idx = verticesFound[b];
if( vertexDone[idx]) if( vertexDone[idx])
continue; continue;
if( meshNorm[idx] * origNorm < angleEpsilon) if( meshNorm[idx] * origNorm < angleEpsilon)
continue; continue;
if( meshTang[idx] * origTang < fLimit) if( meshTang[idx] * origTang < fLimit)
continue; continue;
if( meshBitang[idx] * origBitang < fLimit) if( meshBitang[idx] * origBitang < fLimit)
continue; continue;
// it's similar enough -> add it to the smoothing group // it's similar enough -> add it to the smoothing group
closeVertices.push_back( idx); closeVertices.push_back( idx);
vertexDone[idx] = true; vertexDone[idx] = true;
} }
// smooth the tangents and bitangents of all vertices that were found to be close enough // smooth the tangents and bitangents of all vertices that were found to be close enough
aiVector3D smoothTangent( 0, 0, 0), smoothBitangent( 0, 0, 0); aiVector3D smoothTangent( 0, 0, 0), smoothBitangent( 0, 0, 0);
for( unsigned int b = 0; b < closeVertices.size(); ++b) for( unsigned int b = 0; b < closeVertices.size(); ++b)
{ {
smoothTangent += meshTang[ closeVertices[b] ]; smoothTangent += meshTang[ closeVertices[b] ];
smoothBitangent += meshBitang[ closeVertices[b] ]; smoothBitangent += meshBitang[ closeVertices[b] ];
} }
smoothTangent.Normalize(); smoothTangent.Normalize();
smoothBitangent.Normalize(); smoothBitangent.Normalize();
// and write it back into all affected tangents // and write it back into all affected tangents
for( unsigned int b = 0; b < closeVertices.size(); ++b) for( unsigned int b = 0; b < closeVertices.size(); ++b)
{ {
meshTang[ closeVertices[b] ] = smoothTangent; meshTang[ closeVertices[b] ] = smoothTangent;
meshBitang[ closeVertices[b] ] = smoothBitangent; meshBitang[ closeVertices[b] ] = smoothBitangent;
} }
} }
return true; return true;
} }

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -61,53 +61,53 @@ class ASSIMP_API_WINONLY CalcTangentsProcess : public BaseProcess
{ {
public: public:
CalcTangentsProcess(); CalcTangentsProcess();
~CalcTangentsProcess(); ~CalcTangentsProcess();
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the processing step is present in the given flag. /** Returns whether the processing step is present in the given flag.
* @param pFlags The processing flags the importer was called with. * @param pFlags The processing flags the importer was called with.
* A bitwise combination of #aiPostProcessSteps. * A bitwise combination of #aiPostProcessSteps.
* @return true if the process is present in this flag fields, * @return true if the process is present in this flag fields,
* false if not. * false if not.
*/ */
bool IsActive( unsigned int pFlags) const; bool IsActive( unsigned int pFlags) const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Called prior to ExecuteOnScene(). /** Called prior to ExecuteOnScene().
* The function is a request to the process to update its configuration * The function is a request to the process to update its configuration
* basing on the Importer's configuration property list. * basing on the Importer's configuration property list.
*/ */
void SetupProperties(const Importer* pImp); void SetupProperties(const Importer* pImp);
// setter for configMaxAngle // setter for configMaxAngle
inline void SetMaxSmoothAngle(float f) inline void SetMaxSmoothAngle(float f)
{ {
configMaxAngle =f; configMaxAngle =f;
} }
protected: protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Calculates tangents and bitangents for a specific mesh. /** Calculates tangents and bitangents for a specific mesh.
* @param pMesh The mesh to process. * @param pMesh The mesh to process.
* @param meshIndex Index of the mesh * @param meshIndex Index of the mesh
*/ */
bool ProcessMesh( aiMesh* pMesh, unsigned int meshIndex); bool ProcessMesh( aiMesh* pMesh, unsigned int meshIndex);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Executes the post processing step on the given imported data. /** Executes the post processing step on the given imported data.
* @param pScene The imported data to work at. * @param pScene The imported data to work at.
*/ */
void Execute( aiScene* pScene); void Execute( aiScene* pScene);
private: private:
/** Configuration option: maximum smoothing angle, in radians*/ /** Configuration option: maximum smoothing angle, in radians*/
float configMaxAngle; float configMaxAngle;
unsigned int configSourceUV; unsigned int configSourceUV;
}; };
} // end of namespace Assimp } // end of namespace Assimp

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -65,88 +65,88 @@ namespace Assimp
class ColladaExporter class ColladaExporter
{ {
public: public:
/// Constructor for a specific scene to export /// Constructor for a specific scene to export
ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file); ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file);
/// Destructor /// Destructor
virtual ~ColladaExporter(); virtual ~ColladaExporter();
protected: protected:
/// Starts writing the contents /// Starts writing the contents
void WriteFile(); void WriteFile();
/// Writes the asset header /// Writes the asset header
void WriteHeader(); void WriteHeader();
/// Writes the embedded textures /// Writes the embedded textures
void WriteTextures(); void WriteTextures();
/// Writes the material setup /// Writes the material setup
void WriteMaterials(); void WriteMaterials();
/// Writes the cameras library /// Writes the cameras library
void WriteCamerasLibrary(); void WriteCamerasLibrary();
// Write a camera entry // Write a camera entry
void WriteCamera(size_t pIndex); void WriteCamera(size_t pIndex);
/// Writes the cameras library /// Writes the cameras library
void WriteLightsLibrary(); void WriteLightsLibrary();
// Write a camera entry // Write a camera entry
void WriteLight(size_t pIndex); void WriteLight(size_t pIndex);
void WritePointLight(const aiLight *const light); void WritePointLight(const aiLight *const light);
void WriteDirectionalLight(const aiLight *const light); void WriteDirectionalLight(const aiLight *const light);
void WriteSpotLight(const aiLight *const light); void WriteSpotLight(const aiLight *const light);
void WriteAmbienttLight(const aiLight *const light); void WriteAmbienttLight(const aiLight *const light);
/// Writes the geometry library /// Writes the geometry library
void WriteGeometryLibrary(); void WriteGeometryLibrary();
/// Writes the given mesh /// Writes the given mesh
void WriteGeometry( size_t pIndex); void WriteGeometry( size_t pIndex);
enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color }; enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color };
/// Writes a float array of the given type /// Writes a float array of the given type
void WriteFloatArray( const std::string& pIdString, FloatDataType pType, const float* pData, size_t pElementCount); void WriteFloatArray( const std::string& pIdString, FloatDataType pType, const float* pData, size_t pElementCount);
/// Writes the scene library /// Writes the scene library
void WriteSceneLibrary(); void WriteSceneLibrary();
/// Recursively writes the given node /// Recursively writes the given node
void WriteNode( aiNode* pNode); void WriteNode( aiNode* pNode);
/// Enters a new xml element, which increases the indentation /// Enters a new xml element, which increases the indentation
void PushTag() { startstr.append( " "); } void PushTag() { startstr.append( " "); }
/// Leaves an element, decreasing the indentation /// Leaves an element, decreasing the indentation
void PopTag() { ai_assert( startstr.length() > 1); startstr.erase( startstr.length() - 2); } void PopTag() { ai_assert( startstr.length() > 1); startstr.erase( startstr.length() - 2); }
/// Creates a mesh ID for the given mesh /// Creates a mesh ID for the given mesh
std::string GetMeshId( size_t pIndex) const { return std::string( "meshId" ) + boost::lexical_cast<std::string> (pIndex); } std::string GetMeshId( size_t pIndex) const { return std::string( "meshId" ) + boost::lexical_cast<std::string> (pIndex); }
public: public:
/// Stringstream to write all output into /// Stringstream to write all output into
std::stringstream mOutput; std::stringstream mOutput;
protected: protected:
/// The IOSystem for output /// The IOSystem for output
IOSystem* mIOSystem; IOSystem* mIOSystem;
/// Path of the directory where the scene will be exported /// Path of the directory where the scene will be exported
const std::string mPath; const std::string mPath;
/// Name of the file (without extension) where the scene will be exported /// Name of the file (without extension) where the scene will be exported
const std::string mFile; const std::string mFile;
/// The scene to be written /// The scene to be written
const aiScene* mScene; const aiScene* mScene;
bool mSceneOwned; bool mSceneOwned;
/// current line start string, contains the current indentation for simple stream insertion /// current line start string, contains the current indentation for simple stream insertion
std::string startstr; std::string startstr;
/// current line end string for simple stream insertion /// current line end string for simple stream insertion
std::string endstr; std::string endstr;
// pair of color and texture - texture precedences color // pair of color and texture - texture precedences color
struct Surface struct Surface
@ -161,8 +161,8 @@ protected:
struct Property struct Property
{ {
bool exist; bool exist;
float value; float value;
Property() Property()
: exist(false) : exist(false)
, value(0.0f) , value(0.0f)
{} {}
@ -174,7 +174,7 @@ protected:
std::string name; std::string name;
std::string shading_model; std::string shading_model;
Surface ambient, diffuse, specular, emissive, reflective, transparent, normal; Surface ambient, diffuse, specular, emissive, reflective, transparent, normal;
Property shininess, transparency, index_refraction; Property shininess, transparency, index_refraction;
Material() {} Material() {}
}; };

View File

@ -4,7 +4,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -53,79 +53,79 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
struct aiMaterial; struct aiMaterial;
namespace Assimp { namespace Assimp {
namespace Collada { namespace Collada {
/** Collada file versions which evolved during the years ... */ /** Collada file versions which evolved during the years ... */
enum FormatVersion enum FormatVersion
{ {
FV_1_5_n, FV_1_5_n,
FV_1_4_n, FV_1_4_n,
FV_1_3_n FV_1_3_n
}; };
/** Transformation types that can be applied to a node */ /** Transformation types that can be applied to a node */
enum TransformType enum TransformType
{ {
TF_LOOKAT, TF_LOOKAT,
TF_ROTATE, TF_ROTATE,
TF_TRANSLATE, TF_TRANSLATE,
TF_SCALE, TF_SCALE,
TF_SKEW, TF_SKEW,
TF_MATRIX TF_MATRIX
}; };
/** Different types of input data to a vertex or face */ /** Different types of input data to a vertex or face */
enum InputType enum InputType
{ {
IT_Invalid, IT_Invalid,
IT_Vertex, // special type for per-index data referring to the <vertices> element carrying the per-vertex data. IT_Vertex, // special type for per-index data referring to the <vertices> element carrying the per-vertex data.
IT_Position, IT_Position,
IT_Normal, IT_Normal,
IT_Texcoord, IT_Texcoord,
IT_Color, IT_Color,
IT_Tangent, IT_Tangent,
IT_Bitangent IT_Bitangent
}; };
/** Contains all data for one of the different transformation types */ /** Contains all data for one of the different transformation types */
struct Transform struct Transform
{ {
std::string mID; ///< SID of the transform step, by which anim channels address their target node std::string mID; ///< SID of the transform step, by which anim channels address their target node
TransformType mType; TransformType mType;
float f[16]; ///< Interpretation of data depends on the type of the transformation float f[16]; ///< Interpretation of data depends on the type of the transformation
}; };
/** A collada camera. */ /** A collada camera. */
struct Camera struct Camera
{ {
Camera() Camera()
: mOrtho (false) : mOrtho (false)
, mHorFov (10e10f) , mHorFov (10e10f)
, mVerFov (10e10f) , mVerFov (10e10f)
, mAspect (10e10f) , mAspect (10e10f)
, mZNear (0.1f) , mZNear (0.1f)
, mZFar (1000.f) , mZFar (1000.f)
{} {}
// Name of camera // Name of camera
std::string mName; std::string mName;
// True if it is an orthografic camera // True if it is an orthografic camera
bool mOrtho; bool mOrtho;
//! Horizontal field of view in degrees //! Horizontal field of view in degrees
float mHorFov; float mHorFov;
//! Vertical field of view in degrees //! Vertical field of view in degrees
float mVerFov; float mVerFov;
//! Screen aspect //! Screen aspect
float mAspect; float mAspect;
//! Near& far z //! Near& far z
float mZNear, mZFar; float mZNear, mZFar;
}; };
#define ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET 1e9f #define ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET 1e9f
@ -133,70 +133,70 @@ struct Camera
/** A collada light source. */ /** A collada light source. */
struct Light struct Light
{ {
Light() Light()
: mType (aiLightSource_UNDEFINED) : mType (aiLightSource_UNDEFINED)
, mAttConstant (1.f) , mAttConstant (1.f)
, mAttLinear (0.f) , mAttLinear (0.f)
, mAttQuadratic (0.f) , mAttQuadratic (0.f)
, mFalloffAngle (180.f) , mFalloffAngle (180.f)
, mFalloffExponent (0.f) , mFalloffExponent (0.f)
, mPenumbraAngle (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET) , mPenumbraAngle (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET)
, mOuterAngle (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET) , mOuterAngle (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET)
, mIntensity (1.f) , mIntensity (1.f)
{} {}
//! Type of the light source aiLightSourceType + ambient //! Type of the light source aiLightSourceType + ambient
unsigned int mType; unsigned int mType;
//! Color of the light //! Color of the light
aiColor3D mColor; aiColor3D mColor;
//! Light attenuation //! Light attenuation
float mAttConstant,mAttLinear,mAttQuadratic; float mAttConstant,mAttLinear,mAttQuadratic;
//! Spot light falloff //! Spot light falloff
float mFalloffAngle; float mFalloffAngle;
float mFalloffExponent; float mFalloffExponent;
// ----------------------------------------------------- // -----------------------------------------------------
// FCOLLADA extension from here // FCOLLADA extension from here
//! ... related stuff from maja and max extensions //! ... related stuff from maja and max extensions
float mPenumbraAngle; float mPenumbraAngle;
float mOuterAngle; float mOuterAngle;
//! Common light intensity //! Common light intensity
float mIntensity; float mIntensity;
}; };
/** Short vertex index description */ /** Short vertex index description */
struct InputSemanticMapEntry struct InputSemanticMapEntry
{ {
InputSemanticMapEntry() InputSemanticMapEntry()
: mSet(0) : mSet(0)
, mType(IT_Invalid) , mType(IT_Invalid)
{} {}
//! Index of set, optional //! Index of set, optional
unsigned int mSet; unsigned int mSet;
//! Type of referenced vertex input //! Type of referenced vertex input
InputType mType; InputType mType;
}; };
/** Table to map from effect to vertex input semantics */ /** Table to map from effect to vertex input semantics */
struct SemanticMappingTable struct SemanticMappingTable
{ {
//! Name of material //! Name of material
std::string mMatName; std::string mMatName;
//! List of semantic map commands, grouped by effect semantic name //! List of semantic map commands, grouped by effect semantic name
std::map<std::string, InputSemanticMapEntry> mMap; std::map<std::string, InputSemanticMapEntry> mMap;
//! For std::find //! For std::find
bool operator == (const std::string& s) const { bool operator == (const std::string& s) const {
return s == mMatName; return s == mMatName;
} }
}; };
/** A reference to a mesh inside a node, including materials assigned to the various subgroups. /** A reference to a mesh inside a node, including materials assigned to the various subgroups.
@ -204,414 +204,414 @@ struct SemanticMappingTable
*/ */
struct MeshInstance struct MeshInstance
{ {
///< ID of the mesh or controller to be instanced ///< ID of the mesh or controller to be instanced
std::string mMeshOrController; std::string mMeshOrController;
///< Map of materials by the subgroup ID they're applied to ///< Map of materials by the subgroup ID they're applied to
std::map<std::string, SemanticMappingTable> mMaterials; std::map<std::string, SemanticMappingTable> mMaterials;
}; };
/** A reference to a camera inside a node*/ /** A reference to a camera inside a node*/
struct CameraInstance struct CameraInstance
{ {
///< ID of the camera ///< ID of the camera
std::string mCamera; std::string mCamera;
}; };
/** A reference to a light inside a node*/ /** A reference to a light inside a node*/
struct LightInstance struct LightInstance
{ {
///< ID of the camera ///< ID of the camera
std::string mLight; std::string mLight;
}; };
/** A reference to a node inside a node*/ /** A reference to a node inside a node*/
struct NodeInstance struct NodeInstance
{ {
///< ID of the node ///< ID of the node
std::string mNode; std::string mNode;
}; };
/** A node in a scene hierarchy */ /** A node in a scene hierarchy */
struct Node struct Node
{ {
std::string mName; std::string mName;
std::string mID; std::string mID;
std::string mSID; std::string mSID;
Node* mParent; Node* mParent;
std::vector<Node*> mChildren; std::vector<Node*> mChildren;
/** Operations in order to calculate the resulting transformation to parent. */ /** Operations in order to calculate the resulting transformation to parent. */
std::vector<Transform> mTransforms; std::vector<Transform> mTransforms;
/** Meshes at this node */ /** Meshes at this node */
std::vector<MeshInstance> mMeshes; std::vector<MeshInstance> mMeshes;
/** Lights at this node */ /** Lights at this node */
std::vector<LightInstance> mLights; std::vector<LightInstance> mLights;
/** Cameras at this node */ /** Cameras at this node */
std::vector<CameraInstance> mCameras; std::vector<CameraInstance> mCameras;
/** Node instances at this node */ /** Node instances at this node */
std::vector<NodeInstance> mNodeInstances; std::vector<NodeInstance> mNodeInstances;
/** Rootnodes: Name of primary camera, if any */ /** Rootnodes: Name of primary camera, if any */
std::string mPrimaryCamera; std::string mPrimaryCamera;
//! Constructor. Begin with a zero parent //! Constructor. Begin with a zero parent
Node() { Node() {
mParent = NULL; mParent = NULL;
} }
//! Destructor: delete all children subsequently //! Destructor: delete all children subsequently
~Node() { ~Node() {
for( std::vector<Node*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it) for( std::vector<Node*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it)
delete *it; delete *it;
} }
}; };
/** Data source array: either floats or strings */ /** Data source array: either floats or strings */
struct Data struct Data
{ {
bool mIsStringArray; bool mIsStringArray;
std::vector<float> mValues; std::vector<float> mValues;
std::vector<std::string> mStrings; std::vector<std::string> mStrings;
}; };
/** Accessor to a data array */ /** Accessor to a data array */
struct Accessor struct Accessor
{ {
size_t mCount; // in number of objects size_t mCount; // in number of objects
size_t mSize; // size of an object, in elements (floats or strings, mostly 1) size_t mSize; // size of an object, in elements (floats or strings, mostly 1)
size_t mOffset; // in number of values size_t mOffset; // in number of values
size_t mStride; // Stride in number of values size_t mStride; // Stride in number of values
std::vector<std::string> mParams; // names of the data streams in the accessors. Empty string tells to ignore. std::vector<std::string> mParams; // names of the data streams in the accessors. Empty string tells to ignore.
size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, thats XYZ, for a color RGBA and so on. size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, thats XYZ, for a color RGBA and so on.
// For example, SubOffset[0] denotes which of the values inside the object is the vector X component. // For example, SubOffset[0] denotes which of the values inside the object is the vector X component.
std::string mSource; // URL of the source array std::string mSource; // URL of the source array
mutable const Data* mData; // Pointer to the source array, if resolved. NULL else mutable const Data* mData; // Pointer to the source array, if resolved. NULL else
Accessor() Accessor()
{ {
mCount = 0; mSize = 0; mOffset = 0; mStride = 0; mData = NULL; mCount = 0; mSize = 0; mOffset = 0; mStride = 0; mData = NULL;
mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0; mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0;
} }
}; };
/** A single face in a mesh */ /** A single face in a mesh */
struct Face struct Face
{ {
std::vector<size_t> mIndices; std::vector<size_t> mIndices;
}; };
/** An input channel for mesh data, referring to a single accessor */ /** An input channel for mesh data, referring to a single accessor */
struct InputChannel struct InputChannel
{ {
InputType mType; // Type of the data InputType mType; // Type of the data
size_t mIndex; // Optional index, if multiple sets of the same data type are given size_t mIndex; // Optional index, if multiple sets of the same data type are given
size_t mOffset; // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better. size_t mOffset; // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better.
std::string mAccessor; // ID of the accessor where to read the actual values from. std::string mAccessor; // ID of the accessor where to read the actual values from.
mutable const Accessor* mResolved; // Pointer to the accessor, if resolved. NULL else mutable const Accessor* mResolved; // Pointer to the accessor, if resolved. NULL else
InputChannel() { mType = IT_Invalid; mIndex = 0; mOffset = 0; mResolved = NULL; } InputChannel() { mType = IT_Invalid; mIndex = 0; mOffset = 0; mResolved = NULL; }
}; };
/** Subset of a mesh with a certain material */ /** Subset of a mesh with a certain material */
struct SubMesh struct SubMesh
{ {
std::string mMaterial; ///< subgroup identifier std::string mMaterial; ///< subgroup identifier
size_t mNumFaces; ///< number of faces in this submesh size_t mNumFaces; ///< number of faces in this submesh
}; };
/** Contains data for a single mesh */ /** Contains data for a single mesh */
struct Mesh struct Mesh
{ {
Mesh() Mesh()
{ {
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
mNumUVComponents[i] = 2; mNumUVComponents[i] = 2;
} }
std::string mName; std::string mName;
// just to check if there's some sophisticated addressing involved... // just to check if there's some sophisticated addressing involved...
// which we don't support, and therefore should warn about. // which we don't support, and therefore should warn about.
std::string mVertexID; std::string mVertexID;
// Vertex data addressed by vertex indices // Vertex data addressed by vertex indices
std::vector<InputChannel> mPerVertexData; std::vector<InputChannel> mPerVertexData;
// actual mesh data, assembled on encounter of a <p> element. Verbose format, not indexed // actual mesh data, assembled on encounter of a <p> element. Verbose format, not indexed
std::vector<aiVector3D> mPositions; std::vector<aiVector3D> mPositions;
std::vector<aiVector3D> mNormals; std::vector<aiVector3D> mNormals;
std::vector<aiVector3D> mTangents; std::vector<aiVector3D> mTangents;
std::vector<aiVector3D> mBitangents; std::vector<aiVector3D> mBitangents;
std::vector<aiVector3D> mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; std::vector<aiVector3D> mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
std::vector<aiColor4D> mColors[AI_MAX_NUMBER_OF_COLOR_SETS]; std::vector<aiColor4D> mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS]; unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
// Faces. Stored are only the number of vertices for each face. // Faces. Stored are only the number of vertices for each face.
// 1 == point, 2 == line, 3 == triangle, 4+ == poly // 1 == point, 2 == line, 3 == triangle, 4+ == poly
std::vector<size_t> mFaceSize; std::vector<size_t> mFaceSize;
// Position indices for all faces in the sequence given in mFaceSize - // Position indices for all faces in the sequence given in mFaceSize -
// necessary for bone weight assignment // necessary for bone weight assignment
std::vector<size_t> mFacePosIndices; std::vector<size_t> mFacePosIndices;
// Submeshes in this mesh, each with a given material // Submeshes in this mesh, each with a given material
std::vector<SubMesh> mSubMeshes; std::vector<SubMesh> mSubMeshes;
}; };
/** Which type of primitives the ReadPrimitives() function is going to read */ /** Which type of primitives the ReadPrimitives() function is going to read */
enum PrimitiveType enum PrimitiveType
{ {
Prim_Invalid, Prim_Invalid,
Prim_Lines, Prim_Lines,
Prim_LineStrip, Prim_LineStrip,
Prim_Triangles, Prim_Triangles,
Prim_TriStrips, Prim_TriStrips,
Prim_TriFans, Prim_TriFans,
Prim_Polylist, Prim_Polylist,
Prim_Polygon Prim_Polygon
}; };
/** A skeleton controller to deform a mesh with the use of joints */ /** A skeleton controller to deform a mesh with the use of joints */
struct Controller struct Controller
{ {
// the URL of the mesh deformed by the controller. // the URL of the mesh deformed by the controller.
std::string mMeshId; std::string mMeshId;
// accessor URL of the joint names // accessor URL of the joint names
std::string mJointNameSource; std::string mJointNameSource;
///< The bind shape matrix, as array of floats. I'm not sure what this matrix actually describes, but it can't be ignored in all cases ///< The bind shape matrix, as array of floats. I'm not sure what this matrix actually describes, but it can't be ignored in all cases
float mBindShapeMatrix[16]; float mBindShapeMatrix[16];
// accessor URL of the joint inverse bind matrices // accessor URL of the joint inverse bind matrices
std::string mJointOffsetMatrixSource; std::string mJointOffsetMatrixSource;
// input channel: joint names. // input channel: joint names.
InputChannel mWeightInputJoints; InputChannel mWeightInputJoints;
// input channel: joint weights // input channel: joint weights
InputChannel mWeightInputWeights; InputChannel mWeightInputWeights;
// Number of weights per vertex. // Number of weights per vertex.
std::vector<size_t> mWeightCounts; std::vector<size_t> mWeightCounts;
// JointIndex-WeightIndex pairs for all vertices // JointIndex-WeightIndex pairs for all vertices
std::vector< std::pair<size_t, size_t> > mWeights; std::vector< std::pair<size_t, size_t> > mWeights;
}; };
/** A collada material. Pretty much the only member is a reference to an effect. */ /** A collada material. Pretty much the only member is a reference to an effect. */
struct Material struct Material
{ {
std::string mName; std::string mName;
std::string mEffect; std::string mEffect;
}; };
/** Type of the effect param */ /** Type of the effect param */
enum ParamType enum ParamType
{ {
Param_Sampler, Param_Sampler,
Param_Surface Param_Surface
}; };
/** A param for an effect. Might be of several types, but they all just refer to each other, so I summarize them */ /** A param for an effect. Might be of several types, but they all just refer to each other, so I summarize them */
struct EffectParam struct EffectParam
{ {
ParamType mType; ParamType mType;
std::string mReference; // to which other thing the param is referring to. std::string mReference; // to which other thing the param is referring to.
}; };
/** Shading type supported by the standard effect spec of Collada */ /** Shading type supported by the standard effect spec of Collada */
enum ShadeType enum ShadeType
{ {
Shade_Invalid, Shade_Invalid,
Shade_Constant, Shade_Constant,
Shade_Lambert, Shade_Lambert,
Shade_Phong, Shade_Phong,
Shade_Blinn Shade_Blinn
}; };
/** Represents a texture sampler in collada */ /** Represents a texture sampler in collada */
struct Sampler struct Sampler
{ {
Sampler() Sampler()
: mWrapU (true) : mWrapU (true)
, mWrapV (true) , mWrapV (true)
, mMirrorU () , mMirrorU ()
, mMirrorV () , mMirrorV ()
, mOp (aiTextureOp_Multiply) , mOp (aiTextureOp_Multiply)
, mUVId (UINT_MAX) , mUVId (UINT_MAX)
, mWeighting (1.f) , mWeighting (1.f)
, mMixWithPrevious (1.f) , mMixWithPrevious (1.f)
{} {}
/** Name of image reference /** Name of image reference
*/ */
std::string mName; std::string mName;
/** Wrap U? /** Wrap U?
*/ */
bool mWrapU; bool mWrapU;
/** Wrap V? /** Wrap V?
*/ */
bool mWrapV; bool mWrapV;
/** Mirror U? /** Mirror U?
*/ */
bool mMirrorU; bool mMirrorU;
/** Mirror V? /** Mirror V?
*/ */
bool mMirrorV; bool mMirrorV;
/** Blend mode /** Blend mode
*/ */
aiTextureOp mOp; aiTextureOp mOp;
/** UV transformation /** UV transformation
*/ */
aiUVTransform mTransform; aiUVTransform mTransform;
/** Name of source UV channel /** Name of source UV channel
*/ */
std::string mUVChannel; std::string mUVChannel;
/** Resolved UV channel index or UINT_MAX if not known /** Resolved UV channel index or UINT_MAX if not known
*/ */
unsigned int mUVId; unsigned int mUVId;
// OKINO/MAX3D extensions from here // OKINO/MAX3D extensions from here
// ------------------------------------------------------- // -------------------------------------------------------
/** Weighting factor /** Weighting factor
*/ */
float mWeighting; float mWeighting;
/** Mixing factor from OKINO /** Mixing factor from OKINO
*/ */
float mMixWithPrevious; float mMixWithPrevious;
}; };
/** A collada effect. Can contain about anything according to the Collada spec, /** A collada effect. Can contain about anything according to the Collada spec,
but we limit our version to a reasonable subset. */ but we limit our version to a reasonable subset. */
struct Effect struct Effect
{ {
// Shading mode // Shading mode
ShadeType mShadeType; ShadeType mShadeType;
// Colors // Colors
aiColor4D mEmissive, mAmbient, mDiffuse, mSpecular, aiColor4D mEmissive, mAmbient, mDiffuse, mSpecular,
mTransparent, mReflective; mTransparent, mReflective;
// Textures // Textures
Sampler mTexEmissive, mTexAmbient, mTexDiffuse, mTexSpecular, Sampler mTexEmissive, mTexAmbient, mTexDiffuse, mTexSpecular,
mTexTransparent, mTexBump, mTexReflective; mTexTransparent, mTexBump, mTexReflective;
// Scalar factory // Scalar factory
float mShininess, mRefractIndex, mReflectivity; float mShininess, mRefractIndex, mReflectivity;
float mTransparency; float mTransparency;
bool mHasTransparency; bool mHasTransparency;
bool mRGBTransparency; bool mRGBTransparency;
// local params referring to each other by their SID // local params referring to each other by their SID
typedef std::map<std::string, Collada::EffectParam> ParamLibrary; typedef std::map<std::string, Collada::EffectParam> ParamLibrary;
ParamLibrary mParams; ParamLibrary mParams;
// MAX3D extensions // MAX3D extensions
// --------------------------------------------------------- // ---------------------------------------------------------
// Double-sided? // Double-sided?
bool mDoubleSided, mWireframe, mFaceted; bool mDoubleSided, mWireframe, mFaceted;
Effect() Effect()
: mShadeType (Shade_Phong) : mShadeType (Shade_Phong)
, mEmissive ( 0, 0, 0, 1) , mEmissive ( 0, 0, 0, 1)
, mAmbient ( 0.1f, 0.1f, 0.1f, 1) , mAmbient ( 0.1f, 0.1f, 0.1f, 1)
, mDiffuse ( 0.6f, 0.6f, 0.6f, 1) , mDiffuse ( 0.6f, 0.6f, 0.6f, 1)
, mSpecular ( 0.4f, 0.4f, 0.4f, 1) , mSpecular ( 0.4f, 0.4f, 0.4f, 1)
, mTransparent ( 0, 0, 0, 1) , mTransparent ( 0, 0, 0, 1)
, mShininess (10.0f) , mShininess (10.0f)
, mRefractIndex (1.f) , mRefractIndex (1.f)
, mReflectivity (1.f) , mReflectivity (1.f)
, mTransparency (1.f) , mTransparency (1.f)
, mHasTransparency (false) , mHasTransparency (false)
, mRGBTransparency(false) , mRGBTransparency(false)
, mDoubleSided (false) , mDoubleSided (false)
, mWireframe (false) , mWireframe (false)
, mFaceted (false) , mFaceted (false)
{ {
} }
}; };
/** An image, meaning texture */ /** An image, meaning texture */
struct Image struct Image
{ {
std::string mFileName; std::string mFileName;
/** If image file name is zero, embedded image data /** If image file name is zero, embedded image data
*/ */
std::vector<uint8_t> mImageData; std::vector<uint8_t> mImageData;
/** If image file name is zero, file format of /** If image file name is zero, file format of
* embedded image data. * embedded image data.
*/ */
std::string mEmbeddedFormat; std::string mEmbeddedFormat;
}; };
/** An animation channel. */ /** An animation channel. */
struct AnimationChannel struct AnimationChannel
{ {
/** URL of the data to animate. Could be about anything, but we support only the /** URL of the data to animate. Could be about anything, but we support only the
* "NodeID/TransformID.SubElement" notation * "NodeID/TransformID.SubElement" notation
*/ */
std::string mTarget; std::string mTarget;
/** Source URL of the time values. Collada calls them "input". Meh. */ /** Source URL of the time values. Collada calls them "input". Meh. */
std::string mSourceTimes; std::string mSourceTimes;
/** Source URL of the value values. Collada calls them "output". */ /** Source URL of the value values. Collada calls them "output". */
std::string mSourceValues; std::string mSourceValues;
}; };
/** An animation. Container for 0-x animation channels or 0-x animations */ /** An animation. Container for 0-x animation channels or 0-x animations */
struct Animation struct Animation
{ {
/** Anim name */ /** Anim name */
std::string mName; std::string mName;
/** the animation channels, if any */ /** the animation channels, if any */
std::vector<AnimationChannel> mChannels; std::vector<AnimationChannel> mChannels;
/** the sub-animations, if any */ /** the sub-animations, if any */
std::vector<Animation*> mSubAnims; std::vector<Animation*> mSubAnims;
/** Destructor */ /** Destructor */
~Animation() ~Animation()
{ {
for( std::vector<Animation*>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it) for( std::vector<Animation*>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it)
delete *it; delete *it;
} }
}; };
/** Description of a collada animation channel which has been determined to affect the current node */ /** Description of a collada animation channel which has been determined to affect the current node */
struct ChannelEntry struct ChannelEntry
{ {
const Collada::AnimationChannel* mChannel; ///> the source channel const Collada::AnimationChannel* mChannel; ///> the source channel
std::string mTransformId; // the ID of the transformation step of the node which is influenced std::string mTransformId; // the ID of the transformation step of the node which is influenced
size_t mTransformIndex; // Index into the node's transform chain to apply the channel to size_t mTransformIndex; // Index into the node's transform chain to apply the channel to
size_t mSubElement; // starting index inside the transform data size_t mSubElement; // starting index inside the transform data
// resolved data references // resolved data references
const Collada::Accessor* mTimeAccessor; ///> Collada accessor to the time values const Collada::Accessor* mTimeAccessor; ///> Collada accessor to the time values
const Collada::Data* mTimeData; ///> Source data array for the time values const Collada::Data* mTimeData; ///> Source data array for the time values
const Collada::Accessor* mValueAccessor; ///> Collada accessor to the key value values const Collada::Accessor* mValueAccessor; ///> Collada accessor to the key value values
const Collada::Data* mValueData; ///> Source datat array for the key value values const Collada::Data* mValueData; ///> Source datat array for the key value values
ChannelEntry() ChannelEntry()
: mChannel() : mChannel()
, mTransformIndex() , mTransformIndex()
, mSubElement() , mSubElement()

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -57,26 +57,26 @@ namespace Assimp
struct ColladaMeshIndex struct ColladaMeshIndex
{ {
std::string mMeshID; std::string mMeshID;
size_t mSubMesh; size_t mSubMesh;
std::string mMaterial; std::string mMaterial;
ColladaMeshIndex( const std::string& pMeshID, size_t pSubMesh, const std::string& pMaterial) ColladaMeshIndex( const std::string& pMeshID, size_t pSubMesh, const std::string& pMaterial)
: mMeshID( pMeshID), mSubMesh( pSubMesh), mMaterial( pMaterial) : mMeshID( pMeshID), mSubMesh( pSubMesh), mMaterial( pMaterial)
{ } { }
bool operator < (const ColladaMeshIndex& p) const bool operator < (const ColladaMeshIndex& p) const
{ {
if( mMeshID == p.mMeshID) if( mMeshID == p.mMeshID)
{ {
if( mSubMesh == p.mSubMesh) if( mSubMesh == p.mSubMesh)
return mMaterial < p.mMaterial; return mMaterial < p.mMaterial;
else else
return mSubMesh < p.mSubMesh; return mSubMesh < p.mSubMesh;
} else } else
{ {
return mMeshID < p.mMeshID; return mMeshID < p.mMeshID;
} }
} }
}; };
/** Loader class to read Collada scenes. Collada is over-engineered to death, with every new iteration bringing /** Loader class to read Collada scenes. Collada is over-engineered to death, with every new iteration bringing
@ -85,166 +85,166 @@ struct ColladaMeshIndex
class ColladaLoader : public BaseImporter class ColladaLoader : public BaseImporter
{ {
public: public:
ColladaLoader(); ColladaLoader();
~ColladaLoader(); ~ColladaLoader();
public: public:
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. */ * See BaseImporter::CanRead() for details. */
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const; bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
protected: protected:
/** Return importer meta information. /** Return importer meta information.
* See #BaseImporter::GetInfo for the details * See #BaseImporter::GetInfo for the details
*/ */
const aiImporterDesc* GetInfo () const; const aiImporterDesc* GetInfo () const;
void SetupProperties(const Importer* pImp); void SetupProperties(const Importer* pImp);
/** Imports the given file into the given scene structure. /** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details * See BaseImporter::InternReadFile() for details
*/ */
void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
/** Recursively constructs a scene node for the given parser node and returns it. */ /** Recursively constructs a scene node for the given parser node and returns it. */
aiNode* BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode); aiNode* BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode);
/** Resolve node instances */ /** Resolve node instances */
void ResolveNodeInstances( const ColladaParser& pParser, const Collada::Node* pNode, void ResolveNodeInstances( const ColladaParser& pParser, const Collada::Node* pNode,
std::vector<const Collada::Node*>& resolved); std::vector<const Collada::Node*>& resolved);
/** Builds meshes for the given node and references them */ /** Builds meshes for the given node and references them */
void BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode, void BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode,
aiNode* pTarget); aiNode* pTarget);
/** Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh */ /** Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh */
aiMesh* CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh, aiMesh* CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh,
const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace); const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace);
/** Builds cameras for the given node and references them */ /** Builds cameras for the given node and references them */
void BuildCamerasForNode( const ColladaParser& pParser, const Collada::Node* pNode, void BuildCamerasForNode( const ColladaParser& pParser, const Collada::Node* pNode,
aiNode* pTarget); aiNode* pTarget);
/** Builds lights for the given node and references them */ /** Builds lights for the given node and references them */
void BuildLightsForNode( const ColladaParser& pParser, const Collada::Node* pNode, void BuildLightsForNode( const ColladaParser& pParser, const Collada::Node* pNode,
aiNode* pTarget); aiNode* pTarget);
/** Stores all meshes in the given scene */ /** Stores all meshes in the given scene */
void StoreSceneMeshes( aiScene* pScene); void StoreSceneMeshes( aiScene* pScene);
/** Stores all materials in the given scene */ /** Stores all materials in the given scene */
void StoreSceneMaterials( aiScene* pScene); void StoreSceneMaterials( aiScene* pScene);
/** Stores all lights in the given scene */ /** Stores all lights in the given scene */
void StoreSceneLights( aiScene* pScene); void StoreSceneLights( aiScene* pScene);
/** Stores all cameras in the given scene */ /** Stores all cameras in the given scene */
void StoreSceneCameras( aiScene* pScene); void StoreSceneCameras( aiScene* pScene);
/** Stores all textures in the given scene */ /** Stores all textures in the given scene */
void StoreSceneTextures( aiScene* pScene); void StoreSceneTextures( aiScene* pScene);
/** Stores all animations /** Stores all animations
* @param pScene target scene to store the anims * @param pScene target scene to store the anims
*/ */
void StoreAnimations( aiScene* pScene, const ColladaParser& pParser); void StoreAnimations( aiScene* pScene, const ColladaParser& pParser);
/** Stores all animations for the given source anim and its nested child animations /** Stores all animations for the given source anim and its nested child animations
* @param pScene target scene to store the anims * @param pScene target scene to store the anims
* @param pSrcAnim the source animation to process * @param pSrcAnim the source animation to process
* @param pPrefix Prefix to the name in case of nested animations * @param pPrefix Prefix to the name in case of nested animations
*/ */
void StoreAnimations( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string& pPrefix); void StoreAnimations( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string& pPrefix);
/** Constructs the animation for the given source anim */ /** Constructs the animation for the given source anim */
void CreateAnimation( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string& pName); void CreateAnimation( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string& pName);
/** Constructs materials from the collada material definitions */ /** Constructs materials from the collada material definitions */
void BuildMaterials( ColladaParser& pParser, aiScene* pScene); void BuildMaterials( ColladaParser& pParser, aiScene* pScene);
/** Fill materials from the collada material definitions */ /** Fill materials from the collada material definitions */
void FillMaterials( const ColladaParser& pParser, aiScene* pScene); void FillMaterials( const ColladaParser& pParser, aiScene* pScene);
/** Resolve UV channel mappings*/ /** Resolve UV channel mappings*/
void ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler, void ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler,
const Collada::SemanticMappingTable& table); const Collada::SemanticMappingTable& table);
/** Add a texture and all of its sampling properties to a material*/ /** Add a texture and all of its sampling properties to a material*/
void AddTexture ( aiMaterial& mat, const ColladaParser& pParser, void AddTexture ( aiMaterial& mat, const ColladaParser& pParser,
const Collada::Effect& effect, const Collada::Effect& effect,
const Collada::Sampler& sampler, const Collada::Sampler& sampler,
aiTextureType type, unsigned int idx = 0); aiTextureType type, unsigned int idx = 0);
/** Resolves the texture name for the given effect texture entry */ /** Resolves the texture name for the given effect texture entry */
aiString FindFilenameForEffectTexture( const ColladaParser& pParser, aiString FindFilenameForEffectTexture( const ColladaParser& pParser,
const Collada::Effect& pEffect, const std::string& pName); const Collada::Effect& pEffect, const std::string& pName);
/** Converts a path read from a collada file to the usual representation */ /** Converts a path read from a collada file to the usual representation */
void ConvertPath( aiString& ss); void ConvertPath( aiString& ss);
/** Reads a float value from an accessor and its data array. /** Reads a float value from an accessor and its data array.
* @param pAccessor The accessor to use for reading * @param pAccessor The accessor to use for reading
* @param pData The data array to read from * @param pData The data array to read from
* @param pIndex The index of the element to retrieve * @param pIndex The index of the element to retrieve
* @param pOffset Offset into the element, for multipart elements such as vectors or matrices * @param pOffset Offset into the element, for multipart elements such as vectors or matrices
* @return the specified value * @return the specified value
*/ */
float ReadFloat( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex, size_t pOffset) const; float ReadFloat( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex, size_t pOffset) const;
/** Reads a string value from an accessor and its data array. /** Reads a string value from an accessor and its data array.
* @param pAccessor The accessor to use for reading * @param pAccessor The accessor to use for reading
* @param pData The data array to read from * @param pData The data array to read from
* @param pIndex The index of the element to retrieve * @param pIndex The index of the element to retrieve
* @return the specified value * @return the specified value
*/ */
const std::string& ReadString( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex) const; const std::string& ReadString( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex) const;
/** Recursively collects all nodes into the given array */ /** Recursively collects all nodes into the given array */
void CollectNodes( const aiNode* pNode, std::vector<const aiNode*>& poNodes) const; void CollectNodes( const aiNode* pNode, std::vector<const aiNode*>& poNodes) const;
/** Finds a node in the collada scene by the given name */ /** Finds a node in the collada scene by the given name */
const Collada::Node* FindNode( const Collada::Node* pNode, const std::string& pName) const; const Collada::Node* FindNode( const Collada::Node* pNode, const std::string& pName) const;
/** Finds a node in the collada scene by the given SID */ /** Finds a node in the collada scene by the given SID */
const Collada::Node* FindNodeBySID( const Collada::Node* pNode, const std::string& pSID) const; const Collada::Node* FindNodeBySID( const Collada::Node* pNode, const std::string& pSID) const;
/** Finds a proper name for a node derived from the collada-node's properties */ /** Finds a proper name for a node derived from the collada-node's properties */
std::string FindNameForNode( const Collada::Node* pNode); std::string FindNameForNode( const Collada::Node* pNode);
protected: protected:
/** Filename, for a verbose error message */ /** Filename, for a verbose error message */
std::string mFileName; std::string mFileName;
/** Which mesh-material compound was stored under which mesh ID */ /** Which mesh-material compound was stored under which mesh ID */
std::map<ColladaMeshIndex, size_t> mMeshIndexByID; std::map<ColladaMeshIndex, size_t> mMeshIndexByID;
/** Which material was stored under which index in the scene */ /** Which material was stored under which index in the scene */
std::map<std::string, size_t> mMaterialIndexByName; std::map<std::string, size_t> mMaterialIndexByName;
/** Accumulated meshes for the target scene */ /** Accumulated meshes for the target scene */
std::vector<aiMesh*> mMeshes; std::vector<aiMesh*> mMeshes;
/** Temporary material list */ /** Temporary material list */
std::vector<std::pair<Collada::Effect*, aiMaterial*> > newMats; std::vector<std::pair<Collada::Effect*, aiMaterial*> > newMats;
/** Temporary camera list */ /** Temporary camera list */
std::vector<aiCamera*> mCameras; std::vector<aiCamera*> mCameras;
/** Temporary light list */ /** Temporary light list */
std::vector<aiLight*> mLights; std::vector<aiLight*> mLights;
/** Temporary texture list */ /** Temporary texture list */
std::vector<aiTexture*> mTextures; std::vector<aiTexture*> mTextures;
/** Accumulated animations for the target scene */ /** Accumulated animations for the target scene */
std::vector<aiAnimation*> mAnims; std::vector<aiAnimation*> mAnims;
bool noSkeletonMesh; bool noSkeletonMesh;
bool ignoreUpDirection; bool ignoreUpDirection;
bool invertTransparency; bool invertTransparency;
/** Used by FindNameForNode() to generate unique node names */ /** Used by FindNameForNode() to generate unique node names */
unsigned int mNodeNameCounter; unsigned int mNodeNameCounter;
}; };
} // end of namespace Assimp } // end of namespace Assimp

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -61,279 +61,279 @@ namespace Assimp
*/ */
class ColladaParser class ColladaParser
{ {
friend class ColladaLoader; friend class ColladaLoader;
protected: protected:
/** Constructor from XML file */ /** Constructor from XML file */
ColladaParser( IOSystem* pIOHandler, const std::string& pFile); ColladaParser( IOSystem* pIOHandler, const std::string& pFile);
/** Destructor */ /** Destructor */
~ColladaParser(); ~ColladaParser();
/** Reads the contents of the file */ /** Reads the contents of the file */
void ReadContents(); void ReadContents();
/** Reads the structure of the file */ /** Reads the structure of the file */
void ReadStructure(); void ReadStructure();
/** Reads asset informations such as coordinate system informations and legal blah */ /** Reads asset informations such as coordinate system informations and legal blah */
void ReadAssetInfo(); void ReadAssetInfo();
/** Reads the animation library */ /** Reads the animation library */
void ReadAnimationLibrary(); void ReadAnimationLibrary();
/** Reads an animation into the given parent structure */ /** Reads an animation into the given parent structure */
void ReadAnimation( Collada::Animation* pParent); void ReadAnimation( Collada::Animation* pParent);
/** Reads an animation sampler into the given anim channel */ /** Reads an animation sampler into the given anim channel */
void ReadAnimationSampler( Collada::AnimationChannel& pChannel); void ReadAnimationSampler( Collada::AnimationChannel& pChannel);
/** Reads the skeleton controller library */ /** Reads the skeleton controller library */
void ReadControllerLibrary(); void ReadControllerLibrary();
/** Reads a controller into the given mesh structure */ /** Reads a controller into the given mesh structure */
void ReadController( Collada::Controller& pController); void ReadController( Collada::Controller& pController);
/** Reads the joint definitions for the given controller */ /** Reads the joint definitions for the given controller */
void ReadControllerJoints( Collada::Controller& pController); void ReadControllerJoints( Collada::Controller& pController);
/** Reads the joint weights for the given controller */ /** Reads the joint weights for the given controller */
void ReadControllerWeights( Collada::Controller& pController); void ReadControllerWeights( Collada::Controller& pController);
/** Reads the image library contents */ /** Reads the image library contents */
void ReadImageLibrary(); void ReadImageLibrary();
/** Reads an image entry into the given image */ /** Reads an image entry into the given image */
void ReadImage( Collada::Image& pImage); void ReadImage( Collada::Image& pImage);
/** Reads the material library */ /** Reads the material library */
void ReadMaterialLibrary(); void ReadMaterialLibrary();
/** Reads a material entry into the given material */ /** Reads a material entry into the given material */
void ReadMaterial( Collada::Material& pMaterial); void ReadMaterial( Collada::Material& pMaterial);
/** Reads the camera library */ /** Reads the camera library */
void ReadCameraLibrary(); void ReadCameraLibrary();
/** Reads a camera entry into the given camera */ /** Reads a camera entry into the given camera */
void ReadCamera( Collada::Camera& pCamera); void ReadCamera( Collada::Camera& pCamera);
/** Reads the light library */ /** Reads the light library */
void ReadLightLibrary(); void ReadLightLibrary();
/** Reads a light entry into the given light */ /** Reads a light entry into the given light */
void ReadLight( Collada::Light& pLight); void ReadLight( Collada::Light& pLight);
/** Reads the effect library */ /** Reads the effect library */
void ReadEffectLibrary(); void ReadEffectLibrary();
/** Reads an effect entry into the given effect*/ /** Reads an effect entry into the given effect*/
void ReadEffect( Collada::Effect& pEffect); void ReadEffect( Collada::Effect& pEffect);
/** Reads an COMMON effect profile */ /** Reads an COMMON effect profile */
void ReadEffectProfileCommon( Collada::Effect& pEffect); void ReadEffectProfileCommon( Collada::Effect& pEffect);
/** Read sampler properties */ /** Read sampler properties */
void ReadSamplerProperties( Collada::Sampler& pSampler); void ReadSamplerProperties( Collada::Sampler& pSampler);
/** Reads an effect entry containing a color or a texture defining that color */ /** Reads an effect entry containing a color or a texture defining that color */
void ReadEffectColor( aiColor4D& pColor, Collada::Sampler& pSampler); void ReadEffectColor( aiColor4D& pColor, Collada::Sampler& pSampler);
/** Reads an effect entry containing a float */ /** Reads an effect entry containing a float */
void ReadEffectFloat( float& pFloat); void ReadEffectFloat( float& pFloat);
/** Reads an effect parameter specification of any kind */ /** Reads an effect parameter specification of any kind */
void ReadEffectParam( Collada::EffectParam& pParam); void ReadEffectParam( Collada::EffectParam& pParam);
/** Reads the geometry library contents */ /** Reads the geometry library contents */
void ReadGeometryLibrary(); void ReadGeometryLibrary();
/** Reads a geometry from the geometry library. */ /** Reads a geometry from the geometry library. */
void ReadGeometry( Collada::Mesh* pMesh); void ReadGeometry( Collada::Mesh* pMesh);
/** Reads a mesh from the geometry library */ /** Reads a mesh from the geometry library */
void ReadMesh( Collada::Mesh* pMesh); void ReadMesh( Collada::Mesh* pMesh);
/** Reads a source element - a combination of raw data and an accessor defining /** Reads a source element - a combination of raw data and an accessor defining
* things that should not be redefinable. Yes, that's another rant. * things that should not be redefinable. Yes, that's another rant.
*/ */
void ReadSource(); void ReadSource();
/** Reads a data array holding a number of elements, and stores it in the global library. /** Reads a data array holding a number of elements, and stores it in the global library.
* Currently supported are array of floats and arrays of strings. * Currently supported are array of floats and arrays of strings.
*/ */
void ReadDataArray(); void ReadDataArray();
/** Reads an accessor and stores it in the global library under the given ID - /** Reads an accessor and stores it in the global library under the given ID -
* accessors use the ID of the parent <source> element * accessors use the ID of the parent <source> element
*/ */
void ReadAccessor( const std::string& pID); void ReadAccessor( const std::string& pID);
/** Reads input declarations of per-vertex mesh data into the given mesh */ /** Reads input declarations of per-vertex mesh data into the given mesh */
void ReadVertexData( Collada::Mesh* pMesh); void ReadVertexData( Collada::Mesh* pMesh);
/** Reads input declarations of per-index mesh data into the given mesh */ /** Reads input declarations of per-index mesh data into the given mesh */
void ReadIndexData( Collada::Mesh* pMesh); void ReadIndexData( Collada::Mesh* pMesh);
/** Reads a single input channel element and stores it in the given array, if valid */ /** Reads a single input channel element and stores it in the given array, if valid */
void ReadInputChannel( std::vector<Collada::InputChannel>& poChannels); void ReadInputChannel( std::vector<Collada::InputChannel>& poChannels);
/** Reads a <p> primitive index list and assembles the mesh data into the given mesh */ /** Reads a <p> primitive index list and assembles the mesh data into the given mesh */
size_t ReadPrimitives( Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels, size_t ReadPrimitives( Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels,
size_t pNumPrimitives, const std::vector<size_t>& pVCount, Collada::PrimitiveType pPrimType); size_t pNumPrimitives, const std::vector<size_t>& pVCount, Collada::PrimitiveType pPrimType);
/** Copies the data for a single primitive into the mesh, based on the InputChannels */ /** Copies the data for a single primitive into the mesh, based on the InputChannels */
void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset,
Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels, Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels,
size_t currentPrimitive, const std::vector<size_t>& indices); size_t currentPrimitive, const std::vector<size_t>& indices);
/** Reads one triangle of a tristrip into the mesh */ /** Reads one triangle of a tristrip into the mesh */
void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh* pMesh, void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh* pMesh,
std::vector<Collada::InputChannel>& pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t>& indices); std::vector<Collada::InputChannel>& pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t>& indices);
/** Extracts a single object from an input channel and stores it in the appropriate mesh data array */ /** Extracts a single object from an input channel and stores it in the appropriate mesh data array */
void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh); void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh);
/** Reads the library of node hierarchies and scene parts */ /** Reads the library of node hierarchies and scene parts */
void ReadSceneLibrary(); void ReadSceneLibrary();
/** Reads a scene node's contents including children and stores it in the given node */ /** Reads a scene node's contents including children and stores it in the given node */
void ReadSceneNode( Collada::Node* pNode); void ReadSceneNode( Collada::Node* pNode);
/** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */ /** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */
void ReadNodeTransformation( Collada::Node* pNode, Collada::TransformType pType); void ReadNodeTransformation( Collada::Node* pNode, Collada::TransformType pType);
/** Reads a mesh reference in a node and adds it to the node's mesh list */ /** Reads a mesh reference in a node and adds it to the node's mesh list */
void ReadNodeGeometry( Collada::Node* pNode); void ReadNodeGeometry( Collada::Node* pNode);
/** Reads the collada scene */ /** Reads the collada scene */
void ReadScene(); void ReadScene();
// Processes bind_vertex_input and bind elements // Processes bind_vertex_input and bind elements
void ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl); void ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl);
protected: protected:
/** Aborts the file reading with an exception */ /** Aborts the file reading with an exception */
AI_WONT_RETURN void ThrowException( const std::string& pError) const AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void ThrowException( const std::string& pError) const AI_WONT_RETURN_SUFFIX;
/** Skips all data until the end node of the current element */ /** Skips all data until the end node of the current element */
void SkipElement(); void SkipElement();
/** Skips all data until the end node of the given element */ /** Skips all data until the end node of the given element */
void SkipElement( const char* pElement); void SkipElement( const char* pElement);
/** Compares the current xml element name to the given string and returns true if equal */ /** Compares the current xml element name to the given string and returns true if equal */
bool IsElement( const char* pName) const; bool IsElement( const char* pName) const;
/** Tests for the opening tag of the given element, throws an exception if not found */ /** Tests for the opening tag of the given element, throws an exception if not found */
void TestOpening( const char* pName); void TestOpening( const char* pName);
/** Tests for the closing tag of the given element, throws an exception if not found */ /** Tests for the closing tag of the given element, throws an exception if not found */
void TestClosing( const char* pName); void TestClosing( const char* pName);
/** Checks the present element for the presence of the attribute, returns its index /** Checks the present element for the presence of the attribute, returns its index
or throws an exception if not found */ or throws an exception if not found */
int GetAttribute( const char* pAttr) const; int GetAttribute( const char* pAttr) const;
/** Returns the index of the named attribute or -1 if not found. Does not throw, /** Returns the index of the named attribute or -1 if not found. Does not throw,
therefore useful for optional attributes */ therefore useful for optional attributes */
int TestAttribute( const char* pAttr) const; int TestAttribute( const char* pAttr) const;
/** Reads the text contents of an element, throws an exception if not given. /** Reads the text contents of an element, throws an exception if not given.
Skips leading whitespace. */ Skips leading whitespace. */
const char* GetTextContent(); const char* GetTextContent();
/** Reads the text contents of an element, returns NULL if not given. /** Reads the text contents of an element, returns NULL if not given.
Skips leading whitespace. */ Skips leading whitespace. */
const char* TestTextContent(); const char* TestTextContent();
/** Reads a single bool from current text content */ /** Reads a single bool from current text content */
bool ReadBoolFromTextContent(); bool ReadBoolFromTextContent();
/** Reads a single float from current text content */ /** Reads a single float from current text content */
float ReadFloatFromTextContent(); float ReadFloatFromTextContent();
/** Calculates the resulting transformation from all the given transform steps */ /** Calculates the resulting transformation from all the given transform steps */
aiMatrix4x4 CalculateResultTransform( const std::vector<Collada::Transform>& pTransforms) const; aiMatrix4x4 CalculateResultTransform( const std::vector<Collada::Transform>& pTransforms) const;
/** Determines the input data type for the given semantic string */ /** Determines the input data type for the given semantic string */
Collada::InputType GetTypeForSemantic( const std::string& pSemantic); Collada::InputType GetTypeForSemantic( const std::string& pSemantic);
/** Finds the item in the given library by its reference, throws if not found */ /** Finds the item in the given library by its reference, throws if not found */
template <typename Type> const Type& ResolveLibraryReference( template <typename Type> const Type& ResolveLibraryReference(
const std::map<std::string, Type>& pLibrary, const std::string& pURL) const; const std::map<std::string, Type>& pLibrary, const std::string& pURL) const;
protected: protected:
/** Filename, for a verbose error message */ /** Filename, for a verbose error message */
std::string mFileName; std::string mFileName;
/** XML reader, member for everyday use */ /** XML reader, member for everyday use */
irr::io::IrrXMLReader* mReader; irr::io::IrrXMLReader* mReader;
/** All data arrays found in the file by ID. Might be referred to by actually /** All data arrays found in the file by ID. Might be referred to by actually
everyone. Collada, you are a steaming pile of indirection. */ everyone. Collada, you are a steaming pile of indirection. */
typedef std::map<std::string, Collada::Data> DataLibrary; typedef std::map<std::string, Collada::Data> DataLibrary;
DataLibrary mDataLibrary; DataLibrary mDataLibrary;
/** Same for accessors which define how the data in a data array is accessed. */ /** Same for accessors which define how the data in a data array is accessed. */
typedef std::map<std::string, Collada::Accessor> AccessorLibrary; typedef std::map<std::string, Collada::Accessor> AccessorLibrary;
AccessorLibrary mAccessorLibrary; AccessorLibrary mAccessorLibrary;
/** Mesh library: mesh by ID */ /** Mesh library: mesh by ID */
typedef std::map<std::string, Collada::Mesh*> MeshLibrary; typedef std::map<std::string, Collada::Mesh*> MeshLibrary;
MeshLibrary mMeshLibrary; MeshLibrary mMeshLibrary;
/** node library: root node of the hierarchy part by ID */ /** node library: root node of the hierarchy part by ID */
typedef std::map<std::string, Collada::Node*> NodeLibrary; typedef std::map<std::string, Collada::Node*> NodeLibrary;
NodeLibrary mNodeLibrary; NodeLibrary mNodeLibrary;
/** Image library: stores texture properties by ID */ /** Image library: stores texture properties by ID */
typedef std::map<std::string, Collada::Image> ImageLibrary; typedef std::map<std::string, Collada::Image> ImageLibrary;
ImageLibrary mImageLibrary; ImageLibrary mImageLibrary;
/** Effect library: surface attributes by ID */ /** Effect library: surface attributes by ID */
typedef std::map<std::string, Collada::Effect> EffectLibrary; typedef std::map<std::string, Collada::Effect> EffectLibrary;
EffectLibrary mEffectLibrary; EffectLibrary mEffectLibrary;
/** Material library: surface material by ID */ /** Material library: surface material by ID */
typedef std::map<std::string, Collada::Material> MaterialLibrary; typedef std::map<std::string, Collada::Material> MaterialLibrary;
MaterialLibrary mMaterialLibrary; MaterialLibrary mMaterialLibrary;
/** Light library: surface light by ID */ /** Light library: surface light by ID */
typedef std::map<std::string, Collada::Light> LightLibrary; typedef std::map<std::string, Collada::Light> LightLibrary;
LightLibrary mLightLibrary; LightLibrary mLightLibrary;
/** Camera library: surface material by ID */ /** Camera library: surface material by ID */
typedef std::map<std::string, Collada::Camera> CameraLibrary; typedef std::map<std::string, Collada::Camera> CameraLibrary;
CameraLibrary mCameraLibrary; CameraLibrary mCameraLibrary;
/** Controller library: joint controllers by ID */ /** Controller library: joint controllers by ID */
typedef std::map<std::string, Collada::Controller> ControllerLibrary; typedef std::map<std::string, Collada::Controller> ControllerLibrary;
ControllerLibrary mControllerLibrary; ControllerLibrary mControllerLibrary;
/** Pointer to the root node. Don't delete, it just points to one of /** Pointer to the root node. Don't delete, it just points to one of
the nodes in the node library. */ the nodes in the node library. */
Collada::Node* mRootNode; Collada::Node* mRootNode;
/** Root animation container */ /** Root animation container */
Collada::Animation mAnims; Collada::Animation mAnims;
/** Size unit: how large compared to a meter */ /** Size unit: how large compared to a meter */
float mUnitSize; float mUnitSize;
/** Which is the up vector */ /** Which is the up vector */
enum { UP_X, UP_Y, UP_Z } mUpDirection; enum { UP_X, UP_Y, UP_Z } mUpDirection;
/** Collada file format version */ /** Collada file format version */
Collada::FormatVersion mFormat; Collada::FormatVersion mFormat;
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Check for element match // Check for element match
inline bool ColladaParser::IsElement( const char* pName) const inline bool ColladaParser::IsElement( const char* pName) const
{ {
ai_assert( mReader->getNodeType() == irr::io::EXN_ELEMENT); ai_assert( mReader->getNodeType() == irr::io::EXN_ELEMENT);
return ::strcmp( mReader->getNodeName(), pName) == 0; return ::strcmp( mReader->getNodeName(), pName) == 0;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -341,10 +341,10 @@ inline bool ColladaParser::IsElement( const char* pName) const
template <typename Type> template <typename Type>
const Type& ColladaParser::ResolveLibraryReference( const std::map<std::string, Type>& pLibrary, const std::string& pURL) const const Type& ColladaParser::ResolveLibraryReference( const std::map<std::string, Type>& pLibrary, const std::string& pURL) const
{ {
typename std::map<std::string, Type>::const_iterator it = pLibrary.find( pURL); typename std::map<std::string, Type>::const_iterator it = pLibrary.find( pURL);
if( it == pLibrary.end()) if( it == pLibrary.end())
ThrowException( boost::str( boost::format( "Unable to resolve library reference \"%s\".") % pURL)); ThrowException( boost::str( boost::format( "Unable to resolve library reference \"%s\".") % pURL));
return it->second; return it->second;
} }
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -49,42 +49,42 @@ using namespace Assimp;
namespace { namespace {
const static aiVector3D base_axis_y(0.f,1.f,0.f); const static aiVector3D base_axis_y(0.f,1.f,0.f);
const static aiVector3D base_axis_x(1.f,0.f,0.f); const static aiVector3D base_axis_x(1.f,0.f,0.f);
const static aiVector3D base_axis_z(0.f,0.f,1.f); const static aiVector3D base_axis_z(0.f,0.f,1.f);
const static float angle_epsilon = 0.95f; const static float angle_epsilon = 0.95f;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
ComputeUVMappingProcess::ComputeUVMappingProcess() ComputeUVMappingProcess::ComputeUVMappingProcess()
{ {
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
ComputeUVMappingProcess::~ComputeUVMappingProcess() ComputeUVMappingProcess::~ComputeUVMappingProcess()
{ {
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
bool ComputeUVMappingProcess::IsActive( unsigned int pFlags) const bool ComputeUVMappingProcess::IsActive( unsigned int pFlags) const
{ {
return (pFlags & aiProcess_GenUVCoords) != 0; return (pFlags & aiProcess_GenUVCoords) != 0;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Check whether a ray intersects a plane and find the intersection point // Check whether a ray intersects a plane and find the intersection point
inline bool PlaneIntersect(const aiRay& ray, const aiVector3D& planePos, inline bool PlaneIntersect(const aiRay& ray, const aiVector3D& planePos,
const aiVector3D& planeNormal, aiVector3D& pos) const aiVector3D& planeNormal, aiVector3D& pos)
{ {
const float b = planeNormal * (planePos - ray.pos); const float b = planeNormal * (planePos - ray.pos);
float h = ray.dir * planeNormal; float h = ray.dir * planeNormal;
if ((h < 10e-5f && h > -10e-5f) || (h = b/h) < 0) if ((h < 10e-5f && h > -10e-5f) || (h = b/h) < 0)
return false; return false;
pos = ray.pos + (ray.dir * h); pos = ray.pos + (ray.dir * h);
return true; return true;
@ -94,411 +94,411 @@ inline bool PlaneIntersect(const aiRay& ray, const aiVector3D& planePos,
// Find the first empty UV channel in a mesh // Find the first empty UV channel in a mesh
inline unsigned int FindEmptyUVChannel (aiMesh* mesh) inline unsigned int FindEmptyUVChannel (aiMesh* mesh)
{ {
for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS;++m) for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS;++m)
if (!mesh->mTextureCoords[m])return m; if (!mesh->mTextureCoords[m])return m;
DefaultLogger::get()->error("Unable to compute UV coordinates, no free UV slot found"); DefaultLogger::get()->error("Unable to compute UV coordinates, no free UV slot found");
return UINT_MAX; return UINT_MAX;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Try to remove UV seams // Try to remove UV seams
void RemoveUVSeams (aiMesh* mesh, aiVector3D* out) void RemoveUVSeams (aiMesh* mesh, aiVector3D* out)
{ {
// TODO: just a very rough algorithm. I think it could be done // TODO: just a very rough algorithm. I think it could be done
// much easier, but I don't know how and am currently too tired to // much easier, but I don't know how and am currently too tired to
// to think about a better solution. // to think about a better solution.
const static float LOWER_LIMIT = 0.1f; const static float LOWER_LIMIT = 0.1f;
const static float UPPER_LIMIT = 0.9f; const static float UPPER_LIMIT = 0.9f;
const static float LOWER_EPSILON = 10e-3f; const static float LOWER_EPSILON = 10e-3f;
const static float UPPER_EPSILON = 1.f-10e-3f; const static float UPPER_EPSILON = 1.f-10e-3f;
for (unsigned int fidx = 0; fidx < mesh->mNumFaces;++fidx) for (unsigned int fidx = 0; fidx < mesh->mNumFaces;++fidx)
{ {
const aiFace& face = mesh->mFaces[fidx]; const aiFace& face = mesh->mFaces[fidx];
if (face.mNumIndices < 3) continue; // triangles and polygons only, please if (face.mNumIndices < 3) continue; // triangles and polygons only, please
unsigned int small = face.mNumIndices, large = small; unsigned int small = face.mNumIndices, large = small;
bool zero = false, one = false, round_to_zero = false; bool zero = false, one = false, round_to_zero = false;
// Check whether this face lies on a UV seam. We can just guess, // Check whether this face lies on a UV seam. We can just guess,
// but the assumption that a face with at least one very small // but the assumption that a face with at least one very small
// on the one side and one very large U coord on the other side // on the one side and one very large U coord on the other side
// lies on a UV seam should work for most cases. // lies on a UV seam should work for most cases.
for (unsigned int n = 0; n < face.mNumIndices;++n) for (unsigned int n = 0; n < face.mNumIndices;++n)
{ {
if (out[face.mIndices[n]].x < LOWER_LIMIT) if (out[face.mIndices[n]].x < LOWER_LIMIT)
{ {
small = n; small = n;
// If we have a U value very close to 0 we can't // If we have a U value very close to 0 we can't
// round the others to 0, too. // round the others to 0, too.
if (out[face.mIndices[n]].x <= LOWER_EPSILON) if (out[face.mIndices[n]].x <= LOWER_EPSILON)
zero = true; zero = true;
else round_to_zero = true; else round_to_zero = true;
} }
if (out[face.mIndices[n]].x > UPPER_LIMIT) if (out[face.mIndices[n]].x > UPPER_LIMIT)
{ {
large = n; large = n;
// If we have a U value very close to 1 we can't // If we have a U value very close to 1 we can't
// round the others to 1, too. // round the others to 1, too.
if (out[face.mIndices[n]].x >= UPPER_EPSILON) if (out[face.mIndices[n]].x >= UPPER_EPSILON)
one = true; one = true;
} }
} }
if (small != face.mNumIndices && large != face.mNumIndices) if (small != face.mNumIndices && large != face.mNumIndices)
{ {
for (unsigned int n = 0; n < face.mNumIndices;++n) for (unsigned int n = 0; n < face.mNumIndices;++n)
{ {
// If the u value is over the upper limit and no other u // If the u value is over the upper limit and no other u
// value of that face is 0, round it to 0 // value of that face is 0, round it to 0
if (out[face.mIndices[n]].x > UPPER_LIMIT && !zero) if (out[face.mIndices[n]].x > UPPER_LIMIT && !zero)
out[face.mIndices[n]].x = 0.f; out[face.mIndices[n]].x = 0.f;
// If the u value is below the lower limit and no other u // If the u value is below the lower limit and no other u
// value of that face is 1, round it to 1 // value of that face is 1, round it to 1
else if (out[face.mIndices[n]].x < LOWER_LIMIT && !one) else if (out[face.mIndices[n]].x < LOWER_LIMIT && !one)
out[face.mIndices[n]].x = 1.f; out[face.mIndices[n]].x = 1.f;
// The face contains both 0 and 1 as UV coords. This can occur // The face contains both 0 and 1 as UV coords. This can occur
// for faces which have an edge that lies directly on the seam. // for faces which have an edge that lies directly on the seam.
// Due to numerical inaccuracies one U coord becomes 0, the // Due to numerical inaccuracies one U coord becomes 0, the
// other 1. But we do still have a third UV coord to determine // other 1. But we do still have a third UV coord to determine
// to which side we must round to. // to which side we must round to.
else if (one && zero) else if (one && zero)
{ {
if (round_to_zero && out[face.mIndices[n]].x >= UPPER_EPSILON) if (round_to_zero && out[face.mIndices[n]].x >= UPPER_EPSILON)
out[face.mIndices[n]].x = 0.f; out[face.mIndices[n]].x = 0.f;
else if (!round_to_zero && out[face.mIndices[n]].x <= LOWER_EPSILON) else if (!round_to_zero && out[face.mIndices[n]].x <= LOWER_EPSILON)
out[face.mIndices[n]].x = 1.f; out[face.mIndices[n]].x = 1.f;
} }
} }
} }
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out) void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
{ {
aiVector3D center, min, max; aiVector3D center, min, max;
FindMeshCenter(mesh, center, min, max); FindMeshCenter(mesh, center, min, max);
// If the axis is one of x,y,z run a faster code path. It's worth the extra effort ... // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
// currently the mapping axis will always be one of x,y,z, except if the // currently the mapping axis will always be one of x,y,z, except if the
// PretransformVertices step is used (it transforms the meshes into worldspace, // PretransformVertices step is used (it transforms the meshes into worldspace,
// thus changing the mapping axis) // thus changing the mapping axis)
if (axis * base_axis_x >= angle_epsilon) { if (axis * base_axis_x >= angle_epsilon) {
// For each point get a normalized projection vector in the sphere, // For each point get a normalized projection vector in the sphere,
// get its longitude and latitude and map them to their respective // get its longitude and latitude and map them to their respective
// UV axes. Problems occur around the poles ... unsolvable. // UV axes. Problems occur around the poles ... unsolvable.
// //
// The spherical coordinate system looks like this: // The spherical coordinate system looks like this:
// x = cos(lon)*cos(lat) // x = cos(lon)*cos(lat)
// y = sin(lon)*cos(lat) // y = sin(lon)*cos(lat)
// z = sin(lat) // z = sin(lat)
// //
// Thus we can derive: // Thus we can derive:
// lat = arcsin (z) // lat = arcsin (z)
// lon = arctan (y/x) // lon = arctan (y/x)
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize(); const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
out[pnt] = aiVector3D((atan2 (diff.z, diff.y) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F, out[pnt] = aiVector3D((atan2 (diff.z, diff.y) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
(std::asin (diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f); (std::asin (diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
} }
} }
else if (axis * base_axis_y >= angle_epsilon) { else if (axis * base_axis_y >= angle_epsilon) {
// ... just the same again // ... just the same again
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize(); const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
out[pnt] = aiVector3D((atan2 (diff.x, diff.z) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F, out[pnt] = aiVector3D((atan2 (diff.x, diff.z) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
(std::asin (diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f); (std::asin (diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
} }
} }
else if (axis * base_axis_z >= angle_epsilon) { else if (axis * base_axis_z >= angle_epsilon) {
// ... just the same again // ... just the same again
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize(); const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
out[pnt] = aiVector3D((atan2 (diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F, out[pnt] = aiVector3D((atan2 (diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
(std::asin (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f); (std::asin (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
} }
} }
// slower code path in case the mapping axis is not one of the coordinate system axes // slower code path in case the mapping axis is not one of the coordinate system axes
else { else {
aiMatrix4x4 mTrafo; aiMatrix4x4 mTrafo;
aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo); aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
// again the same, except we're applying a transformation now // again the same, except we're applying a transformation now
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D diff = ((mTrafo*mesh->mVertices[pnt])-center).Normalize(); const aiVector3D diff = ((mTrafo*mesh->mVertices[pnt])-center).Normalize();
out[pnt] = aiVector3D((atan2 (diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F, out[pnt] = aiVector3D((atan2 (diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
(asin (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f); (asin (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
} }
} }
// Now find and remove UV seams. A seam occurs if a face has a tcoord // Now find and remove UV seams. A seam occurs if a face has a tcoord
// close to zero on the one side, and a tcoord close to one on the // close to zero on the one side, and a tcoord close to one on the
// other side. // other side.
RemoveUVSeams(mesh,out); RemoveUVSeams(mesh,out);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out) void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
{ {
aiVector3D center, min, max; aiVector3D center, min, max;
// If the axis is one of x,y,z run a faster code path. It's worth the extra effort ... // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
// currently the mapping axis will always be one of x,y,z, except if the // currently the mapping axis will always be one of x,y,z, except if the
// PretransformVertices step is used (it transforms the meshes into worldspace, // PretransformVertices step is used (it transforms the meshes into worldspace,
// thus changing the mapping axis) // thus changing the mapping axis)
if (axis * base_axis_x >= angle_epsilon) { if (axis * base_axis_x >= angle_epsilon) {
FindMeshCenter(mesh, center, min, max); FindMeshCenter(mesh, center, min, max);
const float diff = max.x - min.x; const float diff = max.x - min.x;
// If the main axis is 'z', the z coordinate of a point 'p' is mapped // If the main axis is 'z', the z coordinate of a point 'p' is mapped
// directly to the texture V axis. The other axis is derived from // directly to the texture V axis. The other axis is derived from
// the angle between ( p.x - c.x, p.y - c.y ) and (1,0), where // the angle between ( p.x - c.x, p.y - c.y ) and (1,0), where
// 'c' is the center point of the mesh. // 'c' is the center point of the mesh.
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D& pos = mesh->mVertices[pnt]; const aiVector3D& pos = mesh->mVertices[pnt];
aiVector3D& uv = out[pnt]; aiVector3D& uv = out[pnt];
uv.y = (pos.x - min.x) / diff; uv.y = (pos.x - min.x) / diff;
uv.x = (atan2 ( pos.z - center.z, pos.y - center.y) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI; uv.x = (atan2 ( pos.z - center.z, pos.y - center.y) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
} }
} }
else if (axis * base_axis_y >= angle_epsilon) { else if (axis * base_axis_y >= angle_epsilon) {
FindMeshCenter(mesh, center, min, max); FindMeshCenter(mesh, center, min, max);
const float diff = max.y - min.y; const float diff = max.y - min.y;
// just the same ... // just the same ...
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D& pos = mesh->mVertices[pnt]; const aiVector3D& pos = mesh->mVertices[pnt];
aiVector3D& uv = out[pnt]; aiVector3D& uv = out[pnt];
uv.y = (pos.y - min.y) / diff; uv.y = (pos.y - min.y) / diff;
uv.x = (atan2 ( pos.x - center.x, pos.z - center.z) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI; uv.x = (atan2 ( pos.x - center.x, pos.z - center.z) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
} }
} }
else if (axis * base_axis_z >= angle_epsilon) { else if (axis * base_axis_z >= angle_epsilon) {
FindMeshCenter(mesh, center, min, max); FindMeshCenter(mesh, center, min, max);
const float diff = max.z - min.z; const float diff = max.z - min.z;
// just the same ... // just the same ...
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D& pos = mesh->mVertices[pnt]; const aiVector3D& pos = mesh->mVertices[pnt];
aiVector3D& uv = out[pnt]; aiVector3D& uv = out[pnt];
uv.y = (pos.z - min.z) / diff; uv.y = (pos.z - min.z) / diff;
uv.x = (atan2 ( pos.y - center.y, pos.x - center.x) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI; uv.x = (atan2 ( pos.y - center.y, pos.x - center.x) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
} }
} }
// slower code path in case the mapping axis is not one of the coordinate system axes // slower code path in case the mapping axis is not one of the coordinate system axes
else { else {
aiMatrix4x4 mTrafo; aiMatrix4x4 mTrafo;
aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo); aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
FindMeshCenterTransformed(mesh, center, min, max,mTrafo); FindMeshCenterTransformed(mesh, center, min, max,mTrafo);
const float diff = max.y - min.y; const float diff = max.y - min.y;
// again the same, except we're applying a transformation now // again the same, except we're applying a transformation now
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt){ for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt){
const aiVector3D pos = mTrafo* mesh->mVertices[pnt]; const aiVector3D pos = mTrafo* mesh->mVertices[pnt];
aiVector3D& uv = out[pnt]; aiVector3D& uv = out[pnt];
uv.y = (pos.y - min.y) / diff; uv.y = (pos.y - min.y) / diff;
uv.x = (atan2 ( pos.x - center.x, pos.z - center.z) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI; uv.x = (atan2 ( pos.x - center.x, pos.z - center.z) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
} }
} }
// Now find and remove UV seams. A seam occurs if a face has a tcoord // Now find and remove UV seams. A seam occurs if a face has a tcoord
// close to zero on the one side, and a tcoord close to one on the // close to zero on the one side, and a tcoord close to one on the
// other side. // other side.
RemoveUVSeams(mesh,out); RemoveUVSeams(mesh,out);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out) void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
{ {
float diffu,diffv; float diffu,diffv;
aiVector3D center, min, max; aiVector3D center, min, max;
// If the axis is one of x,y,z run a faster code path. It's worth the extra effort ... // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
// currently the mapping axis will always be one of x,y,z, except if the // currently the mapping axis will always be one of x,y,z, except if the
// PretransformVertices step is used (it transforms the meshes into worldspace, // PretransformVertices step is used (it transforms the meshes into worldspace,
// thus changing the mapping axis) // thus changing the mapping axis)
if (axis * base_axis_x >= angle_epsilon) { if (axis * base_axis_x >= angle_epsilon) {
FindMeshCenter(mesh, center, min, max); FindMeshCenter(mesh, center, min, max);
diffu = max.z - min.z; diffu = max.z - min.z;
diffv = max.y - min.y; diffv = max.y - min.y;
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D& pos = mesh->mVertices[pnt]; const aiVector3D& pos = mesh->mVertices[pnt];
out[pnt].Set((pos.z - min.z) / diffu,(pos.y - min.y) / diffv,0.f); out[pnt].Set((pos.z - min.z) / diffu,(pos.y - min.y) / diffv,0.f);
} }
} }
else if (axis * base_axis_y >= angle_epsilon) { else if (axis * base_axis_y >= angle_epsilon) {
FindMeshCenter(mesh, center, min, max); FindMeshCenter(mesh, center, min, max);
diffu = max.x - min.x; diffu = max.x - min.x;
diffv = max.z - min.z; diffv = max.z - min.z;
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D& pos = mesh->mVertices[pnt]; const aiVector3D& pos = mesh->mVertices[pnt];
out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.f); out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.f);
} }
} }
else if (axis * base_axis_z >= angle_epsilon) { else if (axis * base_axis_z >= angle_epsilon) {
FindMeshCenter(mesh, center, min, max); FindMeshCenter(mesh, center, min, max);
diffu = max.y - min.y; diffu = max.y - min.y;
diffv = max.z - min.z; diffv = max.z - min.z;
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D& pos = mesh->mVertices[pnt]; const aiVector3D& pos = mesh->mVertices[pnt];
out[pnt].Set((pos.y - min.y) / diffu,(pos.x - min.x) / diffv,0.f); out[pnt].Set((pos.y - min.y) / diffu,(pos.x - min.x) / diffv,0.f);
} }
} }
// slower code path in case the mapping axis is not one of the coordinate system axes // slower code path in case the mapping axis is not one of the coordinate system axes
else else
{ {
aiMatrix4x4 mTrafo; aiMatrix4x4 mTrafo;
aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo); aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
FindMeshCenterTransformed(mesh, center, min, max,mTrafo); FindMeshCenterTransformed(mesh, center, min, max,mTrafo);
diffu = max.x - min.x; diffu = max.x - min.x;
diffv = max.z - min.z; diffv = max.z - min.z;
// again the same, except we're applying a transformation now // again the same, except we're applying a transformation now
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
const aiVector3D pos = mTrafo * mesh->mVertices[pnt]; const aiVector3D pos = mTrafo * mesh->mVertices[pnt];
out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.f); out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.f);
} }
} }
// shouldn't be necessary to remove UV seams ... // shouldn't be necessary to remove UV seams ...
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ComputeUVMappingProcess::ComputeBoxMapping( aiMesh*, aiVector3D* ) void ComputeUVMappingProcess::ComputeBoxMapping( aiMesh*, aiVector3D* )
{ {
DefaultLogger::get()->error("Mapping type currently not implemented"); DefaultLogger::get()->error("Mapping type currently not implemented");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ComputeUVMappingProcess::Execute( aiScene* pScene) void ComputeUVMappingProcess::Execute( aiScene* pScene)
{ {
DefaultLogger::get()->debug("GenUVCoordsProcess begin"); DefaultLogger::get()->debug("GenUVCoordsProcess begin");
char buffer[1024]; char buffer[1024];
if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT)
throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here"); throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
std::list<MappingInfo> mappingStack; std::list<MappingInfo> mappingStack;
/* Iterate through all materials and search for non-UV mapped textures /* Iterate through all materials and search for non-UV mapped textures
*/ */
for (unsigned int i = 0; i < pScene->mNumMaterials;++i) for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
{ {
mappingStack.clear(); mappingStack.clear();
aiMaterial* mat = pScene->mMaterials[i]; aiMaterial* mat = pScene->mMaterials[i];
for (unsigned int a = 0; a < mat->mNumProperties;++a) for (unsigned int a = 0; a < mat->mNumProperties;++a)
{ {
aiMaterialProperty* prop = mat->mProperties[a]; aiMaterialProperty* prop = mat->mProperties[a];
if (!::strcmp( prop->mKey.data, "$tex.mapping")) if (!::strcmp( prop->mKey.data, "$tex.mapping"))
{ {
aiTextureMapping& mapping = *((aiTextureMapping*)prop->mData); aiTextureMapping& mapping = *((aiTextureMapping*)prop->mData);
if (aiTextureMapping_UV != mapping) if (aiTextureMapping_UV != mapping)
{ {
if (!DefaultLogger::isNullLogger()) if (!DefaultLogger::isNullLogger())
{ {
sprintf(buffer, "Found non-UV mapped texture (%s,%u). Mapping type: %s", sprintf(buffer, "Found non-UV mapped texture (%s,%u). Mapping type: %s",
TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex, TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex,
MappingTypeToString(mapping)); MappingTypeToString(mapping));
DefaultLogger::get()->info(buffer); DefaultLogger::get()->info(buffer);
} }
if (aiTextureMapping_OTHER == mapping) if (aiTextureMapping_OTHER == mapping)
continue; continue;
MappingInfo info (mapping); MappingInfo info (mapping);
// Get further properties - currently only the major axis // Get further properties - currently only the major axis
for (unsigned int a2 = 0; a2 < mat->mNumProperties;++a2) for (unsigned int a2 = 0; a2 < mat->mNumProperties;++a2)
{ {
aiMaterialProperty* prop2 = mat->mProperties[a2]; aiMaterialProperty* prop2 = mat->mProperties[a2];
if (prop2->mSemantic != prop->mSemantic || prop2->mIndex != prop->mIndex) if (prop2->mSemantic != prop->mSemantic || prop2->mIndex != prop->mIndex)
continue; continue;
if ( !::strcmp( prop2->mKey.data, "$tex.mapaxis")) { if ( !::strcmp( prop2->mKey.data, "$tex.mapaxis")) {
info.axis = *((aiVector3D*)prop2->mData); info.axis = *((aiVector3D*)prop2->mData);
break; break;
} }
} }
unsigned int idx; unsigned int idx;
// Check whether we have this mapping mode already // Check whether we have this mapping mode already
std::list<MappingInfo>::iterator it = std::find (mappingStack.begin(),mappingStack.end(), info); std::list<MappingInfo>::iterator it = std::find (mappingStack.begin(),mappingStack.end(), info);
if (mappingStack.end() != it) if (mappingStack.end() != it)
{ {
idx = (*it).uv; idx = (*it).uv;
} }
else else
{ {
/* We have found a non-UV mapped texture. Now /* We have found a non-UV mapped texture. Now
* we need to find all meshes using this material * we need to find all meshes using this material
* that we can compute UV channels for them. * that we can compute UV channels for them.
*/ */
for (unsigned int m = 0; m < pScene->mNumMeshes;++m) for (unsigned int m = 0; m < pScene->mNumMeshes;++m)
{ {
aiMesh* mesh = pScene->mMeshes[m]; aiMesh* mesh = pScene->mMeshes[m];
unsigned int outIdx = 0; unsigned int outIdx = 0;
if ( mesh->mMaterialIndex != i || ( outIdx = FindEmptyUVChannel(mesh) ) == UINT_MAX || if ( mesh->mMaterialIndex != i || ( outIdx = FindEmptyUVChannel(mesh) ) == UINT_MAX ||
!mesh->mNumVertices) !mesh->mNumVertices)
{ {
continue; continue;
} }
// Allocate output storage // Allocate output storage
aiVector3D* p = mesh->mTextureCoords[outIdx] = new aiVector3D[mesh->mNumVertices]; aiVector3D* p = mesh->mTextureCoords[outIdx] = new aiVector3D[mesh->mNumVertices];
switch (mapping) switch (mapping)
{ {
case aiTextureMapping_SPHERE: case aiTextureMapping_SPHERE:
ComputeSphereMapping(mesh,info.axis,p); ComputeSphereMapping(mesh,info.axis,p);
break; break;
case aiTextureMapping_CYLINDER: case aiTextureMapping_CYLINDER:
ComputeCylinderMapping(mesh,info.axis,p); ComputeCylinderMapping(mesh,info.axis,p);
break; break;
case aiTextureMapping_PLANE: case aiTextureMapping_PLANE:
ComputePlaneMapping(mesh,info.axis,p); ComputePlaneMapping(mesh,info.axis,p);
break; break;
case aiTextureMapping_BOX: case aiTextureMapping_BOX:
ComputeBoxMapping(mesh,p); ComputeBoxMapping(mesh,p);
break; break;
default: default:
ai_assert(false); ai_assert(false);
} }
if (m && idx != outIdx) if (m && idx != outIdx)
{ {
DefaultLogger::get()->warn("UV index mismatch. Not all meshes assigned to " DefaultLogger::get()->warn("UV index mismatch. Not all meshes assigned to "
"this material have equal numbers of UV channels. The UV index stored in " "this material have equal numbers of UV channels. The UV index stored in "
"the material structure does therefore not apply for all meshes. "); "the material structure does therefore not apply for all meshes. ");
} }
idx = outIdx; idx = outIdx;
} }
info.uv = idx; info.uv = idx;
mappingStack.push_back(info); mappingStack.push_back(info);
} }
// Update the material property list // Update the material property list
mapping = aiTextureMapping_UV; mapping = aiTextureMapping_UV;
((aiMaterial*)mat)->AddProperty(&idx,1,AI_MATKEY_UVWSRC(prop->mSemantic,prop->mIndex)); ((aiMaterial*)mat)->AddProperty(&idx,1,AI_MATKEY_UVWSRC(prop->mSemantic,prop->mIndex));
} }
} }
} }
} }
DefaultLogger::get()->debug("GenUVCoordsProcess finished"); DefaultLogger::get()->debug("GenUVCoordsProcess finished");
} }

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -51,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
class ComputeUVMappingTest; class ComputeUVMappingTest;
namespace Assimp namespace Assimp
{ {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** ComputeUVMappingProcess - converts special mappings, such as spherical, /** ComputeUVMappingProcess - converts special mappings, such as spherical,
@ -60,86 +60,86 @@ namespace Assimp
class ComputeUVMappingProcess : public BaseProcess class ComputeUVMappingProcess : public BaseProcess
{ {
public: public:
ComputeUVMappingProcess(); ComputeUVMappingProcess();
~ComputeUVMappingProcess(); ~ComputeUVMappingProcess();
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the processing step is present in the given flag field. /** Returns whether the processing step is present in the given flag field.
* @param pFlags The processing flags the importer was called with. A bitwise * @param pFlags The processing flags the importer was called with. A bitwise
* combination of #aiPostProcessSteps. * combination of #aiPostProcessSteps.
* @return true if the process is present in this flag fields, false if not. * @return true if the process is present in this flag fields, false if not.
*/ */
bool IsActive( unsigned int pFlags) const; bool IsActive( unsigned int pFlags) const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Executes the post processing step on the given imported data. /** Executes the post processing step on the given imported data.
* At the moment a process is not supposed to fail. * At the moment a process is not supposed to fail.
* @param pScene The imported data to work at. * @param pScene The imported data to work at.
*/ */
void Execute( aiScene* pScene); void Execute( aiScene* pScene);
protected: protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Computes spherical UV coordinates for a mesh /** Computes spherical UV coordinates for a mesh
* *
* @param mesh Mesh to be processed * @param mesh Mesh to be processed
* @param axis Main axis * @param axis Main axis
* @param out Receives output UV coordinates * @param out Receives output UV coordinates
*/ */
void ComputeSphereMapping(aiMesh* mesh,const aiVector3D& axis, void ComputeSphereMapping(aiMesh* mesh,const aiVector3D& axis,
aiVector3D* out); aiVector3D* out);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Computes cylindrical UV coordinates for a mesh /** Computes cylindrical UV coordinates for a mesh
* *
* @param mesh Mesh to be processed * @param mesh Mesh to be processed
* @param axis Main axis * @param axis Main axis
* @param out Receives output UV coordinates * @param out Receives output UV coordinates
*/ */
void ComputeCylinderMapping(aiMesh* mesh,const aiVector3D& axis, void ComputeCylinderMapping(aiMesh* mesh,const aiVector3D& axis,
aiVector3D* out); aiVector3D* out);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Computes planar UV coordinates for a mesh /** Computes planar UV coordinates for a mesh
* *
* @param mesh Mesh to be processed * @param mesh Mesh to be processed
* @param axis Main axis * @param axis Main axis
* @param out Receives output UV coordinates * @param out Receives output UV coordinates
*/ */
void ComputePlaneMapping(aiMesh* mesh,const aiVector3D& axis, void ComputePlaneMapping(aiMesh* mesh,const aiVector3D& axis,
aiVector3D* out); aiVector3D* out);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Computes cubic UV coordinates for a mesh /** Computes cubic UV coordinates for a mesh
* *
* @param mesh Mesh to be processed * @param mesh Mesh to be processed
* @param out Receives output UV coordinates * @param out Receives output UV coordinates
*/ */
void ComputeBoxMapping(aiMesh* mesh, aiVector3D* out); void ComputeBoxMapping(aiMesh* mesh, aiVector3D* out);
private: private:
// temporary structure to describe a mapping // temporary structure to describe a mapping
struct MappingInfo struct MappingInfo
{ {
MappingInfo(aiTextureMapping _type) MappingInfo(aiTextureMapping _type)
: type (_type) : type (_type)
, axis (0.f,1.f,0.f) , axis (0.f,1.f,0.f)
, uv (0u) , uv (0u)
{} {}
aiTextureMapping type; aiTextureMapping type;
aiVector3D axis; aiVector3D axis;
unsigned int uv; unsigned int uv;
bool operator== (const MappingInfo& other) bool operator== (const MappingInfo& other)
{ {
return type == other.type && axis == other.axis; return type == other.type && axis == other.axis;
} }
}; };
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
@ -74,59 +74,59 @@ MakeLeftHandedProcess::~MakeLeftHandedProcess() {
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
bool MakeLeftHandedProcess::IsActive( unsigned int pFlags) const bool MakeLeftHandedProcess::IsActive( unsigned int pFlags) const
{ {
return 0 != (pFlags & aiProcess_MakeLeftHanded); return 0 != (pFlags & aiProcess_MakeLeftHanded);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
void MakeLeftHandedProcess::Execute( aiScene* pScene) void MakeLeftHandedProcess::Execute( aiScene* pScene)
{ {
// Check for an existent root node to proceed // Check for an existent root node to proceed
ai_assert(pScene->mRootNode != NULL); ai_assert(pScene->mRootNode != NULL);
DefaultLogger::get()->debug("MakeLeftHandedProcess begin"); DefaultLogger::get()->debug("MakeLeftHandedProcess begin");
// recursively convert all the nodes // recursively convert all the nodes
ProcessNode( pScene->mRootNode, aiMatrix4x4()); ProcessNode( pScene->mRootNode, aiMatrix4x4());
// process the meshes accordingly // process the meshes accordingly
for( unsigned int a = 0; a < pScene->mNumMeshes; ++a) for( unsigned int a = 0; a < pScene->mNumMeshes; ++a)
ProcessMesh( pScene->mMeshes[a]); ProcessMesh( pScene->mMeshes[a]);
// process the materials accordingly // process the materials accordingly
for( unsigned int a = 0; a < pScene->mNumMaterials; ++a) for( unsigned int a = 0; a < pScene->mNumMaterials; ++a)
ProcessMaterial( pScene->mMaterials[a]); ProcessMaterial( pScene->mMaterials[a]);
// transform all animation channels as well // transform all animation channels as well
for( unsigned int a = 0; a < pScene->mNumAnimations; a++) for( unsigned int a = 0; a < pScene->mNumAnimations; a++)
{ {
aiAnimation* anim = pScene->mAnimations[a]; aiAnimation* anim = pScene->mAnimations[a];
for( unsigned int b = 0; b < anim->mNumChannels; b++) for( unsigned int b = 0; b < anim->mNumChannels; b++)
{ {
aiNodeAnim* nodeAnim = anim->mChannels[b]; aiNodeAnim* nodeAnim = anim->mChannels[b];
ProcessAnimation( nodeAnim); ProcessAnimation( nodeAnim);
} }
} }
DefaultLogger::get()->debug("MakeLeftHandedProcess finished"); DefaultLogger::get()->debug("MakeLeftHandedProcess finished");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Recursively converts a node, all of its children and all of its meshes // Recursively converts a node, all of its children and all of its meshes
void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pParentGlobalRotation) void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pParentGlobalRotation)
{ {
// mirror all base vectors at the local Z axis // mirror all base vectors at the local Z axis
pNode->mTransformation.c1 = -pNode->mTransformation.c1; pNode->mTransformation.c1 = -pNode->mTransformation.c1;
pNode->mTransformation.c2 = -pNode->mTransformation.c2; pNode->mTransformation.c2 = -pNode->mTransformation.c2;
pNode->mTransformation.c3 = -pNode->mTransformation.c3; pNode->mTransformation.c3 = -pNode->mTransformation.c3;
pNode->mTransformation.c4 = -pNode->mTransformation.c4; pNode->mTransformation.c4 = -pNode->mTransformation.c4;
// now invert the Z axis again to keep the matrix determinant positive. // now invert the Z axis again to keep the matrix determinant positive.
// The local meshes will be inverted accordingly so that the result should look just fine again. // The local meshes will be inverted accordingly so that the result should look just fine again.
pNode->mTransformation.a3 = -pNode->mTransformation.a3; pNode->mTransformation.a3 = -pNode->mTransformation.a3;
pNode->mTransformation.b3 = -pNode->mTransformation.b3; pNode->mTransformation.b3 = -pNode->mTransformation.b3;
pNode->mTransformation.c3 = -pNode->mTransformation.c3; pNode->mTransformation.c3 = -pNode->mTransformation.c3;
pNode->mTransformation.d3 = -pNode->mTransformation.d3; // useless, but anyways... pNode->mTransformation.d3 = -pNode->mTransformation.d3; // useless, but anyways...
// continue for all children // continue for all children
for( size_t a = 0; a < pNode->mNumChildren; ++a ) { for( size_t a = 0; a < pNode->mNumChildren; ++a ) {
ProcessNode( pNode->mChildren[ a ], pParentGlobalRotation * pNode->mTransformation ); ProcessNode( pNode->mChildren[ a ], pParentGlobalRotation * pNode->mTransformation );
} }
@ -136,78 +136,78 @@ void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pPare
// Converts a single mesh to left handed coordinates. // Converts a single mesh to left handed coordinates.
void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh)
{ {
// mirror positions, normals and stuff along the Z axis // mirror positions, normals and stuff along the Z axis
for( size_t a = 0; a < pMesh->mNumVertices; ++a) for( size_t a = 0; a < pMesh->mNumVertices; ++a)
{ {
pMesh->mVertices[a].z *= -1.0f; pMesh->mVertices[a].z *= -1.0f;
if( pMesh->HasNormals()) if( pMesh->HasNormals())
pMesh->mNormals[a].z *= -1.0f; pMesh->mNormals[a].z *= -1.0f;
if( pMesh->HasTangentsAndBitangents()) if( pMesh->HasTangentsAndBitangents())
{ {
pMesh->mTangents[a].z *= -1.0f; pMesh->mTangents[a].z *= -1.0f;
pMesh->mBitangents[a].z *= -1.0f; pMesh->mBitangents[a].z *= -1.0f;
} }
} }
// mirror offset matrices of all bones // mirror offset matrices of all bones
for( size_t a = 0; a < pMesh->mNumBones; ++a) for( size_t a = 0; a < pMesh->mNumBones; ++a)
{ {
aiBone* bone = pMesh->mBones[a]; aiBone* bone = pMesh->mBones[a];
bone->mOffsetMatrix.a3 = -bone->mOffsetMatrix.a3; bone->mOffsetMatrix.a3 = -bone->mOffsetMatrix.a3;
bone->mOffsetMatrix.b3 = -bone->mOffsetMatrix.b3; bone->mOffsetMatrix.b3 = -bone->mOffsetMatrix.b3;
bone->mOffsetMatrix.d3 = -bone->mOffsetMatrix.d3; bone->mOffsetMatrix.d3 = -bone->mOffsetMatrix.d3;
bone->mOffsetMatrix.c1 = -bone->mOffsetMatrix.c1; bone->mOffsetMatrix.c1 = -bone->mOffsetMatrix.c1;
bone->mOffsetMatrix.c2 = -bone->mOffsetMatrix.c2; bone->mOffsetMatrix.c2 = -bone->mOffsetMatrix.c2;
bone->mOffsetMatrix.c4 = -bone->mOffsetMatrix.c4; bone->mOffsetMatrix.c4 = -bone->mOffsetMatrix.c4;
} }
// mirror bitangents as well as they're derived from the texture coords // mirror bitangents as well as they're derived from the texture coords
if( pMesh->HasTangentsAndBitangents()) if( pMesh->HasTangentsAndBitangents())
{ {
for( unsigned int a = 0; a < pMesh->mNumVertices; a++) for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
pMesh->mBitangents[a] *= -1.0f; pMesh->mBitangents[a] *= -1.0f;
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Converts a single material to left handed coordinates. // Converts a single material to left handed coordinates.
void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat)
{ {
aiMaterial* mat = (aiMaterial*)_mat; aiMaterial* mat = (aiMaterial*)_mat;
for (unsigned int a = 0; a < mat->mNumProperties;++a) { for (unsigned int a = 0; a < mat->mNumProperties;++a) {
aiMaterialProperty* prop = mat->mProperties[a]; aiMaterialProperty* prop = mat->mProperties[a];
// Mapping axis for UV mappings? // Mapping axis for UV mappings?
if (!::strcmp( prop->mKey.data, "$tex.mapaxis")) { if (!::strcmp( prop->mKey.data, "$tex.mapaxis")) {
ai_assert( prop->mDataLength >= sizeof(aiVector3D)); /* something is wrong with the validation if we end up here */ ai_assert( prop->mDataLength >= sizeof(aiVector3D)); /* something is wrong with the validation if we end up here */
aiVector3D* pff = (aiVector3D*)prop->mData; aiVector3D* pff = (aiVector3D*)prop->mData;
pff->z *= -1.f; pff->z *= -1.f;
} }
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Converts the given animation to LH coordinates. // Converts the given animation to LH coordinates.
void MakeLeftHandedProcess::ProcessAnimation( aiNodeAnim* pAnim) void MakeLeftHandedProcess::ProcessAnimation( aiNodeAnim* pAnim)
{ {
// position keys // position keys
for( unsigned int a = 0; a < pAnim->mNumPositionKeys; a++) for( unsigned int a = 0; a < pAnim->mNumPositionKeys; a++)
pAnim->mPositionKeys[a].mValue.z *= -1.0f; pAnim->mPositionKeys[a].mValue.z *= -1.0f;
// rotation keys // rotation keys
for( unsigned int a = 0; a < pAnim->mNumRotationKeys; a++) for( unsigned int a = 0; a < pAnim->mNumRotationKeys; a++)
{ {
/* That's the safe version, but the float errors add up. So we try the short version instead /* That's the safe version, but the float errors add up. So we try the short version instead
aiMatrix3x3 rotmat = pAnim->mRotationKeys[a].mValue.GetMatrix(); aiMatrix3x3 rotmat = pAnim->mRotationKeys[a].mValue.GetMatrix();
rotmat.a3 = -rotmat.a3; rotmat.b3 = -rotmat.b3; rotmat.a3 = -rotmat.a3; rotmat.b3 = -rotmat.b3;
rotmat.c1 = -rotmat.c1; rotmat.c2 = -rotmat.c2; rotmat.c1 = -rotmat.c1; rotmat.c2 = -rotmat.c2;
aiQuaternion rotquat( rotmat); aiQuaternion rotquat( rotmat);
pAnim->mRotationKeys[a].mValue = rotquat; pAnim->mRotationKeys[a].mValue = rotquat;
*/ */
pAnim->mRotationKeys[a].mValue.x *= -1.0f; pAnim->mRotationKeys[a].mValue.x *= -1.0f;
pAnim->mRotationKeys[a].mValue.y *= -1.0f; pAnim->mRotationKeys[a].mValue.y *= -1.0f;
} }
} }
#endif // !! ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS #endif // !! ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS
@ -228,52 +228,52 @@ FlipUVsProcess::~FlipUVsProcess()
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
bool FlipUVsProcess::IsActive( unsigned int pFlags) const bool FlipUVsProcess::IsActive( unsigned int pFlags) const
{ {
return 0 != (pFlags & aiProcess_FlipUVs); return 0 != (pFlags & aiProcess_FlipUVs);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
void FlipUVsProcess::Execute( aiScene* pScene) void FlipUVsProcess::Execute( aiScene* pScene)
{ {
DefaultLogger::get()->debug("FlipUVsProcess begin"); DefaultLogger::get()->debug("FlipUVsProcess begin");
for (unsigned int i = 0; i < pScene->mNumMeshes;++i) for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
ProcessMesh(pScene->mMeshes[i]); ProcessMesh(pScene->mMeshes[i]);
for (unsigned int i = 0; i < pScene->mNumMaterials;++i) for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
ProcessMaterial(pScene->mMaterials[i]); ProcessMaterial(pScene->mMaterials[i]);
DefaultLogger::get()->debug("FlipUVsProcess finished"); DefaultLogger::get()->debug("FlipUVsProcess finished");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Converts a single material // Converts a single material
void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat) void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat)
{ {
aiMaterial* mat = (aiMaterial*)_mat; aiMaterial* mat = (aiMaterial*)_mat;
for (unsigned int a = 0; a < mat->mNumProperties;++a) { for (unsigned int a = 0; a < mat->mNumProperties;++a) {
aiMaterialProperty* prop = mat->mProperties[a]; aiMaterialProperty* prop = mat->mProperties[a];
if( !prop ) { if( !prop ) {
DefaultLogger::get()->debug( "Property is null" ); DefaultLogger::get()->debug( "Property is null" );
continue; continue;
} }
// UV transformation key? // UV transformation key?
if (!::strcmp( prop->mKey.data, "$tex.uvtrafo")) { if (!::strcmp( prop->mKey.data, "$tex.uvtrafo")) {
ai_assert( prop->mDataLength >= sizeof(aiUVTransform)); /* something is wrong with the validation if we end up here */ ai_assert( prop->mDataLength >= sizeof(aiUVTransform)); /* something is wrong with the validation if we end up here */
aiUVTransform* uv = (aiUVTransform*)prop->mData; aiUVTransform* uv = (aiUVTransform*)prop->mData;
// just flip it, that's everything // just flip it, that's everything
uv->mTranslation.y *= -1.f; uv->mTranslation.y *= -1.f;
uv->mRotation *= -1.f; uv->mRotation *= -1.f;
} }
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Converts a single mesh // Converts a single mesh
void FlipUVsProcess::ProcessMesh( aiMesh* pMesh) void FlipUVsProcess::ProcessMesh( aiMesh* pMesh)
{ {
// mirror texture y coordinate // mirror texture y coordinate
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) { for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
if( !pMesh->HasTextureCoords( a ) ) { if( !pMesh->HasTextureCoords( a ) ) {
break; break;
} }
@ -281,7 +281,7 @@ void FlipUVsProcess::ProcessMesh( aiMesh* pMesh)
for( unsigned int b = 0; b < pMesh->mNumVertices; b++ ) { for( unsigned int b = 0; b < pMesh->mNumVertices; b++ ) {
pMesh->mTextureCoords[ a ][ b ].y = 1.0f - pMesh->mTextureCoords[ a ][ b ].y; pMesh->mTextureCoords[ a ][ b ].y = 1.0f - pMesh->mTextureCoords[ a ][ b ].y;
} }
} }
} }
#endif // !ASSIMP_BUILD_NO_FLIPUVS_PROCESS #endif // !ASSIMP_BUILD_NO_FLIPUVS_PROCESS
@ -302,30 +302,30 @@ FlipWindingOrderProcess::~FlipWindingOrderProcess()
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
bool FlipWindingOrderProcess::IsActive( unsigned int pFlags) const bool FlipWindingOrderProcess::IsActive( unsigned int pFlags) const
{ {
return 0 != (pFlags & aiProcess_FlipWindingOrder); return 0 != (pFlags & aiProcess_FlipWindingOrder);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
void FlipWindingOrderProcess::Execute( aiScene* pScene) void FlipWindingOrderProcess::Execute( aiScene* pScene)
{ {
DefaultLogger::get()->debug("FlipWindingOrderProcess begin"); DefaultLogger::get()->debug("FlipWindingOrderProcess begin");
for (unsigned int i = 0; i < pScene->mNumMeshes;++i) for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
ProcessMesh(pScene->mMeshes[i]); ProcessMesh(pScene->mMeshes[i]);
DefaultLogger::get()->debug("FlipWindingOrderProcess finished"); DefaultLogger::get()->debug("FlipWindingOrderProcess finished");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Converts a single mesh // Converts a single mesh
void FlipWindingOrderProcess::ProcessMesh( aiMesh* pMesh) void FlipWindingOrderProcess::ProcessMesh( aiMesh* pMesh)
{ {
// invert the order of all faces in this mesh // invert the order of all faces in this mesh
for( unsigned int a = 0; a < pMesh->mNumFaces; a++) for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
{ {
aiFace& face = pMesh->mFaces[a]; aiFace& face = pMesh->mFaces[a];
for( unsigned int b = 0; b < face.mNumIndices / 2; b++) for( unsigned int b = 0; b < face.mNumIndices / 2; b++)
std::swap( face.mIndices[b], face.mIndices[ face.mNumIndices - 1 - b]); std::swap( face.mIndices[b], face.mIndices[ face.mNumIndices - 1 - b]);
} }
} }
#endif // !! ASSIMP_BUILD_NO_FLIPWINDING_PROCESS #endif // !! ASSIMP_BUILD_NO_FLIPWINDING_PROCESS

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -57,7 +57,7 @@ struct aiNodeAnim;
struct aiNode; struct aiNode;
struct aiMaterial; struct aiMaterial;
namespace Assimp { namespace Assimp {
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
/** @brief The MakeLeftHandedProcess converts all imported data to a left-handed /** @brief The MakeLeftHandedProcess converts all imported data to a left-handed
@ -74,43 +74,43 @@ class MakeLeftHandedProcess : public BaseProcess
public: public:
MakeLeftHandedProcess(); MakeLeftHandedProcess();
~MakeLeftHandedProcess(); ~MakeLeftHandedProcess();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
bool IsActive( unsigned int pFlags) const; bool IsActive( unsigned int pFlags) const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
void Execute( aiScene* pScene); void Execute( aiScene* pScene);
protected: protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Recursively converts a node and all of its children /** Recursively converts a node and all of its children
*/ */
void ProcessNode( aiNode* pNode, const aiMatrix4x4& pParentGlobalRotation); void ProcessNode( aiNode* pNode, const aiMatrix4x4& pParentGlobalRotation);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Converts a single mesh to left handed coordinates. /** Converts a single mesh to left handed coordinates.
* This means that positions, normals and tangents are mirrored at * This means that positions, normals and tangents are mirrored at
* the local Z axis and the order of all faces are inverted. * the local Z axis and the order of all faces are inverted.
* @param pMesh The mesh to convert. * @param pMesh The mesh to convert.
*/ */
void ProcessMesh( aiMesh* pMesh); void ProcessMesh( aiMesh* pMesh);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Converts a single material to left-handed coordinates /** Converts a single material to left-handed coordinates
* @param pMat Material to convert * @param pMat Material to convert
*/ */
void ProcessMaterial( aiMaterial* pMat); void ProcessMaterial( aiMaterial* pMat);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Converts the given animation to LH coordinates. /** Converts the given animation to LH coordinates.
* The rotation and translation keys are transformed, the scale keys * The rotation and translation keys are transformed, the scale keys
* work in local space and can therefore be left untouched. * work in local space and can therefore be left untouched.
* @param pAnim The bone animation to transform * @param pAnim The bone animation to transform
*/ */
void ProcessAnimation( aiNodeAnim* pAnim); void ProcessAnimation( aiNodeAnim* pAnim);
}; };
@ -119,23 +119,23 @@ protected:
*/ */
class FlipWindingOrderProcess : public BaseProcess class FlipWindingOrderProcess : public BaseProcess
{ {
friend class Importer; friend class Importer;
public: public:
/** Constructor to be privately used by Importer */ /** Constructor to be privately used by Importer */
FlipWindingOrderProcess(); FlipWindingOrderProcess();
/** Destructor, private as well */ /** Destructor, private as well */
~FlipWindingOrderProcess(); ~FlipWindingOrderProcess();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
bool IsActive( unsigned int pFlags) const; bool IsActive( unsigned int pFlags) const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
void Execute( aiScene* pScene); void Execute( aiScene* pScene);
protected: protected:
void ProcessMesh( aiMesh* pMesh); void ProcessMesh( aiMesh* pMesh);
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -143,24 +143,24 @@ protected:
*/ */
class FlipUVsProcess : public BaseProcess class FlipUVsProcess : public BaseProcess
{ {
friend class Importer; friend class Importer;
public: public:
/** Constructor to be privately used by Importer */ /** Constructor to be privately used by Importer */
FlipUVsProcess(); FlipUVsProcess();
/** Destructor, private as well */ /** Destructor, private as well */
~FlipUVsProcess(); ~FlipUVsProcess();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
bool IsActive( unsigned int pFlags) const; bool IsActive( unsigned int pFlags) const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
void Execute( aiScene* pScene); void Execute( aiScene* pScene);
protected: protected:
void ProcessMesh( aiMesh* pMesh); void ProcessMesh( aiMesh* pMesh);
void ProcessMaterial( aiMaterial* mat); void ProcessMaterial( aiMaterial* mat);
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../include/assimp/DefaultLogger.hpp" #include "../include/assimp/DefaultLogger.hpp"
namespace Assimp { namespace Assimp {
namespace DXF { namespace DXF {
// read pairs of lines, parse group code and value and provide utilities // read pairs of lines, parse group code and value and provide utilities
@ -63,113 +63,113 @@ class LineReader
public: public:
LineReader(StreamReaderLE& reader) LineReader(StreamReaderLE& reader)
// do NOT skip empty lines. In DXF files, they count as valid data. // do NOT skip empty lines. In DXF files, they count as valid data.
: splitter(reader,false,true) : splitter(reader,false,true)
, end() , end()
{ {
} }
public: public:
// ----------------------------------------- // -----------------------------------------
bool Is(int gc, const char* what) const { bool Is(int gc, const char* what) const {
return groupcode == gc && !strcmp(what,value.c_str()); return groupcode == gc && !strcmp(what,value.c_str());
} }
// ----------------------------------------- // -----------------------------------------
bool Is(int gc) const { bool Is(int gc) const {
return groupcode == gc; return groupcode == gc;
} }
// ----------------------------------------- // -----------------------------------------
int GroupCode() const { int GroupCode() const {
return groupcode; return groupcode;
} }
// ----------------------------------------- // -----------------------------------------
const std::string& Value() const { const std::string& Value() const {
return value; return value;
} }
// ----------------------------------------- // -----------------------------------------
bool End() const { bool End() const {
return !((bool)*this); return !((bool)*this);
} }
public: public:
// ----------------------------------------- // -----------------------------------------
unsigned int ValueAsUnsignedInt() const { unsigned int ValueAsUnsignedInt() const {
return strtoul10(value.c_str()); return strtoul10(value.c_str());
} }
// ----------------------------------------- // -----------------------------------------
int ValueAsSignedInt() const { int ValueAsSignedInt() const {
return strtol10(value.c_str()); return strtol10(value.c_str());
} }
// ----------------------------------------- // -----------------------------------------
float ValueAsFloat() const { float ValueAsFloat() const {
return fast_atof(value.c_str()); return fast_atof(value.c_str());
} }
public: public:
// ----------------------------------------- // -----------------------------------------
/** pseudo-iterator increment to advance to the next (groupcode/value) pair */ /** pseudo-iterator increment to advance to the next (groupcode/value) pair */
LineReader& operator++() { LineReader& operator++() {
if (end) { if (end) {
if (end == 1) { if (end == 1) {
++end; ++end;
} }
return *this; return *this;
} }
try { try {
groupcode = strtol10(splitter->c_str()); groupcode = strtol10(splitter->c_str());
splitter++; splitter++;
value = *splitter; value = *splitter;
splitter++; splitter++;
// automatically skip over {} meta blocks (these are for application use // automatically skip over {} meta blocks (these are for application use
// and currently not relevant for Assimp). // and currently not relevant for Assimp).
if (value.length() && value[0] == '{') { if (value.length() && value[0] == '{') {
size_t cnt = 0; size_t cnt = 0;
for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++); for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++);
splitter++; splitter++;
DefaultLogger::get()->debug((Formatter::format("DXF: skipped over control group ("),cnt," lines)")); DefaultLogger::get()->debug((Formatter::format("DXF: skipped over control group ("),cnt," lines)"));
} }
} catch(std::logic_error&) { } catch(std::logic_error&) {
ai_assert(!splitter); ai_assert(!splitter);
} }
if (!splitter) { if (!splitter) {
end = 1; end = 1;
} }
return *this; return *this;
} }
// ----------------------------------------- // -----------------------------------------
LineReader& operator++(int) { LineReader& operator++(int) {
return ++(*this); return ++(*this);
} }
// ----------------------------------------- // -----------------------------------------
operator bool() const { operator bool() const {
return end <= 1; return end <= 1;
} }
private: private:
LineSplitter splitter; LineSplitter splitter;
int groupcode; int groupcode;
std::string value; std::string value;
int end; int end;
}; };
@ -177,52 +177,52 @@ private:
// represents a POLYLINE or a LWPOLYLINE. or even a 3DFACE The data is converted as needed. // represents a POLYLINE or a LWPOLYLINE. or even a 3DFACE The data is converted as needed.
struct PolyLine struct PolyLine
{ {
PolyLine() PolyLine()
: flags() : flags()
{} {}
std::vector<aiVector3D> positions; std::vector<aiVector3D> positions;
std::vector<aiColor4D> colors; std::vector<aiColor4D> colors;
std::vector<unsigned int> indices; std::vector<unsigned int> indices;
std::vector<unsigned int> counts; std::vector<unsigned int> counts;
unsigned int flags; unsigned int flags;
std::string layer; std::string layer;
std::string desc; std::string desc;
}; };
// reference to a BLOCK. Specifies its own coordinate system. // reference to a BLOCK. Specifies its own coordinate system.
struct InsertBlock struct InsertBlock
{ {
InsertBlock() InsertBlock()
: scale(1.f,1.f,1.f) : scale(1.f,1.f,1.f)
, angle() , angle()
{} {}
aiVector3D pos; aiVector3D pos;
aiVector3D scale; aiVector3D scale;
float angle; float angle;
std::string name; std::string name;
}; };
// keeps track of all geometry in a single BLOCK. // keeps track of all geometry in a single BLOCK.
struct Block struct Block
{ {
std::vector< boost::shared_ptr<PolyLine> > lines; std::vector< boost::shared_ptr<PolyLine> > lines;
std::vector<InsertBlock> insertions; std::vector<InsertBlock> insertions;
std::string name; std::string name;
aiVector3D base; aiVector3D base;
}; };
struct FileData struct FileData
{ {
// note: the LAST block always contains the stuff from ENTITIES. // note: the LAST block always contains the stuff from ENTITIES.
std::vector<Block> blocks; std::vector<Block> blocks;
}; };

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -46,17 +46,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h" #include "BaseImporter.h"
namespace Assimp { namespace Assimp {
namespace DXF { namespace DXF {
class LineReader; class LineReader;
struct FileData; struct FileData;
struct PolyLine; struct PolyLine;
struct Block; struct Block;
struct InsertBlock; struct InsertBlock;
typedef std::map<std::string, const DXF::Block*> BlockMap; typedef std::map<std::string, const DXF::Block*> BlockMap;
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -66,85 +66,85 @@ namespace Assimp {
class DXFImporter : public BaseImporter class DXFImporter : public BaseImporter
{ {
public: public:
DXFImporter(); DXFImporter();
~DXFImporter(); ~DXFImporter();
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. */ * See BaseImporter::CanRead() for details. */
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const; bool checkSig) const;
protected: protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Return importer meta information. /** Return importer meta information.
* See #BaseImporter::GetInfo for the details*/ * See #BaseImporter::GetInfo for the details*/
const aiImporterDesc* GetInfo () const; const aiImporterDesc* GetInfo () const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Imports the given file into the given scene structure. /** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details */ * See BaseImporter::InternReadFile() for details */
void InternReadFile( const std::string& pFile, void InternReadFile( const std::string& pFile,
aiScene* pScene, aiScene* pScene,
IOSystem* pIOHandler); IOSystem* pIOHandler);
private: private:
// ----------------------------------------------------- // -----------------------------------------------------
void SkipSection(DXF::LineReader& reader); void SkipSection(DXF::LineReader& reader);
// ----------------------------------------------------- // -----------------------------------------------------
void ParseHeader(DXF::LineReader& reader, void ParseHeader(DXF::LineReader& reader,
DXF::FileData& output); DXF::FileData& output);
// ----------------------------------------------------- // -----------------------------------------------------
void ParseEntities(DXF::LineReader& reader, void ParseEntities(DXF::LineReader& reader,
DXF::FileData& output); DXF::FileData& output);
// ----------------------------------------------------- // -----------------------------------------------------
void ParseBlocks(DXF::LineReader& reader, void ParseBlocks(DXF::LineReader& reader,
DXF::FileData& output); DXF::FileData& output);
// ----------------------------------------------------- // -----------------------------------------------------
void ParseBlock(DXF::LineReader& reader, void ParseBlock(DXF::LineReader& reader,
DXF::FileData& output); DXF::FileData& output);
// ----------------------------------------------------- // -----------------------------------------------------
void ParseInsertion(DXF::LineReader& reader, void ParseInsertion(DXF::LineReader& reader,
DXF::FileData& output); DXF::FileData& output);
// ----------------------------------------------------- // -----------------------------------------------------
void ParsePolyLine(DXF::LineReader& reader, void ParsePolyLine(DXF::LineReader& reader,
DXF::FileData& output); DXF::FileData& output);
// ----------------------------------------------------- // -----------------------------------------------------
void ParsePolyLineVertex(DXF::LineReader& reader, void ParsePolyLineVertex(DXF::LineReader& reader,
DXF::PolyLine& line); DXF::PolyLine& line);
// ----------------------------------------------------- // -----------------------------------------------------
void Parse3DFace(DXF::LineReader& reader, void Parse3DFace(DXF::LineReader& reader,
DXF::FileData& output); DXF::FileData& output);
// ----------------------------------------------------- // -----------------------------------------------------
void ConvertMeshes(aiScene* pScene, void ConvertMeshes(aiScene* pScene,
DXF::FileData& output); DXF::FileData& output);
// ----------------------------------------------------- // -----------------------------------------------------
void GenerateHierarchy(aiScene* pScene, void GenerateHierarchy(aiScene* pScene,
DXF::FileData& output); DXF::FileData& output);
// ----------------------------------------------------- // -----------------------------------------------------
void GenerateMaterials(aiScene* pScene, void GenerateMaterials(aiScene* pScene,
DXF::FileData& output); DXF::FileData& output);
// ----------------------------------------------------- // -----------------------------------------------------
void ExpandBlockReferences(DXF::Block& bl, void ExpandBlockReferences(DXF::Block& bl,
const DXF::BlockMap& blocks_by_name); const DXF::BlockMap& blocks_by_name);
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -1,8 +1,8 @@
/* /*
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -55,411 +55,411 @@ using namespace Assimp;
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
DeboneProcess::DeboneProcess() DeboneProcess::DeboneProcess()
{ {
mNumBones = 0; mNumBones = 0;
mNumBonesCanDoWithout = 0; mNumBonesCanDoWithout = 0;
mThreshold = AI_DEBONE_THRESHOLD; mThreshold = AI_DEBONE_THRESHOLD;
mAllOrNone = false; mAllOrNone = false;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
DeboneProcess::~DeboneProcess() DeboneProcess::~DeboneProcess()
{ {
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
bool DeboneProcess::IsActive( unsigned int pFlags) const bool DeboneProcess::IsActive( unsigned int pFlags) const
{ {
return (pFlags & aiProcess_Debone) != 0; return (pFlags & aiProcess_Debone) != 0;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
void DeboneProcess::SetupProperties(const Importer* pImp) void DeboneProcess::SetupProperties(const Importer* pImp)
{ {
// get the current value of the property // get the current value of the property
mAllOrNone = pImp->GetPropertyInteger(AI_CONFIG_PP_DB_ALL_OR_NONE,0)?true:false; mAllOrNone = pImp->GetPropertyInteger(AI_CONFIG_PP_DB_ALL_OR_NONE,0)?true:false;
mThreshold = pImp->GetPropertyFloat(AI_CONFIG_PP_DB_THRESHOLD,AI_DEBONE_THRESHOLD); mThreshold = pImp->GetPropertyFloat(AI_CONFIG_PP_DB_THRESHOLD,AI_DEBONE_THRESHOLD);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
void DeboneProcess::Execute( aiScene* pScene) void DeboneProcess::Execute( aiScene* pScene)
{ {
DefaultLogger::get()->debug("DeboneProcess begin"); DefaultLogger::get()->debug("DeboneProcess begin");
if(!pScene->mNumMeshes) { if(!pScene->mNumMeshes) {
return; return;
} }
std::vector<bool> splitList(pScene->mNumMeshes); std::vector<bool> splitList(pScene->mNumMeshes);
for( unsigned int a = 0; a < pScene->mNumMeshes; a++) { for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
splitList[a] = ConsiderMesh( pScene->mMeshes[a] ); splitList[a] = ConsiderMesh( pScene->mMeshes[a] );
} }
int numSplits = 0; int numSplits = 0;
if(!!mNumBonesCanDoWithout && (!mAllOrNone||mNumBonesCanDoWithout==mNumBones)) { if(!!mNumBonesCanDoWithout && (!mAllOrNone||mNumBonesCanDoWithout==mNumBones)) {
for(unsigned int a = 0; a < pScene->mNumMeshes; a++) { for(unsigned int a = 0; a < pScene->mNumMeshes; a++) {
if(splitList[a]) { if(splitList[a]) {
numSplits++; numSplits++;
} }
} }
} }
if(numSplits) { if(numSplits) {
// we need to do something. Let's go. // we need to do something. Let's go.
//mSubMeshIndices.clear(); // really needed? //mSubMeshIndices.clear(); // really needed?
mSubMeshIndices.resize(pScene->mNumMeshes); // because we're doing it here anyway mSubMeshIndices.resize(pScene->mNumMeshes); // because we're doing it here anyway
// build a new array of meshes for the scene // build a new array of meshes for the scene
std::vector<aiMesh*> meshes; std::vector<aiMesh*> meshes;
for(unsigned int a=0;a<pScene->mNumMeshes;a++) for(unsigned int a=0;a<pScene->mNumMeshes;a++)
{ {
aiMesh* srcMesh = pScene->mMeshes[a]; aiMesh* srcMesh = pScene->mMeshes[a];
std::vector<std::pair<aiMesh*,const aiBone*> > newMeshes; std::vector<std::pair<aiMesh*,const aiBone*> > newMeshes;
if(splitList[a]) { if(splitList[a]) {
SplitMesh(srcMesh,newMeshes); SplitMesh(srcMesh,newMeshes);
} }
// mesh was split // mesh was split
if(!newMeshes.empty()) { if(!newMeshes.empty()) {
unsigned int out = 0, in = srcMesh->mNumBones; unsigned int out = 0, in = srcMesh->mNumBones;
// store new meshes and indices of the new meshes // store new meshes and indices of the new meshes
for(unsigned int b=0;b<newMeshes.size();b++) { for(unsigned int b=0;b<newMeshes.size();b++) {
const aiString *find = newMeshes[b].second?&newMeshes[b].second->mName:0; const aiString *find = newMeshes[b].second?&newMeshes[b].second->mName:0;
aiNode *theNode = find?pScene->mRootNode->FindNode(*find):0; aiNode *theNode = find?pScene->mRootNode->FindNode(*find):0;
std::pair<unsigned int,aiNode*> push_pair(meshes.size(),theNode); std::pair<unsigned int,aiNode*> push_pair(meshes.size(),theNode);
mSubMeshIndices[a].push_back(push_pair); mSubMeshIndices[a].push_back(push_pair);
meshes.push_back(newMeshes[b].first); meshes.push_back(newMeshes[b].first);
out+=newMeshes[b].first->mNumBones; out+=newMeshes[b].first->mNumBones;
} }
if(!DefaultLogger::isNullLogger()) { if(!DefaultLogger::isNullLogger()) {
char buffer[1024]; char buffer[1024];
::sprintf(buffer,"Removed %u bones. Input bones: %u. Output bones: %u",in-out,in,out); ::sprintf(buffer,"Removed %u bones. Input bones: %u. Output bones: %u",in-out,in,out);
DefaultLogger::get()->info(buffer); DefaultLogger::get()->info(buffer);
} }
// and destroy the source mesh. It should be completely contained inside the new submeshes // and destroy the source mesh. It should be completely contained inside the new submeshes
delete srcMesh; delete srcMesh;
} }
else { else {
// Mesh is kept unchanged - store it's new place in the mesh array // Mesh is kept unchanged - store it's new place in the mesh array
mSubMeshIndices[a].push_back(std::pair<unsigned int,aiNode*>(meshes.size(),(aiNode*)0)); mSubMeshIndices[a].push_back(std::pair<unsigned int,aiNode*>(meshes.size(),(aiNode*)0));
meshes.push_back(srcMesh); meshes.push_back(srcMesh);
} }
} }
// rebuild the scene's mesh array // rebuild the scene's mesh array
pScene->mNumMeshes = meshes.size(); pScene->mNumMeshes = meshes.size();
delete [] pScene->mMeshes; delete [] pScene->mMeshes;
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
std::copy( meshes.begin(), meshes.end(), pScene->mMeshes); std::copy( meshes.begin(), meshes.end(), pScene->mMeshes);
// recurse through all nodes and translate the node's mesh indices to fit the new mesh array // recurse through all nodes and translate the node's mesh indices to fit the new mesh array
UpdateNode( pScene->mRootNode); UpdateNode( pScene->mRootNode);
} }
DefaultLogger::get()->debug("DeboneProcess end"); DefaultLogger::get()->debug("DeboneProcess end");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Counts bones total/removable in a given mesh. // Counts bones total/removable in a given mesh.
bool DeboneProcess::ConsiderMesh(const aiMesh* pMesh) bool DeboneProcess::ConsiderMesh(const aiMesh* pMesh)
{ {
if(!pMesh->HasBones()) { if(!pMesh->HasBones()) {
return false; return false;
} }
bool split = false; bool split = false;
//interstitial faces not permitted //interstitial faces not permitted
bool isInterstitialRequired = false; bool isInterstitialRequired = false;
std::vector<bool> isBoneNecessary(pMesh->mNumBones,false); std::vector<bool> isBoneNecessary(pMesh->mNumBones,false);
std::vector<unsigned int> vertexBones(pMesh->mNumVertices,UINT_MAX); std::vector<unsigned int> vertexBones(pMesh->mNumVertices,UINT_MAX);
const unsigned int cUnowned = UINT_MAX; const unsigned int cUnowned = UINT_MAX;
const unsigned int cCoowned = UINT_MAX-1; const unsigned int cCoowned = UINT_MAX-1;
for(unsigned int i=0;i<pMesh->mNumBones;i++) { for(unsigned int i=0;i<pMesh->mNumBones;i++) {
for(unsigned int j=0;j<pMesh->mBones[i]->mNumWeights;j++) { for(unsigned int j=0;j<pMesh->mBones[i]->mNumWeights;j++) {
float w = pMesh->mBones[i]->mWeights[j].mWeight; float w = pMesh->mBones[i]->mWeights[j].mWeight;
if(w==0.0f) { if(w==0.0f) {
continue; continue;
} }
unsigned int vid = pMesh->mBones[i]->mWeights[j].mVertexId; unsigned int vid = pMesh->mBones[i]->mWeights[j].mVertexId;
if(w>=mThreshold) { if(w>=mThreshold) {
if(vertexBones[vid]!=cUnowned) { if(vertexBones[vid]!=cUnowned) {
if(vertexBones[vid]==i) //double entry if(vertexBones[vid]==i) //double entry
{ {
DefaultLogger::get()->warn("Encountered double entry in bone weights"); DefaultLogger::get()->warn("Encountered double entry in bone weights");
} }
else //TODO: track attraction in order to break tie else //TODO: track attraction in order to break tie
{ {
vertexBones[vid] = cCoowned; vertexBones[vid] = cCoowned;
} }
} }
else vertexBones[vid] = i; else vertexBones[vid] = i;
} }
if(!isBoneNecessary[i]) { if(!isBoneNecessary[i]) {
isBoneNecessary[i] = w<mThreshold; isBoneNecessary[i] = w<mThreshold;
} }
} }
if(!isBoneNecessary[i]) { if(!isBoneNecessary[i]) {
isInterstitialRequired = true; isInterstitialRequired = true;
} }
} }
if(isInterstitialRequired) { if(isInterstitialRequired) {
for(unsigned int i=0;i<pMesh->mNumFaces;i++) { for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
unsigned int v = vertexBones[pMesh->mFaces[i].mIndices[0]]; unsigned int v = vertexBones[pMesh->mFaces[i].mIndices[0]];
for(unsigned int j=1;j<pMesh->mFaces[i].mNumIndices;j++) { for(unsigned int j=1;j<pMesh->mFaces[i].mNumIndices;j++) {
unsigned int w = vertexBones[pMesh->mFaces[i].mIndices[j]]; unsigned int w = vertexBones[pMesh->mFaces[i].mIndices[j]];
if(v!=w) { if(v!=w) {
if(v<pMesh->mNumBones) isBoneNecessary[v] = true; if(v<pMesh->mNumBones) isBoneNecessary[v] = true;
if(w<pMesh->mNumBones) isBoneNecessary[w] = true; if(w<pMesh->mNumBones) isBoneNecessary[w] = true;
} }
} }
} }
} }
for(unsigned int i=0;i<pMesh->mNumBones;i++) { for(unsigned int i=0;i<pMesh->mNumBones;i++) {
if(!isBoneNecessary[i]) { if(!isBoneNecessary[i]) {
mNumBonesCanDoWithout++; mNumBonesCanDoWithout++;
split = true; split = true;
} }
mNumBones++; mNumBones++;
} }
return split; return split;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Splits the given mesh by bone count. // Splits the given mesh by bone count.
void DeboneProcess::SplitMesh( const aiMesh* pMesh, std::vector< std::pair< aiMesh*,const aiBone* > >& poNewMeshes) const void DeboneProcess::SplitMesh( const aiMesh* pMesh, std::vector< std::pair< aiMesh*,const aiBone* > >& poNewMeshes) const
{ {
// same deal here as ConsiderMesh basically // same deal here as ConsiderMesh basically
std::vector<bool> isBoneNecessary(pMesh->mNumBones,false); std::vector<bool> isBoneNecessary(pMesh->mNumBones,false);
std::vector<unsigned int> vertexBones(pMesh->mNumVertices,UINT_MAX); std::vector<unsigned int> vertexBones(pMesh->mNumVertices,UINT_MAX);
const unsigned int cUnowned = UINT_MAX; const unsigned int cUnowned = UINT_MAX;
const unsigned int cCoowned = UINT_MAX-1; const unsigned int cCoowned = UINT_MAX-1;
for(unsigned int i=0;i<pMesh->mNumBones;i++) { for(unsigned int i=0;i<pMesh->mNumBones;i++) {
for(unsigned int j=0;j<pMesh->mBones[i]->mNumWeights;j++) { for(unsigned int j=0;j<pMesh->mBones[i]->mNumWeights;j++) {
float w = pMesh->mBones[i]->mWeights[j].mWeight; float w = pMesh->mBones[i]->mWeights[j].mWeight;
if(w==0.0f) { if(w==0.0f) {
continue; continue;
} }
unsigned int vid = pMesh->mBones[i]->mWeights[j].mVertexId; unsigned int vid = pMesh->mBones[i]->mWeights[j].mVertexId;
if(w>=mThreshold) { if(w>=mThreshold) {
if(vertexBones[vid]!=cUnowned) { if(vertexBones[vid]!=cUnowned) {
if(vertexBones[vid]==i) //double entry if(vertexBones[vid]==i) //double entry
{ {
//DefaultLogger::get()->warn("Encountered double entry in bone weights"); //DefaultLogger::get()->warn("Encountered double entry in bone weights");
} }
else //TODO: track attraction in order to break tie else //TODO: track attraction in order to break tie
{ {
vertexBones[vid] = cCoowned; vertexBones[vid] = cCoowned;
} }
} }
else vertexBones[vid] = i; else vertexBones[vid] = i;
} }
if(!isBoneNecessary[i]) { if(!isBoneNecessary[i]) {
isBoneNecessary[i] = w<mThreshold; isBoneNecessary[i] = w<mThreshold;
} }
} }
} }
unsigned int nFacesUnowned = 0; unsigned int nFacesUnowned = 0;
std::vector<unsigned int> faceBones(pMesh->mNumFaces,UINT_MAX); std::vector<unsigned int> faceBones(pMesh->mNumFaces,UINT_MAX);
std::vector<unsigned int> facesPerBone(pMesh->mNumBones,0); std::vector<unsigned int> facesPerBone(pMesh->mNumBones,0);
for(unsigned int i=0;i<pMesh->mNumFaces;i++) { for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
unsigned int nInterstitial = 1; unsigned int nInterstitial = 1;
unsigned int v = vertexBones[pMesh->mFaces[i].mIndices[0]]; unsigned int v = vertexBones[pMesh->mFaces[i].mIndices[0]];
for(unsigned int j=1;j<pMesh->mFaces[i].mNumIndices;j++) { for(unsigned int j=1;j<pMesh->mFaces[i].mNumIndices;j++) {
unsigned int w = vertexBones[pMesh->mFaces[i].mIndices[j]]; unsigned int w = vertexBones[pMesh->mFaces[i].mIndices[j]];
if(v!=w) { if(v!=w) {
if(v<pMesh->mNumBones) isBoneNecessary[v] = true; if(v<pMesh->mNumBones) isBoneNecessary[v] = true;
if(w<pMesh->mNumBones) isBoneNecessary[w] = true; if(w<pMesh->mNumBones) isBoneNecessary[w] = true;
} }
else nInterstitial++; else nInterstitial++;
} }
if(v<pMesh->mNumBones &&nInterstitial==pMesh->mFaces[i].mNumIndices) { if(v<pMesh->mNumBones &&nInterstitial==pMesh->mFaces[i].mNumIndices) {
faceBones[i] = v; //primitive belongs to bone #v faceBones[i] = v; //primitive belongs to bone #v
facesPerBone[v]++; facesPerBone[v]++;
} }
else nFacesUnowned++; else nFacesUnowned++;
} }
// invalidate any "cojoined" faces // invalidate any "cojoined" faces
for(unsigned int i=0;i<pMesh->mNumFaces;i++) { for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
if(faceBones[i]<pMesh->mNumBones&&isBoneNecessary[faceBones[i]]) if(faceBones[i]<pMesh->mNumBones&&isBoneNecessary[faceBones[i]])
{ {
ai_assert(facesPerBone[faceBones[i]]>0); ai_assert(facesPerBone[faceBones[i]]>0);
facesPerBone[faceBones[i]]--; facesPerBone[faceBones[i]]--;
nFacesUnowned++; nFacesUnowned++;
faceBones[i] = cUnowned; faceBones[i] = cUnowned;
} }
} }
if(nFacesUnowned) { if(nFacesUnowned) {
std::vector<unsigned int> subFaces; std::vector<unsigned int> subFaces;
for(unsigned int i=0;i<pMesh->mNumFaces;i++) { for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
if(faceBones[i]==cUnowned) { if(faceBones[i]==cUnowned) {
subFaces.push_back(i); subFaces.push_back(i);
} }
} }
aiMesh *baseMesh = MakeSubmesh(pMesh,subFaces,0); aiMesh *baseMesh = MakeSubmesh(pMesh,subFaces,0);
std::pair<aiMesh*,const aiBone*> push_pair(baseMesh,(const aiBone*)0); std::pair<aiMesh*,const aiBone*> push_pair(baseMesh,(const aiBone*)0);
poNewMeshes.push_back(push_pair); poNewMeshes.push_back(push_pair);
} }
for(unsigned int i=0;i<pMesh->mNumBones;i++) { for(unsigned int i=0;i<pMesh->mNumBones;i++) {
if(!isBoneNecessary[i]&&facesPerBone[i]>0) { if(!isBoneNecessary[i]&&facesPerBone[i]>0) {
std::vector<unsigned int> subFaces; std::vector<unsigned int> subFaces;
for(unsigned int j=0;j<pMesh->mNumFaces;j++) { for(unsigned int j=0;j<pMesh->mNumFaces;j++) {
if(faceBones[j]==i) { if(faceBones[j]==i) {
subFaces.push_back(j); subFaces.push_back(j);
} }
} }
unsigned int f = AI_SUBMESH_FLAGS_SANS_BONES; unsigned int f = AI_SUBMESH_FLAGS_SANS_BONES;
aiMesh *subMesh =MakeSubmesh(pMesh,subFaces,f); aiMesh *subMesh =MakeSubmesh(pMesh,subFaces,f);
//Lifted from PretransformVertices.cpp //Lifted from PretransformVertices.cpp
ApplyTransform(subMesh,pMesh->mBones[i]->mOffsetMatrix); ApplyTransform(subMesh,pMesh->mBones[i]->mOffsetMatrix);
std::pair<aiMesh*,const aiBone*> push_pair(subMesh,pMesh->mBones[i]); std::pair<aiMesh*,const aiBone*> push_pair(subMesh,pMesh->mBones[i]);
poNewMeshes.push_back(push_pair); poNewMeshes.push_back(push_pair);
} }
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Recursively updates the node's mesh list to account for the changed mesh list // Recursively updates the node's mesh list to account for the changed mesh list
void DeboneProcess::UpdateNode(aiNode* pNode) const void DeboneProcess::UpdateNode(aiNode* pNode) const
{ {
// rebuild the node's mesh index list // rebuild the node's mesh index list
std::vector<unsigned int> newMeshList; std::vector<unsigned int> newMeshList;
// this will require two passes // this will require two passes
unsigned int m = pNode->mNumMeshes, n = mSubMeshIndices.size(); unsigned int m = pNode->mNumMeshes, n = mSubMeshIndices.size();
// first pass, look for meshes which have not moved // first pass, look for meshes which have not moved
for(unsigned int a=0;a<m;a++) { for(unsigned int a=0;a<m;a++) {
unsigned int srcIndex = pNode->mMeshes[a]; unsigned int srcIndex = pNode->mMeshes[a];
const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[srcIndex]; const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[srcIndex];
unsigned int nSubmeshes = subMeshes.size(); unsigned int nSubmeshes = subMeshes.size();
for(unsigned int b=0;b<nSubmeshes;b++) { for(unsigned int b=0;b<nSubmeshes;b++) {
if(!subMeshes[b].second) { if(!subMeshes[b].second) {
newMeshList.push_back(subMeshes[b].first); newMeshList.push_back(subMeshes[b].first);
} }
} }
} }
// second pass, collect deboned meshes // second pass, collect deboned meshes
for(unsigned int a=0;a<n;a++) for(unsigned int a=0;a<n;a++)
{ {
const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[a]; const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[a];
unsigned int nSubmeshes = subMeshes.size(); unsigned int nSubmeshes = subMeshes.size();
for(unsigned int b=0;b<nSubmeshes;b++) { for(unsigned int b=0;b<nSubmeshes;b++) {
if(subMeshes[b].second == pNode) { if(subMeshes[b].second == pNode) {
newMeshList.push_back(subMeshes[b].first); newMeshList.push_back(subMeshes[b].first);
} }
} }
} }
if( pNode->mNumMeshes > 0 ) { if( pNode->mNumMeshes > 0 ) {
delete [] pNode->mMeshes; pNode->mMeshes = NULL; delete [] pNode->mMeshes; pNode->mMeshes = NULL;
} }
pNode->mNumMeshes = newMeshList.size(); pNode->mNumMeshes = newMeshList.size();
if(pNode->mNumMeshes) { if(pNode->mNumMeshes) {
pNode->mMeshes = new unsigned int[pNode->mNumMeshes]; pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
std::copy( newMeshList.begin(), newMeshList.end(), pNode->mMeshes); std::copy( newMeshList.begin(), newMeshList.end(), pNode->mMeshes);
} }
// do that also recursively for all children // do that also recursively for all children
for( unsigned int a = 0; a < pNode->mNumChildren; ++a ) { for( unsigned int a = 0; a < pNode->mNumChildren; ++a ) {
UpdateNode( pNode->mChildren[a]); UpdateNode( pNode->mChildren[a]);
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Apply the node transformation to a mesh // Apply the node transformation to a mesh
void DeboneProcess::ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat)const void DeboneProcess::ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat)const
{ {
// Check whether we need to transform the coordinates at all // Check whether we need to transform the coordinates at all
if (!mat.IsIdentity()) { if (!mat.IsIdentity()) {
if (mesh->HasPositions()) { if (mesh->HasPositions()) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
mesh->mVertices[i] = mat * mesh->mVertices[i]; mesh->mVertices[i] = mat * mesh->mVertices[i];
} }
} }
if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) { if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) {
aiMatrix4x4 mWorldIT = mat; aiMatrix4x4 mWorldIT = mat;
mWorldIT.Inverse().Transpose(); mWorldIT.Inverse().Transpose();
// TODO: implement Inverse() for aiMatrix3x3 // TODO: implement Inverse() for aiMatrix3x3
aiMatrix3x3 m = aiMatrix3x3(mWorldIT); aiMatrix3x3 m = aiMatrix3x3(mWorldIT);
if (mesh->HasNormals()) { if (mesh->HasNormals()) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize(); mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize();
} }
} }
if (mesh->HasTangentsAndBitangents()) { if (mesh->HasTangentsAndBitangents()) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize(); mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize();
mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize(); mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize();
} }
} }
} }
} }
} }

View File

@ -1,8 +1,8 @@
/* /*
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -55,7 +55,7 @@ namespace Assimp
{ {
#if (!defined AI_DEBONE_THRESHOLD) #if (!defined AI_DEBONE_THRESHOLD)
# define AI_DEBONE_THRESHOLD 1.0f # define AI_DEBONE_THRESHOLD 1.0f
#endif // !! AI_DEBONE_THRESHOLD #endif // !! AI_DEBONE_THRESHOLD
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -68,63 +68,63 @@ class DeboneProcess : public BaseProcess
{ {
public: public:
DeboneProcess(); DeboneProcess();
~DeboneProcess(); ~DeboneProcess();
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the processing step is present in the given flag. /** Returns whether the processing step is present in the given flag.
* @param pFlags The processing flags the importer was called with. * @param pFlags The processing flags the importer was called with.
* A bitwise combination of #aiPostProcessSteps. * A bitwise combination of #aiPostProcessSteps.
* @return true if the process is present in this flag fields, * @return true if the process is present in this flag fields,
* false if not. * false if not.
*/ */
bool IsActive( unsigned int pFlags) const; bool IsActive( unsigned int pFlags) const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Called prior to ExecuteOnScene(). /** Called prior to ExecuteOnScene().
* The function is a request to the process to update its configuration * The function is a request to the process to update its configuration
* basing on the Importer's configuration property list. * basing on the Importer's configuration property list.
*/ */
void SetupProperties(const Importer* pImp); void SetupProperties(const Importer* pImp);
protected: protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Executes the post processing step on the given imported data. /** Executes the post processing step on the given imported data.
* At the moment a process is not supposed to fail. * At the moment a process is not supposed to fail.
* @param pScene The imported data to work at. * @param pScene The imported data to work at.
*/ */
void Execute( aiScene* pScene); void Execute( aiScene* pScene);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Counts bones total/removable in a given mesh. /** Counts bones total/removable in a given mesh.
* @param pMesh The mesh to process. * @param pMesh The mesh to process.
*/ */
bool ConsiderMesh( const aiMesh* pMesh); bool ConsiderMesh( const aiMesh* pMesh);
/// Splits the given mesh by bone count. /// Splits the given mesh by bone count.
/// @param pMesh the Mesh to split. Is not changed at all, but might be superfluous in case it was split. /// @param pMesh the Mesh to split. Is not changed at all, but might be superfluous in case it was split.
/// @param poNewMeshes Array of submeshes created in the process. Empty if splitting was not necessary. /// @param poNewMeshes Array of submeshes created in the process. Empty if splitting was not necessary.
void SplitMesh(const aiMesh* pMesh, std::vector< std::pair< aiMesh*,const aiBone* > >& poNewMeshes) const; void SplitMesh(const aiMesh* pMesh, std::vector< std::pair< aiMesh*,const aiBone* > >& poNewMeshes) const;
/// Recursively updates the node's mesh list to account for the changed mesh list /// Recursively updates the node's mesh list to account for the changed mesh list
void UpdateNode(aiNode* pNode) const; void UpdateNode(aiNode* pNode) const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Apply transformation to a mesh // Apply transformation to a mesh
void ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat)const; void ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat)const;
public: public:
/** Number of bones present in the scene. */ /** Number of bones present in the scene. */
unsigned int mNumBones; unsigned int mNumBones;
unsigned int mNumBonesCanDoWithout; unsigned int mNumBonesCanDoWithout;
float mThreshold; float mThreshold;
bool mAllOrNone; bool mAllOrNone;
/// Per mesh index: Array of indices of the new submeshes. /// Per mesh index: Array of indices of the new submeshes.
std::vector< std::vector< std::pair< unsigned int,aiNode* > > > mSubMeshIndices; std::vector< std::vector< std::pair< unsigned int,aiNode* > > > mSubMeshIndices;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
@ -54,62 +54,62 @@ using namespace Assimp;
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
DefaultIOStream::~DefaultIOStream() DefaultIOStream::~DefaultIOStream()
{ {
if (mFile) { if (mFile) {
::fclose(mFile); ::fclose(mFile);
} }
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
size_t DefaultIOStream::Read(void* pvBuffer, size_t DefaultIOStream::Read(void* pvBuffer,
size_t pSize, size_t pSize,
size_t pCount) size_t pCount)
{ {
ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount); ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
return (mFile ? ::fread(pvBuffer, pSize, pCount, mFile) : 0); return (mFile ? ::fread(pvBuffer, pSize, pCount, mFile) : 0);
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
size_t DefaultIOStream::Write(const void* pvBuffer, size_t DefaultIOStream::Write(const void* pvBuffer,
size_t pSize, size_t pSize,
size_t pCount) size_t pCount)
{ {
ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount); ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
return (mFile ? ::fwrite(pvBuffer, pSize, pCount, mFile) : 0); return (mFile ? ::fwrite(pvBuffer, pSize, pCount, mFile) : 0);
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
aiReturn DefaultIOStream::Seek(size_t pOffset, aiReturn DefaultIOStream::Seek(size_t pOffset,
aiOrigin pOrigin) aiOrigin pOrigin)
{ {
if (!mFile) { if (!mFile) {
return AI_FAILURE; return AI_FAILURE;
} }
// Just to check whether our enum maps one to one with the CRT constants // Just to check whether our enum maps one to one with the CRT constants
BOOST_STATIC_ASSERT(aiOrigin_CUR == SEEK_CUR && BOOST_STATIC_ASSERT(aiOrigin_CUR == SEEK_CUR &&
aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET); aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET);
// do the seek // do the seek
return (0 == ::fseek(mFile, (long)pOffset,(int)pOrigin) ? AI_SUCCESS : AI_FAILURE); return (0 == ::fseek(mFile, (long)pOffset,(int)pOrigin) ? AI_SUCCESS : AI_FAILURE);
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
size_t DefaultIOStream::Tell() const size_t DefaultIOStream::Tell() const
{ {
if (!mFile) { if (!mFile) {
return 0; return 0;
} }
return ::ftell(mFile); return ::ftell(mFile);
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
size_t DefaultIOStream::FileSize() const size_t DefaultIOStream::FileSize() const
{ {
if (! mFile || mFilename.empty()) { if (! mFile || mFilename.empty()) {
return 0; return 0;
} }
if (SIZE_MAX == cachedSize) { if (SIZE_MAX == cachedSize) {
// Although fseek/ftell would allow us to reuse the exising file handle here, // Although fseek/ftell would allow us to reuse the exising file handle here,
// it is generally unsafe because: // it is generally unsafe because:
@ -120,28 +120,28 @@ size_t DefaultIOStream::FileSize() const
// See here for details: // See here for details:
// https://www.securecoding.cert.org/confluence/display/seccode/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+of+a+regular+file // https://www.securecoding.cert.org/confluence/display/seccode/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+of+a+regular+file
#if defined _WIN32 && !defined __GNUC__ #if defined _WIN32 && !defined __GNUC__
struct __stat64 fileStat; struct __stat64 fileStat;
int err = _stat64( mFilename.c_str(), &fileStat ); int err = _stat64( mFilename.c_str(), &fileStat );
if (0 != err) if (0 != err)
return 0; return 0;
cachedSize = (size_t) (fileStat.st_size); cachedSize = (size_t) (fileStat.st_size);
#else #else
struct stat fileStat; struct stat fileStat;
int err = stat(mFilename.c_str(), &fileStat ); int err = stat(mFilename.c_str(), &fileStat );
if (0 != err) if (0 != err)
return 0; return 0;
cachedSize = (size_t) (fileStat.st_size); cachedSize = (size_t) (fileStat.st_size);
#endif #endif
} }
return cachedSize; return cachedSize;
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
void DefaultIOStream::Flush() void DefaultIOStream::Flush()
{ {
if (mFile) { if (mFile) {
::fflush(mFile); ::fflush(mFile);
} }
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -47,17 +47,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../include/assimp/importerdesc.h" #include "../include/assimp/importerdesc.h"
#include "Defines.h" #include "Defines.h"
namespace Assimp { namespace Assimp {
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
//! @class DefaultIOStream //! @class DefaultIOStream
//! @brief Default IO implementation, use standard IO operations //! @brief Default IO implementation, use standard IO operations
//! @note An instance of this class can exist without a valid file handle //! @note An instance of this class can exist without a valid file handle
//! attached to it. All calls fail, but the instance can nevertheless be //! attached to it. All calls fail, but the instance can nevertheless be
//! used with no restrictions. //! used with no restrictions.
class DefaultIOStream : public IOStream class DefaultIOStream : public IOStream
{ {
friend class DefaultIOSystem; friend class DefaultIOSystem;
#if __ANDROID__ #if __ANDROID__
#if __ANDROID_API__ > 9 #if __ANDROID_API__ > 9
#if defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) #if defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
@ -67,72 +67,72 @@ class DefaultIOStream : public IOStream
#endif // __ANDROID__ #endif // __ANDROID__
protected: protected:
DefaultIOStream(); DefaultIOStream();
DefaultIOStream(FILE* pFile, const std::string &strFilename); DefaultIOStream(FILE* pFile, const std::string &strFilename);
public: public:
/** Destructor public to allow simple deletion to close the file. */ /** Destructor public to allow simple deletion to close the file. */
~DefaultIOStream (); ~DefaultIOStream ();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/// Read from stream /// Read from stream
size_t Read(void* pvBuffer, size_t Read(void* pvBuffer,
size_t pSize, size_t pSize,
size_t pCount); size_t pCount);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/// Write to stream /// Write to stream
size_t Write(const void* pvBuffer, size_t Write(const void* pvBuffer,
size_t pSize, size_t pSize,
size_t pCount); size_t pCount);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/// Seek specific position /// Seek specific position
aiReturn Seek(size_t pOffset, aiReturn Seek(size_t pOffset,
aiOrigin pOrigin); aiOrigin pOrigin);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/// Get current seek position /// Get current seek position
size_t Tell() const; size_t Tell() const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/// Get size of file /// Get size of file
size_t FileSize() const; size_t FileSize() const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/// Flush file contents /// Flush file contents
void Flush(); void Flush();
private: private:
// File datastructure, using clib // File datastructure, using clib
FILE* mFile; FILE* mFile;
// Filename // Filename
std::string mFilename; std::string mFilename;
// Cached file size // Cached file size
mutable size_t cachedSize; mutable size_t cachedSize;
}; };
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
inline DefaultIOStream::DefaultIOStream () : inline DefaultIOStream::DefaultIOStream () :
mFile (NULL), mFile (NULL),
mFilename (""), mFilename (""),
cachedSize (SIZE_MAX) cachedSize (SIZE_MAX)
{ {
// empty // empty
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
inline DefaultIOStream::DefaultIOStream (FILE* pFile, inline DefaultIOStream::DefaultIOStream (FILE* pFile,
const std::string &strFilename) : const std::string &strFilename) :
mFile(pFile), mFile(pFile),
mFilename(strFilename), mFilename(strFilename),
cachedSize (SIZE_MAX) cachedSize (SIZE_MAX)
{ {
// empty // empty
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
@ -60,47 +60,47 @@ using namespace Assimp;
// Constructor. // Constructor.
DefaultIOSystem::DefaultIOSystem() DefaultIOSystem::DefaultIOSystem()
{ {
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor. // Destructor.
DefaultIOSystem::~DefaultIOSystem() DefaultIOSystem::~DefaultIOSystem()
{ {
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Tests for the existence of a file at the given path. // Tests for the existence of a file at the given path.
bool DefaultIOSystem::Exists( const char* pFile) const bool DefaultIOSystem::Exists( const char* pFile) const
{ {
FILE* file = ::fopen( pFile, "rb"); FILE* file = ::fopen( pFile, "rb");
if( !file) if( !file)
return false; return false;
::fclose( file); ::fclose( file);
return true; return true;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Open a new file with a given path. // Open a new file with a given path.
IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode) IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode)
{ {
ai_assert(NULL != strFile); ai_assert(NULL != strFile);
ai_assert(NULL != strMode); ai_assert(NULL != strMode);
FILE* file = ::fopen( strFile, strMode); FILE* file = ::fopen( strFile, strMode);
if( NULL == file) if( NULL == file)
return NULL; return NULL;
return new DefaultIOStream(file, (std::string) strFile); return new DefaultIOStream(file, (std::string) strFile);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Closes the given file and releases all resources associated with it. // Closes the given file and releases all resources associated with it.
void DefaultIOSystem::Close( IOStream* pFile) void DefaultIOSystem::Close( IOStream* pFile)
{ {
delete pFile; delete pFile;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -108,9 +108,9 @@ void DefaultIOSystem::Close( IOStream* pFile)
char DefaultIOSystem::getOsSeparator() const char DefaultIOSystem::getOsSeparator() const
{ {
#ifndef _WIN32 #ifndef _WIN32
return '/'; return '/';
#else #else
return '\\'; return '\\';
#endif #endif
} }
@ -118,80 +118,80 @@ char DefaultIOSystem::getOsSeparator() const
// IOSystem default implementation (ComparePaths isn't a pure virtual function) // IOSystem default implementation (ComparePaths isn't a pure virtual function)
bool IOSystem::ComparePaths (const char* one, const char* second) const bool IOSystem::ComparePaths (const char* one, const char* second) const
{ {
return !ASSIMP_stricmp(one,second); return !ASSIMP_stricmp(one,second);
} }
// maximum path length // maximum path length
// XXX http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html // XXX http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
#ifdef PATH_MAX #ifdef PATH_MAX
# define PATHLIMIT PATH_MAX # define PATHLIMIT PATH_MAX
#else #else
# define PATHLIMIT 4096 # define PATHLIMIT 4096
#endif #endif
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Convert a relative path into an absolute path // Convert a relative path into an absolute path
inline void MakeAbsolutePath (const char* in, char* _out) inline void MakeAbsolutePath (const char* in, char* _out)
{ {
ai_assert(in && _out); ai_assert(in && _out);
char* ret; char* ret;
#ifdef _WIN32 #ifdef _WIN32
ret = ::_fullpath(_out, in,PATHLIMIT); ret = ::_fullpath(_out, in,PATHLIMIT);
#else #else
// use realpath // use realpath
ret = realpath(in, _out); ret = realpath(in, _out);
#endif #endif
if(!ret) { if(!ret) {
// preserve the input path, maybe someone else is able to fix // preserve the input path, maybe someone else is able to fix
// the path before it is accessed (e.g. our file system filter) // the path before it is accessed (e.g. our file system filter)
DefaultLogger::get()->warn("Invalid path: "+std::string(in)); DefaultLogger::get()->warn("Invalid path: "+std::string(in));
strcpy(_out,in); strcpy(_out,in);
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// DefaultIOSystem's more specialized implementation // DefaultIOSystem's more specialized implementation
bool DefaultIOSystem::ComparePaths (const char* one, const char* second) const bool DefaultIOSystem::ComparePaths (const char* one, const char* second) const
{ {
// chances are quite good both paths are formatted identically, // chances are quite good both paths are formatted identically,
// so we can hopefully return here already // so we can hopefully return here already
if( !ASSIMP_stricmp(one,second) ) if( !ASSIMP_stricmp(one,second) )
return true; return true;
char temp1[PATHLIMIT]; char temp1[PATHLIMIT];
char temp2[PATHLIMIT]; char temp2[PATHLIMIT];
MakeAbsolutePath (one, temp1); MakeAbsolutePath (one, temp1);
MakeAbsolutePath (second, temp2); MakeAbsolutePath (second, temp2);
return !ASSIMP_stricmp(temp1,temp2); return !ASSIMP_stricmp(temp1,temp2);
} }
std::string DefaultIOSystem::fileName(std::string path) std::string DefaultIOSystem::fileName(std::string path)
{ {
std::string ret = path; std::string ret = path;
std::size_t last = ret.find_last_of("\\/"); std::size_t last = ret.find_last_of("\\/");
if (last != std::string::npos) ret = ret.substr(last + 1); if (last != std::string::npos) ret = ret.substr(last + 1);
return ret; return ret;
} }
std::string DefaultIOSystem::completeBaseName(std::string path) std::string DefaultIOSystem::completeBaseName(std::string path)
{ {
std::string ret = fileName(path); std::string ret = fileName(path);
std::size_t pos = ret.find_last_of('.'); std::size_t pos = ret.find_last_of('.');
if(pos != ret.npos) ret = ret.substr(0, pos); if(pos != ret.npos) ret = ret.substr(0, pos);
return ret; return ret;
} }
std::string DefaultIOSystem::absolutePath(std::string path) std::string DefaultIOSystem::absolutePath(std::string path)
{ {
std::string ret = path; std::string ret = path;
std::size_t last = ret.find_last_of("\\/"); std::size_t last = ret.find_last_of("\\/");
if (last != std::string::npos) ret = ret.substr(0, last); if (last != std::string::npos) ret = ret.substr(0, last);
return ret; return ret;
} }
#undef PATHLIMIT #undef PATHLIMIT

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -44,53 +44,53 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../include/assimp/IOSystem.hpp" #include "../include/assimp/IOSystem.hpp"
namespace Assimp { namespace Assimp {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Default implementation of IOSystem using the standard C file functions */ /** Default implementation of IOSystem using the standard C file functions */
class DefaultIOSystem : public IOSystem class DefaultIOSystem : public IOSystem
{ {
public: public:
/** Constructor. */ /** Constructor. */
DefaultIOSystem(); DefaultIOSystem();
/** Destructor. */ /** Destructor. */
~DefaultIOSystem(); ~DefaultIOSystem();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Tests for the existence of a file at the given path. */ /** Tests for the existence of a file at the given path. */
bool Exists( const char* pFile) const; bool Exists( const char* pFile) const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns the directory separator. */ /** Returns the directory separator. */
char getOsSeparator() const; char getOsSeparator() const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Open a new file with a given path. */ /** Open a new file with a given path. */
IOStream* Open( const char* pFile, const char* pMode = "rb"); IOStream* Open( const char* pFile, const char* pMode = "rb");
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Closes the given file and releases all resources associated with it. */ /** Closes the given file and releases all resources associated with it. */
void Close( IOStream* pFile); void Close( IOStream* pFile);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Compare two paths */ /** Compare two paths */
bool ComparePaths (const char* one, const char* second) const; bool ComparePaths (const char* one, const char* second) const;
/** @brief get the file name of a full filepath /** @brief get the file name of a full filepath
* example: /tmp/archive.tar.gz -> archive.tar.gz * example: /tmp/archive.tar.gz -> archive.tar.gz
*/ */
static std::string fileName(std::string path); static std::string fileName(std::string path);
/** @brief get the complete base name of a full filepath /** @brief get the complete base name of a full filepath
* example: /tmp/archive.tar.gz -> archive.tar * example: /tmp/archive.tar.gz -> archive.tar
*/ */
static std::string completeBaseName(std::string path); static std::string completeBaseName(std::string path);
/** @brief get the path of a full filepath /** @brief get the path of a full filepath
* example: /tmp/archive.tar.gz -> /tmp/ * example: /tmp/archive.tar.gz -> /tmp/
*/ */
static std::string absolutePath(std::string path); static std::string absolutePath(std::string path);
}; };
} //!ns Assimp } //!ns Assimp

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
@ -56,13 +56,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdio.h> #include <stdio.h>
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
# include <boost/thread/thread.hpp> # include <boost/thread/thread.hpp>
# include <boost/thread/mutex.hpp> # include <boost/thread/mutex.hpp>
boost::mutex loggerMutex; boost::mutex loggerMutex;
#endif #endif
namespace Assimp { namespace Assimp {
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
NullLogger DefaultLogger::s_pNullLogger; NullLogger DefaultLogger::s_pNullLogger;
@ -74,351 +74,347 @@ static const unsigned int SeverityAll = Logger::Info | Logger::Err | Logger::War
// Represents a log-stream + its error severity // Represents a log-stream + its error severity
struct LogStreamInfo struct LogStreamInfo
{ {
unsigned int m_uiErrorSeverity; unsigned int m_uiErrorSeverity;
LogStream *m_pStream; LogStream *m_pStream;
// Constructor // Constructor
LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) : LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) :
m_uiErrorSeverity( uiErrorSev ), m_uiErrorSeverity( uiErrorSev ),
m_pStream( pStream ) m_pStream( pStream )
{ {
// empty // empty
} }
// Destructor // Destructor
~LogStreamInfo() ~LogStreamInfo()
{ {
delete m_pStream; delete m_pStream;
} }
}; };
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Construct a default log stream // Construct a default log stream
LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams, LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams,
const char* name /*= "AssimpLog.txt"*/, const char* name /*= "AssimpLog.txt"*/,
IOSystem* io /*= NULL*/) IOSystem* io /*= NULL*/)
{ {
switch (streams) switch (streams)
{ {
// This is a platform-specific feature // This is a platform-specific feature
case aiDefaultLogStream_DEBUGGER: case aiDefaultLogStream_DEBUGGER:
#ifdef WIN32 #ifdef WIN32
return new Win32DebugLogStream(); return new Win32DebugLogStream();
#else #else
return NULL; return NULL;
#endif #endif
// Platform-independent default streams // Platform-independent default streams
case aiDefaultLogStream_STDERR: case aiDefaultLogStream_STDERR:
return new StdOStreamLogStream(std::cerr); return new StdOStreamLogStream(std::cerr);
case aiDefaultLogStream_STDOUT: case aiDefaultLogStream_STDOUT:
return new StdOStreamLogStream(std::cout); return new StdOStreamLogStream(std::cout);
case aiDefaultLogStream_FILE: case aiDefaultLogStream_FILE:
return (name && *name ? new FileLogStream(name,io) : NULL); return (name && *name ? new FileLogStream(name,io) : NULL);
default: default:
// We don't know this default log stream, so raise an assertion // We don't know this default log stream, so raise an assertion
ai_assert(false); ai_assert(false);
}; };
// For compilers without dead code path detection // For compilers without dead code path detection
return NULL; return NULL;
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Creates the only singleton instance // Creates the only singleton instance
Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/, Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/,
LogSeverity severity /*= NORMAL*/, LogSeverity severity /*= NORMAL*/,
unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/, unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/,
IOSystem* io /*= NULL*/) IOSystem* io /*= NULL*/)
{ {
// enter the mutex here to avoid concurrency problems // enter the mutex here to avoid concurrency problems
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
boost::mutex::scoped_lock lock(loggerMutex); boost::mutex::scoped_lock lock(loggerMutex);
#endif #endif
if (m_pLogger && !isNullLogger() ) if (m_pLogger && !isNullLogger() )
delete m_pLogger; delete m_pLogger;
m_pLogger = new DefaultLogger( severity ); m_pLogger = new DefaultLogger( severity );
// Attach default log streams // Attach default log streams
// Stream the log to the MSVC debugger? // Stream the log to the MSVC debugger?
if (defStreams & aiDefaultLogStream_DEBUGGER) if (defStreams & aiDefaultLogStream_DEBUGGER)
m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_DEBUGGER)); m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_DEBUGGER));
// Stream the log to COUT? // Stream the log to COUT?
if (defStreams & aiDefaultLogStream_STDOUT) if (defStreams & aiDefaultLogStream_STDOUT)
m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDOUT)); m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDOUT));
// Stream the log to CERR? // Stream the log to CERR?
if (defStreams & aiDefaultLogStream_STDERR) if (defStreams & aiDefaultLogStream_STDERR)
m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDERR)); m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDERR));
// Stream the log to a file // Stream the log to a file
if (defStreams & aiDefaultLogStream_FILE && name && *name) if (defStreams & aiDefaultLogStream_FILE && name && *name)
m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_FILE,name,io)); m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_FILE,name,io));
return m_pLogger; return m_pLogger;
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
void Logger::debug(const char* message) { void Logger::debug(const char* message) {
// SECURITY FIX: otherwise it's easy to produce overruns since // SECURITY FIX: otherwise it's easy to produce overruns since
// sometimes importers will include data from the input file // sometimes importers will include data from the input file
// (i.e. node names) in their messages. // (i.e. node names) in their messages.
if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) { if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
ai_assert(false); return;
return; }
} return OnDebug(message);
return OnDebug(message);
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
void Logger::info(const char* message) { void Logger::info(const char* message) {
// SECURITY FIX: see above // SECURITY FIX: see above
if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) { if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
ai_assert(false); return;
return; }
} return OnInfo(message);
return OnInfo(message);
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
void Logger::warn(const char* message) { void Logger::warn(const char* message) {
// SECURITY FIX: see above // SECURITY FIX: see above
if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) { if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
ai_assert(false); return;
return; }
} return OnWarn(message);
return OnWarn(message);
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
void Logger::error(const char* message) { void Logger::error(const char* message) {
// SECURITY FIX: see above // SECURITY FIX: see above
if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) { if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
ai_assert(false); return;
return; }
} return OnError(message);
return OnError(message);
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
void DefaultLogger::set( Logger *logger ) void DefaultLogger::set( Logger *logger )
{ {
// enter the mutex here to avoid concurrency problems // enter the mutex here to avoid concurrency problems
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
boost::mutex::scoped_lock lock(loggerMutex); boost::mutex::scoped_lock lock(loggerMutex);
#endif #endif
if (!logger)logger = &s_pNullLogger; if (!logger)logger = &s_pNullLogger;
if (m_pLogger && !isNullLogger() ) if (m_pLogger && !isNullLogger() )
delete m_pLogger; delete m_pLogger;
DefaultLogger::m_pLogger = logger; DefaultLogger::m_pLogger = logger;
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
bool DefaultLogger::isNullLogger() bool DefaultLogger::isNullLogger()
{ {
return m_pLogger == &s_pNullLogger; return m_pLogger == &s_pNullLogger;
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Singleton getter // Singleton getter
Logger *DefaultLogger::get() Logger *DefaultLogger::get()
{ {
return m_pLogger; return m_pLogger;
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Kills the only instance // Kills the only instance
void DefaultLogger::kill() void DefaultLogger::kill()
{ {
// enter the mutex here to avoid concurrency problems // enter the mutex here to avoid concurrency problems
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
boost::mutex::scoped_lock lock(loggerMutex); boost::mutex::scoped_lock lock(loggerMutex);
#endif #endif
if (m_pLogger == &s_pNullLogger)return; if (m_pLogger == &s_pNullLogger)return;
delete m_pLogger; delete m_pLogger;
m_pLogger = &s_pNullLogger; m_pLogger = &s_pNullLogger;
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Debug message // Debug message
void DefaultLogger::OnDebug( const char* message ) void DefaultLogger::OnDebug( const char* message )
{ {
if ( m_Severity == Logger::NORMAL ) if ( m_Severity == Logger::NORMAL )
return; return;
char msg[MAX_LOG_MESSAGE_LENGTH + 16]; char msg[MAX_LOG_MESSAGE_LENGTH + 16];
::sprintf(msg,"Debug, T%u: %s", GetThreadID(), message ); ::sprintf(msg,"Debug, T%u: %s", GetThreadID(), message );
WriteToStreams( msg, Logger::Debugging ); WriteToStreams( msg, Logger::Debugging );
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Logs an info // Logs an info
void DefaultLogger::OnInfo( const char* message ) void DefaultLogger::OnInfo( const char* message )
{ {
char msg[MAX_LOG_MESSAGE_LENGTH + 16]; char msg[MAX_LOG_MESSAGE_LENGTH + 16];
::sprintf(msg,"Info, T%u: %s", GetThreadID(), message ); ::sprintf(msg,"Info, T%u: %s", GetThreadID(), message );
WriteToStreams( msg , Logger::Info ); WriteToStreams( msg , Logger::Info );
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Logs a warning // Logs a warning
void DefaultLogger::OnWarn( const char* message ) void DefaultLogger::OnWarn( const char* message )
{ {
char msg[MAX_LOG_MESSAGE_LENGTH + 16]; char msg[MAX_LOG_MESSAGE_LENGTH + 16];
::sprintf(msg,"Warn, T%u: %s", GetThreadID(), message ); ::sprintf(msg,"Warn, T%u: %s", GetThreadID(), message );
WriteToStreams( msg, Logger::Warn ); WriteToStreams( msg, Logger::Warn );
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Logs an error // Logs an error
void DefaultLogger::OnError( const char* message ) void DefaultLogger::OnError( const char* message )
{ {
char msg[MAX_LOG_MESSAGE_LENGTH + 16]; char msg[MAX_LOG_MESSAGE_LENGTH + 16];
::sprintf(msg,"Error, T%u: %s", GetThreadID(), message ); ::sprintf(msg,"Error, T%u: %s", GetThreadID(), message );
WriteToStreams( msg, Logger::Err ); WriteToStreams( msg, Logger::Err );
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Will attach a new stream // Will attach a new stream
bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity )
{ {
if (!pStream) if (!pStream)
return false; return false;
if (0 == severity) { if (0 == severity) {
severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging; severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging;
} }
for ( StreamIt it = m_StreamArray.begin(); for ( StreamIt it = m_StreamArray.begin();
it != m_StreamArray.end(); it != m_StreamArray.end();
++it ) ++it )
{ {
if ( (*it)->m_pStream == pStream ) if ( (*it)->m_pStream == pStream )
{ {
(*it)->m_uiErrorSeverity |= severity; (*it)->m_uiErrorSeverity |= severity;
return true; return true;
} }
} }
LogStreamInfo *pInfo = new LogStreamInfo( severity, pStream ); LogStreamInfo *pInfo = new LogStreamInfo( severity, pStream );
m_StreamArray.push_back( pInfo ); m_StreamArray.push_back( pInfo );
return true; return true;
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Detatch a stream // Detatch a stream
bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity )
{ {
if (!pStream) if (!pStream)
return false; return false;
if (0 == severity) { if (0 == severity) {
severity = SeverityAll; severity = SeverityAll;
} }
for ( StreamIt it = m_StreamArray.begin(); for ( StreamIt it = m_StreamArray.begin();
it != m_StreamArray.end(); it != m_StreamArray.end();
++it ) ++it )
{ {
if ( (*it)->m_pStream == pStream ) if ( (*it)->m_pStream == pStream )
{ {
(*it)->m_uiErrorSeverity &= ~severity; (*it)->m_uiErrorSeverity &= ~severity;
if ( (*it)->m_uiErrorSeverity == 0 ) if ( (*it)->m_uiErrorSeverity == 0 )
{ {
// don't delete the underlying stream 'cause the caller gains ownership again // don't delete the underlying stream 'cause the caller gains ownership again
(**it).m_pStream = NULL; (**it).m_pStream = NULL;
delete *it; delete *it;
m_StreamArray.erase( it ); m_StreamArray.erase( it );
break; break;
} }
return true; return true;
} }
} }
return false; return false;
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Constructor // Constructor
DefaultLogger::DefaultLogger(LogSeverity severity) DefaultLogger::DefaultLogger(LogSeverity severity)
: Logger ( severity ) : Logger ( severity )
, noRepeatMsg (false) , noRepeatMsg (false)
, lastLen( 0 ) , lastLen( 0 )
{ {
lastMsg[0] = '\0'; lastMsg[0] = '\0';
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Destructor // Destructor
DefaultLogger::~DefaultLogger() DefaultLogger::~DefaultLogger()
{ {
for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) { for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
// also frees the underlying stream, we are its owner. // also frees the underlying stream, we are its owner.
delete *it; delete *it;
} }
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Writes message to stream // Writes message to stream
void DefaultLogger::WriteToStreams(const char *message, void DefaultLogger::WriteToStreams(const char *message,
ErrorSeverity ErrorSev ) ErrorSeverity ErrorSev )
{ {
ai_assert(NULL != message); ai_assert(NULL != message);
// Check whether this is a repeated message // Check whether this is a repeated message
if (! ::strncmp( message,lastMsg, lastLen-1)) if (! ::strncmp( message,lastMsg, lastLen-1))
{ {
if (!noRepeatMsg) if (!noRepeatMsg)
{ {
noRepeatMsg = true; noRepeatMsg = true;
message = "Skipping one or more lines with the same contents\n"; message = "Skipping one or more lines with the same contents\n";
} }
else return; else return;
} }
else else
{ {
// append a new-line character to the message to be printed // append a new-line character to the message to be printed
lastLen = ::strlen(message); lastLen = ::strlen(message);
::memcpy(lastMsg,message,lastLen+1); ::memcpy(lastMsg,message,lastLen+1);
::strcat(lastMsg+lastLen,"\n"); ::strcat(lastMsg+lastLen,"\n");
message = lastMsg; message = lastMsg;
noRepeatMsg = false; noRepeatMsg = false;
++lastLen; ++lastLen;
} }
for ( ConstStreamIt it = m_StreamArray.begin(); for ( ConstStreamIt it = m_StreamArray.begin();
it != m_StreamArray.end(); it != m_StreamArray.end();
++it) ++it)
{ {
if ( ErrorSev & (*it)->m_uiErrorSeverity ) if ( ErrorSev & (*it)->m_uiErrorSeverity )
(*it)->m_pStream->write( message); (*it)->m_pStream->write( message);
} }
} }
// ---------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------
// Returns thread id, if not supported only a zero will be returned. // Returns thread id, if not supported only a zero will be returned.
unsigned int DefaultLogger::GetThreadID() unsigned int DefaultLogger::GetThreadID()
{ {
// fixme: we can get this value via boost::threads // fixme: we can get this value via boost::threads
#ifdef WIN32 #ifdef WIN32
return (unsigned int)::GetCurrentThreadId(); return (unsigned int)::GetCurrentThreadId();
#else #else
return 0; // not supported return 0; // not supported
#endif #endif
} }

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -45,17 +45,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define INCLUDED_AI_DEFAULTPROGRESSHANDLER_H #define INCLUDED_AI_DEFAULTPROGRESSHANDLER_H
#include "../include/assimp/ProgressHandler.hpp" #include "../include/assimp/ProgressHandler.hpp"
namespace Assimp { namespace Assimp {
// ------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------
/** @brief Internal default implementation of the #ProgressHandler interface. */ /** @brief Internal default implementation of the #ProgressHandler interface. */
class DefaultProgressHandler class DefaultProgressHandler
: public ProgressHandler { : public ProgressHandler {
virtual bool Update(float /*percentage*/) { virtual bool Update(float /*percentage*/) {
return false; return false;
} }
}; // !class DefaultProgressHandler }; // !class DefaultProgressHandler

View File

@ -40,10 +40,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// We need those constants, workaround for any platforms where nobody defined them yet // We need those constants, workaround for any platforms where nobody defined them yet
#if (!defined SIZE_MAX) #if (!defined SIZE_MAX)
# define SIZE_MAX (~((size_t)0)) # define SIZE_MAX (~((size_t)0))
#endif #endif
#if (!defined UINT_MAX) #if (!defined UINT_MAX)
# define UINT_MAX (~((unsigned int)0)) # define UINT_MAX (~((unsigned int)0))
#endif #endif

View File

@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using std::runtime_error; using std::runtime_error;
#ifdef _MSC_VER #ifdef _MSC_VER
# pragma warning(disable : 4275) # pragma warning(disable : 4275)
#endif #endif
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -54,14 +54,14 @@ using std::runtime_error;
* unrecoverable error occurs while importing. Loading APIs return * unrecoverable error occurs while importing. Loading APIs return
* NULL instead of a valid aiScene then. */ * NULL instead of a valid aiScene then. */
class DeadlyImportError class DeadlyImportError
: public runtime_error : public runtime_error
{ {
public: public:
/** Constructor with arguments */ /** Constructor with arguments */
explicit DeadlyImportError( const std::string& pErrorText) explicit DeadlyImportError( const std::string& pErrorText)
: runtime_error(pErrorText) : runtime_error(pErrorText)
{ {
} }
private: private:
}; };
@ -69,57 +69,57 @@ private:
typedef DeadlyImportError DeadlyExportError; typedef DeadlyImportError DeadlyExportError;
#ifdef _MSC_VER #ifdef _MSC_VER
# pragma warning(default : 4275) # pragma warning(default : 4275)
#endif #endif
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <typename T> template <typename T>
struct ExceptionSwallower { struct ExceptionSwallower {
T operator ()() const { T operator ()() const {
return T(); return T();
} }
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <typename T> template <typename T>
struct ExceptionSwallower<T*> { struct ExceptionSwallower<T*> {
T* operator ()() const { T* operator ()() const {
return NULL; return NULL;
} }
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <> template <>
struct ExceptionSwallower<aiReturn> { struct ExceptionSwallower<aiReturn> {
aiReturn operator ()() const { aiReturn operator ()() const {
try { try {
throw; throw;
} }
catch (std::bad_alloc&) { catch (std::bad_alloc&) {
return aiReturn_OUTOFMEMORY; return aiReturn_OUTOFMEMORY;
} }
catch (...) { catch (...) {
return aiReturn_FAILURE; return aiReturn_FAILURE;
} }
} }
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
template <> template <>
struct ExceptionSwallower<void> { struct ExceptionSwallower<void> {
void operator ()() const { void operator ()() const {
return; return;
} }
}; };
#define ASSIMP_BEGIN_EXCEPTION_REGION()\ #define ASSIMP_BEGIN_EXCEPTION_REGION()\
{\ {\
try { try {
#define ASSIMP_END_EXCEPTION_REGION(type)\ #define ASSIMP_END_EXCEPTION_REGION(type)\
} catch(...) {\ } catch(...) {\
return ExceptionSwallower<type>()();\ return ExceptionSwallower<type>()();\
}\ }\
} }
#endif // INCLUDED_EXCEPTIONAL_H #endif // INCLUDED_EXCEPTIONAL_H

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
@ -95,52 +95,52 @@ void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportPrope
Exporter::ExportFormatEntry gExporters[] = Exporter::ExportFormatEntry gExporters[] =
{ {
#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER #ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada), Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada),
#endif #endif
#ifndef ASSIMP_BUILD_NO_XFILE_EXPORTER #ifndef ASSIMP_BUILD_NO_XFILE_EXPORTER
Exporter::ExportFormatEntry( "x", "X Files", "x", &ExportSceneXFile, Exporter::ExportFormatEntry( "x", "X Files", "x", &ExportSceneXFile,
aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs), aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs),
#endif #endif
#ifndef ASSIMP_BUILD_NO_STEP_EXPORTER #ifndef ASSIMP_BUILD_NO_STEP_EXPORTER
Exporter::ExportFormatEntry( "stp", "Step Files", "stp", &ExportSceneStep, 0), Exporter::ExportFormatEntry( "stp", "Step Files", "stp", &ExportSceneStep, 0),
#endif #endif
#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER #ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
Exporter::ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj, Exporter::ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj,
aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */), aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */),
#endif #endif
#ifndef ASSIMP_BUILD_NO_STL_EXPORTER #ifndef ASSIMP_BUILD_NO_STL_EXPORTER
Exporter::ExportFormatEntry( "stl", "Stereolithography", "stl" , &ExportSceneSTL, Exporter::ExportFormatEntry( "stl", "Stereolithography", "stl" , &ExportSceneSTL,
aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices
), ),
Exporter::ExportFormatEntry( "stlb", "Stereolithography (binary)", "stl" , &ExportSceneSTLBinary, Exporter::ExportFormatEntry( "stlb", "Stereolithography (binary)", "stl" , &ExportSceneSTLBinary,
aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices
), ),
#endif #endif
#ifndef ASSIMP_BUILD_NO_PLY_EXPORTER #ifndef ASSIMP_BUILD_NO_PLY_EXPORTER
Exporter::ExportFormatEntry( "ply", "Stanford Polygon Library", "ply" , &ExportScenePly, Exporter::ExportFormatEntry( "ply", "Stanford Polygon Library", "ply" , &ExportScenePly,
aiProcess_PreTransformVertices aiProcess_PreTransformVertices
), ),
Exporter::ExportFormatEntry( "plyb", "Stanford Polygon Library (binary)", "ply", &ExportScenePlyBinary, Exporter::ExportFormatEntry( "plyb", "Stanford Polygon Library (binary)", "ply", &ExportScenePlyBinary,
aiProcess_PreTransformVertices aiProcess_PreTransformVertices
), ),
#endif #endif
#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER #ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
Exporter::ExportFormatEntry( "3ds", "Autodesk 3DS (legacy)", "3ds" , &ExportScene3DS, Exporter::ExportFormatEntry( "3ds", "Autodesk 3DS (legacy)", "3ds" , &ExportScene3DS,
aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices), aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices),
#endif #endif
#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER #ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0), Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0),
#endif #endif
#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER #ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
Exporter::ExportFormatEntry( "assxml", "Assxml Document", "assxml" , &ExportSceneAssxml, 0), Exporter::ExportFormatEntry( "assxml", "Assxml Document", "assxml" , &ExportSceneAssxml, 0),
#endif #endif
}; };
@ -150,42 +150,42 @@ Exporter::ExportFormatEntry gExporters[] =
class ExporterPimpl { class ExporterPimpl {
public: public:
ExporterPimpl() ExporterPimpl()
: blob() : blob()
, mIOSystem(new Assimp::DefaultIOSystem()) , mIOSystem(new Assimp::DefaultIOSystem())
, mIsDefaultIOHandler(true) , mIsDefaultIOHandler(true)
{ {
GetPostProcessingStepInstanceList(mPostProcessingSteps); GetPostProcessingStepInstanceList(mPostProcessingSteps);
// grab all builtin exporters // grab all builtin exporters
mExporters.resize(ASSIMP_NUM_EXPORTERS); mExporters.resize(ASSIMP_NUM_EXPORTERS);
std::copy(gExporters,gExporters+ASSIMP_NUM_EXPORTERS,mExporters.begin()); std::copy(gExporters,gExporters+ASSIMP_NUM_EXPORTERS,mExporters.begin());
} }
~ExporterPimpl() ~ExporterPimpl()
{ {
delete blob; delete blob;
// Delete all post-processing plug-ins // Delete all post-processing plug-ins
for( unsigned int a = 0; a < mPostProcessingSteps.size(); a++) { for( unsigned int a = 0; a < mPostProcessingSteps.size(); a++) {
delete mPostProcessingSteps[a]; delete mPostProcessingSteps[a];
} }
} }
public: public:
aiExportDataBlob* blob; aiExportDataBlob* blob;
boost::shared_ptr< Assimp::IOSystem > mIOSystem; boost::shared_ptr< Assimp::IOSystem > mIOSystem;
bool mIsDefaultIOHandler; bool mIsDefaultIOHandler;
/** Post processing steps we can apply at the imported data. */ /** Post processing steps we can apply at the imported data. */
std::vector< BaseProcess* > mPostProcessingSteps; std::vector< BaseProcess* > mPostProcessingSteps;
/** Last fatal export error */ /** Last fatal export error */
std::string mError; std::string mError;
/** Exporters, this includes those registered using #Assimp::Exporter::RegisterExporter */ /** Exporters, this includes those registered using #Assimp::Exporter::RegisterExporter */
std::vector<Exporter::ExportFormatEntry> mExporters; std::vector<Exporter::ExportFormatEntry> mExporters;
}; };
@ -208,306 +208,306 @@ Exporter :: Exporter()
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Exporter :: ~Exporter() Exporter :: ~Exporter()
{ {
FreeBlob(); FreeBlob();
delete pimpl; delete pimpl;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Exporter :: SetIOHandler( IOSystem* pIOHandler) void Exporter :: SetIOHandler( IOSystem* pIOHandler)
{ {
pimpl->mIsDefaultIOHandler = !pIOHandler; pimpl->mIsDefaultIOHandler = !pIOHandler;
pimpl->mIOSystem.reset(pIOHandler); pimpl->mIOSystem.reset(pIOHandler);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
IOSystem* Exporter :: GetIOHandler() const IOSystem* Exporter :: GetIOHandler() const
{ {
return pimpl->mIOSystem.get(); return pimpl->mIOSystem.get();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool Exporter :: IsDefaultIOHandler() const bool Exporter :: IsDefaultIOHandler() const
{ {
return pimpl->mIsDefaultIOHandler; return pimpl->mIsDefaultIOHandler;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const char* pFormatId, unsigned int, const ExportProperties* pProperties) const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const char* pFormatId, unsigned int, const ExportProperties* pProperties)
{ {
if (pimpl->blob) { if (pimpl->blob) {
delete pimpl->blob; delete pimpl->blob;
pimpl->blob = NULL; pimpl->blob = NULL;
} }
boost::shared_ptr<IOSystem> old = pimpl->mIOSystem; boost::shared_ptr<IOSystem> old = pimpl->mIOSystem;
BlobIOSystem* blobio = new BlobIOSystem(); BlobIOSystem* blobio = new BlobIOSystem();
pimpl->mIOSystem = boost::shared_ptr<IOSystem>( blobio ); pimpl->mIOSystem = boost::shared_ptr<IOSystem>( blobio );
if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName())) { if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName())) {
pimpl->mIOSystem = old; pimpl->mIOSystem = old;
return NULL; return NULL;
} }
pimpl->blob = blobio->GetBlobChain(); pimpl->blob = blobio->GetBlobChain();
pimpl->mIOSystem = old; pimpl->mIOSystem = old;
return pimpl->blob; return pimpl->blob;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool IsVerboseFormat(const aiMesh* mesh) bool IsVerboseFormat(const aiMesh* mesh)
{ {
// avoid slow vector<bool> specialization // avoid slow vector<bool> specialization
std::vector<unsigned int> seen(mesh->mNumVertices,0); std::vector<unsigned int> seen(mesh->mNumVertices,0);
for(unsigned int i = 0; i < mesh->mNumFaces; ++i) { for(unsigned int i = 0; i < mesh->mNumFaces; ++i) {
const aiFace& f = mesh->mFaces[i]; const aiFace& f = mesh->mFaces[i];
for(unsigned int j = 0; j < f.mNumIndices; ++j) { for(unsigned int j = 0; j < f.mNumIndices; ++j) {
if(++seen[f.mIndices[j]] == 2) { if(++seen[f.mIndices[j]] == 2) {
// found a duplicate index // found a duplicate index
return false; return false;
} }
} }
} }
return true; return true;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool IsVerboseFormat(const aiScene* pScene) bool IsVerboseFormat(const aiScene* pScene)
{ {
for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) { for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
if(!IsVerboseFormat(pScene->mMeshes[i])) { if(!IsVerboseFormat(pScene->mMeshes[i])) {
return false; return false;
} }
} }
return true; return true;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing, const ExportProperties* pProperties) aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing, const ExportProperties* pProperties)
{ {
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
// when they create scenes from scratch, users will likely create them not in verbose // when they create scenes from scratch, users will likely create them not in verbose
// format. They will likely not be aware that there is a flag in the scene to indicate // format. They will likely not be aware that there is a flag in the scene to indicate
// this, however. To avoid surprises and bug reports, we check for duplicates in // this, however. To avoid surprises and bug reports, we check for duplicates in
// meshes upfront. // meshes upfront.
const bool is_verbose_format = !(pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) || IsVerboseFormat(pScene); const bool is_verbose_format = !(pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) || IsVerboseFormat(pScene);
pimpl->mError = ""; pimpl->mError = "";
for (size_t i = 0; i < pimpl->mExporters.size(); ++i) { for (size_t i = 0; i < pimpl->mExporters.size(); ++i) {
const Exporter::ExportFormatEntry& exp = pimpl->mExporters[i]; const Exporter::ExportFormatEntry& exp = pimpl->mExporters[i];
if (!strcmp(exp.mDescription.id,pFormatId)) { if (!strcmp(exp.mDescription.id,pFormatId)) {
try { try {
// Always create a full copy of the scene. We might optimize this one day, // Always create a full copy of the scene. We might optimize this one day,
// but for now it is the most pragmatic way. // but for now it is the most pragmatic way.
aiScene* scenecopy_tmp; aiScene* scenecopy_tmp;
SceneCombiner::CopyScene(&scenecopy_tmp,pScene); SceneCombiner::CopyScene(&scenecopy_tmp,pScene);
std::auto_ptr<aiScene> scenecopy(scenecopy_tmp); std::auto_ptr<aiScene> scenecopy(scenecopy_tmp);
const ScenePrivateData* const priv = ScenePriv(pScene); const ScenePrivateData* const priv = ScenePriv(pScene);
// steps that are not idempotent, i.e. we might need to run them again, usually to get back to the // steps that are not idempotent, i.e. we might need to run them again, usually to get back to the
// original state before the step was applied first. When checking which steps we don't need // original state before the step was applied first. When checking which steps we don't need
// to run, those are excluded. // to run, those are excluded.
const unsigned int nonIdempotentSteps = aiProcess_FlipWindingOrder | aiProcess_FlipUVs | aiProcess_MakeLeftHanded; const unsigned int nonIdempotentSteps = aiProcess_FlipWindingOrder | aiProcess_FlipUVs | aiProcess_MakeLeftHanded;
// Erase all pp steps that were already applied to this scene // Erase all pp steps that were already applied to this scene
const unsigned int pp = (exp.mEnforcePP | pPreprocessing) & ~(priv && !priv->mIsCopy const unsigned int pp = (exp.mEnforcePP | pPreprocessing) & ~(priv && !priv->mIsCopy
? (priv->mPPStepsApplied & ~nonIdempotentSteps) ? (priv->mPPStepsApplied & ~nonIdempotentSteps)
: 0u); : 0u);
// If no extra postprocessing was specified, and we obtained this scene from an // If no extra postprocessing was specified, and we obtained this scene from an
// Assimp importer, apply the reverse steps automatically. // Assimp importer, apply the reverse steps automatically.
// TODO: either drop this, or document it. Otherwise it is just a bad surprise. // TODO: either drop this, or document it. Otherwise it is just a bad surprise.
//if (!pPreprocessing && priv) { //if (!pPreprocessing && priv) {
// pp |= (nonIdempotentSteps & priv->mPPStepsApplied); // pp |= (nonIdempotentSteps & priv->mPPStepsApplied);
//} //}
// If the input scene is not in verbose format, but there is at least postprocessing step that relies on it, // If the input scene is not in verbose format, but there is at least postprocessing step that relies on it,
// we need to run the MakeVerboseFormat step first. // we need to run the MakeVerboseFormat step first.
bool must_join_again = false; bool must_join_again = false;
if (!is_verbose_format) { if (!is_verbose_format) {
bool verbosify = false; bool verbosify = false;
for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) { for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
BaseProcess* const p = pimpl->mPostProcessingSteps[a]; BaseProcess* const p = pimpl->mPostProcessingSteps[a];
if (p->IsActive(pp) && p->RequireVerboseFormat()) { if (p->IsActive(pp) && p->RequireVerboseFormat()) {
verbosify = true; verbosify = true;
break; break;
} }
} }
if (verbosify || (exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) { if (verbosify || (exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
DefaultLogger::get()->debug("export: Scene data not in verbose format, applying MakeVerboseFormat step first"); DefaultLogger::get()->debug("export: Scene data not in verbose format, applying MakeVerboseFormat step first");
MakeVerboseFormatProcess proc; MakeVerboseFormatProcess proc;
proc.Execute(scenecopy.get()); proc.Execute(scenecopy.get());
if(!(exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) { if(!(exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
must_join_again = true; must_join_again = true;
} }
} }
} }
if (pp) { if (pp) {
// the three 'conversion' steps need to be executed first because all other steps rely on the standard data layout // the three 'conversion' steps need to be executed first because all other steps rely on the standard data layout
{ {
FlipWindingOrderProcess step; FlipWindingOrderProcess step;
if (step.IsActive(pp)) { if (step.IsActive(pp)) {
step.Execute(scenecopy.get()); step.Execute(scenecopy.get());
} }
} }
{ {
FlipUVsProcess step; FlipUVsProcess step;
if (step.IsActive(pp)) { if (step.IsActive(pp)) {
step.Execute(scenecopy.get()); step.Execute(scenecopy.get());
} }
} }
{ {
MakeLeftHandedProcess step; MakeLeftHandedProcess step;
if (step.IsActive(pp)) { if (step.IsActive(pp)) {
step.Execute(scenecopy.get()); step.Execute(scenecopy.get());
} }
} }
// dispatch other processes // dispatch other processes
for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) { for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
BaseProcess* const p = pimpl->mPostProcessingSteps[a]; BaseProcess* const p = pimpl->mPostProcessingSteps[a];
if (p->IsActive(pp) if (p->IsActive(pp)
&& !dynamic_cast<FlipUVsProcess*>(p) && !dynamic_cast<FlipUVsProcess*>(p)
&& !dynamic_cast<FlipWindingOrderProcess*>(p) && !dynamic_cast<FlipWindingOrderProcess*>(p)
&& !dynamic_cast<MakeLeftHandedProcess*>(p)) { && !dynamic_cast<MakeLeftHandedProcess*>(p)) {
p->Execute(scenecopy.get()); p->Execute(scenecopy.get());
} }
} }
ScenePrivateData* const privOut = ScenePriv(scenecopy.get()); ScenePrivateData* const privOut = ScenePriv(scenecopy.get());
ai_assert(privOut); ai_assert(privOut);
privOut->mPPStepsApplied |= pp; privOut->mPPStepsApplied |= pp;
} }
if(must_join_again) { if(must_join_again) {
JoinVerticesProcess proc; JoinVerticesProcess proc;
proc.Execute(scenecopy.get()); proc.Execute(scenecopy.get());
} }
ExportProperties emptyProperties; // Never pass NULL ExportProperties so Exporters don't have to worry. ExportProperties emptyProperties; // Never pass NULL ExportProperties so Exporters don't have to worry.
exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProperties ? pProperties : &emptyProperties); exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProperties ? pProperties : &emptyProperties);
} }
catch (DeadlyExportError& err) { catch (DeadlyExportError& err) {
pimpl->mError = err.what(); pimpl->mError = err.what();
return AI_FAILURE; return AI_FAILURE;
} }
return AI_SUCCESS; return AI_SUCCESS;
} }
} }
pimpl->mError = std::string("Found no exporter to handle this file format: ") + pFormatId; pimpl->mError = std::string("Found no exporter to handle this file format: ") + pFormatId;
ASSIMP_END_EXCEPTION_REGION(aiReturn); ASSIMP_END_EXCEPTION_REGION(aiReturn);
return AI_FAILURE; return AI_FAILURE;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const char* Exporter :: GetErrorString() const const char* Exporter :: GetErrorString() const
{ {
return pimpl->mError.c_str(); return pimpl->mError.c_str();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Exporter :: FreeBlob( ) void Exporter :: FreeBlob( )
{ {
delete pimpl->blob; delete pimpl->blob;
pimpl->blob = NULL; pimpl->blob = NULL;
pimpl->mError = ""; pimpl->mError = "";
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const aiExportDataBlob* Exporter :: GetBlob() const const aiExportDataBlob* Exporter :: GetBlob() const
{ {
return pimpl->blob; return pimpl->blob;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const aiExportDataBlob* Exporter :: GetOrphanedBlob() const const aiExportDataBlob* Exporter :: GetOrphanedBlob() const
{ {
const aiExportDataBlob* tmp = pimpl->blob; const aiExportDataBlob* tmp = pimpl->blob;
pimpl->blob = NULL; pimpl->blob = NULL;
return tmp; return tmp;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
size_t Exporter :: GetExportFormatCount() const size_t Exporter :: GetExportFormatCount() const
{ {
return pimpl->mExporters.size(); return pimpl->mExporters.size();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const aiExportFormatDesc* Exporter :: GetExportFormatDescription( size_t pIndex ) const const aiExportFormatDesc* Exporter :: GetExportFormatDescription( size_t pIndex ) const
{ {
if (pIndex >= GetExportFormatCount()) { if (pIndex >= GetExportFormatCount()) {
return NULL; return NULL;
} }
// Return from static storage if the requested index is built-in. // Return from static storage if the requested index is built-in.
if (pIndex < sizeof(gExporters) / sizeof(gExporters[0])) { if (pIndex < sizeof(gExporters) / sizeof(gExporters[0])) {
return &gExporters[pIndex].mDescription; return &gExporters[pIndex].mDescription;
} }
return &pimpl->mExporters[pIndex].mDescription; return &pimpl->mExporters[pIndex].mDescription;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiReturn Exporter :: RegisterExporter(const ExportFormatEntry& desc) aiReturn Exporter :: RegisterExporter(const ExportFormatEntry& desc)
{ {
BOOST_FOREACH(const ExportFormatEntry& e, pimpl->mExporters) { BOOST_FOREACH(const ExportFormatEntry& e, pimpl->mExporters) {
if (!strcmp(e.mDescription.id,desc.mDescription.id)) { if (!strcmp(e.mDescription.id,desc.mDescription.id)) {
return aiReturn_FAILURE; return aiReturn_FAILURE;
} }
} }
pimpl->mExporters.push_back(desc); pimpl->mExporters.push_back(desc);
return aiReturn_SUCCESS; return aiReturn_SUCCESS;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Exporter :: UnregisterExporter(const char* id) void Exporter :: UnregisterExporter(const char* id)
{ {
for(std::vector<ExportFormatEntry>::iterator it = pimpl->mExporters.begin(); it != pimpl->mExporters.end(); ++it) { for(std::vector<ExportFormatEntry>::iterator it = pimpl->mExporters.begin(); it != pimpl->mExporters.end(); ++it) {
if (!strcmp((*it).mDescription.id,id)) { if (!strcmp((*it).mDescription.id,id)) {
pimpl->mExporters.erase(it); pimpl->mExporters.erase(it);
break; break;
} }
} }
} }
ExportProperties :: ExportProperties() {} ExportProperties :: ExportProperties() {}
ExportProperties::ExportProperties(const ExportProperties &other) ExportProperties::ExportProperties(const ExportProperties &other)
: mIntProperties(other.mIntProperties), : mIntProperties(other.mIntProperties),
mFloatProperties(other.mFloatProperties), mFloatProperties(other.mFloatProperties),
mStringProperties(other.mStringProperties), mStringProperties(other.mStringProperties),
mMatrixProperties(other.mMatrixProperties) mMatrixProperties(other.mMatrixProperties)
@ -520,95 +520,95 @@ ExportProperties::ExportProperties(const ExportProperties &other)
// Set a configuration property // Set a configuration property
bool ExportProperties :: SetPropertyInteger(const char* szName, int iValue) bool ExportProperties :: SetPropertyInteger(const char* szName, int iValue)
{ {
return SetGenericProperty<int>(mIntProperties, szName,iValue); return SetGenericProperty<int>(mIntProperties, szName,iValue);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Set a configuration property // Set a configuration property
bool ExportProperties :: SetPropertyFloat(const char* szName, float iValue) bool ExportProperties :: SetPropertyFloat(const char* szName, float iValue)
{ {
return SetGenericProperty<float>(mFloatProperties, szName,iValue); return SetGenericProperty<float>(mFloatProperties, szName,iValue);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Set a configuration property // Set a configuration property
bool ExportProperties :: SetPropertyString(const char* szName, const std::string& value) bool ExportProperties :: SetPropertyString(const char* szName, const std::string& value)
{ {
return SetGenericProperty<std::string>(mStringProperties, szName,value); return SetGenericProperty<std::string>(mStringProperties, szName,value);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Set a configuration property // Set a configuration property
bool ExportProperties :: SetPropertyMatrix(const char* szName, const aiMatrix4x4& value) bool ExportProperties :: SetPropertyMatrix(const char* szName, const aiMatrix4x4& value)
{ {
return SetGenericProperty<aiMatrix4x4>(mMatrixProperties, szName,value); return SetGenericProperty<aiMatrix4x4>(mMatrixProperties, szName,value);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Get a configuration property // Get a configuration property
int ExportProperties :: GetPropertyInteger(const char* szName, int ExportProperties :: GetPropertyInteger(const char* szName,
int iErrorReturn /*= 0xffffffff*/) const int iErrorReturn /*= 0xffffffff*/) const
{ {
return GetGenericProperty<int>(mIntProperties,szName,iErrorReturn); return GetGenericProperty<int>(mIntProperties,szName,iErrorReturn);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Get a configuration property // Get a configuration property
float ExportProperties :: GetPropertyFloat(const char* szName, float ExportProperties :: GetPropertyFloat(const char* szName,
float iErrorReturn /*= 10e10*/) const float iErrorReturn /*= 10e10*/) const
{ {
return GetGenericProperty<float>(mFloatProperties,szName,iErrorReturn); return GetGenericProperty<float>(mFloatProperties,szName,iErrorReturn);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Get a configuration property // Get a configuration property
const std::string ExportProperties :: GetPropertyString(const char* szName, const std::string ExportProperties :: GetPropertyString(const char* szName,
const std::string& iErrorReturn /*= ""*/) const const std::string& iErrorReturn /*= ""*/) const
{ {
return GetGenericProperty<std::string>(mStringProperties,szName,iErrorReturn); return GetGenericProperty<std::string>(mStringProperties,szName,iErrorReturn);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Has a configuration property // Has a configuration property
const aiMatrix4x4 ExportProperties :: GetPropertyMatrix(const char* szName, const aiMatrix4x4 ExportProperties :: GetPropertyMatrix(const char* szName,
const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const
{ {
return GetGenericProperty<aiMatrix4x4>(mMatrixProperties,szName,iErrorReturn); return GetGenericProperty<aiMatrix4x4>(mMatrixProperties,szName,iErrorReturn);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Has a configuration property // Has a configuration property
bool ExportProperties :: HasPropertyInteger(const char* szName) const bool ExportProperties :: HasPropertyInteger(const char* szName) const
{ {
return HasGenericProperty<int>(mIntProperties, szName); return HasGenericProperty<int>(mIntProperties, szName);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Has a configuration property // Has a configuration property
bool ExportProperties :: HasPropertyBool(const char* szName) const bool ExportProperties :: HasPropertyBool(const char* szName) const
{ {
return HasGenericProperty<int>(mIntProperties, szName); return HasGenericProperty<int>(mIntProperties, szName);
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Has a configuration property // Has a configuration property
bool ExportProperties :: HasPropertyFloat(const char* szName) const bool ExportProperties :: HasPropertyFloat(const char* szName) const
{ {
return HasGenericProperty<float>(mFloatProperties, szName); return HasGenericProperty<float>(mFloatProperties, szName);
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Has a configuration property // Has a configuration property
bool ExportProperties :: HasPropertyString(const char* szName) const bool ExportProperties :: HasPropertyString(const char* szName) const
{ {
return HasGenericProperty<std::string>(mStringProperties, szName); return HasGenericProperty<std::string>(mStringProperties, szName);
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Has a configuration property // Has a configuration property
bool ExportProperties :: HasPropertyMatrix(const char* szName) const bool ExportProperties :: HasPropertyMatrix(const char* szName) const
{ {
return HasGenericProperty<aiMatrix4x4>(mMatrixProperties, szName); return HasGenericProperty<aiMatrix4x4>(mMatrixProperties, szName);
}; };

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -56,37 +56,37 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
namespace FBX { namespace FBX {
using namespace Util; using namespace Util;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& /*doc*/) AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& /*doc*/)
: Object(id, element, name) : Object(id, element, name)
{ {
const Scope& sc = GetRequiredScope(element); const Scope& sc = GetRequiredScope(element);
const Element& KeyTime = GetRequiredElement(sc,"KeyTime"); const Element& KeyTime = GetRequiredElement(sc,"KeyTime");
const Element& KeyValueFloat = GetRequiredElement(sc,"KeyValueFloat"); const Element& KeyValueFloat = GetRequiredElement(sc,"KeyValueFloat");
ParseVectorDataArray(keys, KeyTime); ParseVectorDataArray(keys, KeyTime);
ParseVectorDataArray(values, KeyValueFloat); ParseVectorDataArray(values, KeyValueFloat);
if(keys.size() != values.size()) { if(keys.size() != values.size()) {
DOMError("the number of key times does not match the number of keyframe values",&KeyTime); DOMError("the number of key times does not match the number of keyframe values",&KeyTime);
} }
// check if the key times are well-ordered // check if the key times are well-ordered
if(!std::equal(keys.begin(), keys.end() - 1, keys.begin() + 1, std::less<KeyTimeList::value_type>())) { if(!std::equal(keys.begin(), keys.end() - 1, keys.begin() + 1, std::less<KeyTimeList::value_type>())) {
DOMError("the keyframes are not in ascending order",&KeyTime); DOMError("the keyframes are not in ascending order",&KeyTime);
} }
const Element* KeyAttrDataFloat = sc["KeyAttrDataFloat"]; const Element* KeyAttrDataFloat = sc["KeyAttrDataFloat"];
if(KeyAttrDataFloat) { if(KeyAttrDataFloat) {
ParseVectorDataArray(attributes, *KeyAttrDataFloat); ParseVectorDataArray(attributes, *KeyAttrDataFloat);
} }
const Element* KeyAttrFlags = sc["KeyAttrFlags"]; const Element* KeyAttrFlags = sc["KeyAttrFlags"];
if(KeyAttrFlags) { if(KeyAttrFlags) {
ParseVectorDataArray(flags, *KeyAttrFlags); ParseVectorDataArray(flags, *KeyAttrFlags);
} }
} }
@ -99,61 +99,61 @@ AnimationCurve::~AnimationCurve()
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc, AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc,
const char* const * target_prop_whitelist /*= NULL*/, size_t whitelist_size /*= 0*/) const char* const * target_prop_whitelist /*= NULL*/, size_t whitelist_size /*= 0*/)
: Object(id, element, name) : Object(id, element, name)
, target() , target()
, doc(doc) , doc(doc)
{ {
const Scope& sc = GetRequiredScope(element); const Scope& sc = GetRequiredScope(element);
// find target node // find target node
const char* whitelist[] = {"Model","NodeAttribute"}; const char* whitelist[] = {"Model","NodeAttribute"};
const std::vector<const Connection*>& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,2); const std::vector<const Connection*>& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,2);
BOOST_FOREACH(const Connection* con, conns) { BOOST_FOREACH(const Connection* con, conns) {
// link should go for a property // link should go for a property
if (!con->PropertyName().length()) { if (!con->PropertyName().length()) {
continue; continue;
} }
if(target_prop_whitelist) { if(target_prop_whitelist) {
const char* const s = con->PropertyName().c_str(); const char* const s = con->PropertyName().c_str();
bool ok = false; bool ok = false;
for (size_t i = 0; i < whitelist_size; ++i) { for (size_t i = 0; i < whitelist_size; ++i) {
if (!strcmp(s, target_prop_whitelist[i])) { if (!strcmp(s, target_prop_whitelist[i])) {
ok = true; ok = true;
break; break;
} }
} }
if (!ok) { if (!ok) {
throw std::range_error("AnimationCurveNode target property is not in whitelist"); throw std::range_error("AnimationCurveNode target property is not in whitelist");
} }
} }
const Object* const ob = con->DestinationObject(); const Object* const ob = con->DestinationObject();
if(!ob) { if(!ob) {
DOMWarning("failed to read destination object for AnimationCurveNode->Model link, ignoring",&element); DOMWarning("failed to read destination object for AnimationCurveNode->Model link, ignoring",&element);
continue; continue;
} }
// XXX support constraints as DOM class // XXX support constraints as DOM class
//ai_assert(dynamic_cast<const Model*>(ob) || dynamic_cast<const NodeAttribute*>(ob)); //ai_assert(dynamic_cast<const Model*>(ob) || dynamic_cast<const NodeAttribute*>(ob));
target = ob; target = ob;
if(!target) { if(!target) {
continue; continue;
} }
prop = con->PropertyName(); prop = con->PropertyName();
break; break;
} }
if(!target) { if(!target) {
DOMWarning("failed to resolve target Model/NodeAttribute/Constraint for AnimationCurveNode",&element); DOMWarning("failed to resolve target Model/NodeAttribute/Constraint for AnimationCurveNode",&element);
} }
props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false); props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false);
} }
@ -167,34 +167,34 @@ AnimationCurveNode::~AnimationCurveNode()
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const AnimationCurveMap& AnimationCurveNode::Curves() const const AnimationCurveMap& AnimationCurveNode::Curves() const
{ {
if(curves.empty()) { if(curves.empty()) {
// resolve attached animation curves // resolve attached animation curves
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve"); const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve");
BOOST_FOREACH(const Connection* con, conns) { BOOST_FOREACH(const Connection* con, conns) {
// link should go for a property // link should go for a property
if (!con->PropertyName().length()) { if (!con->PropertyName().length()) {
continue; continue;
} }
const Object* const ob = con->SourceObject(); const Object* const ob = con->SourceObject();
if(!ob) { if(!ob) {
DOMWarning("failed to read source object for AnimationCurve->AnimationCurveNode link, ignoring",&element); DOMWarning("failed to read source object for AnimationCurve->AnimationCurveNode link, ignoring",&element);
continue; continue;
} }
const AnimationCurve* const anim = dynamic_cast<const AnimationCurve*>(ob); const AnimationCurve* const anim = dynamic_cast<const AnimationCurve*>(ob);
if(!anim) { if(!anim) {
DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve",&element); DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve",&element);
continue; continue;
} }
curves[con->PropertyName()] = anim; curves[con->PropertyName()] = anim;
} }
} }
return curves; return curves;
} }
@ -203,10 +203,10 @@ AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::s
: Object(id, element, name) : Object(id, element, name)
, doc(doc) , doc(doc)
{ {
const Scope& sc = GetRequiredScope(element); const Scope& sc = GetRequiredScope(element);
// note: the props table here bears little importance and is usually absent // note: the props table here bears little importance and is usually absent
props = GetPropertyTable(doc,"AnimationLayer.FbxAnimLayer",element,sc, true); props = GetPropertyTable(doc,"AnimationLayer.FbxAnimLayer",element,sc, true);
} }
@ -219,85 +219,85 @@ AnimationLayer::~AnimationLayer()
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/, AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/,
size_t whitelist_size /*= 0*/) const size_t whitelist_size /*= 0*/) const
{ {
AnimationCurveNodeList nodes; AnimationCurveNodeList nodes;
// resolve attached animation nodes // resolve attached animation nodes
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurveNode"); const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurveNode");
nodes.reserve(conns.size()); nodes.reserve(conns.size());
BOOST_FOREACH(const Connection* con, conns) { BOOST_FOREACH(const Connection* con, conns) {
// link should not go to a property // link should not go to a property
if (con->PropertyName().length()) { if (con->PropertyName().length()) {
continue; continue;
} }
const Object* const ob = con->SourceObject(); const Object* const ob = con->SourceObject();
if(!ob) { if(!ob) {
DOMWarning("failed to read source object for AnimationCurveNode->AnimationLayer link, ignoring",&element); DOMWarning("failed to read source object for AnimationCurveNode->AnimationLayer link, ignoring",&element);
continue; continue;
} }
const AnimationCurveNode* const anim = dynamic_cast<const AnimationCurveNode*>(ob); const AnimationCurveNode* const anim = dynamic_cast<const AnimationCurveNode*>(ob);
if(!anim) { if(!anim) {
DOMWarning("source object for ->AnimationLayer link is not an AnimationCurveNode",&element); DOMWarning("source object for ->AnimationLayer link is not an AnimationCurveNode",&element);
continue; continue;
} }
if(target_prop_whitelist) { if(target_prop_whitelist) {
const char* s = anim->TargetProperty().c_str(); const char* s = anim->TargetProperty().c_str();
bool ok = false; bool ok = false;
for (size_t i = 0; i < whitelist_size; ++i) { for (size_t i = 0; i < whitelist_size; ++i) {
if (!strcmp(s, target_prop_whitelist[i])) { if (!strcmp(s, target_prop_whitelist[i])) {
ok = true; ok = true;
break; break;
} }
} }
if(!ok) { if(!ok) {
continue; continue;
} }
} }
nodes.push_back(anim); nodes.push_back(anim);
} }
return nodes; // pray for NRVO return nodes; // pray for NRVO
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AnimationStack::AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc) AnimationStack::AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc)
: Object(id, element, name) : Object(id, element, name)
{ {
const Scope& sc = GetRequiredScope(element); const Scope& sc = GetRequiredScope(element);
// note: we don't currently use any of these properties so we shouldn't bother if it is missing // note: we don't currently use any of these properties so we shouldn't bother if it is missing
props = GetPropertyTable(doc,"AnimationStack.FbxAnimStack",element,sc, true); props = GetPropertyTable(doc,"AnimationStack.FbxAnimStack",element,sc, true);
// resolve attached animation layers // resolve attached animation layers
const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationLayer"); const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationLayer");
layers.reserve(conns.size()); layers.reserve(conns.size());
BOOST_FOREACH(const Connection* con, conns) { BOOST_FOREACH(const Connection* con, conns) {
// link should not go to a property // link should not go to a property
if (con->PropertyName().length()) { if (con->PropertyName().length()) {
continue; continue;
} }
const Object* const ob = con->SourceObject(); const Object* const ob = con->SourceObject();
if(!ob) { if(!ob) {
DOMWarning("failed to read source object for AnimationLayer->AnimationStack link, ignoring",&element); DOMWarning("failed to read source object for AnimationLayer->AnimationStack link, ignoring",&element);
continue; continue;
} }
const AnimationLayer* const anim = dynamic_cast<const AnimationLayer*>(ob); const AnimationLayer* const anim = dynamic_cast<const AnimationLayer*>(ob);
if(!anim) { if(!anim) {
DOMWarning("source object for ->AnimationStack link is not an AnimationLayer",&element); DOMWarning("source object for ->AnimationStack link is not an AnimationLayer",&element);
continue; continue;
} }
layers.push_back(anim); layers.push_back(anim);
} }
} }

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2015, 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,
@ -58,22 +58,22 @@ namespace FBX {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int offset) Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int offset)
: :
#ifdef DEBUG #ifdef DEBUG
contents(sbegin, static_cast<size_t>(send-sbegin)), contents(sbegin, static_cast<size_t>(send-sbegin)),
#endif #endif
sbegin(sbegin) sbegin(sbegin)
, send(send) , send(send)
, type(type) , type(type)
, line(offset) , line(offset)
, column(BINARY_MARKER) , column(BINARY_MARKER)
{ {
ai_assert(sbegin); ai_assert(sbegin);
ai_assert(send); ai_assert(send);
// binary tokens may have zero length because they are sometimes dummies // binary tokens may have zero length because they are sometimes dummies
// inserted by TokenizeBinary() // inserted by TokenizeBinary()
ai_assert(send >= sbegin); ai_assert(send >= sbegin);
} }
@ -84,85 +84,85 @@ namespace {
AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int offset) AI_WONT_RETURN_SUFFIX; AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int offset) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int offset) AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int offset)
{ {
throw DeadlyImportError(Util::AddOffset("FBX-Tokenize",message,offset)); throw DeadlyImportError(Util::AddOffset("FBX-Tokenize",message,offset));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
uint32_t Offset(const char* begin, const char* cursor) uint32_t Offset(const char* begin, const char* cursor)
{ {
ai_assert(begin <= cursor); ai_assert(begin <= cursor);
return static_cast<unsigned int>(cursor - begin); return static_cast<unsigned int>(cursor - begin);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void TokenizeError(const std::string& message, const char* begin, const char* cursor) void TokenizeError(const std::string& message, const char* begin, const char* cursor)
{ {
TokenizeError(message, Offset(begin, cursor)); TokenizeError(message, Offset(begin, cursor));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
uint32_t ReadWord(const char* input, const char*& cursor, const char* end) uint32_t ReadWord(const char* input, const char*& cursor, const char* end)
{ {
if(Offset(cursor, end) < 4) { if(Offset(cursor, end) < 4) {
TokenizeError("cannot ReadWord, out of bounds",input, cursor); TokenizeError("cannot ReadWord, out of bounds",input, cursor);
} }
uint32_t word = *reinterpret_cast<const uint32_t*>(cursor); uint32_t word = *reinterpret_cast<const uint32_t*>(cursor);
AI_SWAP4(word); AI_SWAP4(word);
cursor += 4; cursor += 4;
return word; return word;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
uint8_t ReadByte(const char* input, const char*& cursor, const char* end) uint8_t ReadByte(const char* input, const char*& cursor, const char* end)
{ {
if(Offset(cursor, end) < 1) { if(Offset(cursor, end) < 1) {
TokenizeError("cannot ReadByte, out of bounds",input, cursor); TokenizeError("cannot ReadByte, out of bounds",input, cursor);
} }
uint8_t word = *reinterpret_cast<const uint8_t*>(cursor); uint8_t word = *reinterpret_cast<const uint8_t*>(cursor);
++cursor; ++cursor;
return word; return word;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
unsigned int ReadString(const char*& sbegin_out, const char*& send_out, const char* input, const char*& cursor, const char* end, unsigned int ReadString(const char*& sbegin_out, const char*& send_out, const char* input, const char*& cursor, const char* end,
bool long_length = false, bool long_length = false,
bool allow_null = false) bool allow_null = false)
{ {
const uint32_t len_len = long_length ? 4 : 1; const uint32_t len_len = long_length ? 4 : 1;
if(Offset(cursor, end) < len_len) { if(Offset(cursor, end) < len_len) {
TokenizeError("cannot ReadString, out of bounds reading length",input, cursor); TokenizeError("cannot ReadString, out of bounds reading length",input, cursor);
} }
const uint32_t length = long_length ? ReadWord(input, cursor, end) : ReadByte(input, cursor, end); const uint32_t length = long_length ? ReadWord(input, cursor, end) : ReadByte(input, cursor, end);
if (Offset(cursor, end) < length) { if (Offset(cursor, end) < length) {
TokenizeError("cannot ReadString, length is out of bounds",input, cursor); TokenizeError("cannot ReadString, length is out of bounds",input, cursor);
} }
sbegin_out = cursor; sbegin_out = cursor;
cursor += length; cursor += length;
send_out = cursor; send_out = cursor;
if(!allow_null) { if(!allow_null) {
for (unsigned int i = 0; i < length; ++i) { for (unsigned int i = 0; i < length; ++i) {
if(sbegin_out[i] == '\0') { if(sbegin_out[i] == '\0') {
TokenizeError("failed ReadString, unexpected NUL character in string",input, cursor); TokenizeError("failed ReadString, unexpected NUL character in string",input, cursor);
} }
} }
} }
return length; return length;
} }
@ -170,203 +170,203 @@ unsigned int ReadString(const char*& sbegin_out, const char*& send_out, const ch
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ReadData(const char*& sbegin_out, const char*& send_out, const char* input, const char*& cursor, const char* end) void ReadData(const char*& sbegin_out, const char*& send_out, const char* input, const char*& cursor, const char* end)
{ {
if(Offset(cursor, end) < 1) { if(Offset(cursor, end) < 1) {
TokenizeError("cannot ReadData, out of bounds reading length",input, cursor); TokenizeError("cannot ReadData, out of bounds reading length",input, cursor);
} }
const char type = *cursor; const char type = *cursor;
sbegin_out = cursor++; sbegin_out = cursor++;
switch(type) switch(type)
{ {
// 16 bit int // 16 bit int
case 'Y': case 'Y':
cursor += 2; cursor += 2;
break; break;
// 1 bit bool flag (yes/no) // 1 bit bool flag (yes/no)
case 'C': case 'C':
cursor += 1; cursor += 1;
break; break;
// 32 bit int // 32 bit int
case 'I': case 'I':
// <- fall thru // <- fall thru
// float // float
case 'F': case 'F':
cursor += 4; cursor += 4;
break; break;
// double // double
case 'D': case 'D':
cursor += 8; cursor += 8;
break; break;
// 64 bit int // 64 bit int
case 'L': case 'L':
cursor += 8; cursor += 8;
break; break;
// note: do not write cursor += ReadWord(...cursor) as this would be UB // note: do not write cursor += ReadWord(...cursor) as this would be UB
// raw binary data // raw binary data
case 'R': case 'R':
{ {
const uint32_t length = ReadWord(input, cursor, end); const uint32_t length = ReadWord(input, cursor, end);
cursor += length; cursor += length;
break; break;
} }
case 'b': case 'b':
// TODO: what is the 'b' type code? Right now we just skip over it / // TODO: what is the 'b' type code? Right now we just skip over it /
// take the full range we could get // take the full range we could get
cursor = end; cursor = end;
break; break;
// array of * // array of *
case 'f': case 'f':
case 'd': case 'd':
case 'l': case 'l':
case 'i': { case 'i': {
const uint32_t length = ReadWord(input, cursor, end); const uint32_t length = ReadWord(input, cursor, end);
const uint32_t encoding = ReadWord(input, cursor, end); const uint32_t encoding = ReadWord(input, cursor, end);
const uint32_t comp_len = ReadWord(input, cursor, end); const uint32_t comp_len = ReadWord(input, cursor, end);
// compute length based on type and check against the stored value // compute length based on type and check against the stored value
if(encoding == 0) { if(encoding == 0) {
uint32_t stride = 0; uint32_t stride = 0;
switch(type) switch(type)
{ {
case 'f': case 'f':
case 'i': case 'i':
stride = 4; stride = 4;
break; break;
case 'd': case 'd':
case 'l': case 'l':
stride = 8; stride = 8;
break; break;
default: default:
ai_assert(false); ai_assert(false);
}; };
ai_assert(stride > 0); ai_assert(stride > 0);
if(length * stride != comp_len) { if(length * stride != comp_len) {
TokenizeError("cannot ReadData, calculated data stride differs from what the file claims",input, cursor); TokenizeError("cannot ReadData, calculated data stride differs from what the file claims",input, cursor);
} }
} }
// zip/deflate algorithm (encoding==1)? take given length. anything else? die // zip/deflate algorithm (encoding==1)? take given length. anything else? die
else if (encoding != 1) { else if (encoding != 1) {
TokenizeError("cannot ReadData, unknown encoding",input, cursor); TokenizeError("cannot ReadData, unknown encoding",input, cursor);
} }
cursor += comp_len; cursor += comp_len;
break; break;
} }
// string // string
case 'S': { case 'S': {
const char* sb, *se; const char* sb, *se;
// 0 characters can legally happen in such strings // 0 characters can legally happen in such strings
ReadString(sb, se, input, cursor, end, true, true); ReadString(sb, se, input, cursor, end, true, true);
break; break;
} }
default: default:
TokenizeError("cannot ReadData, unexpected type code: " + std::string(&type, 1),input, cursor); TokenizeError("cannot ReadData, unexpected type code: " + std::string(&type, 1),input, cursor);
} }
if(cursor > end) { if(cursor > end) {
TokenizeError("cannot ReadData, the remaining size is too small for the data type: " + std::string(&type, 1),input, cursor); TokenizeError("cannot ReadData, the remaining size is too small for the data type: " + std::string(&type, 1),input, cursor);
} }
// the type code is contained in the returned range // the type code is contained in the returned range
send_out = cursor; send_out = cursor;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, const char* end) bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, const char* end)
{ {
// the first word contains the offset at which this block ends // the first word contains the offset at which this block ends
const uint32_t end_offset = ReadWord(input, cursor, end); const uint32_t end_offset = ReadWord(input, cursor, end);
// we may get 0 if reading reached the end of the file - // we may get 0 if reading reached the end of the file -
// fbx files have a mysterious extra footer which I don't know // fbx files have a mysterious extra footer which I don't know
// how to extract any information from, but at least it always // how to extract any information from, but at least it always
// starts with a 0. // starts with a 0.
if(!end_offset) { if(!end_offset) {
return false; return false;
} }
if(end_offset > Offset(input, end)) { if(end_offset > Offset(input, end)) {
TokenizeError("block offset is out of range",input, cursor); TokenizeError("block offset is out of range",input, cursor);
} }
else if(end_offset < Offset(input, cursor)) { else if(end_offset < Offset(input, cursor)) {
TokenizeError("block offset is negative out of range",input, cursor); TokenizeError("block offset is negative out of range",input, cursor);
} }
// the second data word contains the number of properties in the scope // the second data word contains the number of properties in the scope
const uint32_t prop_count = ReadWord(input, cursor, end); const uint32_t prop_count = ReadWord(input, cursor, end);
// the third data word contains the length of the property list // the third data word contains the length of the property list
const uint32_t prop_length = ReadWord(input, cursor, end); const uint32_t prop_length = ReadWord(input, cursor, end);
// now comes the name of the scope/key // now comes the name of the scope/key
const char* sbeg, *send; const char* sbeg, *send;
ReadString(sbeg, send, input, cursor, end); ReadString(sbeg, send, input, cursor, end);
output_tokens.push_back(new_Token(sbeg, send, TokenType_KEY, Offset(input, cursor) )); output_tokens.push_back(new_Token(sbeg, send, TokenType_KEY, Offset(input, cursor) ));
// now come the individual properties // now come the individual properties
const char* begin_cursor = cursor; const char* begin_cursor = cursor;
for (unsigned int i = 0; i < prop_count; ++i) { for (unsigned int i = 0; i < prop_count; ++i) {
ReadData(sbeg, send, input, cursor, begin_cursor + prop_length); ReadData(sbeg, send, input, cursor, begin_cursor + prop_length);
output_tokens.push_back(new_Token(sbeg, send, TokenType_DATA, Offset(input, cursor) )); output_tokens.push_back(new_Token(sbeg, send, TokenType_DATA, Offset(input, cursor) ));
if(i != prop_count-1) { if(i != prop_count-1) {
output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_COMMA, Offset(input, cursor) )); output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_COMMA, Offset(input, cursor) ));
} }
} }
if (Offset(begin_cursor, cursor) != prop_length) { if (Offset(begin_cursor, cursor) != prop_length) {
TokenizeError("property length not reached, something is wrong",input, cursor); TokenizeError("property length not reached, something is wrong",input, cursor);
} }
// at the end of each nested block, there is a NUL record to indicate // at the end of each nested block, there is a NUL record to indicate
// that the sub-scope exists (i.e. to distinguish between P: and P : {}) // that the sub-scope exists (i.e. to distinguish between P: and P : {})
// this NUL record is 13 bytes long. // this NUL record is 13 bytes long.
#define BLOCK_SENTINEL_LENGTH 13 #define BLOCK_SENTINEL_LENGTH 13
if (Offset(input, cursor) < end_offset) { if (Offset(input, cursor) < end_offset) {
if (end_offset - Offset(input, cursor) < BLOCK_SENTINEL_LENGTH) { if (end_offset - Offset(input, cursor) < BLOCK_SENTINEL_LENGTH) {
TokenizeError("insufficient padding bytes at block end",input, cursor); TokenizeError("insufficient padding bytes at block end",input, cursor);
} }
output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_OPEN_BRACKET, Offset(input, cursor) )); output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_OPEN_BRACKET, Offset(input, cursor) ));
// XXX this is vulnerable to stack overflowing .. // XXX this is vulnerable to stack overflowing ..
while(Offset(input, cursor) < end_offset - BLOCK_SENTINEL_LENGTH) { while(Offset(input, cursor) < end_offset - BLOCK_SENTINEL_LENGTH) {
ReadScope(output_tokens, input, cursor, input + end_offset - BLOCK_SENTINEL_LENGTH); ReadScope(output_tokens, input, cursor, input + end_offset - BLOCK_SENTINEL_LENGTH);
} }
output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) )); output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) ));
for (unsigned int i = 0; i < BLOCK_SENTINEL_LENGTH; ++i) { for (unsigned int i = 0; i < BLOCK_SENTINEL_LENGTH; ++i) {
if(cursor[i] != '\0') { if(cursor[i] != '\0') {
TokenizeError("failed to read nested block sentinel, expected all bytes to be 0",input, cursor); TokenizeError("failed to read nested block sentinel, expected all bytes to be 0",input, cursor);
} }
} }
cursor += BLOCK_SENTINEL_LENGTH; cursor += BLOCK_SENTINEL_LENGTH;
} }
if (Offset(input, cursor) != end_offset) { if (Offset(input, cursor) != end_offset) {
TokenizeError("scope length not reached, something is wrong",input, cursor); TokenizeError("scope length not reached, something is wrong",input, cursor);
} }
return true; return true;
} }
@ -375,26 +375,26 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int length) void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int length)
{ {
ai_assert(input); ai_assert(input);
if(length < 0x1b) { if(length < 0x1b) {
TokenizeError("file is too short",0); TokenizeError("file is too short",0);
} }
if (strncmp(input,"Kaydara FBX Binary",18)) { if (strncmp(input,"Kaydara FBX Binary",18)) {
TokenizeError("magic bytes not found",0); TokenizeError("magic bytes not found",0);
} }
//uint32_t offset = 0x1b; //uint32_t offset = 0x1b;
const char* cursor = input + 0x1b; const char* cursor = input + 0x1b;
while (cursor < input + length) { while (cursor < input + length) {
if(!ReadScope(output_tokens, input, cursor, input + length)) { if(!ReadScope(output_tokens, input, cursor, input + length)) {
break; break;
} }
} }
} }
} // !FBX } // !FBX

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