Merge pull request #1 from assimp/master

Update
pull/493/head
Madrich 2014-12-29 16:01:18 +01:00
commit 45988cd238
440 changed files with 11222 additions and 94797 deletions

19
.gitignore vendored
View File

@ -32,3 +32,22 @@ test/results
# Python # Python
__pycache__ __pycache__
*.log
*.vcxproj
*.filters
*.tlog
Assimp.sdf
test/gtest/tmp/gtest-gitupdate.cmake
test/gtest/tmp/gtest-gitclone.cmake
test/gtest/tmp/gtest-cfgcmd.txt.in
test/gtest/tmp/gtest-cfgcmd.txt
test/gtest/src/gtest-stamp/gtest-download.cmake
test/gtest/src/gtest-stamp/gtest-configure.cmake
test/gtest/src/gtest-stamp/gtest-build.cmake
test/gtest/src/gtest-stamp/Debug/gtest-patch
*.cache
test/gtest/src/gtest-stamp/Debug/gtest-build
*.suo
*.lib
test/gtest/src/gtest-stamp/Debug/
tools/assimp_view/assimp_viewer.vcxproj.user

View File

@ -1,11 +1,16 @@
before_install: before_install:
- sudo apt-get install cmake - sudo apt-get install cmake python3
env: env:
- TRAVIS_NO_EXPORT=YES matrix:
- TRAVIS_NO_EXPORT=NO - LINUX=1 TRAVIS_NO_EXPORT=YES
- TRAVIS_STATIC_BUILD=ON - LINUX=1 TRAVIS_NO_EXPORT=NO
- TRAVIS_STATIC_BUILD=OFF - LINUX=1 TRAVIS_STATIC_BUILD=ON
- LINUX=1 TRAVIS_STATIC_BUILD=OFF
- WINDOWS=1 TRAVIS_NO_EXPORT=YES
- WINDOWS=1 TRAVIS_NO_EXPORT=NO
- WINDOWS=1 TRAVIS_STATIC_BUILD=ON
- WINDOWS=1 TRAVIS_STATIC_BUILD=OFF
language: cpp language: cpp
@ -13,7 +18,20 @@ compiler:
- gcc - gcc
- clang - clang
script: cmake -G "Unix Makefiles" -DASSIMP_ENABLE_BOOST_WORKAROUND=YES -DASSIMP_NO_EXPORT=$TRAVIS_NO_EXPORT -STATIC_BUILD=$TRAVIS_STATIC_BUILD && make install:
- if [ $WINDOWS ]; then travis_retry sudo apt-get install -q -y gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 binutils-mingw-w64-x86-64; fi
script:
- cmake -G "Unix Makefiles" -DASSIMP_ENABLE_BOOST_WORKAROUND=YES -DASSIMP_NO_EXPORT=$TRAVIS_NO_EXPORT -STATIC_BUILD=$TRAVIS_STATIC_BUILD
- make
- sudo make install
- sudo ldconfig
- cd test/unit
- ../../bin/unit
- cd ../regression
- chmod 755 run.py
- ./run.py
- echo "=========================================================="
- echo "REGRESSION TEST FAILS (results/run_regression_suite_failures.csv)"
- cat ../results/run_regression_suite_failures.csv

23
CHANGES
View File

@ -2,6 +2,29 @@
CHANGELOG CHANGELOG
---------------------------------------------------------------------- ----------------------------------------------------------------------
3.1.1 (2014-06-15)
FEATURES:
- Support for FBX 2013 and newer, binary and ASCII (this is partly
work from Google Summer of Code 2012)
- Support for OGRE binary mesh and skeleton format
- Updated BLEND support for newer Blender versions
- Support for arbitrary meta data, used to hold FBX and DAE metadata
- OBJ Export now produces smaller files
- Meshes can now have names, this is supported by the major importers
- Improved IFC geometry generation
- M3 support has been removed
FIXES/HOUSEKEEPING:
- Hundreds of bugfixes in all parts of the library
- CMake is now the primary build system
API COMPATIBILITY:
- 3.1.1 is not binary compatible to 3.0 due to aiNode::mMetaData
and aiMesh::mName
- Export interface has been cleaned up and unified
- Other than that no relevant changes
3.0 (2012-07-07) 3.0 (2012-07-07)

View File

@ -3,7 +3,7 @@ PROJECT( Assimp )
# Define here the needed parameters # Define here the needed parameters
set (ASSIMP_VERSION_MAJOR 3) set (ASSIMP_VERSION_MAJOR 3)
set (ASSIMP_VERSION_MINOR 0) set (ASSIMP_VERSION_MINOR 1)
set (ASSIMP_VERSION_PATCH 1) # subversion revision? set (ASSIMP_VERSION_PATCH 1) # subversion revision?
set (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}) set (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH})
set (ASSIMP_SOVERSION 3) set (ASSIMP_SOVERSION 3)
@ -13,30 +13,30 @@ set(ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used f
# 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_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_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_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_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_SOURCE_DIR}/revision.h.in ${CMAKE_CURRENT_SOURCE_DIR}/revision.h.in
${CMAKE_BINARY_DIR}/revision.h ${CMAKE_CURRENT_BINARY_DIR}/revision.h
) )
include_directories(${CMAKE_BINARY_DIR}) include_directories(${CMAKE_CURRENT_BINARY_DIR})
option(ASSIMP_OPT_BUILD_PACKAGES "Set to ON to generate CPack configuration files and packaging targets" OFF) option(ASSIMP_OPT_BUILD_PACKAGES "Set to ON to generate CPack configuration files and packaging targets" OFF)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" ) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" )
@ -45,14 +45,16 @@ set(LIBASSIMP-DEV_COMPONENT "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_M
set(CPACK_COMPONENTS_ALL assimp-bin ${LIBASSIMP_COMPONENT} ${LIBASSIMP-DEV_COMPONENT} assimp-dev) set(CPACK_COMPONENTS_ALL assimp-bin ${LIBASSIMP_COMPONENT} ${LIBASSIMP-DEV_COMPONENT} assimp-dev)
set(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names") set(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names")
option(ASSIMP_ANDROID_JNIIOSYSTEM "Android JNI IOSystem support is active" OFF)
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)
add_definitions(-fPIC) # this is a very important switch and some libraries seem now to have it.... add_definitions(-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
add_definitions( -fvisibility=hidden -Wall ) add_definitions( -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)
INCLUDE_DIRECTORIES( include ) INCLUDE_DIRECTORIES( include )
@ -64,57 +66,54 @@ 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(ASSIMP_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfitx for lib, samples and tools") SET(ASSIMP_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfitx for lib, samples and tools")
# Allow the user to build a static library # Allow the user to build a shared or static library
option ( BUILD_SHARED_LIBS "Build a shared version of the library" ON ) option ( BUILD_SHARED_LIBS "Build a shared version of the library" ON )
# Generate a pkg-config .pc for the Assimp library.
CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/assimp.pc.in" "${PROJECT_BINARY_DIR}/assimp.pc" @ONLY )
INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTALL_DIR}/pkgconfig/ COMPONENT ${LIBASSIMP-DEV_COMPONENT})
# 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.
SET ( ASSIMP_ENABLE_BOOST_WORKAROUND ON CACHE BOOL 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
) )
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") 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" )
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
@ -122,146 +121,152 @@ 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})
SET ( ASSIMP_NO_EXPORT OFF CACHE BOOL option ( ASSIMP_NO_EXPORT
"Disable Assimp's export functionality." "Disable Assimp's export functionality."
OFF
) )
if( CMAKE_COMPILER_IS_GNUCXX )
set(LIBSTDC++_LIBRARIES -lstdc++)
endif( CMAKE_COMPILER_IS_GNUCXX )
# Search for external dependencies, and build them from source if not found # Search for external dependencies, and build them from source if not found
# Search for zlib # Search for zlib
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)
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 )
# if(CMAKE_CL_64)
# set(ASSIMP_BUILD_ARCHITECTURE "amd64")
# else(CMAKE_CL_64)
# set(ASSIMP_BUILD_ARCHITECTURE "x86")
# endif(CMAKE_CL_64)
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 )
ADD_SUBDIRECTORY( code/ ) ADD_SUBDIRECTORY( code/ )
SET ( ASSIMP_BUILD_ASSIMP_TOOLS ON CACHE BOOL 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
) )
IF ( ASSIMP_BUILD_ASSIMP_TOOLS ) IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
IF ( WIN32 ) IF ( WIN32 )
ADD_SUBDIRECTORY( tools/assimp_view/ ) ADD_SUBDIRECTORY( tools/assimp_view/ )
ENDIF ( WIN32 ) ENDIF ( WIN32 )
ADD_SUBDIRECTORY( tools/assimp_cmd/ ) ADD_SUBDIRECTORY( tools/assimp_cmd/ )
ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS ) ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
SET ( ASSIMP_BUILD_SAMPLES OFF CACHE BOOL 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
) )
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 )
IF ( WIN32 ) option ( ASSIMP_BUILD_TESTS
SET ( ASSIMP_BUILD_TESTS ON CACHE BOOL "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
) )
IF ( ASSIMP_BUILD_TESTS ) IF ( ASSIMP_BUILD_TESTS )
ADD_SUBDIRECTORY( test/ ) ADD_SUBDIRECTORY( test/ )
ENDIF ( ASSIMP_BUILD_TESTS ) ENDIF ( ASSIMP_BUILD_TESTS )
ENDIF ( WIN32 )
IF(MSVC) IF(MSVC)
SET ( ASSIMP_INSTALL_PDB ON CACHE BOOL option ( ASSIMP_INSTALL_PDB
"Install MSVC debug files." "Install MSVC debug files."
) ON
)
ENDIF(MSVC) ENDIF(MSVC)
# Generate a pkg-config .pc for the Assimp library.
CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/assimp.pc.in" "${PROJECT_BINARY_DIR}/assimp.pc" @ONLY )
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_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description") 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

@ -148,3 +148,6 @@ Bugfixes for uv-tanget calculation.
- Jonne Nauha - Jonne Nauha
Ogre Binary format support Ogre Binary format support
- Filip Wasil, Tieto Poland Sp. z o.o.
Android JNI asset extraction support

View File

@ -1,10 +1,12 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
======== ========
Open Asset Import Library is a Open Source library designed to load various __3d file formats and convert them into a shared, in-memory format__. It supports more than __30 file formats__ for import and a growing selection of file formats for export. Additionally, assimp features various __post processing tools__ to refine the imported data: _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. Open Asset Import Library is a Open Source library designed to load various __3d file formats and convert them into a shared, in-memory format__. It supports more than __40 file formats__ for import and a growing selection of file formats for export. Additionally, assimp features various __post processing tools__ to refine the imported data: _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 of assimp 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 of the trunk is [![Build Status](https://travis-ci.org/assimp/assimp.png)](https://travis-ci.org/assimp/assimp) This is the development trunk of assimp 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 of the trunk is [![Build Status](https://travis-ci.org/assimp/assimp.png)](https://travis-ci.org/assimp/assimp)
[open3mod](https://github.com/acgessler/open3mod) is an Open Source 3D model viewer based off Assimp's import and export abilities.
#### Supported file formats #### #### Supported file formats ####
The library provides importers for a lot of file formats, including: The library provides importers for a lot of file formats, including:
@ -44,6 +46,7 @@ The library provides importers for a lot of file formats, including:
- Ogre Binary - Ogre Binary
- Ogre XML - Ogre XML
- Q3D - Q3D
- ASSBIN (Assimp scene serialization)
Additionally, the following formats are also supported, but not part of the core library as they depend on proprietary libraries. Additionally, the following formats are also supported, but not part of the core library as they depend on proprietary libraries.
@ -55,7 +58,10 @@ Exporters include:
- STL - STL
- OBJ - OBJ
- PLY - PLY
- X
- 3DS
- JSON (for WebGl, via https://github.com/acgessler/assimp2json) - JSON (for WebGl, via https://github.com/acgessler/assimp2json)
- ASSBIN
See [the full list here](http://assimp.sourceforge.net/main_features_formats.html). See [the full list here](http://assimp.sourceforge.net/main_features_formats.html).
@ -77,7 +83,7 @@ C++ish interface). The directory structure is:
/scripts Scripts used to generate the loading code for some formats /scripts Scripts used to generate the loading code for some formats
/port Ports to other languages and scripts to maintain those. /port Ports to other languages and scripts to maintain those.
/test Unit- and regression tests, test suite of models /test Unit- and regression tests, test suite of models
/tools Tools (viewer, command line `assimp`) /tools Tools (old assimp viewer, command line `assimp`)
/samples A small number of samples to illustrate possible /samples A small number of samples to illustrate possible
use cases for Assimp use cases for Assimp
/workspaces Build enviroments for vc,xcode,... (deprecated, /workspaces Build enviroments for vc,xcode,... (deprecated,

View File

@ -44,20 +44,20 @@ if (CMAKE_BUILD_TYPE EQUAL "DEBUG")
set( ASSIMP_LIBRARIES ${ASSIMP_LIBRARIES}D) set( ASSIMP_LIBRARIES ${ASSIMP_LIBRARIES}D)
endif (CMAKE_BUILD_TYPE EQUAL "DEBUG") endif (CMAKE_BUILD_TYPE EQUAL "DEBUG")
# search for the boost version assimp was compiled with
#set(Boost_USE_MULTITHREAD ON)
#set(Boost_USE_STATIC_LIBS OFF)
#set(Boost_USE_STATIC_RUNTIME OFF)
#find_package(Boost ${ASSIMP_Boost_VERSION} EXACT COMPONENTS thread date_time)
#if(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
# set( ASSIMP_INCLUDE_DIRS "${ASSIMP_INCLUDE_DIRS}" ${Boost_INCLUDE_DIRS})
#else(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
# message(WARNING "Failed to find Boost ${ASSIMP_Boost_VERSION} necessary for assimp")
#endif(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
# the boost version assimp was compiled with # the boost version assimp was compiled with
set( ASSIMP_Boost_VERSION "@Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@") set( ASSIMP_Boost_VERSION "@Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@")
# search for the boost version assimp was compiled with
set(Boost_USE_MULTITHREAD ON)
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost ${ASSIMP_Boost_VERSION} EXACT COMPONENTS thread date_time)
if(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
set( ASSIMP_INCLUDE_DIRS "${ASSIMP_INCLUDE_DIRS}" ${Boost_INCLUDE_DIRS})
else(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
message(WARNING "Failed to find Boost ${ASSIMP_Boost_VERSION} necessary for assimp")
endif(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
# for compatibility wiht pkg-config # for compatibility wiht pkg-config
set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}") set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}")
set(ASSIMP_LDFLAGS_OTHER "${ASSIMP_LINK_FLAGS}") set(ASSIMP_LDFLAGS_OTHER "${ASSIMP_LINK_FLAGS}")

View File

@ -7,4 +7,5 @@ Name: @CMAKE_PROJECT_NAME@
Description: Import various well-known 3D model formats in an uniform manner. Description: Import various well-known 3D model formats in an uniform manner.
Version: @PROJECT_VERSION@ Version: @PROJECT_VERSION@
Libs: -L${libdir} -lassimp@ASSIMP_LIBRARY_SUFFIX@ Libs: -L${libdir} -lassimp@ASSIMP_LIBRARY_SUFFIX@
Libs.private: @LIBSTDC++_LIBRARIES@ @ZLIB_LIBRARIES_LINKED@
Cflags: -I${includedir} Cflags: -I${includedir}

View File

@ -0,0 +1,64 @@
find_package(Threads REQUIRED)
include(ExternalProject)
if(MSYS OR MINGW)
set(DISABLE_PTHREADS ON)
else()
set(DISABLE_PTHREADS OFF)
endif()
if (MSVC)
set(RELEASE_LIB_DIR ReleaseLibs)
set(DEBUG_LIB_DIR DebugLibs)
else()
set(RELEASE_LIB_DIR "")
set(DEBUG_LIB_DIR "")
endif()
set(GTEST_CMAKE_ARGS
"-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
"-Dgtest_force_shared_crt=ON"
"-Dgtest_disable_pthreads:BOOL=${DISABLE_PTHREADS}")
set(GTEST_RELEASE_LIB_DIR "")
set(GTEST_DEBUGLIB_DIR "")
if (MSVC)
set(GTEST_CMAKE_ARGS ${GTEST_CMAKE_ARGS}
"-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG:PATH=${DEBUG_LIB_DIR}"
"-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE:PATH=${RELEASE_LIB_DIR}")
set(GTEST_LIB_DIR)
endif()
set(GTEST_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/gtest")
ExternalProject_Add(gtest
GIT_REPOSITORY https://chromium.googlesource.com/external/googletest
TIMEOUT 10
PREFIX "${GTEST_PREFIX}"
CMAKE_ARGS "${GTEST_CMAKE_ARGS}"
LOG_DOWNLOAD ON
LOG_CONFIGURE ON
LOG_BUILD ON
# Disable install
INSTALL_COMMAND ""
)
set(LIB_PREFIX "${CMAKE_STATIC_LIBRARY_PREFIX}")
set(LIB_SUFFIX "${CMAKE_STATIC_LIBRARY_SUFFIX}")
set(GTEST_LOCATION "${GTEST_PREFIX}/src/gtest-build")
set(GTEST_DEBUG_LIBRARIES
"${GTEST_LOCATION}/${DEBUG_LIB_DIR}/${LIB_PREFIX}gtest${LIB_SUFFIX}"
"${CMAKE_THREAD_LIBS_INIT}")
SET(GTEST_RELEASE_LIBRARIES
"${GTEST_LOCATION}/${RELEASE_LIB_DIR}/${LIB_PREFIX}gtest${LIB_SUFFIX}"
"${CMAKE_THREAD_LIBS_INIT}")
if(MSVC_VERSION EQUAL 1700)
add_definitions(-D_VARIADIC_MAX=10)
endif()
ExternalProject_Get_Property(gtest source_dir)
include_directories(${source_dir}/include)
include_directories(${source_dir}/gtest/include)
ExternalProject_Get_Property(gtest binary_dir)
link_directories(${binary_dir})

View File

@ -0,0 +1,560 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
#include "3DSExporter.h"
#include "3DSLoader.h"
#include "SceneCombiner.h"
#include "SplitLargeMeshes.h"
using namespace Assimp;
namespace Assimp {
namespace {
//////////////////////////////////////////////////////////////////////////////////////
// Scope utility to write a 3DS file chunk.
//
// 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
// size based on the then-position of the output stream cursor is filled in.
class ChunkWriter {
enum {
CHUNK_SIZE_NOT_SET = 0xdeadbeef
, SIZE_OFFSET = 2
};
public:
ChunkWriter(StreamWriterLE& writer, uint16_t chunk_type)
: writer(writer)
{
chunk_start_pos = writer.GetCurrentPos();
writer.PutU2(chunk_type);
writer.PutU4(CHUNK_SIZE_NOT_SET);
}
~ChunkWriter() {
std::size_t head_pos = writer.GetCurrentPos();
ai_assert(head_pos > chunk_start_pos);
const std::size_t chunk_size = head_pos - chunk_start_pos;
writer.SetCurrentPos(chunk_start_pos + SIZE_OFFSET);
writer.PutU4(chunk_size);
writer.SetCurrentPos(head_pos);
}
private:
StreamWriterLE& writer;
std::size_t chunk_start_pos;
};
// 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
// of the mesh in |aiScene::mMeshes|.
std::string GetMeshName(const aiMesh& mesh, unsigned int index, const aiNode& node) {
static const std::string underscore = "_";
char postfix[10] = {0};
ASSIMP_itoa10(postfix, index);
std::string result = node.mName.C_Str();
if (mesh.mName.length > 0) {
result += underscore + mesh.mName.C_Str();
}
return result + underscore + postfix;
}
// Return an unique name for a given |mat| with original position |index|
// in |aiScene::mMaterials|. The name preserves the original material
// name if possible.
std::string GetMaterialName(const aiMaterial& mat, unsigned int index) {
static const std::string underscore = "_";
char postfix[10] = {0};
ASSIMP_itoa10(postfix, index);
aiString mat_name;
if (AI_SUCCESS == mat.Get(AI_MATKEY_NAME, mat_name)) {
return mat_name.C_Str() + underscore + postfix;
}
return "Material" + underscore + postfix;
}
// Collect world transformations for each node
void CollectTrafos(const aiNode* node, std::map<const aiNode*, aiMatrix4x4>& trafos) {
const aiMatrix4x4& parent = node->mParent ? trafos[node->mParent] : aiMatrix4x4();
trafos[node] = parent * node->mTransformation;
for (unsigned int i = 0; i < node->mNumChildren; ++i) {
CollectTrafos(node->mChildren[i], trafos);
}
}
// 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) {
for (unsigned int i = 0; i < node->mNumMeshes; ++i) {
meshes.insert(std::make_pair(node, node->mMeshes[i]));
}
for (unsigned int i = 0; i < node->mNumChildren; ++i) {
CollectMeshes(node->mChildren[i], meshes);
}
}
}
// ------------------------------------------------------------------------------------------------
// Worker function for exporting a scene to 3DS. Prototyped and registered in Exporter.cpp
void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
{
boost::shared_ptr<IOStream> outfile (pIOSystem->Open(pFile, "wb"));
if(!outfile) {
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
// requirement of the 3DS exporter.
//
// 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
// which is not possible with the current way of specifying preprocess steps
// in |Exporter::ExportFormatEntry|.
aiScene* scenecopy_tmp;
SceneCombiner::CopyScene(&scenecopy_tmp,pScene);
std::auto_ptr<aiScene> scenecopy(scenecopy_tmp);
SplitLargeMeshesProcess_Triangle tri_splitter;
tri_splitter.SetLimit(0xffff);
tri_splitter.Execute(scenecopy.get());
SplitLargeMeshesProcess_Vertex vert_splitter;
vert_splitter.SetLimit(0xffff);
vert_splitter.Execute(scenecopy.get());
// Invoke the actual exporter
Discreet3DSExporter exporter(outfile, scenecopy.get());
}
} // end of namespace Assimp
// ------------------------------------------------------------------------------------------------
Discreet3DSExporter:: Discreet3DSExporter(boost::shared_ptr<IOStream> outfile, const aiScene* scene)
: scene(scene)
, writer(outfile)
{
CollectTrafos(scene->mRootNode, trafos);
CollectMeshes(scene->mRootNode, meshes);
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAIN);
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJMESH);
WriteMeshes();
WriteMaterials();
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MASTER_SCALE);
writer.PutF4(1.0f);
}
}
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_KEYFRAMER);
WriteHierarchy(*scene->mRootNode, -1, -1);
}
}
// ------------------------------------------------------------------------------------------------
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
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO);
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME);
// Assimp node names are unique and distinct from all mesh-node
// names we generate; thus we can use them as-is
WriteString(node.mName);
// Two unknown int16 values - it is even unclear if 0 is a safe value
// but luckily importers do not know better either.
writer.PutI4(0);
int16_t hierarchy_pos = static_cast<int16_t>(seq);
if (sibling_level != -1) {
hierarchy_pos = sibling_level;
}
// Write the hierarchy position
writer.PutI2(hierarchy_pos);
}
}
// TODO: write transformation chunks
++seq;
sibling_level = seq;
// Write all children
for (unsigned int i = 0; i < node.mNumChildren; ++i) {
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
for (unsigned int i = 0; i < node.mNumMeshes; ++i) {
const bool first_child = node.mNumChildren == 0 && i == 0;
const unsigned int mesh_idx = node.mMeshes[i];
const aiMesh& mesh = *scene->mMeshes[mesh_idx];
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO);
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME);
WriteString(GetMeshName(mesh, mesh_idx, node));
writer.PutI4(0);
writer.PutI2(static_cast<int16_t>(first_child ? seq : sibling_level));
++seq;
}
}
return seq;
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteMaterials()
{
for (unsigned int i = 0; i < scene->mNumMaterials; ++i) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATERIAL);
const aiMaterial& mat = *scene->mMaterials[i];
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATNAME);
const std::string& name = GetMaterialName(mat, i);
WriteString(name);
}
aiColor3D color;
if (mat.Get(AI_MATKEY_COLOR_DIFFUSE, color) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_DIFFUSE);
WriteColor(color);
}
if (mat.Get(AI_MATKEY_COLOR_SPECULAR, color) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SPECULAR);
WriteColor(color);
}
if (mat.Get(AI_MATKEY_COLOR_AMBIENT, color) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_AMBIENT);
WriteColor(color);
}
if (mat.Get(AI_MATKEY_COLOR_EMISSIVE, color) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SELF_ILLUM);
WriteColor(color);
}
aiShadingMode shading_mode;
if (mat.Get(AI_MATKEY_SHADING_MODEL, shading_mode) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHADING);
Discreet3DS::shadetype3ds shading_mode_out;
switch(shading_mode) {
case aiShadingMode_Flat:
case aiShadingMode_NoShading:
shading_mode_out = Discreet3DS::Flat;
break;
case aiShadingMode_Gouraud:
case aiShadingMode_Toon:
case aiShadingMode_OrenNayar:
case aiShadingMode_Minnaert:
shading_mode_out = Discreet3DS::Gouraud;
break;
case aiShadingMode_Phong:
case aiShadingMode_Blinn:
case aiShadingMode_CookTorrance:
case aiShadingMode_Fresnel:
shading_mode_out = Discreet3DS::Phong;
break;
default:
ai_assert(false);
};
writer.PutU2(static_cast<uint16_t>(shading_mode_out));
}
float f;
if (mat.Get(AI_MATKEY_SHININESS, f) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHININESS);
WritePercentChunk(f);
}
if (mat.Get(AI_MATKEY_SHININESS_STRENGTH, f) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHININESS_PERCENT);
WritePercentChunk(f);
}
int twosided;
if (mat.Get(AI_MATKEY_TWOSIDED, twosided) == AI_SUCCESS && twosided != 0) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_TWO_SIDE);
writer.PutI2(1);
}
WriteTexture(mat, aiTextureType_DIFFUSE, Discreet3DS::CHUNK_MAT_TEXTURE);
WriteTexture(mat, aiTextureType_HEIGHT, Discreet3DS::CHUNK_MAT_BUMPMAP);
WriteTexture(mat, aiTextureType_OPACITY, Discreet3DS::CHUNK_MAT_OPACMAP);
WriteTexture(mat, aiTextureType_SHININESS, Discreet3DS::CHUNK_MAT_MAT_SHINMAP);
WriteTexture(mat, aiTextureType_SPECULAR, Discreet3DS::CHUNK_MAT_SPECMAP);
WriteTexture(mat, aiTextureType_EMISSIVE, Discreet3DS::CHUNK_MAT_SELFIMAP);
WriteTexture(mat, aiTextureType_REFLECTION, Discreet3DS::CHUNK_MAT_REFLMAP);
}
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags)
{
aiString path;
aiTextureMapMode map_mode[2] = {
aiTextureMapMode_Wrap, aiTextureMapMode_Wrap
};
float blend = 1.0f;
if (mat.GetTexture(type, 0, &path, NULL, NULL, &blend, NULL, map_mode) != AI_SUCCESS || !path.length) {
return;
}
// TODO: handle embedded textures properly
if (path.data[0] == '*') {
DefaultLogger::get()->error("Ignoring embedded texture for export: " + std::string(path.C_Str()));
return;
}
ChunkWriter chunk(writer, chunk_flags);
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPFILE);
WriteString(path);
}
WritePercentChunk(blend);
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MAP_TILING);
uint16_t val = 0; // WRAP
if (map_mode[0] == aiTextureMapMode_Mirror) {
val = 0x2;
}
else if (map_mode[0] == aiTextureMapMode_Decal) {
val = 0x10;
}
writer.PutU2(val);
}
// TODO: export texture transformation (i.e. UV offset, scale, rotation)
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteMeshes()
{
// NOTE: 3DS allows for instances. However:
// i) not all importers support reading them
// ii) instances are not as flexible as they are in assimp, in particular,
// nodes can carry (and instance) only one 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.
//
// Furthermore, the TRIMESH is transformed into world space so that it will
// appear correctly if importers don't read the scene hierarchy at all.
for (MeshesByNodeMap::const_iterator it = meshes.begin(); it != meshes.end(); ++it) {
const aiNode& node = *(*it).first;
const unsigned int mesh_idx = (*it).second;
const aiMesh& mesh = *scene->mMeshes[mesh_idx];
// This should not happen if the SLM step is correctly executed
// before the scene is handed to the exporter
ai_assert(mesh.mNumVertices <= 0xffff);
ai_assert(mesh.mNumFaces <= 0xffff);
const aiMatrix4x4& trafo = trafos[&node];
ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJBLOCK);
// 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);
WriteString(name);
// TRIMESH chunk
ChunkWriter chunk2(writer, Discreet3DS::CHUNK_TRIMESH);
// Vertices in world space
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_VERTLIST);
const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
writer.PutU2(count);
for (unsigned int i = 0; i < mesh.mNumVertices; ++i) {
const aiVector3D& v = trafo * mesh.mVertices[i];
writer.PutF4(v.x);
writer.PutF4(v.y);
writer.PutF4(v.z);
}
}
// UV coordinates
if (mesh.HasTextureCoords(0)) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPLIST);
const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
writer.PutU2(count);
for (unsigned int i = 0; i < mesh.mNumVertices; ++i) {
const aiVector3D& v = mesh.mTextureCoords[0][i];
writer.PutF4(v.x);
writer.PutF4(v.y);
}
}
// Faces (indices)
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACELIST);
ai_assert(mesh.mNumFaces <= 0xffff);
// Count triangles, discard lines and points
uint16_t count = 0;
for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
const aiFace& f = mesh.mFaces[i];
if (f.mNumIndices < 3) {
continue;
}
// TRIANGULATE step is a pre-requisite so we should not see polys here
ai_assert(f.mNumIndices == 3);
++count;
}
writer.PutU2(count);
for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
const aiFace& f = mesh.mFaces[i];
if (f.mNumIndices < 3) {
continue;
}
for (unsigned int j = 0; j < 3; ++j) {
ai_assert(f.mIndices[j] <= 0xffff);
writer.PutI2(static_cast<uint16_t>(f.mIndices[j]));
}
// Edge visibility flag
writer.PutI2(0x0);
}
// TODO: write smoothing groups (CHUNK_SMOOLIST)
WriteFaceMaterialChunk(mesh);
}
// Transformation matrix by which the mesh vertices have been pre-transformed with.
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRMATRIX);
for (unsigned int r = 0; r < 4; ++r) {
for (unsigned int c = 0; c < 3; ++c) {
writer.PutF4(trafo[r][c]);
}
}
}
}
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteFaceMaterialChunk(const aiMesh& mesh)
{
ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACEMAT);
const std::string& name = GetMaterialName(*scene->mMaterials[mesh.mMaterialIndex], mesh.mMaterialIndex);
WriteString(name);
// Because assimp splits meshes by material, only a single
// FACEMAT chunk needs to be written
ai_assert(mesh.mNumFaces <= 0xffff);
const uint16_t count = static_cast<uint16_t>(mesh.mNumFaces);
writer.PutU2(count);
for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
writer.PutU2(static_cast<uint16_t>(i));
}
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteString(const std::string& s) {
for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
writer.PutI1(*it);
}
writer.PutI1('\0');
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteString(const aiString& s) {
for (std::size_t i = 0; i < s.length; ++i) {
writer.PutI1(s.data[i]);
}
writer.PutI1('\0');
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WriteColor(const aiColor3D& color) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_RGBF);
writer.PutF4(color.r);
writer.PutF4(color.g);
writer.PutF4(color.b);
}
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WritePercentChunk(float f) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_PERCENTF);
writer.PutF4(f);
}
#endif // ASSIMP_BUILD_NO_3DS_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT

94
code/3DSExporter.h 100644
View File

@ -0,0 +1,94 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file 3DSExporter.h
* 3DS Exporter Main Header
*/
#ifndef AI_3DSEXPORTER_H_INC
#define AI_3DSEXPORTER_H_INC
#include <map>
#include "StreamWriter.h"
struct aiScene;
struct aiNode;
namespace Assimp
{
// ------------------------------------------------------------------------------------------------
/** Helper class to export a given scene to a 3DS file. */
// ------------------------------------------------------------------------------------------------
class Discreet3DSExporter
{
public:
Discreet3DSExporter(boost::shared_ptr<IOStream> outfile, const aiScene* pScene);
private:
void WriteMeshes();
void WriteMaterials();
void WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags);
void WriteFaceMaterialChunk(const aiMesh& mesh);
int WriteHierarchy(const aiNode& node, int level, int sibling_level);
void WriteString(const std::string& s);
void WriteString(const aiString& s);
void WriteColor(const aiColor3D& color);
void WritePercentChunk(float f);
private:
const aiScene* const scene;
StreamWriterLE writer;
std::map<const aiNode*, aiMatrix4x4> trafos;
typedef std::multimap<const aiNode*, unsigned int> MeshesByNodeMap;
MeshesByNodeMap meshes;
};
}
#endif

View File

@ -468,7 +468,7 @@ struct aiFloatKey
{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
}; };

View File

@ -273,8 +273,8 @@ protected:
bool bIsPrj; bool bIsPrj;
}; };
#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER
} // end of namespace Assimp } // end of namespace Assimp
#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER
#endif // AI_3DSIMPORTER_H_INC #endif // AI_3DSIMPORTER_H_INC

View File

@ -1525,7 +1525,7 @@ void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh& mesh)
continue; continue;
} }
// Number of bones // Number of bones
if (TokenMatch(filePtr,"MESH_NUMBONE" ,11)) if (TokenMatch(filePtr,"MESH_NUMBONE" ,12))
{ {
ParseLV4MeshLong(iNumBones); ParseLV4MeshLong(iNumBones);
continue; continue;
@ -1559,7 +1559,7 @@ void Parser::ParseLV4MeshBones(unsigned int iNumBones,ASE::Mesh& mesh)
++filePtr; ++filePtr;
// Mesh bone with name ... // Mesh bone with name ...
if (TokenMatch(filePtr,"MESH_BONE_NAME" ,16)) if (TokenMatch(filePtr,"MESH_BONE_NAME" ,14))
{ {
// parse an index ... // parse an index ...
if(SkipSpaces(&filePtr)) if(SkipSpaces(&filePtr))

View File

@ -0,0 +1,765 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file AssbinExporter.cpp
* ASSBIN exporter main code
*/
#include "AssimpPCH.h"
#include "assbin_chunks.h"
#include "./../include/assimp/version.h"
#include "ProcessHelper.h"
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h>
#else
# include "../contrib/zlib/zlib.h"
#endif
#include <time.h>
#ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
using namespace Assimp;
namespace Assimp {
template <typename T>
size_t Write(IOStream * stream, const T& v)
{
return stream->Write( &v, sizeof(T), 1 );
}
// -----------------------------------------------------------------------------------
// Serialize an aiString
template <>
inline size_t Write<aiString>(IOStream * stream, const aiString& s)
{
const size_t s2 = (uint32_t)s.length;
stream->Write(&s,4,1);
stream->Write(s.data,s2,1);
return s2+4;
}
// -----------------------------------------------------------------------------------
// Serialize an unsigned int as uint32_t
template <>
inline size_t Write<unsigned int>(IOStream * stream, const unsigned int& w)
{
const uint32_t t = (uint32_t)w;
if (w > t) {
// this shouldn't happen, integers in Assimp data structures never exceed 2^32
throw new DeadlyExportError("loss of data due to 64 -> 32 bit integer conversion");
}
stream->Write(&t,4,1);
return 4;
}
// -----------------------------------------------------------------------------------
// Serialize an unsigned int as uint16_t
template <>
inline size_t Write<uint16_t>(IOStream * stream, const uint16_t& w)
{
BOOST_STATIC_ASSERT(sizeof(uint16_t)==2);
stream->Write(&w,2,1);
return 2;
}
// -----------------------------------------------------------------------------------
// Serialize a float
template <>
inline size_t Write<float>(IOStream * stream, const float& f)
{
BOOST_STATIC_ASSERT(sizeof(float)==4);
stream->Write(&f,4,1);
return 4;
}
// -----------------------------------------------------------------------------------
// Serialize a double
template <>
inline size_t Write<double>(IOStream * stream, const double& f)
{
BOOST_STATIC_ASSERT(sizeof(double)==8);
stream->Write(&f,8,1);
return 8;
}
// -----------------------------------------------------------------------------------
// Serialize a vec3
template <>
inline size_t Write<aiVector3D>(IOStream * stream, const aiVector3D& v)
{
size_t t = Write<float>(stream,v.x);
t += Write<float>(stream,v.y);
t += Write<float>(stream,v.z);
return t;
}
// -----------------------------------------------------------------------------------
// Serialize a color value
template <>
inline size_t Write<aiColor4D>(IOStream * stream, const aiColor4D& v)
{
size_t t = Write<float>(stream,v.r);
t += Write<float>(stream,v.g);
t += Write<float>(stream,v.b);
t += Write<float>(stream,v.a);
return t;
}
// -----------------------------------------------------------------------------------
// Serialize a quaternion
template <>
inline size_t Write<aiQuaternion>(IOStream * stream, const aiQuaternion& v)
{
size_t t = Write<float>(stream,v.w);
t += Write<float>(stream,v.x);
t += Write<float>(stream,v.y);
t += Write<float>(stream,v.z);
return 16;
}
// -----------------------------------------------------------------------------------
// Serialize a vertex weight
template <>
inline size_t Write<aiVertexWeight>(IOStream * stream, const aiVertexWeight& v)
{
size_t t = Write<unsigned int>(stream,v.mVertexId);
return t+Write<float>(stream,v.mWeight);
}
// -----------------------------------------------------------------------------------
// Serialize a mat4x4
template <>
inline size_t Write<aiMatrix4x4>(IOStream * stream, const aiMatrix4x4& m)
{
for (unsigned int i = 0; i < 4;++i) {
for (unsigned int i2 = 0; i2 < 4;++i2) {
Write<float>(stream,m[i][i2]);
}
}
return 64;
}
// -----------------------------------------------------------------------------------
// Serialize an aiVectorKey
template <>
inline size_t Write<aiVectorKey>(IOStream * stream, const aiVectorKey& v)
{
const size_t t = Write<double>(stream,v.mTime);
return t + Write<aiVector3D>(stream,v.mValue);
}
// -----------------------------------------------------------------------------------
// Serialize an aiQuatKey
template <>
inline size_t Write<aiQuatKey>(IOStream * stream, const aiQuatKey& v)
{
const size_t t = Write<double>(stream,v.mTime);
return t + Write<aiQuaternion>(stream,v.mValue);
}
template <typename T>
inline size_t WriteBounds(IOStream * stream, const T* in, unsigned int size)
{
T minc,maxc;
ArrayBounds(in,size,minc,maxc);
const size_t t = Write<T>(stream,minc);
return t + Write<T>(stream,maxc);
}
// We use this to write out non-byte arrays so that we write using the specializations.
// This way we avoid writing out extra bytes that potentially come from struct alignment.
template <typename T>
inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
{
size_t n = 0;
for (unsigned int i=0; i<size; i++) n += Write<T>(stream,in[i]);
return n;
}
// ----------------------------------------------------------------------------------
/** @class AssbinChunkWriter
* @brief Chunk writer mechanism for the .assbin file structure
*
* This is a standard in-memory IOStream (most of the code is based on BlobIOStream),
* the difference being that this takes another IOStream as a "container" in the
* constructor, and when it is destroyed, it appends the magic number, the chunk size,
* and the chunk contents to the container stream. This allows relatively easy chunk
* chunk construction, even recursively.
*/
class AssbinChunkWriter : public IOStream
{
private:
uint8_t* buffer;
uint32_t magic;
IOStream * container;
size_t cur_size, cursor, initial;
private:
// -------------------------------------------------------------------
void Grow(size_t need = 0)
{
size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) ));
const uint8_t* const old = buffer;
buffer = new uint8_t[new_size];
if (old) {
memcpy(buffer,old,cur_size);
delete[] old;
}
cur_size = new_size;
}
public:
AssbinChunkWriter( IOStream * container, uint32_t magic, size_t initial = 4096)
: buffer(NULL), magic(magic), container(container), cur_size(0), cursor(0), initial(initial)
{
}
virtual ~AssbinChunkWriter()
{
if (container) {
container->Write( &magic, sizeof(uint32_t), 1 );
container->Write( &cursor, sizeof(uint32_t), 1 );
container->Write( buffer, 1, cursor );
}
if (buffer) delete[] buffer;
}
void * GetBufferPointer() { return buffer; };
// -------------------------------------------------------------------
virtual size_t Read(void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) { return 0; };
virtual aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) { return aiReturn_FAILURE; };
virtual size_t Tell() const { return cursor; };
virtual void Flush() { };
virtual size_t FileSize() const
{
return cursor;
}
// -------------------------------------------------------------------
virtual size_t Write(const void* pvBuffer, size_t pSize, size_t pCount)
{
pSize *= pCount;
if (cursor + pSize > cur_size) {
Grow(cursor + pSize);
}
memcpy(buffer+cursor, pvBuffer, pSize);
cursor += pSize;
return pCount;
}
};
// ----------------------------------------------------------------------------------
/** @class AssbinExport
* @brief Assbin exporter class
*
* This class performs the .assbin exporting, and is responsible for the file layout.
*/
class AssbinExport
{
private:
bool shortened;
bool compressed;
protected:
// -----------------------------------------------------------------------------------
void WriteBinaryNode( IOStream * container, const aiNode* node)
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE );
Write<aiString>(&chunk,node->mName);
Write<aiMatrix4x4>(&chunk,node->mTransformation);
Write<unsigned int>(&chunk,node->mNumChildren);
Write<unsigned int>(&chunk,node->mNumMeshes);
for (unsigned int i = 0; i < node->mNumMeshes;++i) {
Write<unsigned int>(&chunk,node->mMeshes[i]);
}
for (unsigned int i = 0; i < node->mNumChildren;++i) {
WriteBinaryNode( &chunk, node->mChildren[i] );
}
}
// -----------------------------------------------------------------------------------
void WriteBinaryTexture(IOStream * container, const aiTexture* tex)
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AITEXTURE );
Write<unsigned int>(&chunk,tex->mWidth);
Write<unsigned int>(&chunk,tex->mHeight);
chunk.Write( tex->achFormatHint, sizeof(char), 4 );
if(!shortened) {
if (!tex->mHeight) {
chunk.Write(tex->pcData,1,tex->mWidth);
}
else {
chunk.Write(tex->pcData,1,tex->mWidth*tex->mHeight*4);
}
}
}
// -----------------------------------------------------------------------------------
void WriteBinaryBone(IOStream * container, const aiBone* b)
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIBONE );
Write<aiString>(&chunk,b->mName);
Write<unsigned int>(&chunk,b->mNumWeights);
Write<aiMatrix4x4>(&chunk,b->mOffsetMatrix);
// for the moment we write dumb min/max values for the bones, too.
// maybe I'll add a better, hash-like solution later
if (shortened) {
WriteBounds(&chunk,b->mWeights,b->mNumWeights);
} // else write as usual
else WriteArray<aiVertexWeight>(&chunk,b->mWeights,b->mNumWeights);
}
// -----------------------------------------------------------------------------------
void WriteBinaryMesh(IOStream * container, const aiMesh* mesh)
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMESH );
Write<unsigned int>(&chunk,mesh->mPrimitiveTypes);
Write<unsigned int>(&chunk,mesh->mNumVertices);
Write<unsigned int>(&chunk,mesh->mNumFaces);
Write<unsigned int>(&chunk,mesh->mNumBones);
Write<unsigned int>(&chunk,mesh->mMaterialIndex);
// first of all, write bits for all existent vertex components
unsigned int c = 0;
if (mesh->mVertices) {
c |= ASSBIN_MESH_HAS_POSITIONS;
}
if (mesh->mNormals) {
c |= ASSBIN_MESH_HAS_NORMALS;
}
if (mesh->mTangents && mesh->mBitangents) {
c |= ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS;
}
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
if (!mesh->mTextureCoords[n]) {
break;
}
c |= ASSBIN_MESH_HAS_TEXCOORD(n);
}
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) {
if (!mesh->mColors[n]) {
break;
}
c |= ASSBIN_MESH_HAS_COLOR(n);
}
Write<unsigned int>(&chunk,c);
aiVector3D minVec, maxVec;
if (mesh->mVertices) {
if (shortened) {
WriteBounds(&chunk,mesh->mVertices,mesh->mNumVertices);
} // else write as usual
else WriteArray<aiVector3D>(&chunk,mesh->mVertices,mesh->mNumVertices);
}
if (mesh->mNormals) {
if (shortened) {
WriteBounds(&chunk,mesh->mNormals,mesh->mNumVertices);
} // else write as usual
else WriteArray<aiVector3D>(&chunk,mesh->mNormals,mesh->mNumVertices);
}
if (mesh->mTangents && mesh->mBitangents) {
if (shortened) {
WriteBounds(&chunk,mesh->mTangents,mesh->mNumVertices);
WriteBounds(&chunk,mesh->mBitangents,mesh->mNumVertices);
} // else write as usual
else {
WriteArray<aiVector3D>(&chunk,mesh->mTangents,mesh->mNumVertices);
WriteArray<aiVector3D>(&chunk,mesh->mBitangents,mesh->mNumVertices);
}
}
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) {
if (!mesh->mColors[n])
break;
if (shortened) {
WriteBounds(&chunk,mesh->mColors[n],mesh->mNumVertices);
} // else write as usual
else WriteArray<aiColor4D>(&chunk,mesh->mColors[n],mesh->mNumVertices);
}
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
if (!mesh->mTextureCoords[n])
break;
// write number of UV components
Write<unsigned int>(&chunk,mesh->mNumUVComponents[n]);
if (shortened) {
WriteBounds(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices);
} // else write as usual
else WriteArray<aiVector3D>(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices);
}
// write faces. There are no floating-point calculations involved
// in these, so we can write a simple hash over the face data
// to the dump file. We generate a single 32 Bit hash for 512 faces
// using Assimp's standard hashing function.
if (shortened) {
unsigned int processed = 0;
for (unsigned int job;(job = std::min(mesh->mNumFaces-processed,512u));processed += job) {
uint32_t hash = 0;
for (unsigned int a = 0; a < job;++a) {
const aiFace& f = mesh->mFaces[processed+a];
uint32_t tmp = f.mNumIndices;
hash = SuperFastHash(reinterpret_cast<const char*>(&tmp),sizeof tmp,hash);
for (unsigned int i = 0; i < f.mNumIndices; ++i) {
BOOST_STATIC_ASSERT(AI_MAX_VERTICES <= 0xffffffff);
tmp = static_cast<uint32_t>( f.mIndices[i] );
hash = SuperFastHash(reinterpret_cast<const char*>(&tmp),sizeof tmp,hash);
}
}
Write<unsigned int>(&chunk,hash);
}
}
else // else write as usual
{
// if there are less than 2^16 vertices, we can simply use 16 bit integers ...
for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
const aiFace& f = mesh->mFaces[i];
BOOST_STATIC_ASSERT(AI_MAX_FACE_INDICES <= 0xffff);
Write<uint16_t>(&chunk,f.mNumIndices);
for (unsigned int a = 0; a < f.mNumIndices;++a) {
if (mesh->mNumVertices < (1u<<16)) {
Write<uint16_t>(&chunk,f.mIndices[a]);
}
else Write<unsigned int>(&chunk,f.mIndices[a]);
}
}
}
// write bones
if (mesh->mNumBones) {
for (unsigned int a = 0; a < mesh->mNumBones;++a) {
const aiBone* b = mesh->mBones[a];
WriteBinaryBone(&chunk,b);
}
}
}
// -----------------------------------------------------------------------------------
void WriteBinaryMaterialProperty(IOStream * container, const aiMaterialProperty* prop)
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIALPROPERTY );
Write<aiString>(&chunk,prop->mKey);
Write<unsigned int>(&chunk,prop->mSemantic);
Write<unsigned int>(&chunk,prop->mIndex);
Write<unsigned int>(&chunk,prop->mDataLength);
Write<unsigned int>(&chunk,(unsigned int)prop->mType);
chunk.Write(prop->mData,1,prop->mDataLength);
}
// -----------------------------------------------------------------------------------
void WriteBinaryMaterial(IOStream * container, const aiMaterial* mat)
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIAL);
Write<unsigned int>(&chunk,mat->mNumProperties);
for (unsigned int i = 0; i < mat->mNumProperties;++i) {
WriteBinaryMaterialProperty( &chunk, mat->mProperties[i]);
}
}
// -----------------------------------------------------------------------------------
void WriteBinaryNodeAnim(IOStream * container, const aiNodeAnim* nd)
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODEANIM );
Write<aiString>(&chunk,nd->mNodeName);
Write<unsigned int>(&chunk,nd->mNumPositionKeys);
Write<unsigned int>(&chunk,nd->mNumRotationKeys);
Write<unsigned int>(&chunk,nd->mNumScalingKeys);
Write<unsigned int>(&chunk,nd->mPreState);
Write<unsigned int>(&chunk,nd->mPostState);
if (nd->mPositionKeys) {
if (shortened) {
WriteBounds(&chunk,nd->mPositionKeys,nd->mNumPositionKeys);
} // else write as usual
else WriteArray<aiVectorKey>(&chunk,nd->mPositionKeys,nd->mNumPositionKeys);
}
if (nd->mRotationKeys) {
if (shortened) {
WriteBounds(&chunk,nd->mRotationKeys,nd->mNumRotationKeys);
} // else write as usual
else WriteArray<aiQuatKey>(&chunk,nd->mRotationKeys,nd->mNumRotationKeys);
}
if (nd->mScalingKeys) {
if (shortened) {
WriteBounds(&chunk,nd->mScalingKeys,nd->mNumScalingKeys);
} // else write as usual
else WriteArray<aiVectorKey>(&chunk,nd->mScalingKeys,nd->mNumScalingKeys);
}
}
// -----------------------------------------------------------------------------------
void WriteBinaryAnim( IOStream * container, const aiAnimation* anim )
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIANIMATION );
Write<aiString>(&chunk,anim->mName);
Write<double>(&chunk,anim->mDuration);
Write<double>(&chunk,anim->mTicksPerSecond);
Write<unsigned int>(&chunk,anim->mNumChannels);
for (unsigned int a = 0; a < anim->mNumChannels;++a) {
const aiNodeAnim* nd = anim->mChannels[a];
WriteBinaryNodeAnim(&chunk,nd);
}
}
// -----------------------------------------------------------------------------------
void WriteBinaryLight( IOStream * container, const aiLight* l )
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AILIGHT );
Write<aiString>(&chunk,l->mName);
Write<unsigned int>(&chunk,l->mType);
if (l->mType != aiLightSource_DIRECTIONAL) {
Write<float>(&chunk,l->mAttenuationConstant);
Write<float>(&chunk,l->mAttenuationLinear);
Write<float>(&chunk,l->mAttenuationQuadratic);
}
Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorDiffuse);
Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorSpecular);
Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorAmbient);
if (l->mType == aiLightSource_SPOT) {
Write<float>(&chunk,l->mAngleInnerCone);
Write<float>(&chunk,l->mAngleOuterCone);
}
}
// -----------------------------------------------------------------------------------
void WriteBinaryCamera( IOStream * container, const aiCamera* cam )
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AICAMERA );
Write<aiString>(&chunk,cam->mName);
Write<aiVector3D>(&chunk,cam->mPosition);
Write<aiVector3D>(&chunk,cam->mLookAt);
Write<aiVector3D>(&chunk,cam->mUp);
Write<float>(&chunk,cam->mHorizontalFOV);
Write<float>(&chunk,cam->mClipPlaneNear);
Write<float>(&chunk,cam->mClipPlaneFar);
Write<float>(&chunk,cam->mAspect);
}
// -----------------------------------------------------------------------------------
void WriteBinaryScene( IOStream * container, const aiScene* scene)
{
AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AISCENE );
// basic scene information
Write<unsigned int>(&chunk,scene->mFlags);
Write<unsigned int>(&chunk,scene->mNumMeshes);
Write<unsigned int>(&chunk,scene->mNumMaterials);
Write<unsigned int>(&chunk,scene->mNumAnimations);
Write<unsigned int>(&chunk,scene->mNumTextures);
Write<unsigned int>(&chunk,scene->mNumLights);
Write<unsigned int>(&chunk,scene->mNumCameras);
// write node graph
WriteBinaryNode( &chunk, scene->mRootNode );
// write all meshes
for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
const aiMesh* mesh = scene->mMeshes[i];
WriteBinaryMesh( &chunk,mesh);
}
// write materials
for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
const aiMaterial* mat = scene->mMaterials[i];
WriteBinaryMaterial(&chunk,mat);
}
// write all animations
for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
const aiAnimation* anim = scene->mAnimations[i];
WriteBinaryAnim(&chunk,anim);
}
// write all textures
for (unsigned int i = 0; i < scene->mNumTextures;++i) {
const aiTexture* mesh = scene->mTextures[i];
WriteBinaryTexture(&chunk,mesh);
}
// write lights
for (unsigned int i = 0; i < scene->mNumLights;++i) {
const aiLight* l = scene->mLights[i];
WriteBinaryLight(&chunk,l);
}
// write cameras
for (unsigned int i = 0; i < scene->mNumCameras;++i) {
const aiCamera* cam = scene->mCameras[i];
WriteBinaryCamera(&chunk,cam);
}
}
public:
AssbinExport()
: shortened(false), compressed(false) // temporary settings until properties are introduced for exporters
{
}
// -----------------------------------------------------------------------------------
// Write a binary model dump
void WriteBinaryDump(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
{
IOStream * out = pIOSystem->Open( pFile, "wb" );
if (!out) return;
time_t tt = time(NULL);
tm* p = gmtime(&tt);
// header
char s[64];
memset( s, 0, 64 );
#if _MSC_VER >= 1400
sprintf_s(s,"ASSIMP.binary-dump.%s",asctime(p));
#else
snprintf(s,64,"ASSIMP.binary-dump.%s",asctime(p));
#endif
out->Write( s, 44, 1 );
// == 44 bytes
Write<unsigned int>( out, ASSBIN_VERSION_MAJOR );
Write<unsigned int>( out, ASSBIN_VERSION_MINOR );
Write<unsigned int>( out, aiGetVersionRevision() );
Write<unsigned int>( out, aiGetCompileFlags() );
Write<uint16_t>( out, shortened );
Write<uint16_t>( out, compressed );
// == 20 bytes
char buff[256];
strncpy(buff,pFile,256);
out->Write(buff,sizeof(char),256);
char cmd[] = "\0";
strncpy(buff,cmd,128);
out->Write(buff,sizeof(char),128);
// leave 64 bytes free for future extensions
memset(buff,0xcd,64);
out->Write(buff,sizeof(char),64);
// == 435 bytes
// ==== total header size: 512 bytes
ai_assert( out->Tell() == ASSBIN_HEADER_LENGTH );
// Up to here the data is uncompressed. For compressed files, the rest
// is compressed using standard DEFLATE from zlib.
if (compressed)
{
AssbinChunkWriter uncompressedStream( NULL, 0 );
WriteBinaryScene( &uncompressedStream, pScene );
uLongf uncompressedSize = uncompressedStream.Tell();
uLongf compressedSize = (uLongf)(uncompressedStream.Tell() * 1.001 + 12.);
uint8_t* compressedBuffer = new uint8_t[ compressedSize ];
compress2( compressedBuffer, &compressedSize, (const Bytef*)uncompressedStream.GetBufferPointer(), uncompressedSize, 9 );
out->Write( &uncompressedSize, sizeof(uint32_t), 1 );
out->Write( compressedBuffer, sizeof(char), compressedSize );
delete[] compressedBuffer;
}
else
{
WriteBinaryScene( out, pScene );
}
pIOSystem->Close( out );
}
};
void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
{
AssbinExport exporter;
exporter.WriteBinaryDump( pFile, pIOSystem, pScene );
}
} // end of namespace Assimp
#endif // ASSIMP_BUILD_NO_ASSBIN_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT

View File

@ -0,0 +1,49 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file AssbinExporter.h
* ASSBIN Exporter Main Header
*/
#ifndef AI_ASSBINEXPORTER_H_INC
#define AI_ASSBINEXPORTER_H_INC
// nothing really needed here - reserved for future use like properties
#endif

View File

@ -0,0 +1,672 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the following
conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
/** @file AssbinLoader.cpp
* @brief Implementation of the .assbin importer class
*
* see assbin_chunks.h
*/
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
// internal headers
#include "AssbinLoader.h"
#include "assbin_chunks.h"
#include "MemoryIOWrapper.h"
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h>
#else
# include "../contrib/zlib/zlib.h"
#endif
using namespace Assimp;
static const aiImporterDesc desc = {
".assbin Importer",
"Gargaj / Conspiracy",
"",
"",
aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour,
0,
0,
0,
0,
"assbin"
};
const aiImporterDesc* AssbinImporter::GetInfo() const
{
return &desc;
}
bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/ ) const
{
IOStream * in = pIOHandler->Open(pFile);
if (!in)
return false;
char s[32];
in->Read( s, sizeof(char), 32 );
pIOHandler->Close(in);
return strncmp( s, "ASSIMP.binary-dump.", 19 ) == 0;
}
template <typename T>
T Read(IOStream * stream)
{
T t;
stream->Read( &t, sizeof(T), 1 );
return t;
}
template <>
aiVector3D Read<aiVector3D>(IOStream * stream)
{
aiVector3D v;
v.x = Read<float>(stream);
v.y = Read<float>(stream);
v.z = Read<float>(stream);
return v;
}
template <>
aiColor4D Read<aiColor4D>(IOStream * stream)
{
aiColor4D c;
c.r = Read<float>(stream);
c.g = Read<float>(stream);
c.b = Read<float>(stream);
c.a = Read<float>(stream);
return c;
}
template <>
aiQuaternion Read<aiQuaternion>(IOStream * stream)
{
aiQuaternion v;
v.w = Read<float>(stream);
v.x = Read<float>(stream);
v.y = Read<float>(stream);
v.z = Read<float>(stream);
return v;
}
template <>
aiString Read<aiString>(IOStream * stream)
{
aiString s;
stream->Read(&s.length,4,1);
stream->Read(s.data,s.length,1);
s.data[s.length] = 0;
return s;
}
template <>
aiVertexWeight Read<aiVertexWeight>(IOStream * stream)
{
aiVertexWeight w;
w.mVertexId = Read<unsigned int>(stream);
w.mWeight = Read<float>(stream);
return w;
}
template <>
aiMatrix4x4 Read<aiMatrix4x4>(IOStream * stream)
{
aiMatrix4x4 m;
for (unsigned int i = 0; i < 4;++i) {
for (unsigned int i2 = 0; i2 < 4;++i2) {
m[i][i2] = Read<float>(stream);
}
}
return m;
}
template <>
aiVectorKey Read<aiVectorKey>(IOStream * stream)
{
aiVectorKey v;
v.mTime = Read<double>(stream);
v.mValue = Read<aiVector3D>(stream);
return v;
}
template <>
aiQuatKey Read<aiQuatKey>(IOStream * stream)
{
aiQuatKey v;
v.mTime = Read<double>(stream);
v.mValue = Read<aiQuaternion>(stream);
return v;
}
template <typename T>
void ReadArray(IOStream * stream, T * out, unsigned int size)
{
for (unsigned int i=0; i<size; i++) out[i] = Read<T>(stream);
}
template <typename T> void ReadBounds( IOStream * stream, T* /*p*/, unsigned int n )
{
// not sure what to do here, the data isn't really useful.
stream->Seek( sizeof(T) * n, aiOrigin_CUR );
}
void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node )
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AINODE);
/*uint32_t size =*/ Read<uint32_t>(stream);
*node = new aiNode();
(*node)->mName = Read<aiString>(stream);
(*node)->mTransformation = Read<aiMatrix4x4>(stream);
(*node)->mNumChildren = Read<unsigned int>(stream);
(*node)->mNumMeshes = Read<unsigned int>(stream);
if ((*node)->mNumMeshes)
{
(*node)->mMeshes = new unsigned int[(*node)->mNumMeshes];
for (unsigned int i = 0; i < (*node)->mNumMeshes; ++i) {
(*node)->mMeshes[i] = Read<unsigned int>(stream);
}
}
if ((*node)->mNumChildren)
{
(*node)->mChildren = new aiNode*[(*node)->mNumChildren];
for (unsigned int i = 0; i < (*node)->mNumChildren; ++i) {
ReadBinaryNode( stream, &(*node)->mChildren[i] );
}
}
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b )
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIBONE );
/*uint32_t size =*/ Read<uint32_t>(stream);
b->mName = Read<aiString>(stream);
b->mNumWeights = Read<unsigned int>(stream);
b->mOffsetMatrix = Read<aiMatrix4x4>(stream);
// for the moment we write dumb min/max values for the bones, too.
// maybe I'll add a better, hash-like solution later
if (shortened)
{
ReadBounds(stream,b->mWeights,b->mNumWeights);
} // else write as usual
else
{
b->mWeights = new aiVertexWeight[b->mNumWeights];
ReadArray<aiVertexWeight>(stream,b->mWeights,b->mNumWeights);
}
}
void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh )
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIMESH);
/*uint32_t size =*/ Read<uint32_t>(stream);
mesh->mPrimitiveTypes = Read<unsigned int>(stream);
mesh->mNumVertices = Read<unsigned int>(stream);
mesh->mNumFaces = Read<unsigned int>(stream);
mesh->mNumBones = Read<unsigned int>(stream);
mesh->mMaterialIndex = Read<unsigned int>(stream);
// first of all, write bits for all existent vertex components
unsigned int c = Read<unsigned int>(stream);
if (c & ASSBIN_MESH_HAS_POSITIONS)
{
if (shortened) {
ReadBounds(stream,mesh->mVertices,mesh->mNumVertices);
} // else write as usual
else
{
mesh->mVertices = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mVertices,mesh->mNumVertices);
}
}
if (c & ASSBIN_MESH_HAS_NORMALS)
{
if (shortened) {
ReadBounds(stream,mesh->mNormals,mesh->mNumVertices);
} // else write as usual
else
{
mesh->mNormals = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mNormals,mesh->mNumVertices);
}
}
if (c & ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS)
{
if (shortened) {
ReadBounds(stream,mesh->mTangents,mesh->mNumVertices);
ReadBounds(stream,mesh->mBitangents,mesh->mNumVertices);
} // else write as usual
else
{
mesh->mTangents = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mTangents,mesh->mNumVertices);
mesh->mBitangents = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mBitangents,mesh->mNumVertices);
}
}
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n)
{
if (!(c & ASSBIN_MESH_HAS_COLOR(n)))
break;
if (shortened)
{
ReadBounds(stream,mesh->mColors[n],mesh->mNumVertices);
} // else write as usual
else
{
mesh->mColors[n] = new aiColor4D[mesh->mNumVertices];
ReadArray<aiColor4D>(stream,mesh->mColors[n],mesh->mNumVertices);
}
}
for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n)
{
if (!(c & ASSBIN_MESH_HAS_TEXCOORD(n)))
break;
// write number of UV components
mesh->mNumUVComponents[n] = Read<unsigned int>(stream);
if (shortened) {
ReadBounds(stream,mesh->mTextureCoords[n],mesh->mNumVertices);
} // else write as usual
else
{
mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices];
ReadArray<aiVector3D>(stream,mesh->mTextureCoords[n],mesh->mNumVertices);
}
}
// write faces. There are no floating-point calculations involved
// in these, so we can write a simple hash over the face data
// to the dump file. We generate a single 32 Bit hash for 512 faces
// using Assimp's standard hashing function.
if (shortened) {
Read<unsigned int>(stream);
}
else // else write as usual
{
// if there are less than 2^16 vertices, we can simply use 16 bit integers ...
mesh->mFaces = new aiFace[mesh->mNumFaces];
for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
aiFace& f = mesh->mFaces[i];
BOOST_STATIC_ASSERT(AI_MAX_FACE_INDICES <= 0xffff);
f.mNumIndices = Read<uint16_t>(stream);
f.mIndices = new unsigned int[f.mNumIndices];
for (unsigned int a = 0; a < f.mNumIndices;++a) {
if (mesh->mNumVertices < (1u<<16))
{
f.mIndices[a] = Read<uint16_t>(stream);
}
else
{
f.mIndices[a] = Read<unsigned int>(stream);
}
}
}
}
// write bones
if (mesh->mNumBones) {
mesh->mBones = new C_STRUCT aiBone*[mesh->mNumBones];
for (unsigned int a = 0; a < mesh->mNumBones;++a) {
mesh->mBones[a] = new aiBone();
ReadBinaryBone(stream,mesh->mBones[a]);
}
}
}
void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop)
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIMATERIALPROPERTY);
/*uint32_t size =*/ Read<uint32_t>(stream);
prop->mKey = Read<aiString>(stream);
prop->mSemantic = Read<unsigned int>(stream);
prop->mIndex = Read<unsigned int>(stream);
prop->mDataLength = Read<unsigned int>(stream);
prop->mType = (aiPropertyTypeInfo)Read<unsigned int>(stream);
prop->mData = new char [ prop->mDataLength ];
stream->Read(prop->mData,1,prop->mDataLength);
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat)
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIMATERIAL);
/*uint32_t size =*/ Read<uint32_t>(stream);
mat->mNumAllocated = mat->mNumProperties = Read<unsigned int>(stream);
if (mat->mNumProperties)
{
if (mat->mProperties)
{
delete[] mat->mProperties;
}
mat->mProperties = new aiMaterialProperty*[mat->mNumProperties];
for (unsigned int i = 0; i < mat->mNumProperties;++i) {
mat->mProperties[i] = new aiMaterialProperty();
ReadBinaryMaterialProperty( stream, mat->mProperties[i]);
}
}
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd)
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AINODEANIM);
/*uint32_t size =*/ Read<uint32_t>(stream);
nd->mNodeName = Read<aiString>(stream);
nd->mNumPositionKeys = Read<unsigned int>(stream);
nd->mNumRotationKeys = Read<unsigned int>(stream);
nd->mNumScalingKeys = Read<unsigned int>(stream);
nd->mPreState = (aiAnimBehaviour)Read<unsigned int>(stream);
nd->mPostState = (aiAnimBehaviour)Read<unsigned int>(stream);
if (nd->mNumPositionKeys) {
if (shortened) {
ReadBounds(stream,nd->mPositionKeys,nd->mNumPositionKeys);
} // else write as usual
else {
nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
ReadArray<aiVectorKey>(stream,nd->mPositionKeys,nd->mNumPositionKeys);
}
}
if (nd->mNumRotationKeys) {
if (shortened) {
ReadBounds(stream,nd->mRotationKeys,nd->mNumRotationKeys);
} // else write as usual
else
{
nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys];
ReadArray<aiQuatKey>(stream,nd->mRotationKeys,nd->mNumRotationKeys);
}
}
if (nd->mNumScalingKeys) {
if (shortened) {
ReadBounds(stream,nd->mScalingKeys,nd->mNumScalingKeys);
} // else write as usual
else
{
nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys];
ReadArray<aiVectorKey>(stream,nd->mScalingKeys,nd->mNumScalingKeys);
}
}
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim )
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIANIMATION);
/*uint32_t size =*/ Read<uint32_t>(stream);
anim->mName = Read<aiString> (stream);
anim->mDuration = Read<double> (stream);
anim->mTicksPerSecond = Read<double> (stream);
anim->mNumChannels = Read<unsigned int>(stream);
if (anim->mNumChannels)
{
anim->mChannels = new aiNodeAnim*[ anim->mNumChannels ];
for (unsigned int a = 0; a < anim->mNumChannels;++a) {
anim->mChannels[a] = new aiNodeAnim();
ReadBinaryNodeAnim(stream,anim->mChannels[a]);
}
}
}
void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex)
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AITEXTURE);
/*uint32_t size =*/ Read<uint32_t>(stream);
tex->mWidth = Read<unsigned int>(stream);
tex->mHeight = Read<unsigned int>(stream);
stream->Read( tex->achFormatHint, sizeof(char), 4 );
if(!shortened) {
if (!tex->mHeight) {
tex->pcData = new aiTexel[ tex->mWidth ];
stream->Read(tex->pcData,1,tex->mWidth);
}
else {
tex->pcData = new aiTexel[ tex->mWidth*tex->mHeight ];
stream->Read(tex->pcData,1,tex->mWidth*tex->mHeight*4);
}
}
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l )
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AILIGHT);
/*uint32_t size =*/ Read<uint32_t>(stream);
l->mName = Read<aiString>(stream);
l->mType = (aiLightSourceType)Read<unsigned int>(stream);
if (l->mType != aiLightSource_DIRECTIONAL) {
l->mAttenuationConstant = Read<float>(stream);
l->mAttenuationLinear = Read<float>(stream);
l->mAttenuationQuadratic = Read<float>(stream);
}
l->mColorDiffuse = Read<aiColor3D>(stream);
l->mColorSpecular = Read<aiColor3D>(stream);
l->mColorAmbient = Read<aiColor3D>(stream);
if (l->mType == aiLightSource_SPOT) {
l->mAngleInnerCone = Read<float>(stream);
l->mAngleOuterCone = Read<float>(stream);
}
}
// -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam )
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AICAMERA);
/*uint32_t size =*/ Read<uint32_t>(stream);
cam->mName = Read<aiString>(stream);
cam->mPosition = Read<aiVector3D>(stream);
cam->mLookAt = Read<aiVector3D>(stream);
cam->mUp = Read<aiVector3D>(stream);
cam->mHorizontalFOV = Read<float>(stream);
cam->mClipPlaneNear = Read<float>(stream);
cam->mClipPlaneFar = Read<float>(stream);
cam->mAspect = Read<float>(stream);
}
void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
{
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AISCENE);
/*uint32_t size =*/ Read<uint32_t>(stream);
scene->mFlags = Read<unsigned int>(stream);
scene->mNumMeshes = Read<unsigned int>(stream);
scene->mNumMaterials = Read<unsigned int>(stream);
scene->mNumAnimations = Read<unsigned int>(stream);
scene->mNumTextures = Read<unsigned int>(stream);
scene->mNumLights = Read<unsigned int>(stream);
scene->mNumCameras = Read<unsigned int>(stream);
// Read node graph
scene->mRootNode = new aiNode[1];
ReadBinaryNode( stream, &scene->mRootNode );
// Read all meshes
if (scene->mNumMeshes)
{
scene->mMeshes = new aiMesh*[scene->mNumMeshes];
for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
scene->mMeshes[i] = new aiMesh();
ReadBinaryMesh( stream,scene->mMeshes[i]);
}
}
// Read materials
if (scene->mNumMaterials)
{
scene->mMaterials = new aiMaterial*[scene->mNumMaterials];
for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
scene->mMaterials[i] = new aiMaterial();
ReadBinaryMaterial(stream,scene->mMaterials[i]);
}
}
// Read all animations
if (scene->mNumAnimations)
{
scene->mAnimations = new aiAnimation*[scene->mNumAnimations];
for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
scene->mAnimations[i] = new aiAnimation();
ReadBinaryAnim(stream,scene->mAnimations[i]);
}
}
// Read all textures
if (scene->mNumTextures)
{
scene->mTextures = new aiTexture*[scene->mNumTextures];
for (unsigned int i = 0; i < scene->mNumTextures;++i) {
scene->mTextures[i] = new aiTexture();
ReadBinaryTexture(stream,scene->mTextures[i]);
}
}
// Read lights
if (scene->mNumLights)
{
scene->mLights = new aiLight*[scene->mNumLights];
for (unsigned int i = 0; i < scene->mNumLights;++i) {
scene->mLights[i] = new aiLight();
ReadBinaryLight(stream,scene->mLights[i]);
}
}
// Read cameras
if (scene->mNumCameras)
{
scene->mCameras = new aiCamera*[scene->mNumCameras];
for (unsigned int i = 0; i < scene->mNumCameras;++i) {
scene->mCameras[i] = new aiCamera();
ReadBinaryCamera(stream,scene->mCameras[i]);
}
}
}
void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler )
{
IOStream * stream = pIOHandler->Open(pFile,"rb");
if (!stream)
return;
stream->Seek( 44, aiOrigin_CUR ); // signature
/*unsigned int versionMajor =*/ Read<unsigned int>(stream);
/*unsigned int versionMinor =*/ Read<unsigned int>(stream);
/*unsigned int versionRevision =*/ Read<unsigned int>(stream);
/*unsigned int compileFlags =*/ Read<unsigned int>(stream);
shortened = Read<uint16_t>(stream) > 0;
compressed = Read<uint16_t>(stream) > 0;
if (shortened)
throw DeadlyImportError( "Shortened binaries are not supported!" );
stream->Seek( 256, aiOrigin_CUR ); // original filename
stream->Seek( 128, aiOrigin_CUR ); // options
stream->Seek( 64, aiOrigin_CUR ); // padding
if (compressed)
{
uLongf uncompressedSize = Read<uint32_t>(stream);
uLongf compressedSize = stream->FileSize() - stream->Tell();
unsigned char * compressedData = new unsigned char[ compressedSize ];
stream->Read( compressedData, 1, compressedSize );
unsigned char * uncompressedData = new unsigned char[ uncompressedSize ];
uncompress( uncompressedData, &uncompressedSize, compressedData, compressedSize );
MemoryIOStream io( uncompressedData, uncompressedSize );
ReadBinaryScene(&io,pScene);
delete[] uncompressedData;
delete[] compressedData;
}
else
{
ReadBinaryScene(stream,pScene);
}
pIOHandler->Close(stream);
}
#endif // !! ASSIMP_BUILD_NO_ASSBIN_IMPORTER

View File

@ -0,0 +1,94 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file AssbinLoader.h
* @brief .assbin File format loader
*/
#ifndef AI_ASSBINIMPORTER_H_INC
#define AI_ASSBINIMPORTER_H_INC
#include "BaseImporter.h"
#include "../include/assimp/types.h"
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
namespace Assimp {
// ---------------------------------------------------------------------------------
/** Importer class for 3D Studio r3 and r4 3DS files
*/
class AssbinImporter : public BaseImporter
{
private:
bool shortened;
bool compressed;
protected:
public:
virtual bool CanRead(
const std::string& pFile,
IOSystem* pIOHandler,
bool checkSig
) const;
virtual const aiImporterDesc* GetInfo() const;
virtual void InternReadFile(
const std::string& pFile,
aiScene* pScene,
IOSystem* pIOHandler
);
void ReadBinaryScene( IOStream * stream, aiScene* pScene );
void ReadBinaryNode( IOStream * stream, aiNode** mRootNode );
void ReadBinaryMesh( IOStream * stream, aiMesh* mesh );
void ReadBinaryBone( IOStream * stream, aiBone* bone );
void ReadBinaryMaterial(IOStream * stream, aiMaterial* mat);
void ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop);
void ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd);
void ReadBinaryAnim( IOStream * stream, aiAnimation* anim );
void ReadBinaryTexture(IOStream * stream, aiTexture* tex);
void ReadBinaryLight( IOStream * stream, aiLight* l );
void ReadBinaryCamera( IOStream * stream, aiCamera* cam );
};
} // end of namespace Assimp
#endif // !! ASSIMP_BUILD_NO_ASSBIN_IMPORTER
#endif // AI_ASSBINIMPORTER_H_INC

View File

@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "GenericProperty.h" #include "GenericProperty.h"
#include "CInterfaceIOWrapper.h" #include "CInterfaceIOWrapper.h"
#include "../include/assimp/importerdesc.h"
#include "Importer.h" #include "Importer.h"
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -84,7 +85,11 @@ namespace Assimp
/** Verbose logging active or not? */ /** Verbose logging active or not? */
static aiBool gVerboseLogging = false; static aiBool gVerboseLogging = false;
}
/** will return all registered importers. */
void GetImporterInstanceList(std::vector< BaseImporter* >& out);
} // namespace assimp
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
@ -606,4 +611,22 @@ ASSIMP_API void aiIdentityMatrix4(
*mat = aiMatrix4x4(); *mat = aiMatrix4x4();
} }
// ------------------------------------------------------------------------------------------------
ASSIMP_API C_STRUCT const aiImporterDesc* aiGetImporterDesc( const char *extension ) {
if( NULL == extension ) {
return NULL;
}
const aiImporterDesc *desc( NULL );
std::vector< BaseImporter* > out;
GetImporterInstanceList( out );
for( size_t i = 0; i < out.size(); ++i ) {
if( 0 == strncmp( out[ i ]->GetInfo()->mFileExtensions, extension, strlen( extension ) ) ) {
desc = out[ i ]->GetInfo();
break;
}
}
return desc;
}
// ------------------------------------------------------------------------------------------------

View File

@ -61,6 +61,8 @@ ASSIMP_API size_t aiGetExportFormatCount(void)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
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,
// for which the returned structure is guaranteed to be of static storage duration.
return Exporter().GetExportFormatDescription(pIndex); return Exporter().GetExportFormatDescription(pIndex);
} }

View File

@ -0,0 +1,638 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file AssxmlExporter.cpp
* ASSXML exporter main code
*/
#include <stdarg.h>
#include "AssimpPCH.h"
#include "./../include/assimp/version.h"
#include "ProcessHelper.h"
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h>
#else
# include "../contrib/zlib/zlib.h"
#endif
#include <time.h>
#ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
using namespace Assimp;
namespace Assimp {
namespace AssxmlExport {
int ioprintf( IOStream * io, const char * format, ... )
{
char sz[4096];
va_list va;
va_start( va, format );
int nSize = vsnprintf( sz, 4096, format, va );
ai_assert( nSize < 4096 );
va_end( va );
io->Write( sz, sizeof(char), nSize );
return nSize;
}
// -----------------------------------------------------------------------------------
// Convert a name to standard XML format
void ConvertName(aiString& out, const aiString& in)
{
out.length = 0;
for (unsigned int i = 0; i < in.length; ++i) {
switch (in.data[i]) {
case '<':
out.Append("&lt;");break;
case '>':
out.Append("&gt;");break;
case '&':
out.Append("&amp;");break;
case '\"':
out.Append("&quot;");break;
case '\'':
out.Append("&apos;");break;
default:
out.data[out.length++] = in.data[i];
}
}
out.data[out.length] = 0;
}
// -----------------------------------------------------------------------------------
// Write a single node as text dump
void WriteNode(const aiNode* node, IOStream * io, unsigned int depth)
{
char prefix[512];
for (unsigned int i = 0; i < depth;++i)
prefix[i] = '\t';
prefix[depth] = '\0';
const aiMatrix4x4& m = node->mTransformation;
aiString name;
ConvertName(name,node->mName);
ioprintf(io,"%s<Node name=\"%s\"> \n"
"%s\t<Matrix4> \n"
"%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
"%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
"%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
"%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
"%s\t</Matrix4> \n",
prefix,name.data,prefix,
prefix,m.a1,m.a2,m.a3,m.a4,
prefix,m.b1,m.b2,m.b3,m.b4,
prefix,m.c1,m.c2,m.c3,m.c4,
prefix,m.d1,m.d2,m.d3,m.d4,prefix);
if (node->mNumMeshes) {
ioprintf(io, "%s\t<MeshRefs num=\"%i\">\n%s\t",
prefix,node->mNumMeshes,prefix);
for (unsigned int i = 0; i < node->mNumMeshes;++i) {
ioprintf(io,"%i ",node->mMeshes[i]);
}
ioprintf(io,"\n%s\t</MeshRefs>\n",prefix);
}
if (node->mNumChildren) {
ioprintf(io,"%s\t<NodeList num=\"%i\">\n",
prefix,node->mNumChildren);
for (unsigned int i = 0; i < node->mNumChildren;++i) {
WriteNode(node->mChildren[i],io,depth+2);
}
ioprintf(io,"%s\t</NodeList>\n",prefix);
}
ioprintf(io,"%s</Node>\n",prefix);
}
// -----------------------------------------------------------------------------------
// Some chuncks of text will need to be encoded for XML
// http://stackoverflow.com/questions/5665231/most-efficient-way-to-escape-xml-html-in-c-string#5665377
static std::string encodeXML(const std::string& data) {
std::string buffer;
buffer.reserve(data.size());
for(size_t pos = 0; pos != data.size(); ++pos) {
switch(data[pos]) {
case '&': buffer.append("&amp;"); break;
case '\"': buffer.append("&quot;"); break;
case '\'': buffer.append("&apos;"); break;
case '<': buffer.append("&lt;"); break;
case '>': buffer.append("&gt;"); break;
default: buffer.append(&data[pos], 1); break;
}
}
return buffer;
}
// -----------------------------------------------------------------------------------
// Write a text model dump
void WriteDump(const aiScene* scene, IOStream* io, bool shortened)
{
time_t tt = ::time(NULL);
tm* p = ::gmtime(&tt);
aiString name;
// write header
ioprintf(io,
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<ASSIMP format_id=\"1\">\n\n"
"<!-- XML Model dump produced by assimp dump\n"
" Library version: %i.%i.%i\n"
" %s\n"
"-->"
" \n\n"
"<Scene flags=\"%i\" postprocessing=\"%i\">\n",
aiGetVersionMajor(),aiGetVersionMinor(),aiGetVersionRevision(),asctime(p),
scene->mFlags,
0 /*globalImporter->GetEffectivePostProcessing()*/);
// write the node graph
WriteNode(scene->mRootNode, io, 0);
#if 0
// write cameras
for (unsigned int i = 0; i < scene->mNumCameras;++i) {
aiCamera* cam = scene->mCameras[i];
ConvertName(name,cam->mName);
// camera header
ioprintf(io,"\t<Camera parent=\"%s\">\n"
"\t\t<Vector3 name=\"up\" > %0 8f %0 8f %0 8f </Vector3>\n"
"\t\t<Vector3 name=\"lookat\" > %0 8f %0 8f %0 8f </Vector3>\n"
"\t\t<Vector3 name=\"pos\" > %0 8f %0 8f %0 8f </Vector3>\n"
"\t\t<Float name=\"fov\" > %f </Float>\n"
"\t\t<Float name=\"aspect\" > %f </Float>\n"
"\t\t<Float name=\"near_clip\" > %f </Float>\n"
"\t\t<Float name=\"far_clip\" > %f </Float>\n"
"\t</Camera>\n",
name.data,
cam->mUp.x,cam->mUp.y,cam->mUp.z,
cam->mLookAt.x,cam->mLookAt.y,cam->mLookAt.z,
cam->mPosition.x,cam->mPosition.y,cam->mPosition.z,
cam->mHorizontalFOV,cam->mAspect,cam->mClipPlaneNear,cam->mClipPlaneFar,i);
}
// write lights
for (unsigned int i = 0; i < scene->mNumLights;++i) {
aiLight* l = scene->mLights[i];
ConvertName(name,l->mName);
// light header
ioprintf(io,"\t<Light parent=\"%s\"> type=\"%s\"\n"
"\t\t<Vector3 name=\"diffuse\" > %0 8f %0 8f %0 8f </Vector3>\n"
"\t\t<Vector3 name=\"specular\" > %0 8f %0 8f %0 8f </Vector3>\n"
"\t\t<Vector3 name=\"ambient\" > %0 8f %0 8f %0 8f </Vector3>\n",
name.data,
(l->mType == aiLightSource_DIRECTIONAL ? "directional" :
(l->mType == aiLightSource_POINT ? "point" : "spot" )),
l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b,
l->mColorSpecular.r,l->mColorSpecular.g,l->mColorSpecular.b,
l->mColorAmbient.r, l->mColorAmbient.g, l->mColorAmbient.b);
if (l->mType != aiLightSource_DIRECTIONAL) {
ioprintf(io,
"\t\t<Vector3 name=\"pos\" > %0 8f %0 8f %0 8f </Vector3>\n"
"\t\t<Float name=\"atten_cst\" > %f </Float>\n"
"\t\t<Float name=\"atten_lin\" > %f </Float>\n"
"\t\t<Float name=\"atten_sqr\" > %f </Float>\n",
l->mPosition.x,l->mPosition.y,l->mPosition.z,
l->mAttenuationConstant,l->mAttenuationLinear,l->mAttenuationQuadratic);
}
if (l->mType != aiLightSource_POINT) {
ioprintf(io,
"\t\t<Vector3 name=\"lookat\" > %0 8f %0 8f %0 8f </Vector3>\n",
l->mDirection.x,l->mDirection.y,l->mDirection.z);
}
if (l->mType == aiLightSource_SPOT) {
ioprintf(io,
"\t\t<Float name=\"cone_out\" > %f </Float>\n"
"\t\t<Float name=\"cone_inn\" > %f </Float>\n",
l->mAngleOuterCone,l->mAngleInnerCone);
}
ioprintf(io,"\t</Light>\n");
}
#endif
// write textures
if (scene->mNumTextures) {
ioprintf(io,"<TextureList num=\"%i\">\n",scene->mNumTextures);
for (unsigned int i = 0; i < scene->mNumTextures;++i) {
aiTexture* tex = scene->mTextures[i];
bool compressed = (tex->mHeight == 0);
// mesh header
ioprintf(io,"\t<Texture width=\"%i\" height=\"%i\" compressed=\"%s\"> \n",
(compressed ? -1 : tex->mWidth),(compressed ? -1 : tex->mHeight),
(compressed ? "true" : "false"));
if (compressed) {
ioprintf(io,"\t\t<Data length=\"%i\"> \n",tex->mWidth);
if (!shortened) {
for (unsigned int n = 0; n < tex->mWidth;++n) {
ioprintf(io,"\t\t\t%2x",reinterpret_cast<uint8_t*>(tex->pcData)[n]);
if (n && !(n % 50)) {
ioprintf(io,"\n");
}
}
}
}
else if (!shortened){
ioprintf(io,"\t\t<Data length=\"%i\"> \n",tex->mWidth*tex->mHeight*4);
// const unsigned int width = (unsigned int)log10((double)std::max(tex->mHeight,tex->mWidth))+1;
for (unsigned int y = 0; y < tex->mHeight;++y) {
for (unsigned int x = 0; x < tex->mWidth;++x) {
aiTexel* tx = tex->pcData + y*tex->mWidth+x;
unsigned int r = tx->r,g=tx->g,b=tx->b,a=tx->a;
ioprintf(io,"\t\t\t%2x %2x %2x %2x",r,g,b,a);
// group by four for readibility
if (0 == (x+y*tex->mWidth) % 4)
ioprintf(io,"\n");
}
}
}
ioprintf(io,"\t\t</Data>\n\t</Texture>\n");
}
ioprintf(io,"</TextureList>\n");
}
// write materials
if (scene->mNumMaterials) {
ioprintf(io,"<MaterialList num=\"%i\">\n",scene->mNumMaterials);
for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
const aiMaterial* mat = scene->mMaterials[i];
ioprintf(io,"\t<Material>\n");
ioprintf(io,"\t\t<MatPropertyList num=\"%i\">\n",mat->mNumProperties);
for (unsigned int n = 0; n < mat->mNumProperties;++n) {
const aiMaterialProperty* prop = mat->mProperties[n];
const char* sz = "";
if (prop->mType == aiPTI_Float) {
sz = "float";
}
else if (prop->mType == aiPTI_Integer) {
sz = "integer";
}
else if (prop->mType == aiPTI_String) {
sz = "string";
}
else if (prop->mType == aiPTI_Buffer) {
sz = "binary_buffer";
}
ioprintf(io,"\t\t\t<MatProperty key=\"%s\" \n\t\t\ttype=\"%s\" tex_usage=\"%s\" tex_index=\"%i\"",
prop->mKey.data, sz,
::TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex);
if (prop->mType == aiPTI_Float) {
ioprintf(io," size=\"%i\">\n\t\t\t\t",
static_cast<int>(prop->mDataLength/sizeof(float)));
for (unsigned int p = 0; p < prop->mDataLength/sizeof(float);++p) {
ioprintf(io,"%f ",*((float*)(prop->mData+p*sizeof(float))));
}
}
else if (prop->mType == aiPTI_Integer) {
ioprintf(io," size=\"%i\">\n\t\t\t\t",
static_cast<int>(prop->mDataLength/sizeof(int)));
for (unsigned int p = 0; p < prop->mDataLength/sizeof(int);++p) {
ioprintf(io,"%i ",*((int*)(prop->mData+p*sizeof(int))));
}
}
else if (prop->mType == aiPTI_Buffer) {
ioprintf(io," size=\"%i\">\n\t\t\t\t",
static_cast<int>(prop->mDataLength));
for (unsigned int p = 0; p < prop->mDataLength;++p) {
ioprintf(io,"%2x ",prop->mData[p]);
if (p && 0 == p%30) {
ioprintf(io,"\n\t\t\t\t");
}
}
}
else if (prop->mType == aiPTI_String) {
ioprintf(io,">\n\t\t\t\t\"%s\"",encodeXML(prop->mData+4).c_str() /* skip length */);
}
ioprintf(io,"\n\t\t\t</MatProperty>\n");
}
ioprintf(io,"\t\t</MatPropertyList>\n");
ioprintf(io,"\t</Material>\n");
}
ioprintf(io,"</MaterialList>\n");
}
// write animations
if (scene->mNumAnimations) {
ioprintf(io,"<AnimationList num=\"%i\">\n",scene->mNumAnimations);
for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
aiAnimation* anim = scene->mAnimations[i];
// anim header
ConvertName(name,anim->mName);
ioprintf(io,"\t<Animation name=\"%s\" duration=\"%e\" tick_cnt=\"%e\">\n",
name.data, anim->mDuration, anim->mTicksPerSecond);
// write bone animation channels
if (anim->mNumChannels) {
ioprintf(io,"\t\t<NodeAnimList num=\"%i\">\n",anim->mNumChannels);
for (unsigned int n = 0; n < anim->mNumChannels;++n) {
aiNodeAnim* nd = anim->mChannels[n];
// node anim header
ConvertName(name,nd->mNodeName);
ioprintf(io,"\t\t\t<NodeAnim node=\"%s\">\n",name.data);
if (!shortened) {
// write position keys
if (nd->mNumPositionKeys) {
ioprintf(io,"\t\t\t\t<PositionKeyList num=\"%i\">\n",nd->mNumPositionKeys);
for (unsigned int a = 0; a < nd->mNumPositionKeys;++a) {
aiVectorKey* vc = nd->mPositionKeys+a;
ioprintf(io,"\t\t\t\t\t<PositionKey time=\"%e\">\n"
"\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t</PositionKey>\n",
vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z);
}
ioprintf(io,"\t\t\t\t</PositionKeyList>\n");
}
// write scaling keys
if (nd->mNumScalingKeys) {
ioprintf(io,"\t\t\t\t<ScalingKeyList num=\"%i\">\n",nd->mNumScalingKeys);
for (unsigned int a = 0; a < nd->mNumScalingKeys;++a) {
aiVectorKey* vc = nd->mScalingKeys+a;
ioprintf(io,"\t\t\t\t\t<ScalingKey time=\"%e\">\n"
"\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t</ScalingKey>\n",
vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z);
}
ioprintf(io,"\t\t\t\t</ScalingKeyList>\n");
}
// write rotation keys
if (nd->mNumRotationKeys) {
ioprintf(io,"\t\t\t\t<RotationKeyList num=\"%i\">\n",nd->mNumRotationKeys);
for (unsigned int a = 0; a < nd->mNumRotationKeys;++a) {
aiQuatKey* vc = nd->mRotationKeys+a;
ioprintf(io,"\t\t\t\t\t<RotationKey time=\"%e\">\n"
"\t\t\t\t\t\t%0 8f %0 8f %0 8f %0 8f\n\t\t\t\t\t</RotationKey>\n",
vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z,vc->mValue.w);
}
ioprintf(io,"\t\t\t\t</RotationKeyList>\n");
}
}
ioprintf(io,"\t\t\t</NodeAnim>\n");
}
ioprintf(io,"\t\t</NodeAnimList>\n");
}
ioprintf(io,"\t</Animation>\n");
}
ioprintf(io,"</AnimationList>\n");
}
// write meshes
if (scene->mNumMeshes) {
ioprintf(io,"<MeshList num=\"%i\">\n",scene->mNumMeshes);
for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
aiMesh* mesh = scene->mMeshes[i];
// const unsigned int width = (unsigned int)log10((double)mesh->mNumVertices)+1;
// mesh header
ioprintf(io,"\t<Mesh types=\"%s %s %s %s\" material_index=\"%i\">\n",
(mesh->mPrimitiveTypes & aiPrimitiveType_POINT ? "points" : ""),
(mesh->mPrimitiveTypes & aiPrimitiveType_LINE ? "lines" : ""),
(mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE ? "triangles" : ""),
(mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON ? "polygons" : ""),
mesh->mMaterialIndex);
// bones
if (mesh->mNumBones) {
ioprintf(io,"\t\t<BoneList num=\"%i\">\n",mesh->mNumBones);
for (unsigned int n = 0; n < mesh->mNumBones;++n) {
aiBone* bone = mesh->mBones[n];
ConvertName(name,bone->mName);
// bone header
ioprintf(io,"\t\t\t<Bone name=\"%s\">\n"
"\t\t\t\t<Matrix4> \n"
"\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
"\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
"\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
"\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
"\t\t\t\t</Matrix4> \n",
name.data,
bone->mOffsetMatrix.a1,bone->mOffsetMatrix.a2,bone->mOffsetMatrix.a3,bone->mOffsetMatrix.a4,
bone->mOffsetMatrix.b1,bone->mOffsetMatrix.b2,bone->mOffsetMatrix.b3,bone->mOffsetMatrix.b4,
bone->mOffsetMatrix.c1,bone->mOffsetMatrix.c2,bone->mOffsetMatrix.c3,bone->mOffsetMatrix.c4,
bone->mOffsetMatrix.d1,bone->mOffsetMatrix.d2,bone->mOffsetMatrix.d3,bone->mOffsetMatrix.d4);
if (!shortened && bone->mNumWeights) {
ioprintf(io,"\t\t\t\t<WeightList num=\"%i\">\n",bone->mNumWeights);
// bone weights
for (unsigned int a = 0; a < bone->mNumWeights;++a) {
aiVertexWeight* wght = bone->mWeights+a;
ioprintf(io,"\t\t\t\t\t<Weight index=\"%i\">\n\t\t\t\t\t\t%f\n\t\t\t\t\t</Weight>\n",
wght->mVertexId,wght->mWeight);
}
ioprintf(io,"\t\t\t\t</WeightList>\n");
}
ioprintf(io,"\t\t\t</Bone>\n");
}
ioprintf(io,"\t\t</BoneList>\n");
}
// faces
if (!shortened && mesh->mNumFaces) {
ioprintf(io,"\t\t<FaceList num=\"%i\">\n",mesh->mNumFaces);
for (unsigned int n = 0; n < mesh->mNumFaces; ++n) {
aiFace& f = mesh->mFaces[n];
ioprintf(io,"\t\t\t<Face num=\"%i\">\n"
"\t\t\t\t",f.mNumIndices);
for (unsigned int j = 0; j < f.mNumIndices;++j)
ioprintf(io,"%i ",f.mIndices[j]);
ioprintf(io,"\n\t\t\t</Face>\n");
}
ioprintf(io,"\t\t</FaceList>\n");
}
// vertex positions
if (mesh->HasPositions()) {
ioprintf(io,"\t\t<Positions num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
if (!shortened) {
for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
mesh->mVertices[n].x,
mesh->mVertices[n].y,
mesh->mVertices[n].z);
}
}
ioprintf(io,"\t\t</Positions>\n");
}
// vertex normals
if (mesh->HasNormals()) {
ioprintf(io,"\t\t<Normals num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
if (!shortened) {
for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
mesh->mNormals[n].x,
mesh->mNormals[n].y,
mesh->mNormals[n].z);
}
}
else {
}
ioprintf(io,"\t\t</Normals>\n");
}
// vertex tangents and bitangents
if (mesh->HasTangentsAndBitangents()) {
ioprintf(io,"\t\t<Tangents num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
if (!shortened) {
for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
mesh->mTangents[n].x,
mesh->mTangents[n].y,
mesh->mTangents[n].z);
}
}
ioprintf(io,"\t\t</Tangents>\n");
ioprintf(io,"\t\t<Bitangents num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
if (!shortened) {
for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
mesh->mBitangents[n].x,
mesh->mBitangents[n].y,
mesh->mBitangents[n].z);
}
}
ioprintf(io,"\t\t</Bitangents>\n");
}
// texture coordinates
for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
if (!mesh->mTextureCoords[a])
break;
ioprintf(io,"\t\t<TextureCoords num=\"%i\" set=\"%i\" num_components=\"%i\"> \n",mesh->mNumVertices,
a,mesh->mNumUVComponents[a]);
if (!shortened) {
if (mesh->mNumUVComponents[a] == 3) {
for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
mesh->mTextureCoords[a][n].x,
mesh->mTextureCoords[a][n].y,
mesh->mTextureCoords[a][n].z);
}
}
else {
for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
ioprintf(io,"\t\t%0 8f %0 8f\n",
mesh->mTextureCoords[a][n].x,
mesh->mTextureCoords[a][n].y);
}
}
}
ioprintf(io,"\t\t</TextureCoords>\n");
}
// vertex colors
for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) {
if (!mesh->mColors[a])
break;
ioprintf(io,"\t\t<Colors num=\"%i\" set=\"%i\" num_components=\"4\"> \n",mesh->mNumVertices,a);
if (!shortened) {
for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
ioprintf(io,"\t\t%0 8f %0 8f %0 8f %0 8f\n",
mesh->mColors[a][n].r,
mesh->mColors[a][n].g,
mesh->mColors[a][n].b,
mesh->mColors[a][n].a);
}
}
ioprintf(io,"\t\t</Colors>\n");
}
ioprintf(io,"\t</Mesh>\n");
}
ioprintf(io,"</MeshList>\n");
}
ioprintf(io,"</Scene>\n</ASSIMP>");
}
} // end of namespace AssxmlExport
void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
{
IOStream * out = pIOSystem->Open( pFile, "wt" );
if (!out) return;
bool shortened = false;
AssxmlExport::WriteDump( pScene, out, shortened );
pIOSystem->Close( out );
}
} // end of namespace Assimp
#endif // ASSIMP_BUILD_NO_ASSXML_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT

View File

@ -0,0 +1,49 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file AssxmlExporter.h
* ASSXML Exporter Main Header
*/
#ifndef AI_ASSXMLEXPORTER_H_INC
#define AI_ASSXMLEXPORTER_H_INC
// nothing really needed here - reserved for future use like properties
#endif

View File

@ -548,7 +548,7 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
void B3DImporter::ReadBB3D( aiScene *scene ){ void B3DImporter::ReadBB3D( aiScene *scene ){
_textures.clear(); _textures.clear();
_materials.size(); _materials.clear();
_vertices.clear(); _vertices.clear();
_meshes.clear(); _meshes.clear();

View File

@ -90,6 +90,11 @@ struct ScopeGuard
} }
private: private:
// no copying allowed.
ScopeGuard();
ScopeGuard( const ScopeGuard & );
ScopeGuard &operator = ( const ScopeGuard & );
T* obj; T* obj;
bool mdismiss; bool mdismiss;
}; };

View File

@ -65,7 +65,6 @@ BlenderBMeshConverter::BlenderBMeshConverter( const Mesh* mesh ):
BMesh( mesh ), BMesh( mesh ),
triMesh( NULL ) triMesh( NULL )
{ {
AssertValidMesh( );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -143,9 +142,21 @@ void BlenderBMeshConverter::DestroyTriMesh( )
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.
if ( BMesh->mloopuv.size() )
{
if ( (poly.loopstart + poly.totloop ) > static_cast<int>( BMesh->mloopuv.size() ) )
{
ThrowException( "BMesh uv loop array has incorrect size" );
}
const MLoopUV* loopUV = &BMesh->mloopuv[ poly.loopstart ];
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 )
{ {
@ -173,4 +184,20 @@ void BlenderBMeshConverter::AddFace( int v1, int v2, int v3, int v4 )
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 )
{
MTFace mtface;
memcpy( &mtface.uv[ 0 ], uv1, sizeof(float) * 2 );
memcpy( &mtface.uv[ 1 ], uv2, sizeof(float) * 2 );
memcpy( &mtface.uv[ 2 ], uv3, sizeof(float) * 2 );
if ( uv4 )
{
memcpy( &mtface.uv[ 3 ], uv4, sizeof(float) * 2 );
}
triMesh->mtface.push_back( mtface );
}
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER #endif // ASSIMP_BUILD_NO_BLEND_IMPORTER

View File

@ -80,6 +80,7 @@ namespace Assimp
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 );
const Blender::Mesh* BMesh; const Blender::Mesh* BMesh;
Blender::Mesh* triMesh; Blender::Mesh* triMesh;

View File

@ -659,11 +659,15 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
ConversionData& conv_data, TempArray<std::vector,aiMesh>& temp ConversionData& conv_data, TempArray<std::vector,aiMesh>& temp
) )
{ {
// TODO: Resolve various problems with BMesh triangluation before re-enabling.
// See issues #400, #373, #318 #315 and #132.
#if defined(TODO_FIX_BMESH_CONVERSION)
BlenderBMeshConverter BMeshConverter( mesh ); BlenderBMeshConverter BMeshConverter( mesh );
if ( BMeshConverter.ContainsBMesh( ) ) if ( BMeshConverter.ContainsBMesh( ) )
{ {
mesh = BMeshConverter.TriangulateBMesh( ); mesh = BMeshConverter.TriangulateBMesh( );
} }
#endif
typedef std::pair<const int,size_t> MyPair; typedef std::pair<const int,size_t> MyPair;
if ((!mesh->totface && !mesh->totloop) || !mesh->totvert) { if ((!mesh->totface && !mesh->totloop) || !mesh->totvert) {
@ -999,7 +1003,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* camera, ConversionData& /*conv_data*/) aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* /*camera*/, ConversionData& /*conv_data*/)
{ {
ScopeGuard<aiCamera> out(new aiCamera()); ScopeGuard<aiCamera> out(new aiCamera());
out->mName = obj->id.name+2; out->mName = obj->id.name+2;
@ -1010,7 +1014,7 @@ aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiLight* BlenderImporter::ConvertLight(const Scene& in, const Object* obj, const Lamp* lamp, ConversionData& conv_data) aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, const Lamp* lamp, ConversionData& /*conv_data*/)
{ {
ScopeGuard<aiLight> out(new aiLight()); ScopeGuard<aiLight> out(new aiLight());
out->mName = obj->id.name+2; out->mName = obj->id.name+2;

View File

@ -324,7 +324,7 @@ void BlenderTessellatorP2T::Copy3DVertices( const MLoop* polyLoop, int vertexCou
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 ( 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 );
} }
@ -420,7 +420,7 @@ float BlenderTessellatorP2T::FindLargestMatrixElem( const aiMatrix3x3& mtx ) con
{ {
for ( int y = 0; y < 3; ++y ) for ( int y = 0; y < 3; ++y )
{ {
result = p2tMax( fabs( mtx[ x ][ y ] ), result ); result = p2tMax( std::fabs( mtx[ x ][ y ] ), result );
} }
} }

View File

@ -100,7 +100,7 @@ namespace boost {
}; };
// dummy // dummy
list_elem& operator = (const list_elem& other) { list_elem& operator = (const list_elem& /*other*/) {
return *this; return *this;
} }
@ -142,7 +142,7 @@ namespace boost {
return me.me; return me.me;
} }
}; };
}; }
// A very minimal implementation for up to 5 elements // A very minimal implementation for up to 5 elements
template <typename T0 = detail::nulltype, template <typename T0 = detail::nulltype,
@ -278,6 +278,6 @@ namespace boost {
tuple <> t; tuple <> t;
return t; return t;
} }
}; }
#endif // !! BOOST_TUPLE_INCLUDED #endif // !! BOOST_TUPLE_INCLUDED

View File

@ -111,6 +111,7 @@ SET( Common_SRCS
MemoryIOWrapper.h MemoryIOWrapper.h
ParsingUtils.h ParsingUtils.h
StreamReader.h StreamReader.h
StreamWriter.h
StringComparison.h StringComparison.h
SGSpatialSort.cpp SGSpatialSort.cpp
SGSpatialSort.h SGSpatialSort.h
@ -143,6 +144,7 @@ SET( Common_SRCS
LogAux.h LogAux.h
Bitmap.cpp Bitmap.cpp
Bitmap.h Bitmap.h
XMLTools.h
) )
SOURCE_GROUP(Common FILES ${Common_SRCS}) SOURCE_GROUP(Common FILES ${Common_SRCS})
@ -151,6 +153,8 @@ SET( 3DS_SRCS
3DSHelper.h 3DSHelper.h
3DSLoader.cpp 3DSLoader.cpp
3DSLoader.h 3DSLoader.h
3DSExporter.h
3DSExporter.cpp
) )
SOURCE_GROUP(3DS FILES ${3DS_SRCS}) SOURCE_GROUP(3DS FILES ${3DS_SRCS})
@ -168,6 +172,20 @@ SET( ASE_SRCS
) )
SOURCE_GROUP( ASE FILES ${ASE_SRCS}) SOURCE_GROUP( ASE FILES ${ASE_SRCS})
SET( ASSBIN_SRCS
AssbinExporter.h
AssbinExporter.cpp
AssbinLoader.h
AssbinLoader.cpp
)
SOURCE_GROUP( Assbin FILES ${ASSBIN_SRCS})
SET( ASSXML_SRCS
AssxmlExporter.h
AssxmlExporter.cpp
)
SOURCE_GROUP( Assxml FILES ${ASSXML_SRCS})
SET( B3D_SRCS SET( B3D_SRCS
B3DImporter.cpp B3DImporter.cpp
B3DImporter.h B3DImporter.h
@ -612,7 +630,7 @@ SOURCE_GROUP( unzip FILES ${unzip_SRCS})
# VC2010 fixes # VC2010 fixes
if(MSVC10) if(MSVC10)
OPTION( VC10_STDINT_FIX "Fix for VC10 Compiler regarding pstdint.h redefinition errors" OFF ) option( VC10_STDINT_FIX "Fix for VC10 Compiler regarding pstdint.h redefinition errors" OFF )
if( VC10_STDINT_FIX ) if( VC10_STDINT_FIX )
ADD_DEFINITIONS( -D_STDINT ) ADD_DEFINITIONS( -D_STDINT )
endif( VC10_STDINT_FIX ) endif( VC10_STDINT_FIX )
@ -643,6 +661,8 @@ SET( assimp_src
${3DS_SRCS} ${3DS_SRCS}
${AC_SRCS} ${AC_SRCS}
${ASE_SRCS} ${ASE_SRCS}
${ASSBIN_SRCS}
${ASSXML_SRCS}
${B3D_SRCS} ${B3D_SRCS}
${BVH_SRCS} ${BVH_SRCS}
${Collada_SRCS} ${Collada_SRCS}
@ -705,6 +725,13 @@ ADD_LIBRARY( assimp ${assimp_src} )
SET_PROPERTY(TARGET assimp PROPERTY DEBUG_POSTFIX ${ASSIMP_DEBUG_POSTFIX}) SET_PROPERTY(TARGET assimp PROPERTY DEBUG_POSTFIX ${ASSIMP_DEBUG_POSTFIX})
TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES}) TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES})
if(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
set(ASSIMP_ANDROID_JNIIOSYSTEM_PATH port/AndroidJNI)
add_subdirectory(../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/ ../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/)
target_link_libraries(assimp android_jniiosystem)
endif(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
SET_TARGET_PROPERTIES( assimp PROPERTIES SET_TARGET_PROPERTIES( assimp PROPERTIES
VERSION ${ASSIMP_VERSION} VERSION ${ASSIMP_VERSION}
SOVERSION ${ASSIMP_SOVERSION} # use full version SOVERSION ${ASSIMP_SOVERSION} # use full version
@ -731,6 +758,11 @@ INSTALL( TARGETS assimp
COMPONENT ${LIBASSIMP_COMPONENT}) COMPONENT ${LIBASSIMP_COMPONENT})
INSTALL( FILES ${PUBLIC_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp COMPONENT assimp-dev) INSTALL( FILES ${PUBLIC_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp COMPONENT assimp-dev)
INSTALL( FILES ${COMPILER_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp/Compiler COMPONENT assimp-dev) INSTALL( FILES ${COMPILER_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp/Compiler COMPONENT assimp-dev)
if (ASSIMP_ANDROID_JNIIOSYSTEM)
INSTALL(FILES ${HEADER_PATH}/../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/AndroidJNIIOSystem.h
DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}
COMPONENT assimp-dev)
endif(ASSIMP_ANDROID_JNIIOSYSTEM)
if(MSVC AND ASSIMP_INSTALL_PDB) if(MSVC AND ASSIMP_INSTALL_PDB)
install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${ASSIMP_DEBUG_POSTFIX}.pdb install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${ASSIMP_DEBUG_POSTFIX}.pdb

View File

@ -115,9 +115,9 @@ 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) // thisimplies 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
@ -271,7 +271,7 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
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.clear(); 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);

View File

@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Bitmap.h" #include "Bitmap.h"
#include "fast_atof.h" #include "fast_atof.h"
#include "SceneCombiner.h" #include "SceneCombiner.h"
#include "XMLTools.h"
#include <ctime> #include <ctime>
#include <set> #include <set>
@ -93,6 +94,7 @@ void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* p
} // end of namespace Assimp } // end of namespace Assimp
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor for a specific scene to export // Constructor for a specific scene to export
ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) : mIOSystem(pIOSystem), mPath(path), mFile(file) ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) : mIOSystem(pIOSystem), mPath(path), mFile(file)
@ -140,7 +142,7 @@ void ColladaExporter::WriteFile()
// useless Collada fu at the end, just in case we haven't had enough indirections, yet. // useless Collada fu at the end, just in case we haven't had enough indirections, yet.
mOutput << startstr << "<scene>" << endstr; mOutput << startstr << "<scene>" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<instance_visual_scene url=\"#" + std::string(mScene->mRootNode->mName.C_Str()) + "\" />" << endstr; mOutput << startstr << "<instance_visual_scene url=\"#" + XMLEscape(mScene->mRootNode->mName.C_Str()) + "\" />" << endstr;
PopTag(); PopTag();
mOutput << startstr << "</scene>" << endstr; mOutput << startstr << "</scene>" << endstr;
PopTag(); PopTag();
@ -236,12 +238,12 @@ void ColladaExporter::WriteHeader()
if (!meta || !meta->Get("Author", value)) if (!meta || !meta->Get("Author", value))
mOutput << startstr << "<author>" << "Assimp" << "</author>" << endstr; mOutput << startstr << "<author>" << "Assimp" << "</author>" << endstr;
else else
mOutput << startstr << "<author>" << value.C_Str() << "</author>" << endstr; mOutput << startstr << "<author>" << XMLEscape(value.C_Str()) << "</author>" << endstr;
if (!meta || !meta->Get("AuthoringTool", value)) if (!meta || !meta->Get("AuthoringTool", value))
mOutput << startstr << "<authoring_tool>" << "Assimp Exporter" << "</authoring_tool>" << endstr; mOutput << startstr << "<authoring_tool>" << "Assimp Exporter" << "</authoring_tool>" << endstr;
else else
mOutput << startstr << "<authoring_tool>" << value.C_Str() << "</authoring_tool>" << endstr; mOutput << startstr << "<authoring_tool>" << XMLEscape(value.C_Str()) << "</authoring_tool>" << endstr;
//mOutput << startstr << "<author>" << mScene->author.C_Str() << "</author>" << endstr; //mOutput << startstr << "<author>" << mScene->author.C_Str() << "</author>" << endstr;
//mOutput << startstr << "<authoring_tool>" << mScene->authoringTool.C_Str() << "</authoring_tool>" << endstr; //mOutput << startstr << "<authoring_tool>" << mScene->authoringTool.C_Str() << "</authoring_tool>" << endstr;
@ -342,16 +344,20 @@ void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::strin
{ {
if( !pSurface.texture.empty() ) if( !pSurface.texture.empty() )
{ {
mOutput << startstr << "<image id=\"" << pNameAdd << "\">" << endstr; mOutput << startstr << "<image id=\"" << XMLEscape(pNameAdd) << "\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<init_from>"; mOutput << startstr << "<init_from>";
// URL encode image file name first, then XML encode on top
std::stringstream imageUrlEncoded;
for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it ) for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it )
{ {
if( isalnum( *it) || *it == '_' || *it == '.' || *it == '/' || *it == '\\' ) if( isalnum( *it) || *it == '_' || *it == '.' || *it == '/' || *it == '\\' )
mOutput << *it; imageUrlEncoded << *it;
else else
mOutput << '%' << std::hex << size_t( (unsigned char) *it) << std::dec; imageUrlEncoded << '%' << std::hex << size_t( (unsigned char) *it) << std::dec;
} }
mOutput << XMLEscape(imageUrlEncoded.str());
mOutput << "</init_from>" << endstr; mOutput << "</init_from>" << endstr;
PopTag(); PopTag();
mOutput << startstr << "</image>" << endstr; mOutput << startstr << "</image>" << endstr;
@ -371,7 +377,7 @@ void ColladaExporter::WriteTextureColorEntry( const Surface& pSurface, const std
} }
else else
{ {
mOutput << startstr << "<texture texture=\"" << pImageName << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr; mOutput << startstr << "<texture texture=\"" << XMLEscape(pImageName) << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
} }
PopTag(); PopTag();
mOutput << startstr << "</" << pTypeName << ">" << endstr; mOutput << startstr << "</" << pTypeName << ">" << endstr;
@ -385,21 +391,21 @@ void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std
// if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture // if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture
if( !pSurface.texture.empty() ) if( !pSurface.texture.empty() )
{ {
mOutput << startstr << "<newparam sid=\"" << pMatName << "-" << pTypeName << "-surface\">" << endstr; mOutput << startstr << "<newparam sid=\"" << XMLEscape(pMatName) << "-" << pTypeName << "-surface\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<surface type=\"2D\">" << endstr; mOutput << startstr << "<surface type=\"2D\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<init_from>" << pMatName << "-" << pTypeName << "-image</init_from>" << endstr; mOutput << startstr << "<init_from>" << XMLEscape(pMatName) << "-" << pTypeName << "-image</init_from>" << endstr;
PopTag(); PopTag();
mOutput << startstr << "</surface>" << endstr; mOutput << startstr << "</surface>" << endstr;
PopTag(); PopTag();
mOutput << startstr << "</newparam>" << endstr; mOutput << startstr << "</newparam>" << endstr;
mOutput << startstr << "<newparam sid=\"" << pMatName << "-" << pTypeName << "-sampler\">" << endstr; mOutput << startstr << "<newparam sid=\"" << XMLEscape(pMatName) << "-" << pTypeName << "-sampler\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<sampler2D>" << endstr; mOutput << startstr << "<sampler2D>" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<source>" << pMatName << "-" << pTypeName << "-surface</source>" << endstr; mOutput << startstr << "<source>" << XMLEscape(pMatName) << "-" << pTypeName << "-surface</source>" << endstr;
PopTag(); PopTag();
mOutput << startstr << "</sampler2D>" << endstr; mOutput << startstr << "</sampler2D>" << endstr;
PopTag(); PopTag();
@ -439,7 +445,7 @@ void ColladaExporter::WriteMaterials()
name = "mat"; name = "mat";
materials[a].name = std::string( "m") + boost::lexical_cast<std::string> (a) + name.C_Str(); materials[a].name = std::string( "m") + boost::lexical_cast<std::string> (a) + name.C_Str();
for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) { for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) {
// isalnum on MSVC asserts for code points in [0,255]. Thus prevent unwanted promotion // isalnum on MSVC asserts for code points outside [0,255]. Thus prevent unwanted promotion
// of char to signed int and take the unsigned char value. // of char to signed int and take the unsigned char value.
if( !isalnum( static_cast<uint8_t>(*it) ) ) { if( !isalnum( static_cast<uint8_t>(*it) ) ) {
*it = '_'; *it = '_';
@ -510,7 +516,7 @@ void ColladaExporter::WriteMaterials()
{ {
const Material& mat = *it; const Material& mat = *it;
// this is so ridiculous it must be right // this is so ridiculous it must be right
mOutput << startstr << "<effect id=\"" << mat.name << "-fx\" name=\"" << mat.name << "\">" << endstr; mOutput << startstr << "<effect id=\"" << XMLEscape(mat.name) << "-fx\" name=\"" << XMLEscape(mat.name) << "\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<profile_COMMON>" << endstr; mOutput << startstr << "<profile_COMMON>" << endstr;
PushTag(); PushTag();
@ -561,9 +567,9 @@ void ColladaExporter::WriteMaterials()
for( std::vector<Material>::const_iterator it = materials.begin(); it != materials.end(); ++it ) for( std::vector<Material>::const_iterator it = materials.begin(); it != materials.end(); ++it )
{ {
const Material& mat = *it; const Material& mat = *it;
mOutput << startstr << "<material id=\"" << mat.name << "\" name=\"" << mat.name << "\">" << endstr; mOutput << startstr << "<material id=\"" << XMLEscape(mat.name) << "\" name=\"" << mat.name << "\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<instance_effect url=\"#" << mat.name << "-fx\"/>" << endstr; mOutput << startstr << "<instance_effect url=\"#" << XMLEscape(mat.name) << "-fx\"/>" << endstr;
PopTag(); PopTag();
mOutput << startstr << "</material>" << endstr; mOutput << startstr << "</material>" << endstr;
} }
@ -591,13 +597,14 @@ void ColladaExporter::WriteGeometryLibrary()
void ColladaExporter::WriteGeometry( size_t pIndex) void ColladaExporter::WriteGeometry( size_t pIndex)
{ {
const aiMesh* mesh = mScene->mMeshes[pIndex]; const aiMesh* mesh = mScene->mMeshes[pIndex];
std::string idstr = GetMeshId( pIndex); const std::string idstr = GetMeshId( pIndex);
const std::string idstrEscaped = XMLEscape(idstr);
if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
return; return;
// opening tag // opening tag
mOutput << startstr << "<geometry id=\"" << idstr << "\" name=\"" << idstr << "_name\" >" << endstr; mOutput << startstr << "<geometry id=\"" << idstrEscaped << "\" name=\"" << idstrEscaped << "_name\" >" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<mesh>" << endstr; mOutput << startstr << "<mesh>" << endstr;
@ -627,20 +634,20 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
} }
// assemble vertex structure // assemble vertex structure
mOutput << startstr << "<vertices id=\"" << idstr << "-vertices" << "\">" << endstr; mOutput << startstr << "<vertices id=\"" << idstrEscaped << "-vertices" << "\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<input semantic=\"POSITION\" source=\"#" << idstr << "-positions\" />" << endstr; mOutput << startstr << "<input semantic=\"POSITION\" source=\"#" << idstrEscaped << "-positions\" />" << endstr;
if( mesh->HasNormals() ) if( mesh->HasNormals() )
mOutput << startstr << "<input semantic=\"NORMAL\" source=\"#" << idstr << "-normals\" />" << endstr; mOutput << startstr << "<input semantic=\"NORMAL\" source=\"#" << idstrEscaped << "-normals\" />" << endstr;
for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
{ {
if( mesh->HasTextureCoords( a) ) if( mesh->HasTextureCoords( a) )
mOutput << startstr << "<input semantic=\"TEXCOORD\" source=\"#" << idstr << "-tex" << a << "\" " /*<< "set=\"" << a << "\"" */ << " />" << endstr; mOutput << startstr << "<input semantic=\"TEXCOORD\" source=\"#" << idstrEscaped << "-tex" << a << "\" " /*<< "set=\"" << a << "\"" */ << " />" << endstr;
} }
for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a )
{ {
if( mesh->HasVertexColors( a) ) if( mesh->HasVertexColors( a) )
mOutput << startstr << "<input semantic=\"COLOR\" source=\"#" << idstr << "-color" << a << "\" " /*<< set=\"" << a << "\"" */ << " />" << endstr; mOutput << startstr << "<input semantic=\"COLOR\" source=\"#" << idstrEscaped << "-color" << a << "\" " /*<< set=\"" << a << "\"" */ << " />" << endstr;
} }
PopTag(); PopTag();
@ -660,7 +667,7 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
{ {
mOutput << startstr << "<lines count=\"" << countLines << "\" material=\"defaultMaterial\">" << endstr; mOutput << startstr << "<lines count=\"" << countLines << "\" material=\"defaultMaterial\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstr << "-vertices\" />" << endstr; mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstrEscaped << "-vertices\" />" << endstr;
mOutput << startstr << "<p>"; mOutput << startstr << "<p>";
for( size_t a = 0; a < mesh->mNumFaces; ++a ) for( size_t a = 0; a < mesh->mNumFaces; ++a )
{ {
@ -681,7 +688,7 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
{ {
mOutput << startstr << "<polylist count=\"" << countPoly << "\" material=\"defaultMaterial\">" << endstr; mOutput << startstr << "<polylist count=\"" << countPoly << "\" material=\"defaultMaterial\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstr << "-vertices\" />" << endstr; mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstrEscaped << "-vertices\" />" << endstr;
mOutput << startstr << "<vcount>"; mOutput << startstr << "<vcount>";
for( size_t a = 0; a < mesh->mNumFaces; ++a ) for( size_t a = 0; a < mesh->mNumFaces; ++a )
@ -728,11 +735,11 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy
std::string arrayId = pIdString + "-array"; std::string arrayId = pIdString + "-array";
mOutput << startstr << "<source id=\"" << pIdString << "\" name=\"" << pIdString << "\">" << endstr; mOutput << startstr << "<source id=\"" << XMLEscape(pIdString) << "\" name=\"" << XMLEscape(pIdString) << "\">" << endstr;
PushTag(); PushTag();
// source array // source array
mOutput << startstr << "<float_array id=\"" << arrayId << "\" count=\"" << pElementCount * floatsPerElement << "\"> "; mOutput << startstr << "<float_array id=\"" << XMLEscape(arrayId) << "\" count=\"" << pElementCount * floatsPerElement << "\"> ";
PushTag(); PushTag();
if( pType == FloatType_TexCoord2 ) if( pType == FloatType_TexCoord2 )
@ -804,11 +811,11 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy
// Writes the scene library // Writes the scene library
void ColladaExporter::WriteSceneLibrary() void ColladaExporter::WriteSceneLibrary()
{ {
std::string scene_name = mScene->mRootNode->mName.C_Str(); const std::string scene_name_escaped = XMLEscape(mScene->mRootNode->mName.C_Str());
mOutput << startstr << "<library_visual_scenes>" << endstr; mOutput << startstr << "<library_visual_scenes>" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<visual_scene id=\"" + scene_name + "\" name=\"" + scene_name + "\">" << endstr; mOutput << startstr << "<visual_scene id=\"" + scene_name_escaped + "\" name=\"" + scene_name_escaped + "\">" << endstr;
PushTag(); PushTag();
// start recursive write at the root node // start recursive write at the root node
@ -833,7 +840,8 @@ void ColladaExporter::WriteNode(aiNode* pNode)
pNode->mName.Set(ss.str()); pNode->mName.Set(ss.str());
} }
mOutput << startstr << "<node id=\"" << pNode->mName.data << "\" name=\"" << pNode->mName.data << "\">" << endstr; const std::string node_name_escaped = XMLEscape(pNode->mName.data);
mOutput << startstr << "<node id=\"" << node_name_escaped << "\" name=\"" << node_name_escaped << "\">" << endstr;
PushTag(); PushTag();
// write transformation - we can directly put the matrix there // write transformation - we can directly put the matrix there
@ -854,13 +862,13 @@ void ColladaExporter::WriteNode(aiNode* pNode)
if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
continue; continue;
mOutput << startstr << "<instance_geometry url=\"#" << GetMeshId( pNode->mMeshes[a]) << "\">" << endstr; mOutput << startstr << "<instance_geometry url=\"#" << XMLEscape(GetMeshId( pNode->mMeshes[a])) << "\">" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<bind_material>" << endstr; mOutput << startstr << "<bind_material>" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<technique_common>" << endstr; mOutput << startstr << "<technique_common>" << endstr;
PushTag(); PushTag();
mOutput << startstr << "<instance_material symbol=\"defaultMaterial\" target=\"#" << materials[mesh->mMaterialIndex].name << "\" />" << endstr; mOutput << startstr << "<instance_material symbol=\"defaultMaterial\" target=\"#" << XMLEscape(materials[mesh->mMaterialIndex].name) << "\" />" << endstr;
PopTag(); PopTag();
mOutput << startstr << "</technique_common>" << endstr; mOutput << startstr << "</technique_common>" << endstr;
PopTag(); PopTag();

View File

@ -118,7 +118,6 @@ struct Camera
float mZNear, mZFar; float mZNear, mZFar;
}; };
#define aiLightSource_AMBIENT 0xdeaddead
#define ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET 1e9f #define ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET 1e9f
/** A collada light source. */ /** A collada light source. */

View File

@ -73,7 +73,7 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
ColladaLoader::ColladaLoader() ColladaLoader::ColladaLoader()
: noSkeletonMesh(), ignoreUpDirection(false) : noSkeletonMesh(), ignoreUpDirection(false), mNodeNameCounter()
{} {}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -133,6 +133,7 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
mLights.clear(); mLights.clear();
mCameras.clear(); mCameras.clear();
mTextures.clear(); mTextures.clear();
mAnims.clear();
// parse the input file // parse the input file
ColladaParser parser( pIOHandler, pFile); ColladaParser parser( pIOHandler, pFile);
@ -307,10 +308,6 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
continue; continue;
} }
const Collada::Light* srcLight = &srcLightIt->second; const Collada::Light* srcLight = &srcLightIt->second;
if (srcLight->mType == aiLightSource_AMBIENT) {
DefaultLogger::get()->error("Collada: Skipping ambient light for the moment");
continue;
}
// now fill our ai data structure // now fill our ai data structure
aiLight* out = new aiLight(); aiLight* out = new aiLight();
@ -340,7 +337,7 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
{ {
// Need to rely on falloff_exponent. I don't know how to interpret it, so I need to guess .... // Need to rely on falloff_exponent. I don't know how to interpret it, so I need to guess ....
// epsilon chosen to be 0.1 // epsilon chosen to be 0.1
out->mAngleOuterCone = AI_DEG_TO_RAD (acos(pow(0.1f,1.f/srcLight->mFalloffExponent))+ out->mAngleOuterCone = AI_DEG_TO_RAD (std::acos(std::pow(0.1f,1.f/srcLight->mFalloffExponent))+
srcLight->mFalloffAngle); srcLight->mFalloffAngle);
} }
else { else {
@ -904,6 +901,8 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars
pScene->mAnimations = new aiAnimation*[mAnims.size()]; pScene->mAnimations = new aiAnimation*[mAnims.size()];
std::copy( mAnims.begin(), mAnims.end(), pScene->mAnimations); std::copy( mAnims.begin(), mAnims.end(), pScene->mAnimations);
} }
mAnims.clear();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -1544,7 +1543,7 @@ const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, c
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// 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 ColladaLoader::FindNameForNode( const Collada::Node* pNode) const std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode)
{ {
// now setup the name of the node. We take the name if not empty, otherwise the collada ID // now setup the name of the node. We take the name if not empty, otherwise the collada ID
// FIX: Workaround for XSI calling the instanced visual scene 'untitled' by default. // FIX: Workaround for XSI calling the instanced visual scene 'untitled' by default.
@ -1558,7 +1557,7 @@ std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode) const
{ {
// No need to worry. Unnamed nodes are no problem at all, except // No need to worry. Unnamed nodes are no problem at all, except
// if cameras or lights need to be assigned to them. // if cameras or lights need to be assigned to them.
return boost::str( boost::format( "$ColladaAutoName$_%d") % clock()); return boost::str( boost::format( "$ColladaAutoName$_%d") % mNodeNameCounter++);
} }
} }

View File

@ -203,7 +203,7 @@ protected:
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) const; std::string FindNameForNode( const Collada::Node* pNode);
protected: protected:
/** Filename, for a verbose error message */ /** Filename, for a verbose error message */
@ -235,6 +235,9 @@ protected:
bool noSkeletonMesh; bool noSkeletonMesh;
bool ignoreUpDirection; bool ignoreUpDirection;
/** Used by FindNameForNode() to generate unique node names */
unsigned int mNodeNameCounter;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -1163,6 +1163,19 @@ void ColladaParser::ReadEffectProfileCommon( Collada::Effect& pEffect)
// just syntactic sugar // just syntactic sugar
} }
else if( mFormat == FV_1_4_n && IsElement( "image"))
{
// read ID. Another entry which is "optional" by design but obligatory in reality
int attrID = GetAttribute( "id");
std::string id = mReader->getAttributeValue( attrID);
// create an entry and store it in the library under its ID
mImageLibrary[id] = Image();
// read on from there
ReadImage( mImageLibrary[id]);
}
/* Shading modes */ /* Shading modes */
else if( IsElement( "phong")) else if( IsElement( "phong"))
pEffect.mShadeType = Shade_Phong; pEffect.mShadeType = Shade_Phong;
@ -1854,14 +1867,15 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
// read primitive count from the attribute // read primitive count from the attribute
int attrCount = GetAttribute( "count"); int attrCount = GetAttribute( "count");
size_t numPrimitives = (size_t) mReader->getAttributeValueAsInt( attrCount); size_t numPrimitives = (size_t) mReader->getAttributeValueAsInt( attrCount);
// some mesh types (e.g. tristrips) don't specify primitive count upfront,
// so we need to sum up the actual number of primitives while we read the <p>-tags
size_t actualPrimitives = 0;
// material subgroup // material subgroup
int attrMaterial = TestAttribute( "material"); int attrMaterial = TestAttribute( "material");
SubMesh subgroup; SubMesh subgroup;
if( attrMaterial > -1) if( attrMaterial > -1)
subgroup.mMaterial = mReader->getAttributeValue( attrMaterial); subgroup.mMaterial = mReader->getAttributeValue( attrMaterial);
subgroup.mNumFaces = numPrimitives;
pMesh->mSubMeshes.push_back( subgroup);
// distinguish between polys and triangles // distinguish between polys and triangles
std::string elementName = mReader->getNodeName(); std::string elementName = mReader->getNodeName();
@ -1920,7 +1934,7 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
if( !mReader->isEmptyElement()) if( !mReader->isEmptyElement())
{ {
// now here the actual fun starts - these are the indices to construct the mesh data from // now here the actual fun starts - these are the indices to construct the mesh data from
ReadPrimitives( pMesh, perIndexData, numPrimitives, vcount, primType); actualPrimitives += ReadPrimitives(pMesh, perIndexData, numPrimitives, vcount, primType);
} }
} else } else
{ {
@ -1935,6 +1949,14 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
break; break;
} }
} }
// small sanity check
if (primType != Prim_TriFans && primType != Prim_TriStrips)
ai_assert(actualPrimitives == numPrimitives);
// only when we're done reading all <p> tags (and thus know the final vertex count) can we commit the submesh
subgroup.mNumFaces = actualPrimitives;
pMesh->mSubMeshes.push_back(subgroup);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -1982,7 +2004,7 @@ void ColladaParser::ReadInputChannel( std::vector<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
void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels, size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels,
size_t pNumPrimitives, const std::vector<size_t>& pVCount, PrimitiveType pPrimType) size_t pNumPrimitives, const std::vector<size_t>& pVCount, PrimitiveType pPrimType)
{ {
// determine number of indices coming per vertex // determine number of indices coming per vertex
@ -2080,70 +2102,98 @@ void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPer
acc->mData = &ResolveLibraryReference( mDataLibrary, acc->mSource); acc->mData = &ResolveLibraryReference( mDataLibrary, acc->mSource);
} }
// now assemble vertex data according to those indices
std::vector<size_t>::const_iterator idx = indices.begin();
// For continued primitives, the given count does not come all in one <p>, but only one primitive per <p> // For continued primitives, the given count does not come all in one <p>, but only one primitive per <p>
size_t numPrimitives = pNumPrimitives; size_t numPrimitives = pNumPrimitives;
if( pPrimType == Prim_TriFans || pPrimType == Prim_Polygon) if( pPrimType == Prim_TriFans || pPrimType == Prim_Polygon)
numPrimitives = 1; numPrimitives = 1;
// For continued primitives, the given count is actually the number of <p>'s inside the parent tag
if ( pPrimType == Prim_TriStrips){
size_t numberOfVertices = indices.size() / numOffsets;
numPrimitives = numberOfVertices - 2;
}
pMesh->mFaceSize.reserve( numPrimitives); pMesh->mFaceSize.reserve( numPrimitives);
pMesh->mFacePosIndices.reserve( indices.size() / numOffsets); pMesh->mFacePosIndices.reserve( indices.size() / numOffsets);
for( size_t a = 0; a < numPrimitives; a++) size_t polylistStartVertex = 0;
for (size_t currentPrimitive = 0; currentPrimitive < numPrimitives; currentPrimitive++)
{ {
// determine number of points for this primitive // determine number of points for this primitive
size_t numPoints = 0; size_t numPoints = 0;
switch( pPrimType) switch( pPrimType)
{ {
case Prim_Lines: case Prim_Lines:
numPoints = 2; numPoints = 2;
for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
CopyVertex(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
break; break;
case Prim_Triangles: case Prim_Triangles:
numPoints = 3; numPoints = 3;
for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
CopyVertex(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
break;
case Prim_TriStrips:
numPoints = 3;
ReadPrimTriStrips(numOffsets, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
break; break;
case Prim_Polylist: case Prim_Polylist:
numPoints = pVCount[a]; numPoints = pVCount[currentPrimitive];
for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
CopyVertex(polylistStartVertex + currentVertex, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, 0, indices);
polylistStartVertex += numPoints;
break; break;
case Prim_TriFans: case Prim_TriFans:
case Prim_Polygon: case Prim_Polygon:
numPoints = indices.size() / numOffsets; numPoints = indices.size() / numOffsets;
for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
CopyVertex(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
break; break;
default: default:
// LineStrip and TriStrip not supported due to expected index unmangling // LineStrip is not supported due to expected index unmangling
ThrowException( "Unsupported primitive type."); ThrowException( "Unsupported primitive type.");
break; break;
} }
// store the face size to later reconstruct the face from // store the face size to later reconstruct the face from
pMesh->mFaceSize.push_back( numPoints); pMesh->mFaceSize.push_back( numPoints);
// gather that number of vertices
for( size_t b = 0; b < numPoints; b++)
{
// read all indices for this vertex. Yes, in a hacky local array
ai_assert( numOffsets < 20 && perVertexOffset < 20);
size_t vindex[20];
for( size_t offsets = 0; offsets < numOffsets; ++offsets)
vindex[offsets] = *idx++;
// extract per-vertex channels using the global per-vertex offset
for( std::vector<InputChannel>::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it)
ExtractDataObjectFromChannel( *it, vindex[perVertexOffset], pMesh);
// and extract per-index channels using there specified offset
for( std::vector<InputChannel>::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it)
ExtractDataObjectFromChannel( *it, vindex[it->mOffset], pMesh);
// store the vertex-data index for later assignment of bone vertex weights
pMesh->mFacePosIndices.push_back( vindex[perVertexOffset]);
}
} }
// if I ever get my hands on that guy who invented this steaming pile of indirection... // if I ever get my hands on that guy who invented this steaming pile of indirection...
TestClosing( "p"); TestClosing( "p");
return numPrimitives;
}
void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t>& indices){
// calculate the base offset of the vertex whose attributes we ant to copy
size_t baseOffset = currentPrimitive * numOffsets * numPoints + currentVertex * numOffsets;
// don't overrun the boundaries of the index list
size_t maxIndexRequested = baseOffset + numOffsets - 1;
ai_assert(maxIndexRequested < indices.size());
// extract per-vertex channels using the global per-vertex offset
for (std::vector<InputChannel>::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it)
ExtractDataObjectFromChannel(*it, indices[baseOffset + perVertexOffset], pMesh);
// and extract per-index channels using there specified offset
for (std::vector<InputChannel>::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it)
ExtractDataObjectFromChannel(*it, indices[baseOffset + it->mOffset], pMesh);
// store the vertex-data index for later assignment of bone vertex weights
pMesh->mFacePosIndices.push_back(indices[baseOffset + perVertexOffset]);
}
void ColladaParser::ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t>& indices){
if (currentPrimitive % 2 != 0){
//odd tristrip triangles need their indices mangled, to preserve winding direction
CopyVertex(1, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
CopyVertex(0, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
CopyVertex(2, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
}
else {//for non tristrips or even tristrip triangles
CopyVertex(0, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
CopyVertex(1, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
CopyVertex(2, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -177,9 +177,18 @@ protected:
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 */
void 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 */
void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset,
Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels,
size_t currentPrimitive, const std::vector<size_t>& indices);
/** Reads one triangle of a tristrip into the mesh */
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);
/** 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);

View File

@ -207,7 +207,7 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D
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,
(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) {
@ -215,7 +215,7 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D
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,
(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) {
@ -223,7 +223,7 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D
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,
(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

View File

@ -57,12 +57,15 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
MakeLeftHandedProcess::MakeLeftHandedProcess() MakeLeftHandedProcess::MakeLeftHandedProcess()
{} : BaseProcess() {
// empty
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
MakeLeftHandedProcess::~MakeLeftHandedProcess() MakeLeftHandedProcess::~MakeLeftHandedProcess() {
{} // empty
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
@ -121,8 +124,9 @@ void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pPare
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 );
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -244,6 +248,10 @@ 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 ) {
DefaultLogger::get()->debug( "Property is null" );
continue;
}
// UV transformation key? // UV transformation key?
if (!::strcmp( prop->mKey.data, "$tex.uvtrafo")) { if (!::strcmp( prop->mKey.data, "$tex.uvtrafo")) {
@ -263,11 +271,13 @@ 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;
}
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;
}
} }
} }

View File

@ -111,8 +111,8 @@ void DeboneProcess::Execute( aiScene* pScene)
if(numSplits) { if(numSplits) {
// we need to do something. Let's go. // we need to do something. Let's go.
mSubMeshIndices.clear(); //mSubMeshIndices.clear(); // really needed?
mSubMeshIndices.resize(pScene->mNumMeshes); 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;

View File

@ -56,52 +56,59 @@ namespace Assimp {
class DefaultIOStream : public IOStream class DefaultIOStream : public IOStream
{ {
friend class DefaultIOSystem; friend class DefaultIOSystem;
#if __ANDROID__
#if __ANDROID_API__ > 9
#if defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
friend class AndroidJNIIOSystem;
#endif // defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
#endif // __ANDROID_API__ > 9
#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;
}; };

View File

@ -78,7 +78,10 @@ void ExportSceneObj(const char*,IOSystem*, const aiScene*);
void ExportSceneSTL(const char*,IOSystem*, const aiScene*); void ExportSceneSTL(const char*,IOSystem*, const aiScene*);
void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*); void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*);
void ExportScenePly(const char*,IOSystem*, const aiScene*); void ExportScenePly(const char*,IOSystem*, const aiScene*);
void ExportScene3DS(const char*, IOSystem*, const aiScene*) {} void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*);
void ExportScene3DS(const char*, IOSystem*, const aiScene*);
void ExportSceneAssbin(const char*, IOSystem*, const aiScene*);
void ExportSceneAssxml(const char*, IOSystem*, const aiScene*);
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// global array of all export formats which Assimp supports in its current build // global array of all export formats which Assimp supports in its current build
@ -90,7 +93,7 @@ Exporter::ExportFormatEntry gExporters[] =
#ifndef ASSIMP_BUILD_NO_FXILE_EXPORTER #ifndef ASSIMP_BUILD_NO_FXILE_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_OBJ_EXPORTER #ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
@ -111,11 +114,23 @@ Exporter::ExportFormatEntry gExporters[] =
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,
aiProcess_PreTransformVertices
),
#endif #endif
//#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER #ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
// ExportFormatEntry( "3ds", "Autodesk 3DS (legacy format)", "3ds" , &ExportScene3DS), Exporter::ExportFormatEntry( "3ds", "Autodesk 3DS (legacy)", "3ds" , &ExportScene3DS,
//#endif aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices),
#endif
#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0),
#endif
#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
Exporter::ExportFormatEntry( "assxml", "Assxml Document", "assxml" , &ExportSceneAssxml, 0),
#endif
}; };
#define ASSIMP_NUM_EXPORTERS (sizeof(gExporters)/sizeof(gExporters[0])) #define ASSIMP_NUM_EXPORTERS (sizeof(gExporters)/sizeof(gExporters[0]))
@ -443,6 +458,11 @@ const aiExportFormatDesc* Exporter :: GetExportFormatDescription( size_t pIndex
if (pIndex >= GetExportFormatCount()) { if (pIndex >= GetExportFormatCount()) {
return NULL; return NULL;
} }
// Return from static storage if the requested index is built-in.
if (pIndex < sizeof(gExporters) / sizeof(gExporters[0])) {
return &gExporters[pIndex].mDescription;
}
return &pimpl->mExporters[pIndex].mDescription; return &pimpl->mExporters[pIndex].mDescription;
} }

View File

@ -59,7 +59,7 @@ 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);

View File

@ -55,14 +55,15 @@ 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)
: sbegin(sbegin) :
#ifdef DEBUG
contents(sbegin, static_cast<size_t>(send-sbegin)),
#endif
sbegin(sbegin)
, send(send) , send(send)
, type(type) , type(type)
, line(offset) , line(offset)
, column(BINARY_MARKER) , column(BINARY_MARKER)
#ifdef DEBUG
, contents(sbegin, static_cast<size_t>(send-sbegin))
#endif
{ {
ai_assert(sbegin); ai_assert(sbegin);
ai_assert(send); ai_assert(send);
@ -395,4 +396,4 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int le
} // !FBX } // !FBX
} // !Assimp } // !Assimp
#endif #endif

View File

@ -381,8 +381,6 @@ private:
out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight(); out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight();
out_camera->mPosition = cam.Position(); out_camera->mPosition = cam.Position();
out_camera->mLookAt = cam.InterestPosition() - out_camera->mPosition; out_camera->mLookAt = cam.InterestPosition() - out_camera->mPosition;
// BUG HERE cam.FieldOfView() returns 1.0f every time. 1.0f is default value.
out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView()); out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView());
} }
@ -499,15 +497,15 @@ private:
bool is_id[3] = { true, true, true }; bool is_id[3] = { true, true, true };
aiMatrix4x4 temp[3]; aiMatrix4x4 temp[3];
if(fabs(rotation.z) > angle_epsilon) { if(std::fabs(rotation.z) > angle_epsilon) {
aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(rotation.z),temp[2]); aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(rotation.z),temp[2]);
is_id[2] = false; is_id[2] = false;
} }
if(fabs(rotation.y) > angle_epsilon) { if(std::fabs(rotation.y) > angle_epsilon) {
aiMatrix4x4::RotationY(AI_DEG_TO_RAD(rotation.y),temp[1]); aiMatrix4x4::RotationY(AI_DEG_TO_RAD(rotation.y),temp[1]);
is_id[1] = false; is_id[1] = false;
} }
if(fabs(rotation.x) > angle_epsilon) { if(std::fabs(rotation.x) > angle_epsilon) {
aiMatrix4x4::RotationX(AI_DEG_TO_RAD(rotation.x),temp[0]); aiMatrix4x4::RotationX(AI_DEG_TO_RAD(rotation.x),temp[0]);
is_id[0] = false; is_id[0] = false;
} }
@ -676,7 +674,7 @@ private:
} }
const aiVector3D& Scaling = PropertyGet<aiVector3D>(props,"Lcl Scaling",ok); const aiVector3D& Scaling = PropertyGet<aiVector3D>(props,"Lcl Scaling",ok);
if(ok && fabs(Scaling.SquareLength()-1.0f) > zero_epsilon) { if(ok && std::fabs(Scaling.SquareLength()-1.0f) > zero_epsilon) {
aiMatrix4x4::Scaling(Scaling,chain[TransformationComp_Scaling]); aiMatrix4x4::Scaling(Scaling,chain[TransformationComp_Scaling]);
} }
@ -686,7 +684,7 @@ private:
} }
const aiVector3D& GeometricScaling = PropertyGet<aiVector3D>(props, "GeometricScaling", ok); const aiVector3D& GeometricScaling = PropertyGet<aiVector3D>(props, "GeometricScaling", ok);
if (ok && fabs(GeometricScaling.SquareLength() - 1.0f) > zero_epsilon) { if (ok && std::fabs(GeometricScaling.SquareLength() - 1.0f) > zero_epsilon) {
aiMatrix4x4::Scaling(GeometricScaling, chain[TransformationComp_GeometricScaling]); aiMatrix4x4::Scaling(GeometricScaling, chain[TransformationComp_GeometricScaling]);
} }
@ -767,7 +765,6 @@ private:
// find user defined properties (3ds Max) // find user defined properties (3ds Max)
data->Set(index++, "UserProperties", aiString(PropertyGet<std::string>(props, "UDP3DSMAX", ""))); data->Set(index++, "UserProperties", aiString(PropertyGet<std::string>(props, "UDP3DSMAX", "")));
unparsedProperties.erase("UDP3DSMAX");
// preserve the info that a node was marked as Null node in the original file. // preserve the info that a node was marked as Null node in the original file.
data->Set(index++, "IsNull", model.IsNull() ? true : false); data->Set(index++, "IsNull", model.IsNull() ? true : false);
@ -1320,7 +1317,7 @@ private:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertCluster(std::vector<aiBone*>& bones, const Model& model, const Cluster& cl, void ConvertCluster(std::vector<aiBone*>& bones, const Model& /*model*/, const Cluster& cl,
std::vector<size_t>& out_indices, std::vector<size_t>& out_indices,
std::vector<size_t>& index_out_indices, std::vector<size_t>& index_out_indices,
std::vector<size_t>& count_out_indices, std::vector<size_t>& count_out_indices,
@ -2348,7 +2345,7 @@ private:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiNodeAnim* GenerateScalingNodeAnim(const std::string& name, aiNodeAnim* GenerateScalingNodeAnim(const std::string& name,
const Model& target, const Model& /*target*/,
const std::vector<const AnimationCurveNode*>& curves, const std::vector<const AnimationCurveNode*>& curves,
const LayerMap& layer_map, const LayerMap& layer_map,
double& max_time, double& max_time,
@ -2379,7 +2376,7 @@ private:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiNodeAnim* GenerateTranslationNodeAnim(const std::string& name, aiNodeAnim* GenerateTranslationNodeAnim(const std::string& name,
const Model& target, const Model& /*target*/,
const std::vector<const AnimationCurveNode*>& curves, const std::vector<const AnimationCurveNode*>& curves,
const LayerMap& layer_map, const LayerMap& layer_map,
double& max_time, double& max_time,
@ -2831,7 +2828,7 @@ private:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& layers, void ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/,
double& maxTime, double& maxTime,
double& minTime) double& minTime)
{ {
@ -2852,7 +2849,7 @@ private:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, void ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
const LayerMap& layers, const LayerMap& /*layers*/,
double& maxTime, double& maxTime,
double& minTime) double& minTime)
{ {
@ -2870,7 +2867,7 @@ private:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, void ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
const LayerMap& layers, const LayerMap& /*layers*/,
double& maxTime, double& maxTime,
double& minTime, double& minTime,
Model::RotOrder order) Model::RotOrder order)

View File

@ -253,8 +253,8 @@ Document::Document(const Parser& parser, const ImportSettings& settings)
: settings(settings) : settings(settings)
, parser(parser) , parser(parser)
{ {
// cannot use array default initialization syntax because vc8 fails on it // Cannot use array default initialization syntax because vc8 fails on it
for (unsigned int i = 0; i < 7; ++i) { for (unsigned int i = 0; i < sizeof(creationTimeStamp) / sizeof(creationTimeStamp[0]); ++i) {
creationTimeStamp[i] = 0; creationTimeStamp[i] = 0;
} }
@ -263,7 +263,7 @@ Document::Document(const Parser& parser, const ImportSettings& settings)
ReadGlobalSettings(); ReadGlobalSettings();
// this order is important, connections need parsed objects to check // This order is important, connections need parsed objects to check
// whether connections are ok or not. Objects may not be evaluated yet, // whether connections are ok or not. Objects may not be evaluated yet,
// though, since this may require valid connections. // though, since this may require valid connections.
ReadObjects(); ReadObjects();
@ -277,13 +277,18 @@ Document::~Document()
BOOST_FOREACH(ObjectMap::value_type& v, objects) { BOOST_FOREACH(ObjectMap::value_type& v, objects) {
delete v.second; delete v.second;
} }
BOOST_FOREACH(ConnectionMap::value_type& v, src_connections) {
delete v.second;
}
// |dest_connections| contain the same Connection objects as the |src_connections|
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Document::ReadHeader() void Document::ReadHeader()
{ {
// read ID objects from "Objects" section // Read ID objects from "Objects" section
const Scope& sc = parser.GetRootScope(); const Scope& sc = parser.GetRootScope();
const Element* const ehead = sc["FBXHeaderExtension"]; const Element* const ehead = sc["FBXHeaderExtension"];
if(!ehead || !ehead->Compound()) { if(!ehead || !ehead->Compound()) {
@ -293,7 +298,7 @@ void Document::ReadHeader()
const Scope& shead = *ehead->Compound(); const Scope& shead = *ehead->Compound();
fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0)); fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0));
// while we maye have some success with newer files, we don't support // While we maye have some success with newer files, we don't support
// the older 6.n fbx format // the older 6.n fbx format
if(fbxVersion < 7100) { if(fbxVersion < 7100) {
DOMError("unsupported, old format version, supported are only FBX 2011, FBX 2012 and FBX 2013"); DOMError("unsupported, old format version, supported are only FBX 2011, FBX 2012 and FBX 2013");

View File

@ -696,7 +696,7 @@ public:
public: public:
/** Get the Skin attached to this geometry or NULL */ /** Get the Skin attached to this geometry or NULL */
const Skin* const DeformerSkin() const { const Skin* DeformerSkin() const {
return skin; return skin;
} }
@ -1096,7 +1096,7 @@ public:
return transformLink; return transformLink;
} }
const Model* const TargetNode() const { const Model* TargetNode() const {
return node; return node;
} }

View File

@ -105,7 +105,7 @@ bool FBXImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
else if ((!extension.length() || checkSig) && pIOHandler) { else if ((!extension.length() || checkSig) && pIOHandler) {
// at least ascii FBX files usually have a 'FBX' somewhere in their head // at least ascii FBX files usually have a 'FBX' somewhere in their head
const char* tokens[] = {"FBX"}; const char* tokens[] = {"fbx"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
} }
return false; return false;
@ -179,6 +179,8 @@ void FBXImporter::InternReadFile( const std::string& pFile,
// convert the FBX DOM to aiScene // convert the FBX DOM to aiScene
ConvertToAssimpScene(pScene,doc); ConvertToAssimpScene(pScene,doc);
std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
} }
catch(std::exception&) { catch(std::exception&) {
std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>()); std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());

View File

@ -207,7 +207,7 @@ Texture::~Texture()
} }
LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& doc, const std::string& name) LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& /*doc*/, const std::string& name)
: Object(id,element,name) : Object(id,element,name)
,texture(0) ,texture(0)
,blendMode(BlendMode_Modulate) ,blendMode(BlendMode_Modulate)

View File

@ -466,8 +466,9 @@ void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D>& tangents_out,
const std::string& MappingInformationType, const std::string& MappingInformationType,
const std::string& ReferenceInformationType) const std::string& ReferenceInformationType)
{ {
const char * str = source.Elements().count( "Tangents" ) > 0 ? "Tangents" : "Tangent";
ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType, ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType,
"Tangent", str,
"TangentIndex", "TangentIndex",
vertices.size(), vertices.size(),
mapping_counts, mapping_counts,
@ -481,8 +482,9 @@ void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D>& binormals_ou
const std::string& MappingInformationType, const std::string& MappingInformationType,
const std::string& ReferenceInformationType) const std::string& ReferenceInformationType)
{ {
const char * str = source.Elements().count( "Binormals" ) > 0 ? "Binormals" : "Binormal";
ResolveVertexDataArray(binormals_out,source,MappingInformationType,ReferenceInformationType, ResolveVertexDataArray(binormals_out,source,MappingInformationType,ReferenceInformationType,
"Binormal", str,
"BinormalIndex", "BinormalIndex",
vertices.size(), vertices.size(),
mapping_counts, mapping_counts,

View File

@ -93,7 +93,7 @@ namespace {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ParseWarning(const std::string& message, const Element* element = NULL) /* void ParseWarning(const std::string& message, const Element* element = NULL)
{ {
if(element) { if(element) {
ParseWarning(message,element->KeyToken()); ParseWarning(message,element->KeyToken());
@ -103,7 +103,7 @@ namespace {
DefaultLogger::get()->warn("FBX-Parser: " + message); DefaultLogger::get()->warn("FBX-Parser: " + message);
} }
} }
*/
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ParseError(const std::string& message, TokenPtr token) void ParseError(const std::string& message, TokenPtr token)
{ {
@ -113,6 +113,18 @@ namespace {
ParseError(message); ParseError(message);
} }
// Initially, we did reinterpret_cast, breaking strict aliasing rules.
// This actually caused trouble on Android, so let's be safe this time.
// https://github.com/assimp/assimp/issues/24
template <typename T>
T SafeParse(const char* data, const char* end) {
// Actual size validation happens during Tokenization so
// this is valid as an assertion.
ai_assert(static_cast<size_t>(end - data) >= sizeof(T));
T result = static_cast<T>(0);
::memcpy(&result, data, sizeof(T));
return result;
}
} }
namespace Assimp { namespace Assimp {
@ -275,9 +287,7 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
return 0L; return 0L;
} }
ai_assert(t.end() - data == 9); BE_NCONST uint64_t id = SafeParse<uint64_t>(data+1, t.end());
BE_NCONST uint64_t id = *reinterpret_cast<const uint64_t*>(data+1);
AI_SWAP8(id); AI_SWAP8(id);
return id; return id;
} }
@ -316,8 +326,7 @@ size_t ParseTokenAsDim(const Token& t, const char*& err_out)
return 0; return 0;
} }
ai_assert(t.end() - data == 9); BE_NCONST uint64_t id = SafeParse<uint64_t>(data+1, t.end());
BE_NCONST uint64_t id = *reinterpret_cast<const uint64_t*>(data+1);
AI_SWAP8(id); AI_SWAP8(id);
return static_cast<size_t>(id); return static_cast<size_t>(id);
} }
@ -364,24 +373,10 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out)
} }
if (data[0] == 'F') { if (data[0] == 'F') {
// Actual size validation happens during Tokenization so return SafeParse<float>(data+1, t.end());
// this is valid as an assertion.
ai_assert(t.end() - data == sizeof(float) + 1);
// Initially, we did reinterpret_cast, breaking strict aliasing rules.
// This actually caused trouble on Android, so let's be safe this time.
// https://github.com/assimp/assimp/issues/24
float out_float;
::memcpy(&out_float, data+1, sizeof(float));
return out_float;
} }
else { else {
ai_assert(t.end() - data == sizeof(double) + 1); return static_cast<float>( SafeParse<double>(data+1, t.end()) );
// Same
double out_double;
::memcpy(&out_double, data+1, sizeof(double));
return out_double;
} }
} }
@ -416,8 +411,7 @@ int ParseTokenAsInt(const Token& t, const char*& err_out)
return 0; return 0;
} }
ai_assert(t.end() - data == 5); BE_NCONST int32_t ival = SafeParse<int32_t>(data+1, t.end());
BE_NCONST int32_t ival = *reinterpret_cast<const int32_t*>(data+1);
AI_SWAP4(ival); AI_SWAP4(ival);
return static_cast<int>(ival); return static_cast<int>(ival);
} }
@ -453,10 +447,8 @@ std::string ParseTokenAsString(const Token& t, const char*& err_out)
return ""; return "";
} }
ai_assert(t.end() - data >= 5);
// read string length // read string length
BE_NCONST int32_t len = *reinterpret_cast<const int32_t*>(data+1); BE_NCONST int32_t len = SafeParse<int32_t>(data+1, t.end());
AI_SWAP4(len); AI_SWAP4(len);
ai_assert(t.end() - data == 5 + len); ai_assert(t.end() - data == 5 + len);
@ -494,7 +486,7 @@ void ReadBinaryDataArrayHead(const char*& data, const char* end, char& type, uin
type = *data; type = *data;
// read number of elements // read number of elements
BE_NCONST uint32_t len = *reinterpret_cast<const uint32_t*>(data+1); BE_NCONST uint32_t len = SafeParse<uint32_t>(data+1, end);
AI_SWAP4(len); AI_SWAP4(len);
count = len; count = len;
@ -506,16 +498,14 @@ void ReadBinaryDataArrayHead(const char*& data, const char* end, char& type, uin
// read binary data array, assume cursor points to the 'compression mode' field (i.e. behind the header) // read binary data array, assume cursor points to the 'compression mode' field (i.e. behind the header)
void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const char* end, void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const char* end,
std::vector<char>& buff, std::vector<char>& buff,
const Element& el) const Element& /*el*/)
{ {
ai_assert(static_cast<size_t>(end-data) >= 4); // runtime check for this happens at tokenization stage BE_NCONST uint32_t encmode = SafeParse<uint32_t>(data, end);
BE_NCONST uint32_t encmode = *reinterpret_cast<const uint32_t*>(data);
AI_SWAP4(encmode); AI_SWAP4(encmode);
data += 4; data += 4;
// next comes the compressed length // next comes the compressed length
BE_NCONST uint32_t comp_len = *reinterpret_cast<const uint32_t*>(data); BE_NCONST uint32_t comp_len = SafeParse<uint32_t>(data, end);
AI_SWAP4(comp_len); AI_SWAP4(comp_len);
data += 4; data += 4;

View File

@ -85,7 +85,7 @@ Property* ReadTypedProperty(const Element& element)
else if (!strcmp(cs,"bool") || !strcmp(cs,"Bool")) { else if (!strcmp(cs,"bool") || !strcmp(cs,"Bool")) {
return new TypedProperty<bool>(ParseTokenAsInt(*tok[4]) != 0); return new TypedProperty<bool>(ParseTokenAsInt(*tok[4]) != 0);
} }
else if (!strcmp(cs,"int") || !strcmp(cs,"enum")) { else if (!strcmp(cs, "int") || !strcmp(cs, "Int") || !strcmp(cs, "enum") || !strcmp(cs, "Enum")) {
return new TypedProperty<int>(ParseTokenAsInt(*tok[4])); return new TypedProperty<int>(ParseTokenAsInt(*tok[4]));
} }
else if (!strcmp(cs,"ULongLong")) { else if (!strcmp(cs,"ULongLong")) {
@ -105,7 +105,7 @@ Property* ReadTypedProperty(const Element& element)
ParseTokenAsFloat(*tok[6])) ParseTokenAsFloat(*tok[6]))
); );
} }
else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"KTime") || !strcmp(cs,"Float")) { else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"KTime") || !strcmp(cs,"Float") || !strcmp(cs,"FieldOfView")) {
return new TypedProperty<float>(ParseTokenAsFloat(*tok[4])); return new TypedProperty<float>(ParseTokenAsFloat(*tok[4]));
} }
return NULL; return NULL;

View File

@ -143,8 +143,7 @@ private:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
template <typename T> template <typename T>
inline T PropertyGet(const PropertyTable& in, const std::string& name, inline T PropertyGet(const PropertyTable& in, const std::string& name,
const T& defaultValue, const T& defaultValue)
bool ignoreTemplate = false)
{ {
const Property* const prop = in.Get(name); const Property* const prop = in.Get(name);
if(!prop) { if(!prop) {
@ -164,8 +163,7 @@ inline T PropertyGet(const PropertyTable& in, const std::string& name,
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
template <typename T> template <typename T>
inline T PropertyGet(const PropertyTable& in, const std::string& name, inline T PropertyGet(const PropertyTable& in, const std::string& name,
bool& result, bool& result)
bool ignoreTemplate = false)
{ {
const Property* const prop = in.Get(name); const Property* const prop = in.Get(name);
if(!prop) { if(!prop) {

View File

@ -58,14 +58,15 @@ namespace FBX {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int line, unsigned int column) Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int line, unsigned int column)
: sbegin(sbegin) :
#ifdef DEBUG
contents(sbegin, static_cast<size_t>(send-sbegin)),
#endif
sbegin(sbegin)
, send(send) , send(send)
, type(type) , type(type)
, line(line) , line(line)
, column(column) , column(column)
#ifdef DEBUG
, contents(sbegin, static_cast<size_t>(send-sbegin))
#endif
{ {
ai_assert(sbegin); ai_assert(sbegin);
ai_assert(send); ai_assert(send);

View File

@ -85,8 +85,7 @@ bool CompareBones(const aiMesh* orig, const aiMesh* inst)
aiBone* oha = inst->mBones[i]; aiBone* oha = inst->mBones[i];
if (aha->mNumWeights != oha->mNumWeights || if (aha->mNumWeights != oha->mNumWeights ||
aha->mOffsetMatrix != oha->mOffsetMatrix || aha->mOffsetMatrix != oha->mOffsetMatrix) {
aha->mNumWeights != oha->mNumWeights) {
return false; return false;
} }
@ -174,7 +173,6 @@ void FindInstancesProcess::Execute( aiScene* pScene)
// use a constant epsilon for colors and UV coordinates // use a constant epsilon for colors and UV coordinates
static const float uvEpsilon = 10e-4f; static const float uvEpsilon = 10e-4f;
{ {
unsigned int i, end = orig->GetNumUVChannels(); unsigned int i, end = orig->GetNumUVChannels();
for(i = 0; i < end; ++i) { for(i = 0; i < end; ++i) {
@ -260,7 +258,7 @@ void FindInstancesProcess::Execute( aiScene* pScene)
pScene->mMeshes[real++] = pScene->mMeshes[i]; pScene->mMeshes[real++] = pScene->mMeshes[i];
} }
// And update the nodegraph with our nice lookup table // And update the node graph with our nice lookup table
UpdateMeshIndices(pScene->mRootNode,remapping.get()); UpdateMeshIndices(pScene->mRootNode,remapping.get());
// write to log // write to log

View File

@ -221,7 +221,7 @@ AI_FORCE_INLINE bool EpsilonCompare(const T& n, const T& s, float epsilon);
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AI_FORCE_INLINE bool EpsilonCompare(float n, float s, float epsilon) { AI_FORCE_INLINE bool EpsilonCompare(float n, float s, float epsilon) {
return fabs(n-s)>epsilon; return std::fabs(n-s)>epsilon;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -149,8 +149,8 @@ bool FixInfacingNormalsProcess::ProcessMesh( aiMesh* pcMesh, unsigned int index)
if (fDelta1_z < 0.05f * sqrtf( fDelta1_y * fDelta1_x ))return false; if (fDelta1_z < 0.05f * sqrtf( fDelta1_y * fDelta1_x ))return false;
// now compare the volumes of the bounding boxes // now compare the volumes of the bounding boxes
if (::fabsf(fDelta0_x * fDelta1_yz) < if (std::fabs(fDelta0_x * fDelta1_yz) <
::fabsf(fDelta1_x * fDelta1_y * fDelta1_z)) std::fabs(fDelta1_x * fDelta1_y * fDelta1_z))
{ {
if (!DefaultLogger::isNullLogger()) if (!DefaultLogger::isNullLogger())
{ {

View File

@ -93,7 +93,7 @@ void GenVertexNormalsProcess::Execute( aiScene* pScene)
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(GenMeshVertexNormals( pScene->mMeshes[a],a)) if(GenMeshVertexNormals( pScene->mMeshes[a],a))
bHas = true; bHas = true;
} }
@ -204,7 +204,7 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
// Slower code path if a smooth angle is set. There are many ways to achieve // Slower code path if a smooth angle is set. There are many ways to achieve
// the effect, this one is the most straightforward one. // the effect, this one is the most straightforward one.
else { else {
const float fLimit = ::cos(configMaxAngle); const float fLimit = std::cos(configMaxAngle);
for (unsigned int i = 0; i < pMesh->mNumVertices;++i) { for (unsigned int i = 0; i < pMesh->mNumVertices;++i) {
// Get all vertices that share this one ... // Get all vertices that share this one ...
vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound); vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound);

View File

@ -53,7 +53,7 @@ namespace Assimp {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** The GenFaceNormalsProcess computes vertex normals for all vertizes /** The GenFaceNormalsProcess computes vertex normals for all vertizes
*/ */
class ASSIMP_API_WINONLY GenVertexNormalsProcess : public BaseProcess class ASSIMP_API GenVertexNormalsProcess : public BaseProcess
{ {
public: public:

View File

@ -69,8 +69,8 @@ Intersect IntersectSegmentPlane(const IfcVector3& p,const IfcVector3& n, const I
const IfcVector3 pdelta = e0 - p, seg = e1-e0; const IfcVector3 pdelta = e0 - p, seg = e1-e0;
const IfcFloat dotOne = n*seg, dotTwo = -(n*pdelta); const IfcFloat dotOne = n*seg, dotTwo = -(n*pdelta);
if (fabs(dotOne) < 1e-6) { if (std::fabs(dotOne) < 1e-6) {
return fabs(dotTwo) < 1e-6f ? Intersect_LiesOnPlane : Intersect_No; return std::fabs(dotTwo) < 1e-6f ? Intersect_LiesOnPlane : Intersect_No;
} }
const IfcFloat t = dotTwo/dotOne; const IfcFloat t = dotTwo/dotOne;
@ -85,7 +85,7 @@ Intersect IntersectSegmentPlane(const IfcVector3& p,const IfcVector3& n, const I
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ProcessBooleanHalfSpaceDifference(const IfcHalfSpaceSolid* hs, TempMesh& result, void ProcessBooleanHalfSpaceDifference(const IfcHalfSpaceSolid* hs, TempMesh& result,
const TempMesh& first_operand, const TempMesh& first_operand,
ConversionData& conv) ConversionData& /*conv*/)
{ {
ai_assert(hs != NULL); ai_assert(hs != NULL);
@ -210,7 +210,7 @@ bool IntersectsBoundaryProfile( const IfcVector3& e0, const IfcVector3& e1, cons
// segment-segment intersection // segment-segment intersection
// solve b0 + b*s = e0 + e*t for (s,t) // solve b0 + b*s = e0 + e*t for (s,t)
const IfcFloat det = (-b.x * e.y + e.x * b.y); const IfcFloat det = (-b.x * e.y + e.x * b.y);
if(fabs(det) < 1e-6) { if(std::fabs(det) < 1e-6) {
// no solutions (parallel lines) // no solutions (parallel lines)
continue; continue;
} }
@ -234,7 +234,7 @@ bool IntersectsBoundaryProfile( const IfcVector3& e0, const IfcVector3& e1, cons
if (t >= -epsilon && (t <= 1.0+epsilon || half_open) && s >= -epsilon && s <= 1.0) { if (t >= -epsilon && (t <= 1.0+epsilon || half_open) && s >= -epsilon && s <= 1.0) {
if (e0_hits_border && !*e0_hits_border) { if (e0_hits_border && !*e0_hits_border) {
*e0_hits_border = fabs(t) < 1e-5f; *e0_hits_border = std::fabs(t) < 1e-5f;
} }
const IfcVector3& p = e0 + e*t; const IfcVector3& p = e0 + e*t;
@ -419,7 +419,7 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const IfcPolygonalBounded
#ifdef ASSIMP_BUILD_DEBUG #ifdef ASSIMP_BUILD_DEBUG
if (isect == Intersect_Yes) { if (isect == Intersect_Yes) {
const IfcFloat f = fabs((isectpos - p)*n); const IfcFloat f = std::fabs((isectpos - p)*n);
ai_assert(f < 1e-5); ai_assert(f < 1e-5);
} }
#endif #endif

View File

@ -88,10 +88,10 @@ public:
a *= conv.angle_scale; a *= conv.angle_scale;
b *= conv.angle_scale; b *= conv.angle_scale;
a = fmod(a,static_cast<IfcFloat>( AI_MATH_TWO_PI )); a = std::fmod(a,static_cast<IfcFloat>( AI_MATH_TWO_PI ));
b = fmod(b,static_cast<IfcFloat>( AI_MATH_TWO_PI )); b = std::fmod(b,static_cast<IfcFloat>( AI_MATH_TWO_PI ));
const IfcFloat setting = static_cast<IfcFloat>( AI_MATH_PI * conv.settings.conicSamplingAngle / 180.0 ); const IfcFloat setting = static_cast<IfcFloat>( AI_MATH_PI * conv.settings.conicSamplingAngle / 180.0 );
return static_cast<size_t>( ceil(abs( b-a)) / setting); return static_cast<size_t>( std::ceil(abs( b-a)) / setting);
} }
// -------------------------------------------------- // --------------------------------------------------
@ -124,8 +124,8 @@ public:
// -------------------------------------------------- // --------------------------------------------------
IfcVector3 Eval(IfcFloat u) const { IfcVector3 Eval(IfcFloat u) const {
u = -conv.angle_scale * u; u = -conv.angle_scale * u;
return location + static_cast<IfcFloat>(entity.Radius)*(static_cast<IfcFloat>(::cos(u))*p[0] + return location + static_cast<IfcFloat>(entity.Radius)*(static_cast<IfcFloat>(std::cos(u))*p[0] +
static_cast<IfcFloat>(::sin(u))*p[1]); static_cast<IfcFloat>(std::sin(u))*p[1]);
} }
private: private:
@ -153,8 +153,8 @@ public:
// -------------------------------------------------- // --------------------------------------------------
IfcVector3 Eval(IfcFloat u) const { IfcVector3 Eval(IfcFloat u) const {
u = -conv.angle_scale * u; u = -conv.angle_scale * u;
return location + static_cast<IfcFloat>(entity.SemiAxis1)*static_cast<IfcFloat>(::cos(u))*p[0] + return location + static_cast<IfcFloat>(entity.SemiAxis1)*static_cast<IfcFloat>(std::cos(u))*p[0] +
static_cast<IfcFloat>(entity.SemiAxis2)*static_cast<IfcFloat>(::sin(u))*p[1]; static_cast<IfcFloat>(entity.SemiAxis2)*static_cast<IfcFloat>(std::sin(u))*p[1];
} }
private: private:
@ -486,7 +486,7 @@ public:
IfcVector3 Eval(IfcFloat p) const { IfcVector3 Eval(IfcFloat p) const {
ai_assert(InRange(p)); ai_assert(InRange(p));
const size_t b = static_cast<size_t>(floor(p)); const size_t b = static_cast<size_t>(std::floor(p));
if (b == points.size()-1) { if (b == points.size()-1) {
return points.back(); return points.back();
} }
@ -498,7 +498,7 @@ public:
// -------------------------------------------------- // --------------------------------------------------
size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const { size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
ai_assert(InRange(a) && InRange(b)); ai_assert(InRange(a) && InRange(b));
return static_cast<size_t>( ceil(b) - floor(a) ); return static_cast<size_t>( std::ceil(b) - std::floor(a) );
} }
// -------------------------------------------------- // --------------------------------------------------
@ -558,7 +558,7 @@ bool Curve :: InRange(IfcFloat u) const
if (IsClosed()) { if (IsClosed()) {
return true; return true;
//ai_assert(range.first != std::numeric_limits<IfcFloat>::infinity() && range.second != std::numeric_limits<IfcFloat>::infinity()); //ai_assert(range.first != std::numeric_limits<IfcFloat>::infinity() && range.second != std::numeric_limits<IfcFloat>::infinity());
//u = range.first + fmod(u-range.first,range.second-range.first); //u = range.first + std::fmod(u-range.first,range.second-range.first);
} }
const IfcFloat epsilon = 1e-5; const IfcFloat epsilon = 1e-5;
return u - range.first > -epsilon && range.second - u > -epsilon; return u - range.first > -epsilon && range.second - u > -epsilon;
@ -606,12 +606,12 @@ IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, Ifc
} }
ai_assert(min_diff[0] != inf && min_diff[1] != inf); ai_assert(min_diff[0] != inf && min_diff[1] != inf);
if ( fabs(a-min_point[0]) < threshold || recurse >= max_recurse) { if ( std::fabs(a-min_point[0]) < threshold || recurse >= max_recurse) {
return min_point[0]; return min_point[0];
} }
// fix for closed curves to take their wrap-over into account // fix for closed curves to take their wrap-over into account
if (cv->IsClosed() && fabs(min_point[0]-min_point[1]) > cv->GetParametricRangeDelta()*0.5 ) { if (cv->IsClosed() && std::fabs(min_point[0]-min_point[1]) > cv->GetParametricRangeDelta()*0.5 ) {
const Curve::ParamRange& range = cv->GetParametricRange(); const Curve::ParamRange& range = cv->GetParametricRange();
const IfcFloat wrapdiff = (cv->Eval(range.first)-val).SquareLength(); const IfcFloat wrapdiff = (cv->Eval(range.first)-val).SquareLength();

View File

@ -250,17 +250,17 @@ void ProcessRevolvedAreaSolid(const IfcRevolvedAreaSolid& solid, TempMesh& resul
bool has_area = solid.SweptArea->ProfileType == "AREA" && size>2; bool has_area = solid.SweptArea->ProfileType == "AREA" && size>2;
const IfcFloat max_angle = solid.Angle*conv.angle_scale; const IfcFloat max_angle = solid.Angle*conv.angle_scale;
if(fabs(max_angle) < 1e-3) { if(std::fabs(max_angle) < 1e-3) {
if(has_area) { if(has_area) {
result = meshout; result = meshout;
} }
return; return;
} }
const unsigned int cnt_segments = std::max(2u,static_cast<unsigned int>(16 * fabs(max_angle)/AI_MATH_HALF_PI_F)); const unsigned int cnt_segments = std::max(2u,static_cast<unsigned int>(16 * std::fabs(max_angle)/AI_MATH_HALF_PI_F));
const IfcFloat delta = max_angle/cnt_segments; const IfcFloat delta = max_angle/cnt_segments;
has_area = has_area && fabs(max_angle) < AI_MATH_TWO_PI_F*0.99; has_area = has_area && std::fabs(max_angle) < AI_MATH_TWO_PI_F*0.99;
result.verts.reserve(size*((cnt_segments+1)*4+(has_area?2:0))); result.verts.reserve(size*((cnt_segments+1)*4+(has_area?2:0)));
result.vertcnt.reserve(size*cnt_segments+2); result.vertcnt.reserve(size*cnt_segments+2);
@ -480,7 +480,7 @@ IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh, bool& ok, IfcVect
for (i = 0; !done && i < s-2; done || ++i) { for (i = 0; !done && i < s-2; done || ++i) {
for (j = i+1; j < s-1; ++j) { for (j = i+1; j < s-1; ++j) {
nor = -((out[i]-any_point)^(out[j]-any_point)); nor = -((out[i]-any_point)^(out[j]-any_point));
if(fabs(nor.Length()) > 1e-8f) { if(std::fabs(nor.Length()) > 1e-8f) {
done = true; done = true;
break; break;
} }

View File

@ -259,7 +259,7 @@ BoundingBox GetBoundingBox(const ClipperLib::Polygon& poly)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void InsertWindowContours(const ContourVector& contours, void InsertWindowContours(const ContourVector& contours,
const std::vector<TempOpening>& openings, const std::vector<TempOpening>& /*openings*/,
TempMesh& curmesh) TempMesh& curmesh)
{ {
// fix windows - we need to insert the real, polygonal shapes into the quadratic holes that we have now // fix windows - we need to insert the real, polygonal shapes into the quadratic holes that we have now
@ -303,20 +303,20 @@ void InsertWindowContours(const ContourVector& contours,
const IfcVector2& v = contour[n]; const IfcVector2& v = contour[n];
bool hit = false; bool hit = false;
if (fabs(v.x-bb.first.x)<epsilon) { if (std::fabs(v.x-bb.first.x)<epsilon) {
edge.x = bb.first.x; edge.x = bb.first.x;
hit = true; hit = true;
} }
else if (fabs(v.x-bb.second.x)<epsilon) { else if (std::fabs(v.x-bb.second.x)<epsilon) {
edge.x = bb.second.x; edge.x = bb.second.x;
hit = true; hit = true;
} }
if (fabs(v.y-bb.first.y)<epsilon) { if (std::fabs(v.y-bb.first.y)<epsilon) {
edge.y = bb.first.y; edge.y = bb.first.y;
hit = true; hit = true;
} }
else if (fabs(v.y-bb.second.y)<epsilon) { else if (std::fabs(v.y-bb.second.y)<epsilon) {
edge.y = bb.second.y; edge.y = bb.second.y;
hit = true; hit = true;
} }
@ -343,17 +343,17 @@ void InsertWindowContours(const ContourVector& contours,
IfcVector2 corner = edge; IfcVector2 corner = edge;
if (fabs(contour[last_hit].x-bb.first.x)<epsilon) { if (std::fabs(contour[last_hit].x-bb.first.x)<epsilon) {
corner.x = bb.first.x; corner.x = bb.first.x;
} }
else if (fabs(contour[last_hit].x-bb.second.x)<epsilon) { else if (std::fabs(contour[last_hit].x-bb.second.x)<epsilon) {
corner.x = bb.second.x; corner.x = bb.second.x;
} }
if (fabs(contour[last_hit].y-bb.first.y)<epsilon) { if (std::fabs(contour[last_hit].y-bb.first.y)<epsilon) {
corner.y = bb.first.y; corner.y = bb.first.y;
} }
else if (fabs(contour[last_hit].y-bb.second.y)<epsilon) { else if (std::fabs(contour[last_hit].y-bb.second.y)<epsilon) {
corner.y = bb.second.y; corner.y = bb.second.y;
} }
@ -590,10 +590,10 @@ bool BoundingBoxesAdjacent(const BoundingBox& bb, const BoundingBox& ibb)
{ {
// TODO: I'm pretty sure there is a much more compact way to check this // TODO: I'm pretty sure there is a much more compact way to check this
const IfcFloat epsilon = 1e-5f; const IfcFloat epsilon = 1e-5f;
return (fabs(bb.second.x - ibb.first.x) < epsilon && bb.first.y <= ibb.second.y && bb.second.y >= ibb.first.y) || return (std::fabs(bb.second.x - ibb.first.x) < epsilon && bb.first.y <= ibb.second.y && bb.second.y >= ibb.first.y) ||
(fabs(bb.first.x - ibb.second.x) < epsilon && ibb.first.y <= bb.second.y && ibb.second.y >= bb.first.y) || (std::fabs(bb.first.x - ibb.second.x) < epsilon && ibb.first.y <= bb.second.y && ibb.second.y >= bb.first.y) ||
(fabs(bb.second.y - ibb.first.y) < epsilon && bb.first.x <= ibb.second.x && bb.second.x >= ibb.first.x) || (std::fabs(bb.second.y - ibb.first.y) < epsilon && bb.first.x <= ibb.second.x && bb.second.x >= ibb.first.x) ||
(fabs(bb.first.y - ibb.second.y) < epsilon && ibb.first.x <= bb.second.x && ibb.second.x >= bb.first.x); (std::fabs(bb.first.y - ibb.second.y) < epsilon && ibb.first.x <= bb.second.x && ibb.second.x >= bb.first.x);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -615,11 +615,11 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
static const IfcFloat inf = std::numeric_limits<IfcFloat>::infinity(); static const IfcFloat inf = std::numeric_limits<IfcFloat>::infinity();
if (!(n0_to_m0.SquareLength() < e*e || fabs(n0_to_m0 * n0_to_n1) / (n0_to_m0.Length() * n0_to_n1.Length()) > 1-1e-5 )) { if (!(n0_to_m0.SquareLength() < e*e || std::fabs(n0_to_m0 * n0_to_n1) / (n0_to_m0.Length() * n0_to_n1.Length()) > 1-1e-5 )) {
return false; return false;
} }
if (!(n1_to_m1.SquareLength() < e*e || fabs(n1_to_m1 * n0_to_n1) / (n1_to_m1.Length() * n0_to_n1.Length()) > 1-1e-5 )) { if (!(n1_to_m1.SquareLength() < e*e || std::fabs(n1_to_m1 * n0_to_n1) / (n1_to_m1.Length() * n0_to_n1.Length()) > 1-1e-5 )) {
return false; return false;
} }
@ -631,14 +631,14 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
// the higher absolute difference is big enough as to avoid // the higher absolute difference is big enough as to avoid
// divisions by zero, the case 0/0 ~ infinity is detected and // divisions by zero, the case 0/0 ~ infinity is detected and
// handled separately. // handled separately.
if(fabs(n0_to_n1.x) > fabs(n0_to_n1.y)) { if(std::fabs(n0_to_n1.x) > std::fabs(n0_to_n1.y)) {
s0 = n0_to_m0.x / n0_to_n1.x; s0 = n0_to_m0.x / n0_to_n1.x;
s1 = n0_to_m1.x / n0_to_n1.x; s1 = n0_to_m1.x / n0_to_n1.x;
if (fabs(s0) == inf && fabs(n0_to_m0.x) < smalle) { if (std::fabs(s0) == inf && std::fabs(n0_to_m0.x) < smalle) {
s0 = 0.; s0 = 0.;
} }
if (fabs(s1) == inf && fabs(n0_to_m1.x) < smalle) { if (std::fabs(s1) == inf && std::fabs(n0_to_m1.x) < smalle) {
s1 = 0.; s1 = 0.;
} }
} }
@ -646,10 +646,10 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
s0 = n0_to_m0.y / n0_to_n1.y; s0 = n0_to_m0.y / n0_to_n1.y;
s1 = n0_to_m1.y / n0_to_n1.y; s1 = n0_to_m1.y / n0_to_n1.y;
if (fabs(s0) == inf && fabs(n0_to_m0.y) < smalle) { if (std::fabs(s0) == inf && std::fabs(n0_to_m0.y) < smalle) {
s0 = 0.; s0 = 0.;
} }
if (fabs(s1) == inf && fabs(n0_to_m1.y) < smalle) { if (std::fabs(s1) == inf && std::fabs(n0_to_m1.y) < smalle) {
s1 = 0.; s1 = 0.;
} }
} }
@ -664,7 +664,7 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
s0 = std::min(1.0,s0); s0 = std::min(1.0,s0);
s1 = std::min(1.0,s1); s1 = std::min(1.0,s1);
if (fabs(s1-s0) < e) { if (std::fabs(s1-s0) < e) {
return false; return false;
} }
@ -755,7 +755,7 @@ void FindAdjacentContours(ContourVector::iterator current, const ContourVector&
AI_FORCE_INLINE bool LikelyBorder(const IfcVector2& vdelta) AI_FORCE_INLINE bool LikelyBorder(const IfcVector2& vdelta)
{ {
const IfcFloat dot_point_epsilon = static_cast<IfcFloat>(1e-5); const IfcFloat dot_point_epsilon = static_cast<IfcFloat>(1e-5);
return fabs(vdelta.x * vdelta.y) < dot_point_epsilon; return std::fabs(vdelta.x * vdelta.y) < dot_point_epsilon;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -812,9 +812,9 @@ void FindBorderContours(ContourVector::iterator current)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
AI_FORCE_INLINE bool LikelyDiagonal(IfcVector2 vdelta) AI_FORCE_INLINE bool LikelyDiagonal(IfcVector2 vdelta)
{ {
vdelta.x = fabs(vdelta.x); vdelta.x = std::fabs(vdelta.x);
vdelta.y = fabs(vdelta.y); vdelta.y = std::fabs(vdelta.y);
return (fabs(vdelta.x-vdelta.y) < 0.8 * std::max(vdelta.x, vdelta.y)); return (std::fabs(vdelta.x-vdelta.y) < 0.8 * std::max(vdelta.x, vdelta.y));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -926,7 +926,7 @@ size_t CloseWindows(ContourVector& contours,
/* debug code to check for unwanted diagonal lines in window contours /* debug code to check for unwanted diagonal lines in window contours
if (cit != cbegin) { if (cit != cbegin) {
const IfcVector2& vdelta = proj_point - last_proj; const IfcVector2& vdelta = proj_point - last_proj;
if (fabs(vdelta.x-vdelta.y) < 0.5 * std::max(vdelta.x, vdelta.y)) { if (std::fabs(vdelta.x-vdelta.y) < 0.5 * std::max(vdelta.x, vdelta.y)) {
//continue; //continue;
} }
} */ } */
@ -1065,7 +1065,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh
} }
#ifdef ASSIMP_BUILD_DEBUG #ifdef ASSIMP_BUILD_DEBUG
const IfcFloat det = m.Determinant(); const IfcFloat det = m.Determinant();
ai_assert(fabs(det-1) < 1e-5); ai_assert(std::fabs(det-1) < 1e-5);
#endif #endif
IfcFloat zcoord = 0; IfcFloat zcoord = 0;
@ -1085,7 +1085,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh
// XXX this should be guarded, but we somehow need to pick a suitable // XXX this should be guarded, but we somehow need to pick a suitable
// epsilon // epsilon
// if(coord != -1.0f) { // if(coord != -1.0f) {
// assert(fabs(coord - vv.z) < 1e-3f); // assert(std::fabs(coord - vv.z) < 1e-3f);
// } // }
zcoord += vv.z; zcoord += vv.z;
vmin = std::min(vv, vmin); vmin = std::min(vv, vmin);
@ -1125,7 +1125,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh
const IfcVector3& vv = m * x; const IfcVector3& vv = m * x;
out_contour2.push_back(IfcVector2(vv.x,vv.y)); out_contour2.push_back(IfcVector2(vv.x,vv.y));
ai_assert(fabs(vv.z) < vmax.z + 1e-8); ai_assert(std::fabs(vv.z) < vmax.z + 1e-8);
} }
for(size_t i = 0; i < out_contour.size(); ++i) { for(size_t i = 0; i < out_contour.size(); ++i) {
@ -1188,9 +1188,9 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
bool is_2d_source = false; bool is_2d_source = false;
if (opening.profileMesh2D && norm_extrusion_dir.SquareLength() > 0) { if (opening.profileMesh2D && norm_extrusion_dir.SquareLength() > 0) {
if(fabs(norm_extrusion_dir * wall_extrusion_axis_norm) < 0.1) { if(std::fabs(norm_extrusion_dir * wall_extrusion_axis_norm) < 0.1) {
// horizontal extrusion // horizontal extrusion
if (fabs(norm_extrusion_dir * nor) > 0.9) { if (std::fabs(norm_extrusion_dir * nor) > 0.9) {
profile_data = opening.profileMesh2D.get(); profile_data = opening.profileMesh2D.get();
is_2d_source = true; is_2d_source = true;
} }
@ -1200,7 +1200,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
} }
else { else {
// vertical extrusion // vertical extrusion
if (fabs(norm_extrusion_dir * nor) > 0.9) { if (std::fabs(norm_extrusion_dir * nor) > 0.9) {
continue; continue;
} }
continue; continue;
@ -1289,7 +1289,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
ai_assert(!is_2d_source); ai_assert(!is_2d_source);
const IfcVector2 area = vpmax-vpmin; const IfcVector2 area = vpmax-vpmin;
const IfcVector2 area2 = vpmax2-vpmin2; const IfcVector2 area2 = vpmax2-vpmin2;
if (temp_contour.size() <= 2 || fabs(area2.x * area2.y) > fabs(area.x * area.y)) { if (temp_contour.size() <= 2 || std::fabs(area2.x * area2.y) > std::fabs(area.x * area.y)) {
temp_contour.swap(temp_contour2); temp_contour.swap(temp_contour2);
vpmax = vpmax2; vpmax = vpmax2;
@ -1301,7 +1301,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
} }
// TODO: This epsilon may be too large // TODO: This epsilon may be too large
const IfcFloat epsilon = fabs(dmax-dmin) * 0.0001; const IfcFloat epsilon = std::fabs(dmax-dmin) * 0.0001;
if (!is_2d_source && check_intersection && (0 < dmin-epsilon || 0 > dmax+epsilon)) { if (!is_2d_source && check_intersection && (0 < dmin-epsilon || 0 > dmax+epsilon)) {
continue; continue;
} }
@ -1310,7 +1310,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
// Skip over very small openings - these are likely projection errors // Skip over very small openings - these are likely projection errors
// (i.e. they don't belong to this side of the wall) // (i.e. they don't belong to this side of the wall)
if(fabs(vpmax.x - vpmin.x) * fabs(vpmax.y - vpmin.y) < static_cast<IfcFloat>(1e-10)) { if(std::fabs(vpmax.x - vpmin.x) * std::fabs(vpmax.y - vpmin.y) < static_cast<IfcFloat>(1e-10)) {
continue; continue;
} }
std::vector<TempOpening*> joined_openings(1, &opening); std::vector<TempOpening*> joined_openings(1, &opening);
@ -1480,7 +1480,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
// XXX this should be guarded, but we somehow need to pick a suitable // XXX this should be guarded, but we somehow need to pick a suitable
// epsilon // epsilon
// if(coord != -1.0f) { // if(coord != -1.0f) {
// assert(fabs(coord - vv.z) < 1e-3f); // assert(std::fabs(coord - vv.z) < 1e-3f);
// } // }
coord = vv.z; coord = vv.z;
@ -1515,7 +1515,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
BOOST_FOREACH(const TempOpening& t,openings) { BOOST_FOREACH(const TempOpening& t,openings) {
const IfcVector3& outernor = nors[c++]; const IfcVector3& outernor = nors[c++];
const IfcFloat dot = nor * outernor; const IfcFloat dot = nor * outernor;
if (fabs(dot)<1.f-1e-6f) { if (std::fabs(dot)<1.f-1e-6f) {
continue; continue;
} }
@ -1529,7 +1529,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
BOOST_FOREACH(const IfcVector3& xx, t.profileMesh->verts) { BOOST_FOREACH(const IfcVector3& xx, t.profileMesh->verts) {
IfcVector3 vv = m * xx, vv_extr = m * (xx + t.extrusionDir); IfcVector3 vv = m * xx, vv_extr = m * (xx + t.extrusionDir);
const bool is_extruded_side = fabs(vv.z - coord) > fabs(vv_extr.z - coord); const bool is_extruded_side = std::fabs(vv.z - coord) > std::fabs(vv_extr.z - coord);
if (first) { if (first) {
first = false; first = false;
if (dot > 0.f) { if (dot > 0.f) {
@ -1741,4 +1741,4 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
#undef from_int64 #undef from_int64
#undef one_vec #undef one_vec
#endif #endif

View File

@ -101,7 +101,7 @@ void ProcessOpenProfile(const IfcArbitraryOpenProfileDef& def, TempMesh& meshout
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& conv) void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& /*conv*/)
{ {
if(const IfcRectangleProfileDef* const cprofile = def.ToPtr<IfcRectangleProfileDef>()) { if(const IfcRectangleProfileDef* const cprofile = def.ToPtr<IfcRectangleProfileDef>()) {
const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f; const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f;
@ -124,7 +124,7 @@ void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh&
IfcFloat angle = 0.f; IfcFloat angle = 0.f;
for(size_t i = 0; i < segments; ++i, angle += delta) { for(size_t i = 0; i < segments; ++i, angle += delta) {
meshout.verts.push_back( IfcVector3( cos(angle)*radius, sin(angle)*radius, 0.f )); meshout.verts.push_back( IfcVector3( std::cos(angle)*radius, std::sin(angle)*radius, 0.f ));
} }
meshout.vertcnt.push_back(segments); meshout.vertcnt.push_back(segments);

View File

@ -1045,7 +1045,7 @@ void IFC::GetSchema(EXPRESS::ConversionSchema& out)
namespace STEP { namespace STEP {
// ----------------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<NotImplemented>(const STEP::DB& db, const LIST& params, NotImplemented* in) template <> size_t GenericFill<NotImplemented>(const STEP::DB& /*db*/, const LIST& /*params*/, NotImplemented* /*in*/)
{ {
return 0; return 0;
} }
@ -1253,7 +1253,7 @@ template <> size_t GenericFill<IfcPerformanceHistory>(const DB& db, const LIST&
return base; return base;
} }
// ----------------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<IfcRepresentationItem>(const DB& db, const LIST& params, IfcRepresentationItem* in) template <> size_t GenericFill<IfcRepresentationItem>(const DB& /*db*/, const LIST& /*params*/, IfcRepresentationItem* /*in*/)
{ {
size_t base = 0; size_t base = 0;
return base; return base;
@ -1715,7 +1715,7 @@ template <> size_t GenericFill<IfcPlateType>(const DB& db, const LIST& params, I
return base; return base;
} }
// ----------------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------------
template <> size_t GenericFill<IfcObjectPlacement>(const DB& db, const LIST& params, IfcObjectPlacement* in) template <> size_t GenericFill<IfcObjectPlacement>(const DB& /*db*/, const LIST& /*params*/, IfcObjectPlacement* /*in*/)
{ {
size_t base = 0; size_t base = 0;
return base; return base;

View File

@ -278,7 +278,7 @@ void TempMesh::RemoveAdjacentDuplicates()
// continue; // continue;
// } // }
// const IfcFloat d = (d0/sqrt(l0))*(d1/sqrt(l1)); // const IfcFloat d = (d0/std::sqrt(l0))*(d1/std::sqrt(l1));
// if ( d >= 1.f-dotepsilon ) { // if ( d >= 1.f-dotepsilon ) {
// v1 = v0; // v1 = v0;

View File

@ -220,7 +220,7 @@ struct FuzzyVectorCompare {
FuzzyVectorCompare(IfcFloat epsilon) : epsilon(epsilon) {} FuzzyVectorCompare(IfcFloat epsilon) : epsilon(epsilon) {}
bool operator()(const IfcVector3& a, const IfcVector3& b) { bool operator()(const IfcVector3& a, const IfcVector3& b) {
return fabs((a-b).SquareLength()) < epsilon; return std::fabs((a-b).SquareLength()) < epsilon;
} }
const IfcFloat epsilon; const IfcFloat epsilon;

View File

@ -12,8 +12,6 @@
namespace Assimp { namespace Assimp {
namespace IFF { namespace IFF {
#include "./../include/assimp/Compiler/pushpack1.h"
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
//! Describes an IFF chunk header //! Describes an IFF chunk header
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
@ -24,7 +22,7 @@ struct ChunkHeader
//! Length of the chunk data, in bytes //! Length of the chunk data, in bytes
uint32_t length; uint32_t length;
} PACK_STRUCT; };
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
@ -37,9 +35,7 @@ struct SubChunkHeader
//! Length of the chunk data, in bytes //! Length of the chunk data, in bytes
uint16_t length; uint16_t length;
} PACK_STRUCT; };
#include "./../include/assimp/Compiler/poppack1.h"
#define AI_IFF_FOURCC(a,b,c,d) ((uint32_t) (((uint8_t)a << 24u) | \ #define AI_IFF_FOURCC(a,b,c,d) ((uint32_t) (((uint8_t)a << 24u) | \
@ -52,28 +48,34 @@ struct SubChunkHeader
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
//! Load a chunk header //! Load a chunk header
//! @param outFile Pointer to the file data - points to the chunk data afterwards //! @param outFile Pointer to the file data - points to the chunk data afterwards
//! @return Pointer to the chunk header //! @return Copy of the chunk header
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
inline ChunkHeader* LoadChunk(uint8_t*& outFile) inline ChunkHeader LoadChunk(uint8_t*& outFile)
{ {
ChunkHeader* head = (ChunkHeader*) outFile; ChunkHeader head;
AI_LSWAP4(head->length); ::memcpy(&head.type, outFile, 4);
AI_LSWAP4(head->type); outFile += 4;
outFile += sizeof(ChunkHeader); ::memcpy(&head.length, outFile, 4);
outFile += 4;
AI_LSWAP4(head.length);
AI_LSWAP4(head.type);
return head; return head;
} }
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
//! Load a sub chunk header //! Load a sub chunk header
//! @param outFile Pointer to the file data - points to the chunk data afterwards //! @param outFile Pointer to the file data - points to the chunk data afterwards
//! @return Pointer to the sub chunk header //! @return Copy of the sub chunk header
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
inline SubChunkHeader* LoadSubChunk(uint8_t*& outFile) inline SubChunkHeader LoadSubChunk(uint8_t*& outFile)
{ {
SubChunkHeader* head = (SubChunkHeader*) outFile; SubChunkHeader head;
AI_LSWAP2(head->length); ::memcpy(&head.type, outFile, 4);
AI_LSWAP4(head->type); outFile += 4;
outFile += sizeof(SubChunkHeader); ::memcpy(&head.length, outFile, 2);
outFile += 2;
AI_LSWAP2(head.length);
AI_LSWAP4(head.type);
return head; return head;
} }
@ -84,14 +86,14 @@ inline SubChunkHeader* LoadSubChunk(uint8_t*& outFile)
//! @param fileType Receives the type of the file //! @param fileType Receives the type of the file
//! @return 0 if everything was OK, otherwise an error message //! @return 0 if everything was OK, otherwise an error message
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
inline const char* ReadHeader(uint8_t* outFile,uint32_t& fileType) inline const char* ReadHeader(uint8_t* outFile, uint32_t& fileType)
{ {
ChunkHeader* head = LoadChunk(outFile); ChunkHeader head = LoadChunk(outFile);
if(AI_IFF_FOURCC_FORM != head->type) if(AI_IFF_FOURCC_FORM != head.type)
{ {
return "The file is not an IFF file: FORM chunk is missing"; return "The file is not an IFF file: FORM chunk is missing";
} }
fileType = *((uint32_t*)(head+1)); ::memcpy(&fileType, outFile, 4);
AI_LSWAP4(fileType); AI_LSWAP4(fileType);
return 0; return 0;
} }

View File

@ -470,7 +470,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
key.mTime = i * tdelta; key.mTime = i * tdelta;
const float t = (float) ( in.speed * key.mTime ); const float t = (float) ( in.speed * key.mTime );
key.mValue = in.circleCenter + in.circleRadius * ((vecU*::cosf(t)) + (vecV*::sinf(t))); key.mValue = in.circleCenter + in.circleRadius * ((vecU * std::cos(t)) + (vecV * std::sin(t)));
} }
// This animation is repeated and repeated ... // This animation is repeated and repeated ...
@ -533,8 +533,8 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
aiVectorKey& key = anim->mPositionKeys[i]; aiVectorKey& key = anim->mPositionKeys[i];
const float dt = (i * in.speed * 0.001f ); const float dt = (i * in.speed * 0.001f );
const float u = dt - floor(dt); const float u = dt - std::floor(dt);
const int idx = (int)floor(dt) % size; const int idx = (int)std::floor(dt) % size;
// get the 4 current points to evaluate the spline // get the 4 current points to evaluate the spline
const aiVector3D& p0 = in.splineKeys[ ClampSpline( idx - 1, size ) ].mValue; const aiVector3D& p0 = in.splineKeys[ ClampSpline( idx - 1, size ) ].mValue;

View File

@ -640,16 +640,25 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
} }
} }
// Get file size for progress handler
IOStream * fileIO = pimpl->mIOHandler->Open( pFile );
uint32_t fileSize = 0;
if (fileIO)
{
fileSize = fileIO->FileSize();
pimpl->mIOHandler->Close( fileIO );
}
// Dispatch the reading to the worker class for this format // Dispatch the reading to the worker class for this format
DefaultLogger::get()->info("Found a matching importer for this file format"); DefaultLogger::get()->info("Found a matching importer for this file format");
pimpl->mProgressHandler->Update(); pimpl->mProgressHandler->UpdateFileRead( 0, fileSize );
if (profiler) { if (profiler) {
profiler->BeginRegion("import"); profiler->BeginRegion("import");
} }
pimpl->mScene = imp->ReadFile( this, pFile, pimpl->mIOHandler); pimpl->mScene = imp->ReadFile( this, pFile, pimpl->mIOHandler);
pimpl->mProgressHandler->Update(); pimpl->mProgressHandler->UpdateFileRead( fileSize, fileSize );
if (profiler) { if (profiler) {
profiler->EndRegion("import"); profiler->EndRegion("import");
@ -678,7 +687,6 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
ScenePreprocessor pre(pimpl->mScene); ScenePreprocessor pre(pimpl->mScene);
pre.ProcessScene(); pre.ProcessScene();
pimpl->mProgressHandler->Update();
if (profiler) { if (profiler) {
profiler->EndRegion("preprocess"); profiler->EndRegion("preprocess");
} }
@ -768,6 +776,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) { for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
BaseProcess* process = pimpl->mPostProcessingSteps[a]; BaseProcess* process = pimpl->mPostProcessingSteps[a];
pimpl->mProgressHandler->UpdatePostProcess( a, pimpl->mPostProcessingSteps.size() );
if( process->IsActive( pFlags)) { if( process->IsActive( pFlags)) {
if (profiler) { if (profiler) {
@ -775,7 +784,6 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
} }
process->ExecuteOnScene ( this ); process->ExecuteOnScene ( this );
pimpl->mProgressHandler->Update();
if (profiler) { if (profiler) {
profiler->EndRegion("postprocess"); profiler->EndRegion("postprocess");
@ -803,6 +811,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
} }
#endif // ! DEBUG #endif // ! DEBUG
} }
pimpl->mProgressHandler->UpdatePostProcess( pimpl->mPostProcessingSteps.size(), pimpl->mPostProcessingSteps.size() );
// update private scene flags // update private scene flags
if( pimpl->mScene ) if( pimpl->mScene )

View File

@ -166,6 +166,9 @@ corresponding preprocessor flag to selectively disable formats.
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
# include "FBXImporter.h" # include "FBXImporter.h"
#endif #endif
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
# include "AssbinLoader.h"
#endif
namespace Assimp { namespace Assimp {
@ -291,6 +294,9 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
#if ( !defined ASSIMP_BUILD_NO_FBX_IMPORTER ) #if ( !defined ASSIMP_BUILD_NO_FBX_IMPORTER )
out.push_back( new FBXImporter() ); out.push_back( new FBXImporter() );
#endif #endif
#if ( !defined ASSIMP_BUILD_NO_ASSBIN_IMPORTER )
out.push_back( new AssbinImporter() );
#endif
} }
} }

View File

@ -49,8 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp namespace Assimp
{ {
class JoinVerticesTest;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** The JoinVerticesProcess unites identical vertices in all imported meshes. /** The JoinVerticesProcess unites identical vertices in all imported meshes.
* By default the importer returns meshes where each face addressed its own * By default the importer returns meshes where each face addressed its own
@ -59,7 +57,7 @@ class JoinVerticesTest;
* erases all but one of the copies. This usually reduces the number of vertices * erases all but one of the copies. This usually reduces the number of vertices
* in a mesh by a serious amount and is the standard form to render a mesh. * in a mesh by a serious amount and is the standard form to render a mesh.
*/ */
class ASSIMP_API_WINONLY JoinVerticesProcess : public BaseProcess class ASSIMP_API JoinVerticesProcess : public BaseProcess
{ {
public: public:

View File

@ -58,30 +58,31 @@ void LWOImporter::LoadLWOBFile()
while (running) while (running)
{ {
if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break; if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break;
LE_NCONST IFF::ChunkHeader* const head = IFF::LoadChunk(mFileBuffer); const IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
if (mFileBuffer + head->length > end) if (mFileBuffer + head.length > end)
{ {
throw DeadlyImportError("LWOB: Invalid chunk length"); throw DeadlyImportError("LWOB: Invalid chunk length");
break; break;
} }
uint8_t* const next = mFileBuffer+head->length; uint8_t* const next = mFileBuffer+head.length;
switch (head->type) switch (head.type)
{ {
// vertex list // vertex list
case AI_LWO_PNTS: case AI_LWO_PNTS:
{ {
if (!mCurLayer->mTempPoints.empty()) if (!mCurLayer->mTempPoints.empty())
DefaultLogger::get()->warn("LWO: PNTS chunk encountered twice"); DefaultLogger::get()->warn("LWO: PNTS chunk encountered twice");
else LoadLWOPoints(head->length); else LoadLWOPoints(head.length);
break; break;
} }
// face list // face list
case AI_LWO_POLS: case AI_LWO_POLS:
{ {
if (!mCurLayer->mFaces.empty()) if (!mCurLayer->mFaces.empty())
DefaultLogger::get()->warn("LWO: POLS chunk encountered twice"); DefaultLogger::get()->warn("LWO: POLS chunk encountered twice");
else LoadLWOBPolygons(head->length); else LoadLWOBPolygons(head.length);
break; break;
} }
// list of tags // list of tags
@ -89,14 +90,14 @@ void LWOImporter::LoadLWOBFile()
{ {
if (!mTags->empty()) if (!mTags->empty())
DefaultLogger::get()->warn("LWO: SRFS chunk encountered twice"); DefaultLogger::get()->warn("LWO: SRFS chunk encountered twice");
else LoadLWOTags(head->length); else LoadLWOTags(head.length);
break; break;
} }
// surface chunk // surface chunk
case AI_LWO_SURF: case AI_LWO_SURF:
{ {
LoadLWOBSurface(head->length); LoadLWOBSurface(head.length);
break; break;
} }
} }
@ -137,14 +138,17 @@ void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& face
{ {
while (cursor < end && max--) while (cursor < end && max--)
{ {
uint16_t numIndices = *cursor++; uint16_t numIndices;
verts += numIndices;faces++; ::memcpy(&numIndices, cursor++, 2);
verts += numIndices;
faces++;
cursor += numIndices; cursor += numIndices;
int16_t surface = *cursor++; int16_t surface;
::memcpy(&surface, cursor++, 2);
if (surface < 0) if (surface < 0)
{ {
// there are detail polygons // there are detail polygons
numIndices = *cursor++; ::memcpy(&numIndices, cursor++, 2);
CountVertsAndFacesLWOB(verts,faces,cursor,end,numIndices); CountVertsAndFacesLWOB(verts,faces,cursor,end,numIndices);
} }
} }
@ -159,13 +163,22 @@ void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
while (cursor < end && max--) while (cursor < end && max--)
{ {
LWO::Face& face = *it;++it; LWO::Face& face = *it;++it;
if((face.mNumIndices = *cursor++)) uint16_t numIndices;
::memcpy(&numIndices, cursor++, 2);
face.mNumIndices = numIndices;
if(face.mNumIndices)
{ {
if (cursor + face.mNumIndices >= end)break; if (cursor + face.mNumIndices >= end)
{
break;
}
face.mIndices = new unsigned int[face.mNumIndices]; face.mIndices = new unsigned int[face.mNumIndices];
for (unsigned int i = 0; i < face.mNumIndices;++i) for (unsigned int i = 0; i < face.mNumIndices;++i)
{ {
unsigned int & mi = face.mIndices[i] = *cursor++; unsigned int & mi = face.mIndices[i];
uint16_t index;
::memcpy(&index, cursor++, 2);
mi = index;
if (mi > mCurLayer->mTempPoints.size()) if (mi > mCurLayer->mTempPoints.size())
{ {
DefaultLogger::get()->warn("LWOB: face index is out of range"); DefaultLogger::get()->warn("LWOB: face index is out of range");
@ -174,14 +187,19 @@ void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
} }
} }
else DefaultLogger::get()->warn("LWOB: Face has 0 indices"); else DefaultLogger::get()->warn("LWOB: Face has 0 indices");
int16_t surface = *cursor++; int16_t surface;
::memcpy(&surface, cursor++, 2);
if (surface < 0) if (surface < 0)
{ {
surface = -surface; surface = -surface;
// there are detail polygons. // there are detail polygons.
const uint16_t numPolygons = *cursor++; uint16_t numPolygons;
if (cursor < end)CopyFaceIndicesLWOB(it,cursor,end,numPolygons); ::memcpy(&numPolygons, cursor++, 2);
if (cursor < end)
{
CopyFaceIndicesLWOB(it,cursor,end,numPolygons);
}
} }
face.surfaceIndex = surface-1; face.surfaceIndex = surface-1;
} }
@ -235,7 +253,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
if (mFileBuffer + 6 >= end) if (mFileBuffer + 6 >= end)
break; break;
IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
/* A single test file (sonycam.lwo) seems to have invalid surface chunks. /* A single test file (sonycam.lwo) seems to have invalid surface chunks.
* I'm assuming it's the fault of a single, unknown exporter so there are * I'm assuming it's the fault of a single, unknown exporter so there are
@ -244,18 +262,18 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
* We don't break if the chunk limit is exceeded. Instead, we're computing * We don't break if the chunk limit is exceeded. Instead, we're computing
* how much storage is actually left and work with this value from now on. * how much storage is actually left and work with this value from now on.
*/ */
if (mFileBuffer + head->length > end) { if (mFileBuffer + head.length > end) {
DefaultLogger::get()->error("LWOB: Invalid surface chunk length. Trying to continue."); DefaultLogger::get()->error("LWOB: Invalid surface chunk length. Trying to continue.");
head->length = (uint16_t) (end - mFileBuffer); head.length = (uint16_t) (end - mFileBuffer);
} }
uint8_t* const next = mFileBuffer+head->length; uint8_t* const next = mFileBuffer+head.length;
switch (head->type) switch (head.type)
{ {
// diffuse color // diffuse color
case AI_LWO_COLR: case AI_LWO_COLR:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,COLR,3); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,COLR,3);
surf.mColor.r = GetU1() / 255.0f; surf.mColor.r = GetU1() / 255.0f;
surf.mColor.g = GetU1() / 255.0f; surf.mColor.g = GetU1() / 255.0f;
surf.mColor.b = GetU1() / 255.0f; surf.mColor.b = GetU1() / 255.0f;
@ -264,35 +282,35 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
// diffuse strength ... // diffuse strength ...
case AI_LWO_DIFF: case AI_LWO_DIFF:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,DIFF,2); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,DIFF,2);
surf.mDiffuseValue = GetU2() / 255.0f; surf.mDiffuseValue = GetU2() / 255.0f;
break; break;
} }
// specular strength ... // specular strength ...
case AI_LWO_SPEC: case AI_LWO_SPEC:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPEC,2); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPEC,2);
surf.mSpecularValue = GetU2() / 255.0f; surf.mSpecularValue = GetU2() / 255.0f;
break; break;
} }
// luminosity ... // luminosity ...
case AI_LWO_LUMI: case AI_LWO_LUMI:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LUMI,2); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LUMI,2);
surf.mLuminosity = GetU2() / 255.0f; surf.mLuminosity = GetU2() / 255.0f;
break; break;
} }
// transparency // transparency
case AI_LWO_TRAN: case AI_LWO_TRAN:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,2); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TRAN,2);
surf.mTransparency = GetU2() / 255.0f; surf.mTransparency = GetU2() / 255.0f;
break; break;
} }
// surface flags // surface flags
case AI_LWO_FLAG: case AI_LWO_FLAG:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,FLAG,2); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,FLAG,2);
uint16_t flag = GetU2(); uint16_t flag = GetU2();
if (flag & 0x4 ) surf.mMaximumSmoothAngle = 1.56207f; if (flag & 0x4 ) surf.mMaximumSmoothAngle = 1.56207f;
if (flag & 0x8 ) surf.mColorHighlights = 1.f; if (flag & 0x8 ) surf.mColorHighlights = 1.f;
@ -302,14 +320,14 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
// maximum smoothing angle // maximum smoothing angle
case AI_LWO_SMAN: case AI_LWO_SMAN:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SMAN,4);
surf.mMaximumSmoothAngle = fabs( GetF4() ); surf.mMaximumSmoothAngle = std::fabs( GetF4() );
break; break;
} }
// glossiness // glossiness
case AI_LWO_GLOS: case AI_LWO_GLOS:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,GLOS,2); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,GLOS,2);
surf.mGlossiness = (float)GetU2(); surf.mGlossiness = (float)GetU2();
break; break;
} }
@ -317,42 +335,42 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
case AI_LWO_CTEX: case AI_LWO_CTEX:
{ {
pTex = SetupNewTextureLWOB(surf.mColorTextures, pTex = SetupNewTextureLWOB(surf.mColorTextures,
head->length); head.length);
break; break;
} }
// diffuse texture // diffuse texture
case AI_LWO_DTEX: case AI_LWO_DTEX:
{ {
pTex = SetupNewTextureLWOB(surf.mDiffuseTextures, pTex = SetupNewTextureLWOB(surf.mDiffuseTextures,
head->length); head.length);
break; break;
} }
// specular texture // specular texture
case AI_LWO_STEX: case AI_LWO_STEX:
{ {
pTex = SetupNewTextureLWOB(surf.mSpecularTextures, pTex = SetupNewTextureLWOB(surf.mSpecularTextures,
head->length); head.length);
break; break;
} }
// bump texture // bump texture
case AI_LWO_BTEX: case AI_LWO_BTEX:
{ {
pTex = SetupNewTextureLWOB(surf.mBumpTextures, pTex = SetupNewTextureLWOB(surf.mBumpTextures,
head->length); head.length);
break; break;
} }
// transparency texture // transparency texture
case AI_LWO_TTEX: case AI_LWO_TTEX:
{ {
pTex = SetupNewTextureLWOB(surf.mOpacityTextures, pTex = SetupNewTextureLWOB(surf.mOpacityTextures,
head->length); head.length);
break; break;
} }
// texture path // texture path
case AI_LWO_TIMG: case AI_LWO_TIMG:
{ {
if (pTex) { if (pTex) {
GetS0(pTex->mFileName,head->length); GetS0(pTex->mFileName,head.length);
} }
else DefaultLogger::get()->warn("LWOB: Unexpected TIMG chunk"); else DefaultLogger::get()->warn("LWOB: Unexpected TIMG chunk");
break; break;
@ -360,7 +378,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
// texture strength // texture strength
case AI_LWO_TVAL: case AI_LWO_TVAL:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TVAL,1); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TVAL,1);
if (pTex) { if (pTex) {
pTex->mStrength = (float)GetU1()/ 255.f; pTex->mStrength = (float)GetU1()/ 255.f;
} }
@ -370,7 +388,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
// texture flags // texture flags
case AI_LWO_TFLG: case AI_LWO_TFLG:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TFLG,2); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TFLG,2);
if (pTex) if (pTex)
{ {

View File

@ -503,7 +503,7 @@ void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>&
// Generate vertex normals. We have O(logn) for the binary lookup, which we need // Generate vertex normals. We have O(logn) for the binary lookup, which we need
// for n elements, thus the EXPECTED complexity is O(nlogn) // for n elements, thus the EXPECTED complexity is O(nlogn)
if (surface.mMaximumSmoothAngle < 3.f && !configSpeedFlag) { if (surface.mMaximumSmoothAngle < 3.f && !configSpeedFlag) {
const float fLimit = cos(surface.mMaximumSmoothAngle); const float fLimit = std::cos(surface.mMaximumSmoothAngle);
for( begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it) { for( begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it) {
const aiFace& face = *begin; const aiFace& face = *begin;
@ -787,7 +787,8 @@ void LWOImporter::LoadLWO2Polygons(unsigned int length)
CountVertsAndFacesLWO2(iNumVertices,iNumFaces,cursor,end); CountVertsAndFacesLWO2(iNumVertices,iNumFaces,cursor,end);
// allocate the output array and copy face indices // allocate the output array and copy face indices
if (iNumFaces) { if (iNumFaces)
{
cursor = (uint16_t*)mFileBuffer; cursor = (uint16_t*)mFileBuffer;
mCurLayer->mFaces.resize(iNumFaces,LWO::Face(type)); mCurLayer->mFaces.resize(iNumFaces,LWO::Face(type));
@ -802,13 +803,18 @@ void LWOImporter::CountVertsAndFacesLWO2(unsigned int& verts, unsigned int& face
{ {
while (cursor < end && max--) while (cursor < end && max--)
{ {
AI_LSWAP2P(cursor); uint16_t numIndices;
uint16_t numIndices = *cursor++; ::memcpy(&numIndices, cursor++, 2);
AI_LSWAP2(numIndices);
numIndices &= 0x03FF; numIndices &= 0x03FF;
verts += numIndices;++faces;
verts += numIndices;
++faces;
for(uint16_t i = 0; i < numIndices; i++) for(uint16_t i = 0; i < numIndices; i++)
{
ReadVSizedIntLWO2((uint8_t*&)cursor); ReadVSizedIntLWO2((uint8_t*&)cursor);
}
} }
} }
@ -817,10 +823,16 @@ void LWOImporter::CopyFaceIndicesLWO2(FaceList::iterator& it,
uint16_t*& cursor, uint16_t*& cursor,
const uint16_t* const end) const uint16_t* const end)
{ {
while (cursor < end) { while (cursor < end)
{
LWO::Face& face = *it++;; LWO::Face& face = *it++;
if((face.mNumIndices = (*cursor++) & 0x03FF)) /* byte swapping has already been done */ { uint16_t numIndices;
::memcpy(&numIndices, cursor++, 2);
AI_LSWAP2(numIndices);
face.mNumIndices = numIndices & 0x03FF;
if(face.mNumIndices) /* byte swapping has already been done */
{
face.mIndices = new unsigned int[face.mNumIndices]; face.mIndices = new unsigned int[face.mNumIndices];
for(unsigned int i = 0; i < face.mNumIndices; i++) for(unsigned int i = 0; i < face.mNumIndices; i++)
{ {
@ -848,8 +860,8 @@ void LWOImporter::LoadLWO2PolygonTags(unsigned int length)
if (type != AI_LWO_SURF && type != AI_LWO_SMGP) if (type != AI_LWO_SURF && type != AI_LWO_SMGP)
return; return;
while (mFileBuffer < end) { while (mFileBuffer < end)
{
unsigned int i = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mFaceIDXOfs; unsigned int i = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mFaceIDXOfs;
unsigned int j = GetU2(); unsigned int j = GetU2();
@ -1106,19 +1118,19 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
// first - get the index of the clip // first - get the index of the clip
clip.idx = GetU4(); clip.idx = GetU4();
IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
switch (head->type) switch (head.type)
{ {
case AI_LWO_STIL: case AI_LWO_STIL:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,STIL,1); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,STIL,1);
// "Normal" texture // "Normal" texture
GetS0(clip.path,head->length); GetS0(clip.path,head.length);
clip.type = Clip::STILL; clip.type = Clip::STILL;
break; break;
case AI_LWO_ISEQ: case AI_LWO_ISEQ:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,ISEQ,16); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,ISEQ,16);
// Image sequence. We'll later take the first. // Image sequence. We'll later take the first.
{ {
uint8_t digits = GetU1(); mFileBuffer++; uint8_t digits = GetU1(); mFileBuffer++;
@ -1127,12 +1139,12 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
std::string s; std::string s;
std::ostringstream ss; std::ostringstream ss;
GetS0(s,head->length); GetS0(s,head.length);
head->length -= (unsigned int)s.length()+1; head.length -= (unsigned int)s.length()+1;
ss << s; ss << s;
ss << std::setw(digits) << offset + start; ss << std::setw(digits) << offset + start;
GetS0(s,head->length); GetS0(s,head.length);
ss << s; ss << s;
clip.path = ss.str(); clip.path = ss.str();
clip.type = Clip::SEQ; clip.type = Clip::SEQ;
@ -1148,7 +1160,7 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
break; break;
case AI_LWO_XREF: case AI_LWO_XREF:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,XREF,4); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,XREF,4);
// Just a cross-reference to another CLIp // Just a cross-reference to another CLIp
clip.type = Clip::REF; clip.type = Clip::REF;
@ -1156,7 +1168,7 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
break; break;
case AI_LWO_NEGA: case AI_LWO_NEGA:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,NEGA,2); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,NEGA,2);
clip.negate = (0 != GetU2()); clip.negate = (0 != GetU2());
break; break;
@ -1194,17 +1206,17 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
while (true) while (true)
{ {
if (mFileBuffer + 6 >= end)break; if (mFileBuffer + 6 >= end)break;
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); LE_NCONST IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
if (mFileBuffer + head->length > end) if (mFileBuffer + head.length > end)
throw DeadlyImportError("LWO2: Invalid envelope chunk length"); throw DeadlyImportError("LWO2: Invalid envelope chunk length");
uint8_t* const next = mFileBuffer+head->length; uint8_t* const next = mFileBuffer+head.length;
switch (head->type) switch (head.type)
{ {
// Type & representation of the envelope // Type & representation of the envelope
case AI_LWO_TYPE: case AI_LWO_TYPE:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TYPE,2); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TYPE,2);
mFileBuffer++; // skip user format mFileBuffer++; // skip user format
// Determine type of envelope // Determine type of envelope
@ -1214,20 +1226,20 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
// precondition // precondition
case AI_LWO_PRE: case AI_LWO_PRE:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,PRE,2); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,PRE,2);
envelope.pre = (LWO::PrePostBehaviour)GetU2(); envelope.pre = (LWO::PrePostBehaviour)GetU2();
break; break;
// postcondition // postcondition
case AI_LWO_POST: case AI_LWO_POST:
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,POST,2); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,POST,2);
envelope.post = (LWO::PrePostBehaviour)GetU2(); envelope.post = (LWO::PrePostBehaviour)GetU2();
break; break;
// keyframe // keyframe
case AI_LWO_KEY: case AI_LWO_KEY:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,KEY,8); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,KEY,8);
envelope.keys.push_back(LWO::Key()); envelope.keys.push_back(LWO::Key());
LWO::Key& key = envelope.keys.back(); LWO::Key& key = envelope.keys.back();
@ -1240,7 +1252,7 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
// interval interpolation // interval interpolation
case AI_LWO_SPAN: case AI_LWO_SPAN:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPAN,4); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPAN,4);
if (envelope.keys.size()<2) if (envelope.keys.size()<2)
DefaultLogger::get()->warn("LWO2: Unexpected SPAN chunk"); DefaultLogger::get()->warn("LWO2: Unexpected SPAN chunk");
else { else {
@ -1286,22 +1298,22 @@ void LWOImporter::LoadLWO2File()
while (true) while (true)
{ {
if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break; if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break;
IFF::ChunkHeader* const head = IFF::LoadChunk(mFileBuffer); const IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
if (mFileBuffer + head->length > end) if (mFileBuffer + head.length > end)
{ {
throw DeadlyImportError("LWO2: Chunk length points behind the file"); throw DeadlyImportError("LWO2: Chunk length points behind the file");
break; break;
} }
uint8_t* const next = mFileBuffer+head->length; uint8_t* const next = mFileBuffer+head.length;
unsigned int iUnnamed = 0; unsigned int iUnnamed = 0;
if(!head->length) { if(!head.length) {
mFileBuffer = next; mFileBuffer = next;
continue; continue;
} }
switch (head->type) switch (head.type)
{ {
// new layer // new layer
case AI_LWO_LAYR: case AI_LWO_LAYR:
@ -1311,7 +1323,7 @@ void LWOImporter::LoadLWO2File()
LWO::Layer& layer = mLayers->back(); LWO::Layer& layer = mLayers->back();
mCurLayer = &layer; mCurLayer = &layer;
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LAYR,16); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LAYR,16);
// layer index. // layer index.
layer.mIndex = GetU2(); layer.mIndex = GetU2();
@ -1327,7 +1339,7 @@ void LWOImporter::LoadLWO2File()
mCurLayer->mPivot.x = GetF4(); mCurLayer->mPivot.x = GetF4();
mCurLayer->mPivot.y = GetF4(); mCurLayer->mPivot.y = GetF4();
mCurLayer->mPivot.z = GetF4(); mCurLayer->mPivot.z = GetF4();
GetS0(layer.mName,head->length-16); GetS0(layer.mName,head.length-16);
// if the name is empty, generate a default name // if the name is empty, generate a default name
if (layer.mName.empty()) { if (layer.mName.empty()) {
@ -1360,7 +1372,7 @@ void LWOImporter::LoadLWO2File()
break; break;
unsigned int old = (unsigned int)mCurLayer->mTempPoints.size(); unsigned int old = (unsigned int)mCurLayer->mTempPoints.size();
LoadLWOPoints(head->length); LoadLWOPoints(head.length);
mCurLayer->mPointIDXOfs = old; mCurLayer->mPointIDXOfs = old;
break; break;
} }
@ -1379,7 +1391,7 @@ void LWOImporter::LoadLWO2File()
if (mCurLayer->mTempPoints.empty()) if (mCurLayer->mTempPoints.empty())
DefaultLogger::get()->warn("LWO2: Unexpected VMAP chunk"); DefaultLogger::get()->warn("LWO2: Unexpected VMAP chunk");
else LoadLWO2VertexMap(head->length,head->type == AI_LWO_VMAD); else LoadLWO2VertexMap(head.length,head.type == AI_LWO_VMAD);
break; break;
} }
// face list // face list
@ -1389,7 +1401,7 @@ void LWOImporter::LoadLWO2File()
break; break;
unsigned int old = (unsigned int)mCurLayer->mFaces.size(); unsigned int old = (unsigned int)mCurLayer->mFaces.size();
LoadLWO2Polygons(head->length); LoadLWO2Polygons(head.length);
mCurLayer->mFaceIDXOfs = old; mCurLayer->mFaceIDXOfs = old;
break; break;
} }
@ -1401,7 +1413,7 @@ void LWOImporter::LoadLWO2File()
if (mCurLayer->mFaces.empty()) if (mCurLayer->mFaces.empty())
DefaultLogger::get()->warn("LWO2: Unexpected PTAG"); DefaultLogger::get()->warn("LWO2: Unexpected PTAG");
else LoadLWO2PolygonTags(head->length); else LoadLWO2PolygonTags(head.length);
break; break;
} }
// list of tags // list of tags
@ -1409,28 +1421,28 @@ void LWOImporter::LoadLWO2File()
{ {
if (!mTags->empty()) if (!mTags->empty())
DefaultLogger::get()->warn("LWO2: SRFS chunk encountered twice"); DefaultLogger::get()->warn("LWO2: SRFS chunk encountered twice");
else LoadLWOTags(head->length); else LoadLWOTags(head.length);
break; break;
} }
// surface chunk // surface chunk
case AI_LWO_SURF: case AI_LWO_SURF:
{ {
LoadLWO2Surface(head->length); LoadLWO2Surface(head.length);
break; break;
} }
// clip chunk // clip chunk
case AI_LWO_CLIP: case AI_LWO_CLIP:
{ {
LoadLWO2Clip(head->length); LoadLWO2Clip(head.length);
break; break;
} }
// envelope chunk // envelope chunk
case AI_LWO_ENVL: case AI_LWO_ENVL:
{ {
LoadLWO2Envelope(head->length); LoadLWO2Envelope(head.length);
break; break;
} }
} }

View File

@ -402,7 +402,9 @@ protected:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
inline float LWOImporter::GetF4() inline float LWOImporter::GetF4()
{ {
float f = *((float*)mFileBuffer);mFileBuffer += 4; float f;
::memcpy(&f, mFileBuffer, 4);
mFileBuffer += 4;
AI_LSWAP4(f); AI_LSWAP4(f);
return f; return f;
} }
@ -410,7 +412,9 @@ inline float LWOImporter::GetF4()
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
inline uint32_t LWOImporter::GetU4() inline uint32_t LWOImporter::GetU4()
{ {
uint32_t f = *((uint32_t*)mFileBuffer);mFileBuffer += 4; uint32_t f;
::memcpy(&f, mFileBuffer, 4);
mFileBuffer += 4;
AI_LSWAP4(f); AI_LSWAP4(f);
return f; return f;
} }
@ -418,7 +422,9 @@ inline uint32_t LWOImporter::GetU4()
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
inline uint16_t LWOImporter::GetU2() inline uint16_t LWOImporter::GetU2()
{ {
uint16_t f = *((uint16_t*)mFileBuffer);mFileBuffer += 2; uint16_t f;
::memcpy(&f, mFileBuffer, 2);
mFileBuffer += 2;
AI_LSWAP2(f); AI_LSWAP2(f);
return f; return f;
} }

View File

@ -285,7 +285,7 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
{ {
float fGloss; float fGloss;
if (mIsLWO2) { if (mIsLWO2) {
fGloss = pow( surf.mGlossiness*10.0f+2.0f, 2.0f); fGloss = std::pow( surf.mGlossiness*10.0f+2.0f, 2.0f);
} }
else else
{ {
@ -527,13 +527,13 @@ void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
while (true) while (true)
{ {
if (mFileBuffer + 6 >= end)break; if (mFileBuffer + 6 >= end)break;
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); LE_NCONST IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
if (mFileBuffer + head->length > end) if (mFileBuffer + head.length > end)
throw DeadlyImportError("LWO2: Invalid SURF.BLOCK chunk length"); throw DeadlyImportError("LWO2: Invalid SURF.BLOCK chunk length");
uint8_t* const next = mFileBuffer+head->length; uint8_t* const next = mFileBuffer+head.length;
switch (head->type) switch (head.type)
{ {
case AI_LWO_PROJ: case AI_LWO_PROJ:
tex.mapMode = (Texture::MappingMode)GetU2(); tex.mapMode = (Texture::MappingMode)GetU2();
@ -549,7 +549,7 @@ void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
tex.mClipIdx = GetU2(); tex.mClipIdx = GetU2();
break; break;
case AI_LWO_VMAP: case AI_LWO_VMAP:
GetS0(tex.mUVChannelIndex,head->length); GetS0(tex.mUVChannelIndex,head.length);
break; break;
case AI_LWO_WRPH: case AI_LWO_WRPH:
tex.wrapAmountH = GetF4(); tex.wrapAmountH = GetF4();
@ -595,13 +595,13 @@ void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex )
while (true) while (true)
{ {
if (mFileBuffer + 6 >= end)break; if (mFileBuffer + 6 >= end)break;
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
if (mFileBuffer + head->length > end) if (mFileBuffer + head.length > end)
throw DeadlyImportError("LWO2: Invalid texture header chunk length"); throw DeadlyImportError("LWO2: Invalid texture header chunk length");
uint8_t* const next = mFileBuffer+head->length; uint8_t* const next = mFileBuffer+head.length;
switch (head->type) switch (head.type)
{ {
case AI_LWO_CHAN: case AI_LWO_CHAN:
tex.type = GetU4(); tex.type = GetU4();
@ -698,20 +698,20 @@ void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* /*head*/, u
while (true) while (true)
{ {
if (mFileBuffer + 6 >= end)break; if (mFileBuffer + 6 >= end)break;
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
if (mFileBuffer + head->length > end) if (mFileBuffer + head.length > end)
throw DeadlyImportError("LWO2: Invalid shader header chunk length"); throw DeadlyImportError("LWO2: Invalid shader header chunk length");
uint8_t* const next = mFileBuffer+head->length; uint8_t* const next = mFileBuffer+head.length;
switch (head->type) switch (head.type)
{ {
case AI_LWO_ENAB: case AI_LWO_ENAB:
shader.enabled = GetU2() ? true : false; shader.enabled = GetU2() ? true : false;
break; break;
case AI_LWO_FUNC: case AI_LWO_FUNC:
GetS0( shader.functionName, head->length ); GetS0( shader.functionName, head.length );
} }
mFileBuffer = next; mFileBuffer = next;
} }
@ -756,18 +756,18 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
{ {
if (mFileBuffer + 6 >= end) if (mFileBuffer + 6 >= end)
break; break;
LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
if (mFileBuffer + head->length > end) if (mFileBuffer + head.length > end)
throw DeadlyImportError("LWO2: Invalid surface chunk length"); throw DeadlyImportError("LWO2: Invalid surface chunk length");
uint8_t* const next = mFileBuffer+head->length; uint8_t* const next = mFileBuffer+head.length;
switch (head->type) switch (head.type)
{ {
// diffuse color // diffuse color
case AI_LWO_COLR: case AI_LWO_COLR:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,COLR,12); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,COLR,12);
surf.mColor.r = GetF4(); surf.mColor.r = GetF4();
surf.mColor.g = GetF4(); surf.mColor.g = GetF4();
surf.mColor.b = GetF4(); surf.mColor.b = GetF4();
@ -776,14 +776,14 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
// diffuse strength ... hopefully // diffuse strength ... hopefully
case AI_LWO_DIFF: case AI_LWO_DIFF:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,DIFF,4); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,DIFF,4);
surf.mDiffuseValue = GetF4(); surf.mDiffuseValue = GetF4();
break; break;
} }
// specular strength ... hopefully // specular strength ... hopefully
case AI_LWO_SPEC: case AI_LWO_SPEC:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPEC,4); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPEC,4);
surf.mSpecularValue = GetF4(); surf.mSpecularValue = GetF4();
break; break;
} }
@ -794,21 +794,21 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
if (surf.mTransparency == 10e10f) if (surf.mTransparency == 10e10f)
break; break;
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,4); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TRAN,4);
surf.mTransparency = GetF4(); surf.mTransparency = GetF4();
break; break;
} }
// additive transparency // additive transparency
case AI_LWO_ADTR: case AI_LWO_ADTR:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,ADTR,4); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,ADTR,4);
surf.mAdditiveTransparency = GetF4(); surf.mAdditiveTransparency = GetF4();
break; break;
} }
// wireframe mode // wireframe mode
case AI_LWO_LINE: case AI_LWO_LINE:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LINE,2); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LINE,2);
if (GetU2() & 0x1) if (GetU2() & 0x1)
surf.mWireframe = true; surf.mWireframe = true;
break; break;
@ -816,49 +816,49 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
// glossiness // glossiness
case AI_LWO_GLOS: case AI_LWO_GLOS:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,GLOS,4); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,GLOS,4);
surf.mGlossiness = GetF4(); surf.mGlossiness = GetF4();
break; break;
} }
// bump intensity // bump intensity
case AI_LWO_BUMP: case AI_LWO_BUMP:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BUMP,4); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,BUMP,4);
surf.mBumpIntensity = GetF4(); surf.mBumpIntensity = GetF4();
break; break;
} }
// color highlights // color highlights
case AI_LWO_CLRH: case AI_LWO_CLRH:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,CLRH,4); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,CLRH,4);
surf.mColorHighlights = GetF4(); surf.mColorHighlights = GetF4();
break; break;
} }
// index of refraction // index of refraction
case AI_LWO_RIND: case AI_LWO_RIND:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,RIND,4); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,RIND,4);
surf.mIOR = GetF4(); surf.mIOR = GetF4();
break; break;
} }
// polygon sidedness // polygon sidedness
case AI_LWO_SIDE: case AI_LWO_SIDE:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SIDE,2); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SIDE,2);
surf.bDoubleSided = (3 == GetU2()); surf.bDoubleSided = (3 == GetU2());
break; break;
} }
// maximum smoothing angle // maximum smoothing angle
case AI_LWO_SMAN: case AI_LWO_SMAN:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SMAN,4);
surf.mMaximumSmoothAngle = fabs( GetF4() ); surf.mMaximumSmoothAngle = fabs( GetF4() );
break; break;
} }
// vertex color channel to be applied to the surface // vertex color channel to be applied to the surface
case AI_LWO_VCOL: case AI_LWO_VCOL:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,VCOL,12); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,VCOL,12);
surf.mDiffuseValue *= GetF4(); // strength surf.mDiffuseValue *= GetF4(); // strength
ReadVSizedIntLWO2(mFileBuffer); // skip envelope ReadVSizedIntLWO2(mFileBuffer); // skip envelope
surf.mVCMapType = GetU4(); // type of the channel surf.mVCMapType = GetU4(); // type of the channel
@ -870,18 +870,18 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
// surface bock entry // surface bock entry
case AI_LWO_BLOK: case AI_LWO_BLOK:
{ {
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BLOK,4); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,BLOK,4);
LE_NCONST IFF::SubChunkHeader* head2 = IFF::LoadSubChunk(mFileBuffer); IFF::SubChunkHeader head2 = IFF::LoadSubChunk(mFileBuffer);
switch (head2->type) switch (head2.type)
{ {
case AI_LWO_PROC: case AI_LWO_PROC:
case AI_LWO_GRAD: case AI_LWO_GRAD:
case AI_LWO_IMAP: case AI_LWO_IMAP:
LoadLWO2TextureBlock(head2, head->length); LoadLWO2TextureBlock(&head2, head.length);
break; break;
case AI_LWO_SHDR: case AI_LWO_SHDR:
LoadLWO2ShaderBlock(head2, head->length); LoadLWO2ShaderBlock(&head2, head.length);
break; break;
default: default:

View File

@ -464,7 +464,7 @@ std::string LWSImporter::FindLWOFile(const std::string& in)
std::string tmp; std::string tmp;
if (in.length() > 3 && in[1] == ':'&& in[2] != '\\' && in[2] != '/') if (in.length() > 3 && in[1] == ':'&& in[2] != '\\' && in[2] != '/')
{ {
tmp = in[0] + (":\\" + in.substr(2)); tmp = in[0] + (std::string(":\\") + in.substr(2));
} }
else tmp = in; else tmp = in;
@ -480,12 +480,12 @@ std::string LWSImporter::FindLWOFile(const std::string& in)
// <folder>\Scenes\<hh>\<*>.lws // <folder>\Scenes\<hh>\<*>.lws
// where <hh> is optional. // where <hh> is optional.
std::string test = ".." + (io->getOsSeparator() + tmp); std::string test = std::string("..") + (io->getOsSeparator() + tmp);
if (io->Exists(test)) { if (io->Exists(test)) {
return test; return test;
} }
test = ".." + (io->getOsSeparator() + test); test = std::string("..") + (io->getOsSeparator() + test);
if (io->Exists(test)) { if (io->Exists(test)) {
return test; return test;
} }

View File

@ -131,10 +131,15 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
// and renormalize the weights // and renormalize the weights
float sum = 0.0f; float sum = 0.0f;
for( std::vector<Weight>::const_iterator it = vit->begin(); it != vit->end(); ++it) for( std::vector<Weight>::const_iterator it = vit->begin(); it != vit->end(); ++it ) {
sum += it->mWeight; sum += it->mWeight;
for( std::vector<Weight>::iterator it = vit->begin(); it != vit->end(); ++it) }
it->mWeight /= sum; if( 0.0f != sum ) {
const float invSum = 1.0f / sum;
for( std::vector<Weight>::iterator it = vit->begin(); it != vit->end(); ++it ) {
it->mWeight *= invSum;
}
}
} }
if (bChanged) { if (bChanged) {
@ -157,18 +162,6 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
const std::vector<aiVertexWeight>& bw = boneWeights[a]; const std::vector<aiVertexWeight>& bw = boneWeights[a];
aiBone* bone = pMesh->mBones[a]; aiBone* bone = pMesh->mBones[a];
// ignore the bone if no vertex weights were removed there
// FIX (Aramis, 07|22|08)
// NO! we can't ignore it in this case ... it is possible that
// the number of weights did not change, but the weight values did.
// if( bw.size() == bone->mNumWeights)
// continue;
// FIX (Aramis, 07|21|08)
// It is possible that all weights of a bone have been removed.
// This would naturally cause an exception in &bw[0].
if ( bw.empty() ) if ( bw.empty() )
{ {
abNoNeed[a] = bChanged = true; abNoNeed[a] = bChanged = true;
@ -177,7 +170,7 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
// copy the weight list. should always be less weights than before, so we don't need a new allocation // copy the weight list. should always be less weights than before, so we don't need a new allocation
ai_assert( bw.size() <= bone->mNumWeights); ai_assert( bw.size() <= bone->mNumWeights);
bone->mNumWeights = (unsigned int) bw.size(); bone->mNumWeights = static_cast<unsigned int>( bw.size() );
::memcpy( bone->mWeights, &bw[0], bw.size() * sizeof( aiVertexWeight)); ::memcpy( bone->mWeights, &bw[0], bw.size() * sizeof( aiVertexWeight));
} }

View File

@ -263,9 +263,9 @@ inline void LatLngNormalToVec3(uint16_t p_iNormal, float* p_afOut)
lat *= 3.141926f/128.0f; lat *= 3.141926f/128.0f;
lng *= 3.141926f/128.0f; lng *= 3.141926f/128.0f;
p_afOut[0] = cosf(lat) * sinf(lng); p_afOut[0] = std::cos(lat) * std::sin(lng);
p_afOut[1] = sinf(lat) * sinf(lng); p_afOut[1] = std::sin(lat) * std::sin(lng);
p_afOut[2] = cosf(lng); p_afOut[2] = std::cos(lng);
return; return;
} }

View File

@ -259,7 +259,7 @@ inline void ConvertQuaternion (const aiVector3D& in, aiQuaternion& out) {
if (t < 0.0f) if (t < 0.0f)
out.w = 0.0f; out.w = 0.0f;
else out.w = sqrt (t); else out.w = std::sqrt (t);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -75,6 +75,7 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
} // end of namespace Assimp } // end of namespace Assimp
static const std::string MaterialExt = ".mtl";
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ObjExporter :: ObjExporter(const char* _filename, const aiScene* pScene) ObjExporter :: ObjExporter(const char* _filename, const aiScene* pScene)
@ -107,7 +108,7 @@ std::string ObjExporter :: GetMaterialLibName()
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
std::string ObjExporter :: GetMaterialLibFileName() std::string ObjExporter :: GetMaterialLibFileName()
{ {
return filename + ".mtl"; return filename + MaterialExt;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -132,7 +133,7 @@ std::string ObjExporter :: GetMaterialName(unsigned int index)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ObjExporter :: WriteMaterialFile() void ObjExporter::WriteMaterialFile()
{ {
WriteHeader(mOutputMat); WriteHeader(mOutputMat);
@ -144,16 +145,16 @@ void ObjExporter :: WriteMaterialFile()
aiColor4D c; aiColor4D c;
if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_DIFFUSE,c)) { if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_DIFFUSE,c)) {
mOutputMat << "kd " << c.r << " " << c.g << " " << c.b << endl; mOutputMat << "Kd " << c.r << " " << c.g << " " << c.b << endl;
} }
if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_AMBIENT,c)) { if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_AMBIENT,c)) {
mOutputMat << "ka " << c.r << " " << c.g << " " << c.b << endl; mOutputMat << "Ka " << c.r << " " << c.g << " " << c.b << endl;
} }
if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_SPECULAR,c)) { if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_SPECULAR,c)) {
mOutputMat << "ks " << c.r << " " << c.g << " " << c.b << endl; mOutputMat << "Ks " << c.r << " " << c.g << " " << c.b << endl;
} }
if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_EMISSIVE,c)) { if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_EMISSIVE,c)) {
mOutputMat << "ke " << c.r << " " << c.g << " " << c.b << endl; mOutputMat << "Ke " << c.r << " " << c.g << " " << c.b << endl;
} }
float o; float o;
@ -170,16 +171,19 @@ void ObjExporter :: WriteMaterialFile()
aiString s; aiString s;
if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_DIFFUSE(0),s)) { if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_DIFFUSE(0),s)) {
mOutputMat << "map_kd " << s.data << endl; mOutputMat << "map_Kd " << s.data << endl;
} }
if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_AMBIENT(0),s)) { if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_AMBIENT(0),s)) {
mOutputMat << "map_ka " << s.data << endl; mOutputMat << "map_Ka " << s.data << endl;
} }
if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SPECULAR(0),s)) { if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SPECULAR(0),s)) {
mOutputMat << "map_ks " << s.data << endl; mOutputMat << "map_Ks " << s.data << endl;
} }
if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SHININESS(0),s)) { if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_SHININESS(0),s)) {
mOutputMat << "map_ns " << s.data << endl; mOutputMat << "map_Ns " << s.data << endl;
}
if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_OPACITY(0),s)) {
mOutputMat << "map_d " << s.data << endl;
} }
if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_HEIGHT(0),s) || AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_NORMALS(0),s)) { if(AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_HEIGHT(0),s) || AI_SUCCESS == mat->Get(AI_MATKEY_TEXTURE_NORMALS(0),s)) {
// implementations seem to vary here, so write both variants // implementations seem to vary here, so write both variants
@ -199,7 +203,7 @@ void ObjExporter :: WriteGeometryFile()
// collect mesh geometry // collect mesh geometry
aiMatrix4x4 mBase; aiMatrix4x4 mBase;
AddNode(pScene->mRootNode,mBase); AddNode(pScene->mRootNode, mBase);
// write vertex positions // write vertex positions
vpMap.getVectors(vp); vpMap.getVectors(vp);
@ -228,7 +232,9 @@ void ObjExporter :: WriteGeometryFile()
// now write all mesh instances // now write all mesh instances
BOOST_FOREACH(const MeshInstance& m, meshes) { BOOST_FOREACH(const MeshInstance& m, meshes) {
mOutput << "# Mesh \'" << m.name << "\' with " << m.faces.size() << " faces" << endl; mOutput << "# Mesh \'" << m.name << "\' with " << m.faces.size() << " faces" << endl;
mOutput << "g " << m.name << endl; if (!m.name.empty()) {
mOutput << "g " << m.name << endl;
}
mOutput << "usemtl " << m.matname << endl; mOutput << "usemtl " << m.matname << endl;
BOOST_FOREACH(const Face& f, m.faces) { BOOST_FOREACH(const Face& f, m.faces) {
@ -243,11 +249,8 @@ void ObjExporter :: WriteGeometryFile()
if (fv.vt) { if (fv.vt) {
mOutput << fv.vt; mOutput << fv.vt;
} }
if (f.kind == 'f') { if (f.kind == 'f' && fv.vn) {
mOutput << '/'; mOutput << '/' << fv.vn;
if (fv.vn) {
mOutput << fv.vn;
}
} }
} }
} }
@ -258,14 +261,12 @@ void ObjExporter :: WriteGeometryFile()
} }
} }
// ------------------------------------------------------------------------------------------------
int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec) int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec)
{ {
vecIndexMap::dataType::iterator vertIt = vecMap.find(vec); vecIndexMap::dataType::iterator vertIt = vecMap.find(vec);
if(vertIt != vecMap.end()){// vertex already exists, so reference it // vertex already exists, so reference it
if(vertIt != vecMap.end()){
return vertIt->second; return vertIt->second;
} }
vecMap[vec] = mNextIndex; vecMap[vec] = mNextIndex;
@ -274,6 +275,7 @@ int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec)
return ret; return ret;
} }
// ------------------------------------------------------------------------------------------------
void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs ) void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs )
{ {
vecs.resize(vecMap.size()); vecs.resize(vecMap.size());
@ -282,14 +284,13 @@ void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs )
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat)
{ {
meshes.push_back(MeshInstance()); meshes.push_back(MeshInstance());
MeshInstance& mesh = meshes.back(); MeshInstance& mesh = meshes.back();
mesh.name = std::string(name.data,name.length) + (m->mName.length ? "_"+std::string(m->mName.data,m->mName.length) : ""); mesh.name = std::string(name.data,name.length) + (m->mName.length ? "_" + std::string(m->mName.data,m->mName.length) : "");
mesh.matname = GetMaterialName(m->mMaterialIndex); mesh.matname = GetMaterialName(m->mMaterialIndex);
mesh.faces.resize(m->mNumFaces); mesh.faces.resize(m->mNumFaces);
@ -317,7 +318,8 @@ void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatri
face.indices[a].vp = vpMap.getIndex(vert); face.indices[a].vp = vpMap.getIndex(vert);
if (m->mNormals) { if (m->mNormals) {
face.indices[a].vn = vnMap.getIndex(m->mNormals[idx]); aiVector3D norm = aiMatrix3x3(mat) * m->mNormals[idx];
face.indices[a].vn = vnMap.getIndex(norm);
} }
else{ else{
face.indices[a].vn = 0; face.indices[a].vn = 0;
@ -334,18 +336,20 @@ void ObjExporter :: AddMesh(const aiString& name, const aiMesh* m, const aiMatri
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ObjExporter :: AddNode(const aiNode* nd, const aiMatrix4x4& mParent) void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent)
{ {
const aiMatrix4x4& mAbs = mParent * nd->mTransformation; const aiMatrix4x4& mAbs = mParent * nd->mTransformation;
for(unsigned int i = 0; i < nd->mNumMeshes; ++i) { for(unsigned int i = 0; i < nd->mNumMeshes; ++i) {
AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]],mAbs); AddMesh(nd->mName, pScene->mMeshes[nd->mMeshes[i]], mAbs);
} }
for(unsigned int i = 0; i < nd->mNumChildren; ++i) { for(unsigned int i = 0; i < nd->mNumChildren; ++i) {
AddNode(nd->mChildren[i],mAbs); AddNode(nd->mChildren[i], mAbs);
} }
} }
#endif // ------------------------------------------------------------------------------------------------
#endif
#endif // ASSIMP_BUILD_NO_OBJ_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT

View File

@ -62,7 +62,7 @@ static const aiImporterDesc desc = {
static const unsigned int ObjMinSize = 16; static const unsigned int ObjMinSize = 16;
namespace Assimp { namespace Assimp {
using namespace std; using namespace std;
@ -109,9 +109,7 @@ const aiImporterDesc* ObjFileImporter::GetInfo () const
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Obj-file import implementation // Obj-file import implementation
void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
{ {
DefaultIOSystem io;
// Read file into memory // Read file into memory
const std::string mode = "rb"; const std::string mode = "rb";
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, mode)); boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, mode));
@ -139,7 +137,23 @@ void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
{ {
strModelName = pFile; strModelName = pFile;
} }
// process all '\'
std::vector<char> ::iterator iter = m_Buffer.begin();
while (iter != m_Buffer.end())
{
if (*iter == '\\')
{
// remove '\'
iter = m_Buffer.erase(iter);
// remove next character
while (*iter == '\r' || *iter == '\n')
iter = m_Buffer.erase(iter);
}
else
++iter;
}
// parse the file into a temporary representation // parse the file into a temporary representation
ObjFileParser parser(m_Buffer, strModelName, pIOHandler); ObjFileParser parser(m_Buffer, strModelName, pIOHandler);
@ -216,16 +230,10 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
for ( unsigned int i=0; i< pObject->m_Meshes.size(); i++ ) for ( unsigned int i=0; i< pObject->m_Meshes.size(); i++ )
{ {
unsigned int meshId = pObject->m_Meshes[ i ]; unsigned int meshId = pObject->m_Meshes[ i ];
aiMesh *pMesh = new aiMesh; aiMesh *pMesh = createTopology( pModel, pObject, meshId );
createTopology( pModel, pObject, meshId, pMesh ); if( pMesh && pMesh->mNumFaces > 0 ) {
if ( pMesh->mNumVertices > 0 )
{
MeshArray.push_back( pMesh ); MeshArray.push_back( pMesh );
} }
else
{
delete pMesh;
}
} }
// Create all nodes from the sub-objects stored in the current object // Create all nodes from the sub-objects stored in the current object
@ -258,45 +266,44 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Create topology data // Create topology data
void ObjFileImporter::createTopology(const ObjFile::Model* pModel, aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData,
const ObjFile::Object* pData, unsigned int uiMeshIndex )
unsigned int uiMeshIndex,
aiMesh* pMesh )
{ {
// Checking preconditions // Checking preconditions
ai_assert( NULL != pModel ); ai_assert( NULL != pModel );
if( NULL == pData ) { if( NULL == pData ) {
return; return NULL;
} }
// Create faces // Create faces
ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ]; ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
ai_assert( NULL != pObjMesh ); if( !pObjMesh ) {
return NULL;
pMesh->mNumFaces = 0; }
ai_assert( NULL != pObjMesh );
aiMesh* pMesh = new aiMesh;
for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
{ {
ObjFile::Face* const inp = pObjMesh->m_Faces[ index ]; ObjFile::Face *const inp = pObjMesh->m_Faces[ index ];
ai_assert( NULL != inp );
if (inp->m_PrimitiveType == aiPrimitiveType_LINE) { if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
pMesh->mNumFaces += inp->m_pVertices->size() - 1; pMesh->mNumFaces += inp->m_pVertices->size() - 1;
pMesh->mPrimitiveTypes |= aiPrimitiveType_LINE; pMesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
} } else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
else if (inp->m_PrimitiveType == aiPrimitiveType_POINT) {
pMesh->mNumFaces += inp->m_pVertices->size(); pMesh->mNumFaces += inp->m_pVertices->size();
pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT; pMesh->mPrimitiveTypes |= aiPrimitiveType_POINT;
} else { } else {
++pMesh->mNumFaces; ++pMesh->mNumFaces;
if (inp->m_pVertices->size() > 3) { if (inp->m_pVertices->size() > 3) {
pMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; pMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
} } else {
else {
pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
} }
} }
} }
unsigned int uiIdxCount = 0u; unsigned int uiIdxCount( 0u );
if ( pMesh->mNumFaces > 0 ) if ( pMesh->mNumFaces > 0 )
{ {
pMesh->mFaces = new aiFace[ pMesh->mNumFaces ]; pMesh->mFaces = new aiFace[ pMesh->mNumFaces ];
@ -305,7 +312,7 @@ void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
pMesh->mMaterialIndex = pObjMesh->m_uiMaterialIndex; pMesh->mMaterialIndex = pObjMesh->m_uiMaterialIndex;
} }
unsigned int outIndex = 0; unsigned int outIndex( 0 );
// Copy all data from all stored meshes // Copy all data from all stored meshes
for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++)
@ -339,6 +346,8 @@ void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
// Create mesh vertices // Create mesh vertices
createVertexArray(pModel, pData, uiMeshIndex, pMesh, uiIdxCount); createVertexArray(pModel, pData, uiMeshIndex, pMesh, uiIdxCount);
return pMesh;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -91,8 +91,8 @@ private:
aiNode *pParent, aiScene* pScene, std::vector<aiMesh*> &MeshArray); aiNode *pParent, aiScene* pScene, std::vector<aiMesh*> &MeshArray);
//! \brief Creates topology data like faces and meshes for the geometry. //! \brief Creates topology data like faces and meshes for the geometry.
void createTopology(const ObjFile::Model* pModel, const ObjFile::Object* pData, aiMesh *createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData,
unsigned int uiMeshIndex, aiMesh* pMesh); unsigned int uiMeshIndex );
//! \brief Creates vertices from model. //! \brief Creates vertices from model.
void createVertexArray(const ObjFile::Model* pModel, const ObjFile::Object* pCurrentObject, void createVertexArray(const ObjFile::Model* pModel, const ObjFile::Object* pCurrentObject,

View File

@ -46,14 +46,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ObjTools.h" #include "ObjTools.h"
#include "ObjFileData.h" #include "ObjFileData.h"
#include "fast_atof.h" #include "fast_atof.h"
#include "ParsingUtils.h"
namespace Assimp { namespace Assimp {
// Material specific token // Material specific token
static const std::string DiffuseTexture = "map_kd"; static const std::string DiffuseTexture = "map_Kd";
static const std::string AmbientTexture = "map_ka"; static const std::string AmbientTexture = "map_Ka";
static const std::string SpecularTexture = "map_ks"; static const std::string SpecularTexture = "map_Ks";
static const std::string OpacityTexture = "map_d"; static const std::string OpacityTexture = "map_d";
static const std::string EmmissiveTexture = "map_emissive";
static const std::string BumpTexture1 = "map_bump"; static const std::string BumpTexture1 = "map_bump";
static const std::string BumpTexture2 = "map_Bump"; static const std::string BumpTexture2 = "map_Bump";
static const std::string BumpTexture3 = "bump"; static const std::string BumpTexture3 = "bump";
@ -128,6 +130,7 @@ void ObjFileMtlImporter::load()
{ {
switch (*m_DataIt) switch (*m_DataIt)
{ {
case 'k':
case 'K': case 'K':
{ {
++m_DataIt; ++m_DataIt;
@ -163,25 +166,27 @@ void ObjFileMtlImporter::load()
} }
break; break;
case 'N': // Shineness case 'N':
case 'n':
{ {
++m_DataIt; ++m_DataIt;
switch(*m_DataIt) switch(*m_DataIt)
{ {
case 's': case 's': // Specular exponent
++m_DataIt; ++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->shineness); getFloatValue(m_pModel->m_pCurrentMaterial->shineness);
break; break;
case 'i': //Index Of refraction case 'i': // Index Of refraction
++m_DataIt; ++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->ior); getFloatValue(m_pModel->m_pCurrentMaterial->ior);
break; break;
case 'e': // New material
createMaterial();
break;
} }
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
break;
} }
break; break;
case 'm': // Texture case 'm': // Texture
case 'b': // quick'n'dirty - for 'bump' sections case 'b': // quick'n'dirty - for 'bump' sections
@ -191,13 +196,6 @@ void ObjFileMtlImporter::load()
} }
break; break;
case 'n': // New material name
{
createMaterial();
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
}
break;
case 'i': // Illumination model case 'i': // Illumination model
{ {
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
@ -221,15 +219,17 @@ void ObjFileMtlImporter::getColorRGBA( aiColor3D *pColor )
{ {
ai_assert( NULL != pColor ); ai_assert( NULL != pColor );
float r, g, b; float r( 0.0f ), g( 0.0f ), b( 0.0f );
m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, r ); m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, r );
pColor->r = r; pColor->r = r;
m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, g ); // we have to check if color is default 0 with only one token
pColor->g = g; if( !IsLineEnd( *m_DataIt ) ) {
m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, g );
m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, b ); m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, b );
pColor->b = b; }
pColor->g = g;
pColor->b = b;
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -253,7 +253,7 @@ void ObjFileMtlImporter::getFloatValue( float &value )
void ObjFileMtlImporter::createMaterial() void ObjFileMtlImporter::createMaterial()
{ {
std::string line( "" ); std::string line( "" );
while ( !isNewLine( *m_DataIt ) ) { while( !IsLineEnd( *m_DataIt ) ) {
line += *m_DataIt; line += *m_DataIt;
++m_DataIt; ++m_DataIt;
} }
@ -303,11 +303,7 @@ void ObjFileMtlImporter::getTexture() {
// Opacity texture // Opacity texture
out = & m_pModel->m_pCurrentMaterial->textureOpacity; out = & m_pModel->m_pCurrentMaterial->textureOpacity;
clampIndex = ObjFile::Material::TextureOpacityType; clampIndex = ObjFile::Material::TextureOpacityType;
} else if (!ASSIMP_strincmp( pPtr,"map_ka",6)) { } else if (!ASSIMP_strincmp( pPtr, EmmissiveTexture.c_str(), EmmissiveTexture.size())) {
// Ambient texture
out = & m_pModel->m_pCurrentMaterial->textureAmbient;
clampIndex = ObjFile::Material::TextureAmbientType;
} else if (!ASSIMP_strincmp(&(*m_DataIt),"map_emissive",6)) {
// Emissive texture // Emissive texture
out = & m_pModel->m_pCurrentMaterial->textureEmissive; out = & m_pModel->m_pCurrentMaterial->textureEmissive;
clampIndex = ObjFile::Material::TextureEmissiveType; clampIndex = ObjFile::Material::TextureEmissiveType;

View File

@ -113,8 +113,8 @@ void ObjFileParser::parseFile()
getVector3(m_pModel->m_Vertices); getVector3(m_pModel->m_Vertices);
} else if (*m_DataIt == 't') { } else if (*m_DataIt == 't') {
// read in texture coordinate ( 2D or 3D ) // read in texture coordinate ( 2D or 3D )
++m_DataIt; ++m_DataIt;
getVector( m_pModel->m_TextureCoord ); getVector( m_pModel->m_TextureCoord );
} else if (*m_DataIt == 'n') { } else if (*m_DataIt == 'n') {
// Read in normal vector definition // Read in normal vector definition
++m_DataIt; ++m_DataIt;
@ -186,12 +186,12 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
{ {
size_t index = 0; size_t index = 0;
m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd); m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
while ( m_DataIt != m_DataItEnd && !isSeparator(*m_DataIt) ) while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
{
pBuffer[index] = *m_DataIt; pBuffer[index] = *m_DataIt;
index++; index++;
if (index == length-1) if( index == length - 1 ) {
break; break;
}
++m_DataIt; ++m_DataIt;
} }
@ -233,12 +233,13 @@ void ObjFileParser::copyNextLine(char *pBuffer, size_t length)
// ------------------------------------------------------------------- // -------------------------------------------------------------------
void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) { void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
size_t numComponents( 0 ); size_t numComponents( 0 );
DataArrayIt tmp( m_DataIt ); const char* tmp( &m_DataIt[0] );
while( !IsLineEnd( *tmp ) ) { while( !IsLineEnd( *tmp ) ) {
if( *tmp == ' ' ) { if ( !SkipSpaces( &tmp ) ) {
++numComponents; break;
} }
tmp++; SkipToken( tmp );
++numComponents;
} }
float x, y, z; float x, y, z;
if( 2 == numComponents ) { if( 2 == numComponents ) {
@ -344,7 +345,7 @@ void ObjFileParser::getFace(aiPrimitiveType type)
} }
iPos++; iPos++;
} }
else if ( isSeparator(*pPtr) ) else if( IsSpaceOrNewLine( *pPtr ) )
{ {
iPos = 0; iPos = 0;
} }
@ -462,8 +463,9 @@ void ObjFileParser::getMaterialDesc()
return; return;
char *pStart = &(*m_DataIt); char *pStart = &(*m_DataIt);
while ( m_DataIt != m_DataItEnd && !isSeparator(*m_DataIt) ) while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
++m_DataIt; ++m_DataIt;
}
// Get name // Get name
std::string strName(pStart, &(*m_DataIt)); std::string strName(pStart, &(*m_DataIt));
@ -517,12 +519,14 @@ void ObjFileParser::getMaterialLib()
{ {
// Translate tuple // Translate tuple
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
if (m_DataIt == m_DataItEnd) if( m_DataIt == m_DataItEnd ) {
return; return;
}
char *pStart = &(*m_DataIt); char *pStart = &(*m_DataIt);
while (m_DataIt != m_DataItEnd && !isNewLine(*m_DataIt)) while( m_DataIt != m_DataItEnd && !IsLineEnd( *m_DataIt ) ) {
m_DataIt++; ++m_DataIt;
}
// Check for existence // Check for existence
const std::string strMatName(pStart, &(*m_DataIt)); const std::string strMatName(pStart, &(*m_DataIt));
@ -550,13 +554,15 @@ void ObjFileParser::getNewMaterial()
{ {
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd); m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
if ( m_DataIt == m_DataItEnd ) if( m_DataIt == m_DataItEnd ) {
return; return;
}
char *pStart = &(*m_DataIt); char *pStart = &(*m_DataIt);
std::string strMat( pStart, *m_DataIt ); std::string strMat( pStart, *m_DataIt );
while ( m_DataIt != m_DataItEnd && isSeparator( *m_DataIt ) ) while( m_DataIt != m_DataItEnd && IsSpaceOrNewLine( *m_DataIt ) ) {
m_DataIt++; ++m_DataIt;
}
std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat ); std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat );
if ( it == m_pModel->m_MaterialMap.end() ) if ( it == m_pModel->m_MaterialMap.end() )
{ {
@ -581,8 +587,9 @@ void ObjFileParser::getNewMaterial()
int ObjFileParser::getMaterialIndex( const std::string &strMaterialName ) int ObjFileParser::getMaterialIndex( const std::string &strMaterialName )
{ {
int mat_index = -1; int mat_index = -1;
if ( strMaterialName.empty() ) if( strMaterialName.empty() ) {
return mat_index; return mat_index;
}
for (size_t index = 0; index < m_pModel->m_MaterialLib.size(); ++index) for (size_t index = 0; index < m_pModel->m_MaterialLib.size(); ++index)
{ {
if ( strMaterialName == m_pModel->m_MaterialLib[ index ]) if ( strMaterialName == m_pModel->m_MaterialLib[ index ])
@ -601,8 +608,9 @@ void ObjFileParser::getGroupName()
std::string strGroupName; std::string strGroupName;
m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, strGroupName); m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, strGroupName);
if ( isEndOfBuffer( m_DataIt, m_DataItEnd ) ) if( isEndOfBuffer( m_DataIt, m_DataItEnd ) ) {
return; return;
}
// Change active group, if necessary // Change active group, if necessary
if ( m_pModel->m_strActiveGroup != strGroupName ) if ( m_pModel->m_strActiveGroup != strGroupName )
@ -653,11 +661,13 @@ void ObjFileParser::getGroupNumberAndResolution()
void ObjFileParser::getObjectName() void ObjFileParser::getObjectName()
{ {
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
if (m_DataIt == m_DataItEnd) if( m_DataIt == m_DataItEnd ) {
return; return;
}
char *pStart = &(*m_DataIt); char *pStart = &(*m_DataIt);
while ( m_DataIt != m_DataItEnd && !isSeparator( *m_DataIt ) ) while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
++m_DataIt; ++m_DataIt;
}
std::string strObjectName(pStart, &(*m_DataIt)); std::string strObjectName(pStart, &(*m_DataIt));
if (!strObjectName.empty()) if (!strObjectName.empty())
@ -678,8 +688,9 @@ void ObjFileParser::getObjectName()
} }
// Allocate a new object, if current one was not found before // Allocate a new object, if current one was not found before
if ( NULL == m_pModel->m_pCurrent ) if( NULL == m_pModel->m_pCurrent ) {
createObject(strObjectName); createObject( strObjectName );
}
} }
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
} }
@ -694,7 +705,6 @@ void ObjFileParser::createObject(const std::string &strObjectName)
m_pModel->m_pCurrent->m_strObjName = strObjectName; m_pModel->m_pCurrent->m_strObjName = strObjectName;
m_pModel->m_Objects.push_back( m_pModel->m_pCurrent ); m_pModel->m_Objects.push_back( m_pModel->m_pCurrent );
createMesh(); createMesh();
if( m_pModel->m_pCurrentMaterial ) if( m_pModel->m_pCurrentMaterial )

View File

@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define OBJ_TOOLS_H_INC #define OBJ_TOOLS_H_INC
#include "fast_atof.h" #include "fast_atof.h"
#include "ParsingUtils.h"
namespace Assimp namespace Assimp
{ {
@ -68,28 +69,6 @@ inline bool isEndOfBuffer( char_t it, char_t end )
return ( it == end ); return ( it == end );
} }
/** @brief Returns true, if token is a space on any supported platform
* @param token Token to search in
* @return true, if token is a space
*/
inline bool isSeparator( char token )
{
return ( token == ' ' ||
token == '\n' ||
token == '\f' ||
token == '\r' ||
token == '\t' );
}
/** @brief Returns true, fi token id a new line marking token.
* @param token Token to search in
* @return true, if token is a newline token.
*/
inline bool isNewLine( char token )
{
return ( token == '\n' || token == '\f' || token == '\r' );
}
/** @brief Returns next word separated by a space /** @brief Returns next word separated by a space
* @param pBuffer Pointer to data buffer * @param pBuffer Pointer to data buffer
* @param pEnd Pointer to end of buffer * @param pEnd Pointer to end of buffer
@ -100,7 +79,7 @@ inline Char_T getNextWord( Char_T pBuffer, Char_T pEnd )
{ {
while ( !isEndOfBuffer( pBuffer, pEnd ) ) while ( !isEndOfBuffer( pBuffer, pEnd ) )
{ {
if ( !isSeparator( *pBuffer ) || isNewLine( *pBuffer ) ) if( !IsSpaceOrNewLine( *pBuffer ) || IsLineEnd( *pBuffer ) )
break; break;
pBuffer++; pBuffer++;
} }
@ -117,7 +96,7 @@ inline Char_T getNextToken( Char_T pBuffer, Char_T pEnd )
{ {
while ( !isEndOfBuffer( pBuffer, pEnd ) ) while ( !isEndOfBuffer( pBuffer, pEnd ) )
{ {
if ( isSeparator( *pBuffer ) ) if( IsSpaceOrNewLine( *pBuffer ) )
break; break;
pBuffer++; pBuffer++;
} }
@ -127,14 +106,14 @@ inline Char_T getNextToken( Char_T pBuffer, Char_T pEnd )
/** @brief Skips a line /** @brief Skips a line
* @param it Iterator set to current position * @param it Iterator set to current position
* @param end Iterator set to end of scratch buffer for readout * @param end Iterator set to end of scratch buffer for readout
* @param uiLine Current linenumber in format * @param uiLine Current line number in format
* @return Current-iterator with new position * @return Current-iterator with new position
*/ */
template<class char_t> template<class char_t>
inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine ) inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine ) {
{ while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) {
while ( !isEndOfBuffer( it, end ) && !isNewLine( *it ) ) ++it;
++it; }
if ( it != end ) if ( it != end )
{ {
++it; ++it;
@ -157,15 +136,16 @@ template<class char_t>
inline char_t getName( char_t it, char_t end, std::string &name ) inline char_t getName( char_t it, char_t end, std::string &name )
{ {
name = ""; name = "";
if ( isEndOfBuffer( it, end ) ) if( isEndOfBuffer( it, end ) ) {
return end; return end;
}
char *pStart = &( *it ); char *pStart = &( *it );
while ( !isEndOfBuffer( it, end ) && !isNewLine( *it ) ) { while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) {
++it; ++it;
} }
while(isEndOfBuffer( it, end ) || isNewLine( *it ) || isSeparator(*it)) { while( isEndOfBuffer( it, end ) || IsLineEnd( *it ) || IsSpaceOrNewLine( *it ) ) {
--it; --it;
} }
++it; ++it;
@ -196,7 +176,7 @@ inline char_t CopyNextWord( char_t it, char_t end, char *pBuffer, size_t length
{ {
size_t index = 0; size_t index = 0;
it = getNextWord<char_t>( it, end ); it = getNextWord<char_t>( it, end );
while ( !isSeparator( *it ) && !isEndOfBuffer( it, end ) ) while( !IsSpaceOrNewLine( *it ) && !isEndOfBuffer( it, end ) )
{ {
pBuffer[index] = *it ; pBuffer[index] = *it ;
index++; index++;
@ -259,4 +239,4 @@ unsigned int tokenize( const string_type& str, std::vector<string_type>& tokens,
} // Namespace Assimp } // Namespace Assimp
#endif #endif // OBJ_TOOLS_H_INC

View File

@ -376,14 +376,14 @@ void OgreBinarySerializer::ReadMeshSkeletonLink(Mesh *mesh)
mesh->skeletonRef = ReadLine(); mesh->skeletonRef = ReadLine();
} }
void OgreBinarySerializer::ReadMeshBounds(Mesh *mesh) void OgreBinarySerializer::ReadMeshBounds(Mesh * /*mesh*/)
{ {
// Skip bounds, not compatible with Assimp. // Skip bounds, not compatible with Assimp.
// 2x float vec3 + 1x float sphere radius // 2x float vec3 + 1x float sphere radius
SkipBytes(sizeof(float) * 7); SkipBytes(sizeof(float) * 7);
} }
void OgreBinarySerializer::ReadMeshExtremes(Mesh *mesh) void OgreBinarySerializer::ReadMeshExtremes(Mesh * /*mesh*/)
{ {
// Skip extremes, not compatible with Assimp. // Skip extremes, not compatible with Assimp.
size_t numBytes = m_currentLen - MSTREAM_OVERHEAD_SIZE; size_t numBytes = m_currentLen - MSTREAM_OVERHEAD_SIZE;
@ -534,7 +534,6 @@ void OgreBinarySerializer::ReadSubMeshTextureAlias(SubMesh *submesh)
void OgreBinarySerializer::ReadSubMeshNames(Mesh *mesh) void OgreBinarySerializer::ReadSubMeshNames(Mesh *mesh)
{ {
uint16_t id = 0; uint16_t id = 0;
uint16_t submeshIndex = 0;
if (!AtEnd()) if (!AtEnd())
{ {
@ -644,7 +643,7 @@ void OgreBinarySerializer::ReadGeometryVertexBuffer(VertexData *dest)
DefaultLogger::get()->debug(Formatter::format() << " - Read vertex buffer for source " << bindIndex << " of " << numBytes << " bytes"); DefaultLogger::get()->debug(Formatter::format() << " - Read vertex buffer for source " << bindIndex << " of " << numBytes << " bytes");
} }
void OgreBinarySerializer::ReadEdgeList(Mesh *mesh) void OgreBinarySerializer::ReadEdgeList(Mesh * /*mesh*/)
{ {
// Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped. // Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped.
@ -1055,7 +1054,7 @@ void OgreBinarySerializer::ReadSkeletonAnimation(Skeleton *skeleton)
DefaultLogger::get()->debug(Formatter::format() << " " << anim->name << " (" << anim->length << " sec, " << anim->tracks.size() << " tracks)"); DefaultLogger::get()->debug(Formatter::format() << " " << anim->name << " (" << anim->length << " sec, " << anim->tracks.size() << " tracks)");
} }
void OgreBinarySerializer::ReadSkeletonAnimationTrack(Skeleton *skeleton, Animation *dest) void OgreBinarySerializer::ReadSkeletonAnimationTrack(Skeleton * /*skeleton*/, Animation *dest)
{ {
uint16_t boneId = Read<uint16_t>(); uint16_t boneId = Read<uint16_t>();
Bone *bone = dest->parentSkeleton->BoneById(boneId); Bone *bone = dest->parentSkeleton->BoneById(boneId);
@ -1097,7 +1096,7 @@ void OgreBinarySerializer::ReadSkeletonAnimationKeyFrame(VertexAnimationTrack *d
dest->transformKeyFrames.push_back(keyframe); dest->transformKeyFrames.push_back(keyframe);
} }
void OgreBinarySerializer::ReadSkeletonAnimationLink(Skeleton *skeleton) void OgreBinarySerializer::ReadSkeletonAnimationLink(Skeleton * /*skeleton*/)
{ {
// Skip bounds, not compatible with Assimp. // Skip bounds, not compatible with Assimp.
ReadLine(); // skeleton name ReadLine(); // skeleton name

View File

@ -75,8 +75,8 @@ private:
}; };
OgreBinarySerializer(MemoryStreamReader *reader, AssetMode mode) : OgreBinarySerializer(MemoryStreamReader *reader, AssetMode mode) :
m_reader(reader),
m_currentLen(0), m_currentLen(0),
m_reader(reader),
assetMode(mode) assetMode(mode)
{ {
} }
@ -301,11 +301,12 @@ enum MeshChunkId
// unsigned short poseIndex // unsigned short poseIndex
// float influence // float influence
// Optional submesh extreme vertex list chink // Optional submesh extreme vertex list chink
M_TABLE_EXTREMES = 0xE000, M_TABLE_EXTREMES = 0xE000
// unsigned short submesh_index; // unsigned short submesh_index;
// float extremes [n_extremes][3]; // float extremes [n_extremes][3];
}; };
/*
static std::string MeshHeaderToString(MeshChunkId id) static std::string MeshHeaderToString(MeshChunkId id)
{ {
switch(id) switch(id)
@ -347,6 +348,7 @@ static std::string MeshHeaderToString(MeshChunkId id)
} }
return "Unknown_MeshChunkId"; return "Unknown_MeshChunkId";
} }
*/
enum SkeletonChunkId enum SkeletonChunkId
{ {
@ -393,6 +395,7 @@ enum SkeletonChunkId
// float scale : scale to apply to trans/scale keys // float scale : scale to apply to trans/scale keys
}; };
/*
static std::string SkeletonHeaderToString(SkeletonChunkId id) static std::string SkeletonHeaderToString(SkeletonChunkId id)
{ {
switch(id) switch(id)
@ -409,6 +412,7 @@ static std::string SkeletonHeaderToString(SkeletonChunkId id)
} }
return "Unknown_SkeletonChunkId"; return "Unknown_SkeletonChunkId";
} }
*/
} // Ogre } // Ogre
} // Assimp } // Assimp

View File

@ -108,10 +108,10 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
MemoryStreamReader reader(f); MemoryStreamReader reader(f);
// Import mesh // Import mesh
boost::scoped_ptr<Mesh> mesh = OgreBinarySerializer::ImportMesh(&reader); boost::scoped_ptr<Mesh> mesh(OgreBinarySerializer::ImportMesh(&reader));
// Import skeleton // Import skeleton
OgreBinarySerializer::ImportSkeleton(pIOHandler, mesh); OgreBinarySerializer::ImportSkeleton(pIOHandler, mesh.get());
// Import mesh referenced materials // Import mesh referenced materials
ReadMaterials(pFile, pIOHandler, pScene, mesh.get()); ReadMaterials(pFile, pIOHandler, pScene, mesh.get());
@ -128,10 +128,10 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
boost::scoped_ptr<XmlReader> reader(irr::io::createIrrXMLReader(xmlStream.get())); boost::scoped_ptr<XmlReader> reader(irr::io::createIrrXMLReader(xmlStream.get()));
// Import mesh // Import mesh
boost::scoped_ptr<MeshXml> mesh = OgreXmlSerializer::ImportMesh(reader.get()); boost::scoped_ptr<MeshXml> mesh(OgreXmlSerializer::ImportMesh(reader.get()));
// Import skeleton // Import skeleton
OgreXmlSerializer::ImportSkeleton(pIOHandler, mesh); OgreXmlSerializer::ImportSkeleton(pIOHandler, mesh.get());
// Import mesh referenced materials // Import mesh referenced materials
ReadMaterials(pFile, pIOHandler, pScene, mesh.get()); ReadMaterials(pFile, pIOHandler, pScene, mesh.get());

View File

@ -325,7 +325,7 @@ uint32_t VertexData::VertexSize(uint16_t source) const
MemoryStream *VertexData::VertexBuffer(uint16_t source) MemoryStream *VertexData::VertexBuffer(uint16_t source)
{ {
if (vertexBindings.find(source) != vertexBindings.end()) if (vertexBindings.find(source) != vertexBindings.end())
return vertexBindings[source]; return vertexBindings[source].get();
return 0; return 0;
} }
@ -404,9 +404,9 @@ size_t IndexData::FaceSize() const
// Mesh // Mesh
Mesh::Mesh() : Mesh::Mesh() :
sharedVertexData(0), hasSkeletalAnimations(false),
skeleton(0), skeleton(NULL),
hasSkeletalAnimations(false) sharedVertexData(NULL)
{ {
} }
@ -712,8 +712,8 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent)
// MeshXml // MeshXml
MeshXml::MeshXml() : MeshXml::MeshXml() :
sharedVertexData(0), skeleton(0),
skeleton(0) sharedVertexData(0)
{ {
} }
@ -797,8 +797,8 @@ void MeshXml::ConvertToAssimpScene(aiScene* dest)
// SubMeshXml // SubMeshXml
SubMeshXml::SubMeshXml() : SubMeshXml::SubMeshXml() :
vertexData(0), indexData(new IndexDataXml()),
indexData(new IndexDataXml()) vertexData(0)
{ {
} }
@ -912,8 +912,8 @@ aiMesh *SubMeshXml::ConvertToAssimpMesh(MeshXml *parent)
// Animation // Animation
Animation::Animation(Skeleton *parent) : Animation::Animation(Skeleton *parent) :
parentMesh(NULL),
parentSkeleton(parent), parentSkeleton(parent),
parentMesh(0),
length(0.0f), length(0.0f),
baseTime(-1.0f) baseTime(-1.0f)
{ {
@ -963,6 +963,8 @@ aiAnimation *Animation::ConvertToAssimpAnimation()
// Skeleton // Skeleton
Skeleton::Skeleton() : Skeleton::Skeleton() :
bones(),
animations(),
blendMode(ANIMBLEND_AVERAGE) blendMode(ANIMBLEND_AVERAGE)
{ {
} }
@ -1103,7 +1105,7 @@ aiNode *Bone::ConvertToAssimpNode(Skeleton *skeleton, aiNode *parentNode)
return node; return node;
} }
aiBone *Bone::ConvertToAssimpBone(Skeleton *parent, const std::vector<aiVertexWeight> &boneWeights) aiBone *Bone::ConvertToAssimpBone(Skeleton * /*parent*/, const std::vector<aiVertexWeight> &boneWeights)
{ {
aiBone *bone = new aiBone(); aiBone *bone = new aiBone();
bone->mName = name; bone->mName = name;
@ -1122,8 +1124,8 @@ aiBone *Bone::ConvertToAssimpBone(Skeleton *parent, const std::vector<aiVertexWe
// VertexAnimationTrack // VertexAnimationTrack
VertexAnimationTrack::VertexAnimationTrack() : VertexAnimationTrack::VertexAnimationTrack() :
target(0), type(VAT_NONE),
type(VAT_NONE) target(0)
{ {
} }

View File

@ -47,22 +47,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS #ifndef ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS
using namespace Assimp; using namespace Assimp;
#include "OptimizeMeshes.h" #include "OptimizeMeshes.h"
#include "ProcessHelper.h" #include "ProcessHelper.h"
#include "SceneCombiner.h" #include "SceneCombiner.h"
static const unsigned int NotSet = 0xffffffff;
static const unsigned int DeadBeef = 0xdeadbeef;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
OptimizeMeshesProcess::OptimizeMeshesProcess() OptimizeMeshesProcess::OptimizeMeshesProcess()
: pts (false) : pts (false)
, max_verts (0xffffffff) , max_verts( NotSet )
, max_faces (0xffffffff) , max_faces( NotSet ) {
{} // empty
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
OptimizeMeshesProcess::~OptimizeMeshesProcess() OptimizeMeshesProcess::~OptimizeMeshesProcess() {
{} // empty
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
@ -74,17 +80,17 @@ bool OptimizeMeshesProcess::IsActive( unsigned int pFlags) const
// That's a serious design flaw, consider redesign. // That's a serious design flaw, consider redesign.
if( 0 != (pFlags & aiProcess_OptimizeMeshes) ) { if( 0 != (pFlags & aiProcess_OptimizeMeshes) ) {
pts = (0 != (pFlags & aiProcess_SortByPType)); pts = (0 != (pFlags & aiProcess_SortByPType));
max_verts = (0 != (pFlags & aiProcess_SplitLargeMeshes)) ? 0xdeadbeef : max_verts; max_verts = ( 0 != ( pFlags & aiProcess_SplitLargeMeshes ) ) ? DeadBeef : max_verts;
return true; return true;
} }
return false; return false;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Setup properties for the postprocessing step // Setup properties for the post-processing step
void OptimizeMeshesProcess::SetupProperties(const Importer* pImp) void OptimizeMeshesProcess::SetupProperties(const Importer* pImp)
{ {
if (max_verts == 0xdeadbeef /* magic hack */) { if( max_verts == DeadBeef /* magic hack */ ) {
max_faces = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT,AI_SLM_DEFAULT_MAX_TRIANGLES); max_faces = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT,AI_SLM_DEFAULT_MAX_TRIANGLES);
max_verts = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT,AI_SLM_DEFAULT_MAX_VERTICES); max_verts = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT,AI_SLM_DEFAULT_MAX_VERTICES);
} }
@ -104,35 +110,36 @@ void OptimizeMeshesProcess::Execute( aiScene* pScene)
mScene = pScene; mScene = pScene;
// need to clear persistent members from previous runs // need to clear persistent members from previous runs
merge_list.clear(); merge_list.resize( 0 );
output.clear(); output.resize( 0 );
// ensure we have the right sizes
merge_list.reserve(pScene->mNumMeshes); merge_list.reserve(pScene->mNumMeshes);
output.reserve(pScene->mNumMeshes); output.reserve(pScene->mNumMeshes);
// Prepare lookup tables // Prepare lookup tables
meshes.resize(pScene->mNumMeshes); meshes.resize(pScene->mNumMeshes);
FindInstancedMeshes(pScene->mRootNode); FindInstancedMeshes(pScene->mRootNode);
if (max_verts == 0xdeadbeef) /* undo the magic hack */ if( max_verts == DeadBeef ) /* undo the magic hack */
max_verts = 0xffffffff; max_verts = NotSet;
// ... instanced meshes are immediately processed and added to the output list // ... instanced meshes are immediately processed and added to the output list
for (unsigned int i = 0, n = 0; i < pScene->mNumMeshes;++i) { for (unsigned int i = 0, n = 0; i < pScene->mNumMeshes;++i) {
meshes[i].vertex_format = GetMeshVFormatUnique(pScene->mMeshes[i]); meshes[i].vertex_format = GetMeshVFormatUnique(pScene->mMeshes[i]);
if (meshes[i].instance_cnt > 1 && meshes[i].output_id == 0xffffffff) { if (meshes[i].instance_cnt > 1 && meshes[i].output_id == NotSet ) {
meshes[i].output_id = n++; meshes[i].output_id = n++;
output.push_back(mScene->mMeshes[i]); output.push_back(mScene->mMeshes[i]);
} }
} }
// and process all nodes in the scenegraoh recursively // and process all nodes in the scenegraph recursively
ProcessNode(pScene->mRootNode); ProcessNode(pScene->mRootNode);
if (!output.size()) { if (!output.size()) {
throw DeadlyImportError("OptimizeMeshes: No meshes remaining; there's definitely something wrong"); throw DeadlyImportError("OptimizeMeshes: No meshes remaining; there's definitely something wrong");
} }
meshes.clear(); meshes.resize( 0 );
ai_assert(output.size() <= num_old); ai_assert(output.size() <= num_old);
mScene->mNumMeshes = output.size(); mScene->mNumMeshes = output.size();
@ -142,8 +149,9 @@ void OptimizeMeshesProcess::Execute( aiScene* pScene)
char tmp[512]; char tmp[512];
::sprintf(tmp,"OptimizeMeshesProcess finished. Input meshes: %i, Output meshes: %i",num_old,pScene->mNumMeshes); ::sprintf(tmp,"OptimizeMeshesProcess finished. Input meshes: %i, Output meshes: %i",num_old,pScene->mNumMeshes);
DefaultLogger::get()->info(tmp); DefaultLogger::get()->info(tmp);
} } else {
else DefaultLogger::get()->debug("OptimizeMeshesProcess finished"); DefaultLogger::get()->debug( "OptimizeMeshesProcess finished" );
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -157,7 +165,7 @@ void OptimizeMeshesProcess::ProcessNode( aiNode* pNode)
im = meshes[im].output_id; im = meshes[im].output_id;
} }
else { else {
merge_list.clear(); merge_list.resize( 0 );
unsigned int verts = 0, faces = 0; unsigned int verts = 0, faces = 0;
// Find meshes to merge with us // Find meshes to merge with us
@ -170,8 +178,9 @@ void OptimizeMeshesProcess::ProcessNode( aiNode* pNode)
faces += mScene->mMeshes[am]->mNumFaces; faces += mScene->mMeshes[am]->mNumFaces;
--pNode->mNumMeshes; --pNode->mNumMeshes;
for (unsigned int n = a; n < pNode->mNumMeshes; ++n) for( unsigned int n = a; n < pNode->mNumMeshes; ++n ) {
pNode->mMeshes[n] = pNode->mMeshes[n+1]; pNode->mMeshes[ n ] = pNode->mMeshes[ n + 1 ];
}
--a; --a;
} }
@ -184,8 +193,7 @@ void OptimizeMeshesProcess::ProcessNode( aiNode* pNode)
aiMesh* out; aiMesh* out;
SceneCombiner::MergeMeshes(&out,0,merge_list.begin(),merge_list.end()); SceneCombiner::MergeMeshes(&out,0,merge_list.begin(),merge_list.end());
output.push_back(out); output.push_back(out);
} } else {
else {
output.push_back(mScene->mMeshes[im]); output.push_back(mScene->mMeshes[im]);
} }
im = output.size()-1; im = output.size()-1;
@ -193,8 +201,9 @@ void OptimizeMeshesProcess::ProcessNode( aiNode* pNode)
} }
for (unsigned int i = 0; i < pNode->mNumChildren; ++i) for( unsigned int i = 0; i < pNode->mNumChildren; ++i ) {
ProcessNode(pNode->mChildren[i]); ProcessNode( pNode->mChildren[ i ] );
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -206,8 +215,8 @@ bool OptimizeMeshesProcess::CanJoin ( unsigned int a, unsigned int b, unsigned i
aiMesh* ma = mScene->mMeshes[a], *mb = mScene->mMeshes[b]; aiMesh* ma = mScene->mMeshes[a], *mb = mScene->mMeshes[b];
if ((0xffffffff != max_verts && verts+mb->mNumVertices > max_verts) || if ((NotSet != max_verts && verts+mb->mNumVertices > max_verts) ||
(0xffffffff != max_faces && faces+mb->mNumFaces > max_faces)) { (NotSet != max_faces && faces+mb->mNumFaces > max_faces)) {
return false; return false;
} }
@ -221,7 +230,7 @@ bool OptimizeMeshesProcess::CanJoin ( unsigned int a, unsigned int b, unsigned i
return false; return false;
// If both meshes are skinned, check whether we have many bones defined in both meshes. // If both meshes are skinned, check whether we have many bones defined in both meshes.
// If yes, we can savely join them. // If yes, we can join them.
if (ma->HasBones()) { if (ma->HasBones()) {
// TODO // TODO
return false; return false;
@ -230,14 +239,18 @@ bool OptimizeMeshesProcess::CanJoin ( unsigned int a, unsigned int b, unsigned i
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Buidl a LUT of all instanced meshes // Build a LUT of all instanced meshes
void OptimizeMeshesProcess::FindInstancedMeshes (aiNode* pNode) void OptimizeMeshesProcess::FindInstancedMeshes (aiNode* pNode)
{ {
for (unsigned int i = 0; i < pNode->mNumMeshes;++i) for( unsigned int i = 0; i < pNode->mNumMeshes; ++i ) {
++meshes[pNode->mMeshes[i]].instance_cnt; ++meshes[ pNode->mMeshes[ i ] ].instance_cnt;
}
for (unsigned int i = 0; i < pNode->mNumChildren; ++i) for( unsigned int i = 0; i < pNode->mNumChildren; ++i ) {
FindInstancedMeshes(pNode->mChildren[i]); FindInstancedMeshes( pNode->mChildren[ i ] );
}
} }
// ------------------------------------------------------------------------------------------------
#endif // !! ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS #endif // !! ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS

View File

@ -46,16 +46,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_PARSING_UTILS_H_INC #define AI_PARSING_UTILS_H_INC
#include "StringComparison.h" #include "StringComparison.h"
namespace Assimp { namespace Assimp {
// NOTE: the functions below are mostly intended as replacement for // NOTE: the functions below are mostly intended as replacement for
// std::upper, std::lower, std::isupper, std::islower, std::isspace. // std::upper, std::lower, std::isupper, std::islower, std::isspace.
// we don't bother of locales. We don't want them. We want reliable // we don't bother of locales. We don't want them. We want reliable
// (i.e. identical) results across all locales. // (i.e. identical) results across all locales.
// The functions below accept any character type, but know only // The functions below accept any character type, but know only
// about ASCII. However, UTF-32 is the only safe ASCII superset to // about ASCII. However, UTF-32 is the only safe ASCII superset to
// use since it doesn't have multibyte sequences. // use since it doesn't have multi-byte sequences.
static const unsigned int BufferSize = 4096;
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
@ -63,118 +66,145 @@ AI_FORCE_INLINE char_t ToLower( char_t in)
{ {
return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in+0x20) : in; return (in >= (char_t)'A' && in <= (char_t)'Z') ? (char_t)(in+0x20) : in;
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE char_t ToUpper( char_t in) AI_FORCE_INLINE char_t ToUpper( char_t in) {
{ return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in-0x20) : in;
return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in-0x20) : in;
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool IsUpper( char_t in) AI_FORCE_INLINE bool IsUpper( char_t in)
{ {
return (in >= (char_t)'A' && in <= (char_t)'Z'); return (in >= (char_t)'A' && in <= (char_t)'Z');
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool IsLower( char_t in) AI_FORCE_INLINE bool IsLower( char_t in)
{ {
return (in >= (char_t)'a' && in <= (char_t)'z'); return (in >= (char_t)'a' && in <= (char_t)'z');
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool IsSpace( char_t in) AI_FORCE_INLINE bool IsSpace( char_t in)
{ {
return (in == (char_t)' ' || in == (char_t)'\t'); return (in == (char_t)' ' || in == (char_t)'\t');
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool IsLineEnd( char_t in) AI_FORCE_INLINE bool IsLineEnd( char_t in)
{ {
return (in == (char_t)'\r' || in == (char_t)'\n' || in == (char_t)'\0'); return (in==(char_t)'\r'||in==(char_t)'\n'||in==(char_t)'\0'||in==(char_t)'\f');
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool IsSpaceOrNewLine( char_t in) AI_FORCE_INLINE bool IsSpaceOrNewLine( char_t in)
{ {
return IsSpace<char_t>(in) || IsLineEnd<char_t>(in); return IsSpace<char_t>(in) || IsLineEnd<char_t>(in);
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool SkipSpaces( const char_t* in, const char_t** out) AI_FORCE_INLINE bool SkipSpaces( const char_t* in, const char_t** out)
{ {
while (*in == (char_t)' ' || *in == (char_t)'\t')in++; while( *in == ( char_t )' ' || *in == ( char_t )'\t' ) {
++in;
}
*out = in; *out = in;
return !IsLineEnd<char_t>(*in); return !IsLineEnd<char_t>(*in);
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool SkipSpaces( const char_t** inout) AI_FORCE_INLINE bool SkipSpaces( const char_t** inout)
{ {
return SkipSpaces<char_t>(*inout,inout); return SkipSpaces<char_t>(*inout,inout);
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool SkipLine( const char_t* in, const char_t** out) AI_FORCE_INLINE bool SkipLine( const char_t* in, const char_t** out)
{ {
while (*in != (char_t)'\r' && *in != (char_t)'\n' && *in != (char_t)'\0')in++; while( *in != ( char_t )'\r' && *in != ( char_t )'\n' && *in != ( char_t )'\0' ) {
++in;
}
// files are opened in binary mode. Ergo there are both NL and CR // files are opened in binary mode. Ergo there are both NL and CR
while (*in == (char_t)'\r' || *in == (char_t)'\n')in++; while( *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
++in;
}
*out = in; *out = in;
return *in != (char_t)'\0'; return *in != (char_t)'\0';
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool SkipLine( const char_t** inout) AI_FORCE_INLINE bool SkipLine( const char_t** inout)
{ {
return SkipLine<char_t>(*inout,inout); return SkipLine<char_t>(*inout,inout);
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out)
{ {
while (*in == (char_t)' ' || *in == (char_t)'\t' || while( *in == ( char_t )' ' || *in == ( char_t )'\t' || *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
*in == (char_t)'\r' || *in == (char_t)'\n')in++; ++in;
}
*out = in; *out = in;
return *in != '\0'; return *in != '\0';
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t** inout) AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t** inout)
{ {
return SkipSpacesAndLineEnd<char_t>(*inout,inout); return SkipSpacesAndLineEnd<char_t>(*inout,inout);
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool GetNextLine(const char_t*& buffer, char_t out[4096]) AI_FORCE_INLINE bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] )
{ {
if ((char_t)'\0' == *buffer)return false; if( ( char_t )'\0' == *buffer ) {
return false;
}
char* _out = out; char* _out = out;
char* const end = _out+4096; char* const end = _out + BufferSize;
while (!IsLineEnd( *buffer ) && _out < end) while( !IsLineEnd( *buffer ) && _out < end ) {
*_out++ = *buffer++; *_out++ = *buffer++;
}
*_out = (char_t)'\0'; *_out = (char_t)'\0';
while (IsLineEnd( *buffer ) && '\0' != *buffer)++buffer; while( IsLineEnd( *buffer ) && '\0' != *buffer ) {
return true; ++buffer;
}
return true;
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool IsNumeric( char_t in) AI_FORCE_INLINE bool IsNumeric( char_t in)
{ {
return ( in >= '0' && in <= '9' ) || '-' == in || '+' == in; return ( in >= '0' && in <= '9' ) || '-' == in || '+' == in;
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len) AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len)
{ {
if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len])) if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
{
in += len+1; in += len+1;
return true; return true;
} }
return false; return false;
} }
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
@ -185,8 +215,7 @@ AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len
*/ */
AI_FORCE_INLINE bool TokenMatchI(const char*& in, const char* token, unsigned int len) AI_FORCE_INLINE bool TokenMatchI(const char*& in, const char* token, unsigned int len)
{ {
if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len])) if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
{
in += len+1; in += len+1;
return true; return true;
} }
@ -206,5 +235,9 @@ AI_FORCE_INLINE std::string GetNextToken(const char*& in)
while (!IsSpaceOrNewLine(*in))++in; while (!IsSpaceOrNewLine(*in))++in;
return std::string(cur,(size_t)(in-cur)); return std::string(cur,(size_t)(in-cur));
} }
// ---------------------------------------------------------------------------------
} // ! namespace Assimp } // ! namespace Assimp
#endif // ! AI_PARSING_UTILS_H_INC #endif // ! AI_PARSING_UTILS_H_INC

View File

@ -64,6 +64,20 @@ void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1); outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
} }
void ExportScenePlyBinary(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
{
// invoke the exporter
PlyExporter exporter(pFile, pScene, true);
// we're still here - export successfully completed. Write the file.
boost::scoped_ptr<IOStream> outfile(pIOSystem->Open(pFile, "wb"));
if (outfile == NULL) {
throw DeadlyExportError("could not open output .ply file: " + std::string(pFile));
}
outfile->Write(exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()), 1);
}
} // end of namespace Assimp } // end of namespace Assimp
#define PLY_EXPORT_HAS_NORMALS 0x1 #define PLY_EXPORT_HAS_NORMALS 0x1
@ -72,7 +86,7 @@ void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
#define PLY_EXPORT_HAS_COLORS (PLY_EXPORT_HAS_TEXCOORDS << AI_MAX_NUMBER_OF_TEXTURECOORDS) #define PLY_EXPORT_HAS_COLORS (PLY_EXPORT_HAS_TEXCOORDS << AI_MAX_NUMBER_OF_TEXTURECOORDS)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
PlyExporter :: PlyExporter(const char* _filename, const aiScene* pScene) PlyExporter::PlyExporter(const char* _filename, const aiScene* pScene, bool binary)
: filename(_filename) : filename(_filename)
, pScene(pScene) , pScene(pScene)
, endl("\n") , endl("\n")
@ -102,7 +116,16 @@ PlyExporter :: PlyExporter(const char* _filename, const aiScene* pScene)
} }
mOutput << "ply" << endl; mOutput << "ply" << endl;
mOutput << "format ascii 1.0" << endl; if (binary) {
#if (defined AI_BUILD_BIG_ENDIAN)
mOutput << "format binary_big_endian 1.0" << endl;
#else
mOutput << "format binary_little_endian 1.0" << endl;
#endif
}
else {
mOutput << "format ascii 1.0" << endl;
}
mOutput << "comment Created by Open Asset Import Library - http://assimp.sf.net (v" mOutput << "comment Created by Open Asset Import Library - http://assimp.sf.net (v"
<< aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.' << aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.'
<< aiGetVersionRevision() << ")" << endl; << aiGetVersionRevision() << ")" << endl;
@ -163,17 +186,29 @@ PlyExporter :: PlyExporter(const char* _filename, const aiScene* pScene)
mOutput << "end_header" << endl; mOutput << "end_header" << endl;
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
WriteMeshVerts(pScene->mMeshes[i],components); if (binary) {
WriteMeshVertsBinary(pScene->mMeshes[i], components);
}
else {
WriteMeshVerts(pScene->mMeshes[i], components);
}
} }
for (unsigned int i = 0, ofs = 0; i < pScene->mNumMeshes; ++i) { for (unsigned int i = 0, ofs = 0; i < pScene->mNumMeshes; ++i) {
WriteMeshIndices(pScene->mMeshes[i],ofs); if (binary) {
WriteMeshIndicesBinary(pScene->mMeshes[i], ofs);
}
else {
WriteMeshIndices(pScene->mMeshes[i], ofs);
}
ofs += pScene->mMeshes[i]->mNumVertices; ofs += pScene->mMeshes[i]->mNumVertices;
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void PlyExporter :: WriteMeshVerts(const aiMesh* m, unsigned int components) void PlyExporter::WriteMeshVerts(const aiMesh* m, unsigned int components)
{ {
// If a component (for instance normal vectors) is present in at least one mesh in the scene,
// then default values are written for meshes that do not contain this component.
for (unsigned int i = 0; i < m->mNumVertices; ++i) { for (unsigned int i = 0; i < m->mNumVertices; ++i) {
mOutput << mOutput <<
m->mVertices[i].x << " " << m->mVertices[i].x << " " <<
@ -237,7 +272,57 @@ void PlyExporter :: WriteMeshVerts(const aiMesh* m, unsigned int components)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void PlyExporter :: WriteMeshIndices(const aiMesh* m, unsigned int offset) void PlyExporter::WriteMeshVertsBinary(const aiMesh* m, unsigned int components)
{
// If a component (for instance normal vectors) is present in at least one mesh in the scene,
// then default values are written for meshes that do not contain this component.
aiVector3D defaultNormal(0, 0, 0);
aiVector2D defaultUV(-1, -1);
aiColor4D defaultColor(-1, -1, -1, -1);
for (unsigned int i = 0; i < m->mNumVertices; ++i) {
mOutput.write(reinterpret_cast<const char*>(&m->mVertices[i].x), 12);
if (components & PLY_EXPORT_HAS_NORMALS) {
if (m->HasNormals()) {
mOutput.write(reinterpret_cast<const char*>(&m->mNormals[i].x), 12);
}
else {
mOutput.write(reinterpret_cast<const char*>(&defaultNormal.x), 12);
}
}
for (unsigned int n = PLY_EXPORT_HAS_TEXCOORDS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_TEXTURECOORDS; n <<= 1, ++c) {
if (m->HasTextureCoords(c)) {
mOutput.write(reinterpret_cast<const char*>(&m->mTextureCoords[c][i].x), 6);
}
else {
mOutput.write(reinterpret_cast<const char*>(&defaultUV.x), 6);
}
}
for (unsigned int n = PLY_EXPORT_HAS_COLORS, c = 0; (components & n) && c != AI_MAX_NUMBER_OF_COLOR_SETS; n <<= 1, ++c) {
if (m->HasVertexColors(c)) {
mOutput.write(reinterpret_cast<const char*>(&m->mColors[c][i].r), 16);
}
else {
mOutput.write(reinterpret_cast<const char*>(&defaultColor.r), 16);
}
}
if (components & PLY_EXPORT_HAS_TANGENTS_BITANGENTS) {
if (m->HasTangentsAndBitangents()) {
mOutput.write(reinterpret_cast<const char*>(&m->mTangents[i].x), 12);
mOutput.write(reinterpret_cast<const char*>(&m->mBitangents[i].x), 12);
}
else {
mOutput.write(reinterpret_cast<const char*>(&defaultNormal.x), 12);
mOutput.write(reinterpret_cast<const char*>(&defaultNormal.x), 12);
}
}
}
}
// ------------------------------------------------------------------------------------------------
void PlyExporter::WriteMeshIndices(const aiMesh* m, unsigned int offset)
{ {
for (unsigned int i = 0; i < m->mNumFaces; ++i) { for (unsigned int i = 0; i < m->mNumFaces; ++i) {
const aiFace& f = m->mFaces[i]; const aiFace& f = m->mFaces[i];
@ -248,4 +333,16 @@ void PlyExporter :: WriteMeshIndices(const aiMesh* m, unsigned int offset)
} }
} }
void PlyExporter::WriteMeshIndicesBinary(const aiMesh* m, unsigned int offset)
{
for (unsigned int i = 0; i < m->mNumFaces; ++i) {
const aiFace& f = m->mFaces[i];
mOutput.write(reinterpret_cast<const char*>(&f.mNumIndices), 4);
for (unsigned int c = 0; c < f.mNumIndices; ++c) {
unsigned int index = f.mIndices[c] + offset;
mOutput.write(reinterpret_cast<const char*>(&index), 4);
}
}
}
#endif #endif

View File

@ -59,7 +59,7 @@ class PlyExporter
{ {
public: public:
/// Constructor for a specific scene to export /// Constructor for a specific scene to export
PlyExporter(const char* filename, const aiScene* pScene); PlyExporter(const char* filename, const aiScene* pScene, bool binary = false);
public: public:
@ -71,6 +71,9 @@ private:
void WriteMeshVerts(const aiMesh* m, unsigned int components); void WriteMeshVerts(const aiMesh* m, unsigned int components);
void WriteMeshIndices(const aiMesh* m, unsigned int ofs); void WriteMeshIndices(const aiMesh* m, unsigned int ofs);
void WriteMeshVertsBinary(const aiMesh* m, unsigned int components);
void WriteMeshIndicesBinary(const aiMesh* m, unsigned int offset);
private: private:
const std::string filename; const std::string filename;

View File

@ -182,7 +182,7 @@ PLY::ESemantic PLY::Property::ParseSemantic(const char* pCur,const char** pCurOu
{ {
eOut = PLY::EST_Opacity; eOut = PLY::EST_Opacity;
} }
else if (TokenMatch(pCur,"specular_power",6)) else if (TokenMatch(pCur,"specular_power",14))
{ {
eOut = PLY::EST_PhongPower; eOut = PLY::EST_PhongPower;
} }

View File

@ -118,9 +118,9 @@ inline bool IsCCW(T* in, size_t npoints) {
((-in[i+2].y + in[i+1].y) * ((-in[i+2].y + in[i+1].y) *
(-in[i+2].y + in[i+1].y)); (-in[i+2].y + in[i+1].y));
b = sqrt(bb); b = std::sqrt(bb);
c = sqrt(cc); c = std::sqrt(cc);
theta = acos((bb + cc - aa) / (2 * b * c)); theta = std::acos((bb + cc - aa) / (2 * b * c));
if (OnLeftSideOfLine2D(in[i],in[i+2],in[i+1])) { if (OnLeftSideOfLine2D(in[i],in[i+2],in[i+1])) {
// if (convex(in[i].x, in[i].y, // if (convex(in[i].x, in[i].y,
@ -146,9 +146,9 @@ inline bool IsCCW(T* in, size_t npoints) {
cc = ((in[1].x - in[0].x) * (in[1].x - in[0].x)) + cc = ((in[1].x - in[0].x) * (in[1].x - in[0].x)) +
((-in[1].y + in[0].y) * (-in[1].y + in[0].y)); ((-in[1].y + in[0].y) * (-in[1].y + in[0].y));
b = sqrt(bb); b = std::sqrt(bb);
c = sqrt(cc); c = std::sqrt(cc);
theta = acos((bb + cc - aa) / (2 * b * c)); theta = std::acos((bb + cc - aa) / (2 * b * c));
//if (convex(in[npoints-2].x, in[npoints-2].y, //if (convex(in[npoints-2].x, in[npoints-2].y,
// in[0].x, in[0].y, // in[0].x, in[0].y,

View File

@ -73,11 +73,13 @@ static const aiImporterDesc desc = {
namespace Assimp { namespace Assimp {
/*
static void getSupportedExtensions(std::vector<std::string> &supportedExtensions) { static void getSupportedExtensions(std::vector<std::string> &supportedExtensions) {
supportedExtensions.push_back( ".jpg" ); supportedExtensions.push_back( ".jpg" );
supportedExtensions.push_back( ".png" ); supportedExtensions.push_back( ".png" );
supportedExtensions.push_back( ".tga" ); supportedExtensions.push_back( ".tga" );
} }
*/
using namespace Q3BSP; using namespace Q3BSP;
@ -628,7 +630,7 @@ aiFace *Q3BSPFileImporter::getNextFace( aiMesh *pMesh, unsigned int &rFaceIdx )
bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *pModel, bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *pModel,
Q3BSP::Q3BSPZipArchive *pArchive, aiScene*, Q3BSP::Q3BSPZipArchive *pArchive, aiScene*,
aiMaterial *pMatHelper, int textureId ) { aiMaterial *pMatHelper, int textureId ) {
if ( NULL == pArchive || NULL == pArchive || NULL == pMatHelper ) { if ( NULL == pArchive || NULL == pMatHelper ) {
return false; return false;
} }
@ -639,17 +641,17 @@ bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *pMode
bool res = true; bool res = true;
sQ3BSPTexture *pTexture = pModel->m_Textures[ textureId ]; sQ3BSPTexture *pTexture = pModel->m_Textures[ textureId ];
if ( !pTexture ) { if ( !pTexture ) {
return false; return false;
} }
std::vector<std::string> supportedExtensions; std::vector<std::string> supportedExtensions;
supportedExtensions.push_back( ".jpg" ); supportedExtensions.push_back( ".jpg" );
supportedExtensions.push_back( ".png" ); supportedExtensions.push_back( ".png" );
supportedExtensions.push_back( ".tga" ); supportedExtensions.push_back( ".tga" );
std::string textureName, ext; std::string textureName, ext;
if ( expandFile( pArchive, pTexture->strName, supportedExtensions, textureName, ext ) ) { if ( expandFile( pArchive, pTexture->strName, supportedExtensions, textureName, ext ) ) {
IOStream *pTextureStream = pArchive->Open( textureName.c_str() ); IOStream *pTextureStream = pArchive->Open( textureName.c_str() );
if ( !pTextureStream ) { if ( pTextureStream ) {
size_t texSize = pTextureStream->FileSize(); size_t texSize = pTextureStream->FileSize();
aiTexture *pTexture = new aiTexture; aiTexture *pTexture = new aiTexture;
pTexture->mHeight = 0; pTexture->mHeight = 0;

View File

@ -68,25 +68,25 @@ voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) {
return (voidpf) io_system->Open(filename, mode_fopen); return (voidpf) io_system->Open(filename, mode_fopen);
} }
uLong IOSystem2Unzip::read(voidpf opaque, voidpf stream, void* buf, uLong size) { uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void* buf, uLong size) {
IOStream* io_stream = (IOStream*) stream; IOStream* io_stream = (IOStream*) stream;
return io_stream->Read(buf, 1, size); return io_stream->Read(buf, 1, size);
} }
uLong IOSystem2Unzip::write(voidpf opaque, voidpf stream, const void* buf, uLong size) { uLong IOSystem2Unzip::write(voidpf /*opaque*/, voidpf stream, const void* buf, uLong size) {
IOStream* io_stream = (IOStream*) stream; IOStream* io_stream = (IOStream*) stream;
return io_stream->Write(buf, 1, size); return io_stream->Write(buf, 1, size);
} }
long IOSystem2Unzip::tell(voidpf opaque, voidpf stream) { long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) {
IOStream* io_stream = (IOStream*) stream; IOStream* io_stream = (IOStream*) stream;
return io_stream->Tell(); return io_stream->Tell();
} }
long IOSystem2Unzip::seek(voidpf opaque, voidpf stream, uLong offset, int origin) { long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int origin) {
IOStream* io_stream = (IOStream*) stream; IOStream* io_stream = (IOStream*) stream;
aiOrigin assimp_origin; aiOrigin assimp_origin;
@ -115,7 +115,7 @@ int IOSystem2Unzip::close(voidpf opaque, voidpf stream) {
return 0; return 0;
} }
int IOSystem2Unzip::testerror(voidpf opaque, voidpf stream) { int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) {
return 0; return 0;
} }

View File

@ -348,8 +348,8 @@ bool STLImporter::LoadBinaryFile()
bool bIsMaterialise = false; bool bIsMaterialise = false;
// search for an occurence of "COLOR=" in the header // search for an occurence of "COLOR=" in the header
const char* sz2 = (const char*)mBuffer; const unsigned char* sz2 = (const unsigned char*)mBuffer;
const char* const szEnd = sz2+80; const unsigned char* const szEnd = sz2+80;
while (sz2 < szEnd) { while (sz2 < szEnd) {
if ('C' == *sz2++ && 'O' == *sz2++ && 'L' == *sz2++ && if ('C' == *sz2++ && 'O' == *sz2++ && 'L' == *sz2++ &&

View File

@ -38,6 +38,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
// TODO: refactor entire file to get rid of the "flat-copy" first approach
// to copying structures. This easily breaks in the most unintuitive way
// possible as new fields are added to assimp structures.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** @file Implements Assimp::SceneCombiner. This is a smart utility /** @file Implements Assimp::SceneCombiner. This is a smart utility
@ -1194,10 +1197,53 @@ void SceneCombiner::Copy (aiNode** _dest, const aiNode* src)
// get a flat copy // get a flat copy
::memcpy(dest,src,sizeof(aiNode)); ::memcpy(dest,src,sizeof(aiNode));
if (src->mMetaData) {
Copy(&dest->mMetaData, src->mMetaData);
}
// and reallocate all arrays // and reallocate all arrays
GetArrayCopy( dest->mMeshes, dest->mNumMeshes ); GetArrayCopy( dest->mMeshes, dest->mNumMeshes );
CopyPtrArray( dest->mChildren, src->mChildren,dest->mNumChildren); CopyPtrArray( dest->mChildren, src->mChildren,dest->mNumChildren);
} }
// ------------------------------------------------------------------------------------------------
void SceneCombiner::Copy (aiMetadata** _dest, const aiMetadata* src)
{
ai_assert(NULL != _dest && NULL != src);
aiMetadata* dest = *_dest = new aiMetadata();
dest->mNumProperties = src->mNumProperties;
dest->mKeys = new aiString[src->mNumProperties];
std::copy(src->mKeys, src->mKeys + src->mNumProperties, dest->mKeys);
dest->mValues = new aiMetadataEntry[src->mNumProperties];
for (unsigned int i = 0; i < src->mNumProperties; ++i) {
aiMetadataEntry& in = src->mValues[i];
aiMetadataEntry& out = dest->mValues[i];
out.mType = in.mType;
switch (dest->mValues[i].mType) {
case AI_BOOL:
out.mData = new bool(*static_cast<bool*>(in.mData));
break;
case AI_INT:
out.mData = new int(*static_cast<int*>(in.mData));
break;
case AI_UINT64:
out.mData = new uint64_t(*static_cast<uint64_t*>(in.mData));
break;
case AI_FLOAT:
out.mData = new float(*static_cast<float*>(in.mData));
break;
case AI_AISTRING:
out.mData = new aiString(*static_cast<aiString*>(in.mData));
break;
case AI_AIVECTOR3D:
out.mData = new aiVector3D(*static_cast<aiVector3D*>(in.mData));
break;
default:
ai_assert(false);
}
}
}
} }

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