commit
45988cd238
|
@ -32,3 +32,22 @@ test/results
|
|||
|
||||
# Python
|
||||
__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
|
||||
|
|
32
.travis.yml
32
.travis.yml
|
@ -1,11 +1,16 @@
|
|||
before_install:
|
||||
- sudo apt-get install cmake
|
||||
- sudo apt-get install cmake python3
|
||||
|
||||
env:
|
||||
- TRAVIS_NO_EXPORT=YES
|
||||
- TRAVIS_NO_EXPORT=NO
|
||||
- TRAVIS_STATIC_BUILD=ON
|
||||
- TRAVIS_STATIC_BUILD=OFF
|
||||
matrix:
|
||||
- LINUX=1 TRAVIS_NO_EXPORT=YES
|
||||
- LINUX=1 TRAVIS_NO_EXPORT=NO
|
||||
- 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
|
||||
|
||||
|
@ -13,7 +18,20 @@ compiler:
|
|||
- gcc
|
||||
- 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
23
CHANGES
|
@ -2,6 +2,29 @@
|
|||
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)
|
||||
|
||||
|
|
285
CMakeLists.txt
285
CMakeLists.txt
|
@ -3,7 +3,7 @@ PROJECT( Assimp )
|
|||
|
||||
# Define here the needed parameters
|
||||
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 ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH})
|
||||
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
|
||||
execute_process(
|
||||
COMMAND git rev-parse --abbrev-ref HEAD
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_BRANCH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
COMMAND git rev-parse --abbrev-ref HEAD
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_BRANCH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# Get the latest abbreviated commit hash of the working branch
|
||||
execute_process(
|
||||
COMMAND git log -1 --format=%h
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_COMMIT_HASH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
COMMAND git log -1 --format=%h
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_COMMIT_HASH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
if(NOT GIT_COMMIT_HASH)
|
||||
set(GIT_COMMIT_HASH 0)
|
||||
set(GIT_COMMIT_HASH 0)
|
||||
endif(NOT GIT_COMMIT_HASH)
|
||||
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/revision.h.in
|
||||
${CMAKE_BINARY_DIR}/revision.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/revision.h.in
|
||||
${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)
|
||||
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(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)
|
||||
add_definitions(-fPIC) # this is a very important switch and some libraries seem now to have it....
|
||||
# hide all not-exported symbols
|
||||
add_definitions( -fvisibility=hidden -Wall )
|
||||
add_definitions(-fPIC) # this is a very important switch and some libraries seem now to have it....
|
||||
# hide all not-exported symbols
|
||||
add_definitions( -fvisibility=hidden -Wall )
|
||||
elseif(MSVC)
|
||||
# enable multi-core compilation with MSVC
|
||||
add_definitions(/MP)
|
||||
endif()
|
||||
# enable multi-core compilation with MSVC
|
||||
add_definitions(/MP)
|
||||
endif()
|
||||
|
||||
INCLUDE (FindPkgConfig)
|
||||
INCLUDE_DIRECTORIES( include )
|
||||
|
@ -64,57 +66,54 @@ INCLUDE (PrecompiledHeader)
|
|||
# source tree. During an out-of-source build, however, do not litter this
|
||||
# directory, since that is probably what the user wanted to avoid.
|
||||
IF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
|
||||
SET( CMAKE_LIBRARY_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_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib" )
|
||||
SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib" )
|
||||
SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/bin" )
|
||||
ENDIF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
|
||||
|
||||
# Cache these to allow the user to override them manually.
|
||||
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
|
||||
"Path the header files are installed to." )
|
||||
"Path the header files are installed to." )
|
||||
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")
|
||||
|
||||
# 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 )
|
||||
|
||||
# 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
|
||||
IF (NOT TARGET uninstall)
|
||||
# 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)
|
||||
add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
||||
# 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)
|
||||
add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
|
||||
ENDIF()
|
||||
|
||||
# Globally enable Boost resp. the Boost workaround – it is also needed by the
|
||||
# tools which include the Assimp headers.
|
||||
SET ( ASSIMP_ENABLE_BOOST_WORKAROUND ON CACHE BOOL
|
||||
"If a simple implementation of the used Boost functions is used. Slightly reduces functionality, but enables builds without Boost available."
|
||||
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."
|
||||
ON
|
||||
)
|
||||
IF ( ASSIMP_ENABLE_BOOST_WORKAROUND )
|
||||
INCLUDE_DIRECTORIES( code/BoostWorkaround )
|
||||
ADD_DEFINITIONS( -DASSIMP_BUILD_BOOST_WORKAROUND )
|
||||
MESSAGE( STATUS "Building a non-boost version of Assimp." )
|
||||
INCLUDE_DIRECTORIES( code/BoostWorkaround )
|
||||
ADD_DEFINITIONS( -DASSIMP_BUILD_BOOST_WORKAROUND )
|
||||
MESSAGE( STATUS "Building a non-boost version of Assimp." )
|
||||
ELSE ( ASSIMP_ENABLE_BOOST_WORKAROUND )
|
||||
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")
|
||||
FIND_PACKAGE( Boost )
|
||||
IF ( NOT Boost_FOUND )
|
||||
MESSAGE( FATAL_ERROR
|
||||
"Boost libraries (http://www.boost.org/) not found. "
|
||||
"You can build a non-boost version of Assimp with slightly reduced "
|
||||
SET( Boost_DETAILED_FAILURE_MSG ON )
|
||||
SET( Boost_ADDITIONAL_VERSIONS "1.47" "1.47.0" "1.48.0" "1.48" "1.49" "1.49.0" "1.50" "1.50.0" "1.51" "1.51.0" "1.52.0" "1.53.0" "1.54.0" "1.55" "1.55.0" "1.56" "1.56.0" "1.57" "1.57.0" )
|
||||
FIND_PACKAGE( Boost )
|
||||
IF ( NOT Boost_FOUND )
|
||||
MESSAGE( FATAL_ERROR
|
||||
"Boost libraries (http://www.boost.org/) not found. "
|
||||
"You can build a non-boost version of Assimp with slightly reduced "
|
||||
"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 )
|
||||
|
||||
# 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)
|
||||
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
|
||||
"Disable Assimp's export functionality."
|
||||
option ( ASSIMP_NO_EXPORT
|
||||
"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 zlib
|
||||
find_package(ZLIB)
|
||||
if( NOT ZLIB_FOUND )
|
||||
message(STATUS "compiling zlib from souces")
|
||||
include(CheckIncludeFile)
|
||||
include(CheckTypeSize)
|
||||
include(CheckFunctionExists)
|
||||
# compile from sources
|
||||
add_subdirectory(contrib/zlib)
|
||||
set(ZLIB_FOUND 1)
|
||||
set(ZLIB_LIBRARIES zlibstatic)
|
||||
set(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib)
|
||||
message(STATUS "compiling zlib from souces")
|
||||
include(CheckIncludeFile)
|
||||
include(CheckTypeSize)
|
||||
include(CheckFunctionExists)
|
||||
# compile from sources
|
||||
add_subdirectory(contrib/zlib)
|
||||
set(ZLIB_FOUND 1)
|
||||
set(ZLIB_LIBRARIES zlibstatic)
|
||||
set(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib)
|
||||
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)
|
||||
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
|
||||
|
||||
# Search for unzip
|
||||
if (PKG_CONFIG_FOUND)
|
||||
PKG_CHECK_MODULES(UNZIP minizip)
|
||||
PKG_CHECK_MODULES(UNZIP minizip)
|
||||
endif (PKG_CONFIG_FOUND)
|
||||
|
||||
IF ( ASSIMP_NO_EXPORT )
|
||||
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_EXPORT)
|
||||
MESSAGE( STATUS "Build an import-only version of Assimp." )
|
||||
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_EXPORT)
|
||||
MESSAGE( STATUS "Build an import-only version of Assimp." )
|
||||
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
|
||||
"describe the current architecture."
|
||||
"describe the current architecture."
|
||||
)
|
||||
IF ( 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 "")
|
||||
|
||||
# ${CMAKE_GENERATOR}
|
||||
SET ( ASSIMP_BUILD_COMPILER "" CACHE STRING
|
||||
"describe the current compiler."
|
||||
"describe the current compiler."
|
||||
)
|
||||
IF ( 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 "")
|
||||
|
||||
MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER )
|
||||
|
||||
ADD_SUBDIRECTORY( code/ )
|
||||
SET ( ASSIMP_BUILD_ASSIMP_TOOLS ON CACHE BOOL
|
||||
"If the supplementary tools for Assimp are built in addition to the library."
|
||||
option ( ASSIMP_BUILD_ASSIMP_TOOLS
|
||||
"If the supplementary tools for Assimp are built in addition to the library."
|
||||
ON
|
||||
)
|
||||
IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
|
||||
IF ( WIN32 )
|
||||
ADD_SUBDIRECTORY( tools/assimp_view/ )
|
||||
ENDIF ( WIN32 )
|
||||
ADD_SUBDIRECTORY( tools/assimp_cmd/ )
|
||||
IF ( WIN32 )
|
||||
ADD_SUBDIRECTORY( tools/assimp_view/ )
|
||||
ENDIF ( WIN32 )
|
||||
ADD_SUBDIRECTORY( tools/assimp_cmd/ )
|
||||
ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
|
||||
|
||||
SET ( ASSIMP_BUILD_SAMPLES OFF CACHE BOOL
|
||||
"If the official samples are built as well (needs Glut)."
|
||||
option ( ASSIMP_BUILD_SAMPLES
|
||||
"If the official samples are built as well (needs Glut)."
|
||||
OFF
|
||||
)
|
||||
|
||||
IF ( ASSIMP_BUILD_SAMPLES)
|
||||
IF ( WIN32 )
|
||||
ADD_SUBDIRECTORY( samples/SimpleTexturedOpenGL/ )
|
||||
ENDIF ( WIN32 )
|
||||
ADD_SUBDIRECTORY( samples/SimpleOpenGL/ )
|
||||
IF ( WIN32 )
|
||||
ADD_SUBDIRECTORY( samples/SimpleTexturedOpenGL/ )
|
||||
ENDIF ( WIN32 )
|
||||
ADD_SUBDIRECTORY( samples/SimpleOpenGL/ )
|
||||
ENDIF ( ASSIMP_BUILD_SAMPLES )
|
||||
|
||||
IF ( WIN32 )
|
||||
SET ( ASSIMP_BUILD_TESTS ON CACHE BOOL
|
||||
"If the test suite for Assimp is built in addition to the library."
|
||||
)
|
||||
|
||||
IF ( ASSIMP_BUILD_TESTS )
|
||||
ADD_SUBDIRECTORY( test/ )
|
||||
ENDIF ( ASSIMP_BUILD_TESTS )
|
||||
ENDIF ( WIN32 )
|
||||
option ( ASSIMP_BUILD_TESTS
|
||||
"If the test suite for Assimp is built in addition to the library."
|
||||
ON
|
||||
)
|
||||
|
||||
IF ( ASSIMP_BUILD_TESTS )
|
||||
ADD_SUBDIRECTORY( test/ )
|
||||
ENDIF ( ASSIMP_BUILD_TESTS )
|
||||
|
||||
IF(MSVC)
|
||||
SET ( ASSIMP_INSTALL_PDB ON CACHE BOOL
|
||||
"Install MSVC debug files."
|
||||
)
|
||||
option ( ASSIMP_INSTALL_PDB
|
||||
"Install MSVC debug files."
|
||||
ON
|
||||
)
|
||||
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)
|
||||
# Packing information
|
||||
set(CPACK_PACKAGE_NAME "assimp{ASSIMP_VERSION_MAJOR}")
|
||||
set(CPACK_PACKAGE_CONTACT "" CACHE STRING "Package maintainer and PGP signer.")
|
||||
set(CPACK_PACKAGE_VENDOR "http://assimp.sourceforge.net/")
|
||||
set(CPACK_PACKAGE_DISPLAY_NAME "Assimp ${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_MAJOR "${ASSIMP_VERSION_MAJOR}")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "${ASSIMP_VERSION_MINOR}")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "${ASSIMP_VERSION_PATCH}")
|
||||
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")
|
||||
# Packing information
|
||||
set(CPACK_PACKAGE_NAME "assimp{ASSIMP_VERSION_MAJOR}")
|
||||
set(CPACK_PACKAGE_CONTACT "" CACHE STRING "Package maintainer and PGP signer.")
|
||||
set(CPACK_PACKAGE_VENDOR "http://assimp.sourceforge.net/")
|
||||
set(CPACK_PACKAGE_DISPLAY_NAME "Assimp ${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_MAJOR "${ASSIMP_VERSION_MAJOR}")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "${ASSIMP_VERSION_MINOR}")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "${ASSIMP_VERSION_PATCH}")
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "assimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
|
||||
|
||||
string(TOUPPER ${LIBASSIMP_COMPONENT} "LIBASSIMP_COMPONENT_UPPER")
|
||||
string(TOUPPER ${LIBASSIMP-DEV_COMPONENT} "LIBASSIMP-DEV_COMPONENT_UPPER")
|
||||
string(TOUPPER ${LIBASSIMP_COMPONENT} "LIBASSIMP_COMPONENT_UPPER")
|
||||
string(TOUPPER ${LIBASSIMP-DEV_COMPONENT} "LIBASSIMP-DEV_COMPONENT_UPPER")
|
||||
|
||||
set(CPACK_COMPONENT_ASSIMP-BIN_DISPLAY_NAME "tools")
|
||||
set(CPACK_COMPONENT_ASSIMP-BIN_DEPENDS "${LIBASSIMP_COMPONENT}" )
|
||||
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}_DEPENDS $ "{LIBASSIMP_COMPONENT}" )
|
||||
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_DEBIAN_BUILD_DEPENDS debhelper cmake libboost-dev libboost-thread-dev libboost-math-dev zlib1g-dev pkg-config)
|
||||
set(CPACK_COMPONENT_ASSIMP-BIN_DISPLAY_NAME "tools")
|
||||
set(CPACK_COMPONENT_ASSIMP-BIN_DEPENDS "${LIBASSIMP_COMPONENT}" )
|
||||
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}_DEPENDS $ "{LIBASSIMP_COMPONENT}" )
|
||||
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_DEBIAN_BUILD_DEPENDS debhelper cmake libboost-dev libboost-thread-dev libboost-math-dev zlib1g-dev pkg-config)
|
||||
|
||||
# debian
|
||||
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
||||
set(CPACK_DEBIAN_CMAKE_OPTIONS "-DBUILD_ASSIMP_SAMPLES:BOOL=${ASSIMP_BUILD_SAMPLES}")
|
||||
set(CPACK_DEBIAN_PACKAGE_SECTION "libs" )
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_COMPONENTS_ALL}")
|
||||
set(CPACK_DEBIAN_PACKAGE_SUGGESTS)
|
||||
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_SOURCE_COPY svn export --force)
|
||||
set(CPACK_DEBIAN_CHANGELOG)
|
||||
execute_process(COMMAND lsb_release -is
|
||||
OUTPUT_VARIABLE _lsb_distribution OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE _lsb_release_failed)
|
||||
set(CPACK_DEBIAN_DISTRIBUTION_NAME ${_lsb_distribution} CACHE STRING "Name of the distrubiton")
|
||||
string(TOLOWER ${CPACK_DEBIAN_DISTRIBUTION_NAME} CPACK_DEBIAN_DISTRIBUTION_NAME)
|
||||
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")
|
||||
endif()
|
||||
set(DPUT_HOST "" CACHE STRING "PPA repository to upload the debian sources")
|
||||
include(CPack)
|
||||
include(DebSourcePPA)
|
||||
# debian
|
||||
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
||||
set(CPACK_DEBIAN_CMAKE_OPTIONS "-DBUILD_ASSIMP_SAMPLES:BOOL=${ASSIMP_BUILD_SAMPLES}")
|
||||
set(CPACK_DEBIAN_PACKAGE_SECTION "libs" )
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_COMPONENTS_ALL}")
|
||||
set(CPACK_DEBIAN_PACKAGE_SUGGESTS)
|
||||
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_SOURCE_COPY svn export --force)
|
||||
set(CPACK_DEBIAN_CHANGELOG)
|
||||
execute_process(COMMAND lsb_release -is
|
||||
OUTPUT_VARIABLE _lsb_distribution OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
RESULT_VARIABLE _lsb_release_failed)
|
||||
set(CPACK_DEBIAN_DISTRIBUTION_NAME ${_lsb_distribution} CACHE STRING "Name of the distrubiton")
|
||||
string(TOLOWER ${CPACK_DEBIAN_DISTRIBUTION_NAME} CPACK_DEBIAN_DISTRIBUTION_NAME)
|
||||
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")
|
||||
endif()
|
||||
set(DPUT_HOST "" CACHE STRING "PPA repository to upload the debian sources")
|
||||
include(CPack)
|
||||
include(DebSourcePPA)
|
||||
endif()
|
||||
|
|
3
CREDITS
3
CREDITS
|
@ -148,3 +148,6 @@ Bugfixes for uv-tanget calculation.
|
|||
|
||||
- Jonne Nauha
|
||||
Ogre Binary format support
|
||||
|
||||
- Filip Wasil, Tieto Poland Sp. z o.o.
|
||||
Android JNI asset extraction support
|
||||
|
|
10
Readme.md
10
Readme.md
|
@ -1,10 +1,12 @@
|
|||
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)
|
||||
|
||||
[open3mod](https://github.com/acgessler/open3mod) is an Open Source 3D model viewer based off Assimp's import and export abilities.
|
||||
|
||||
#### Supported file formats ####
|
||||
|
||||
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 XML
|
||||
- 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.
|
||||
|
||||
|
@ -55,7 +58,10 @@ Exporters include:
|
|||
- STL
|
||||
- OBJ
|
||||
- PLY
|
||||
- X
|
||||
- 3DS
|
||||
- JSON (for WebGl, via https://github.com/acgessler/assimp2json)
|
||||
- ASSBIN
|
||||
|
||||
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
|
||||
/port Ports to other languages and scripts to maintain those.
|
||||
/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
|
||||
use cases for Assimp
|
||||
/workspaces Build enviroments for vc,xcode,... (deprecated,
|
||||
|
|
|
@ -44,20 +44,20 @@ if (CMAKE_BUILD_TYPE EQUAL "DEBUG")
|
|||
set( ASSIMP_LIBRARIES ${ASSIMP_LIBRARIES}D)
|
||||
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
|
||||
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
|
||||
set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}")
|
||||
set(ASSIMP_LDFLAGS_OTHER "${ASSIMP_LINK_FLAGS}")
|
||||
|
|
|
@ -7,4 +7,5 @@ Name: @CMAKE_PROJECT_NAME@
|
|||
Description: Import various well-known 3D model formats in an uniform manner.
|
||||
Version: @PROJECT_VERSION@
|
||||
Libs: -L${libdir} -lassimp@ASSIMP_LIBRARY_SUFFIX@
|
||||
Libs.private: @LIBSTDC++_LIBRARIES@ @ZLIB_LIBRARIES_LINKED@
|
||||
Cflags: -I${includedir}
|
||||
|
|
|
@ -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})
|
|
@ -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
|
|
@ -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
|
|
@ -468,7 +468,7 @@ struct aiFloatKey
|
|||
{return mTime < o.mTime;}
|
||||
|
||||
bool operator > (const aiFloatKey& o) const
|
||||
{return mTime < o.mTime;}
|
||||
{return mTime > o.mTime;}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -273,8 +273,8 @@ protected:
|
|||
bool bIsPrj;
|
||||
};
|
||||
|
||||
#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
||||
#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER
|
||||
|
||||
#endif // AI_3DSIMPORTER_H_INC
|
||||
|
|
|
@ -1525,7 +1525,7 @@ void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh& mesh)
|
|||
continue;
|
||||
}
|
||||
// Number of bones
|
||||
if (TokenMatch(filePtr,"MESH_NUMBONE" ,11))
|
||||
if (TokenMatch(filePtr,"MESH_NUMBONE" ,12))
|
||||
{
|
||||
ParseLV4MeshLong(iNumBones);
|
||||
continue;
|
||||
|
@ -1559,7 +1559,7 @@ void Parser::ParseLV4MeshBones(unsigned int iNumBones,ASE::Mesh& mesh)
|
|||
++filePtr;
|
||||
|
||||
// Mesh bone with name ...
|
||||
if (TokenMatch(filePtr,"MESH_BONE_NAME" ,16))
|
||||
if (TokenMatch(filePtr,"MESH_BONE_NAME" ,14))
|
||||
{
|
||||
// parse an index ...
|
||||
if(SkipSpaces(&filePtr))
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "GenericProperty.h"
|
||||
#include "CInterfaceIOWrapper.h"
|
||||
#include "../include/assimp/importerdesc.h"
|
||||
#include "Importer.h"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -84,7 +85,11 @@ namespace Assimp
|
|||
|
||||
/** Verbose logging active or not? */
|
||||
static aiBool gVerboseLogging = false;
|
||||
}
|
||||
|
||||
/** will return all registered importers. */
|
||||
void GetImporterInstanceList(std::vector< BaseImporter* >& out);
|
||||
|
||||
} // namespace assimp
|
||||
|
||||
|
||||
#ifndef ASSIMP_BUILD_SINGLETHREADED
|
||||
|
@ -606,4 +611,22 @@ ASSIMP_API void aiIdentityMatrix4(
|
|||
*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;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -61,6 +61,8 @@ ASSIMP_API size_t aiGetExportFormatCount(void)
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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("<");break;
|
||||
case '>':
|
||||
out.Append(">");break;
|
||||
case '&':
|
||||
out.Append("&");break;
|
||||
case '\"':
|
||||
out.Append(""");break;
|
||||
case '\'':
|
||||
out.Append("'");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("&"); break;
|
||||
case '\"': buffer.append("""); break;
|
||||
case '\'': buffer.append("'"); break;
|
||||
case '<': buffer.append("<"); break;
|
||||
case '>': buffer.append(">"); 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
|
|
@ -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
|
|
@ -548,7 +548,7 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
|
|||
void B3DImporter::ReadBB3D( aiScene *scene ){
|
||||
|
||||
_textures.clear();
|
||||
_materials.size();
|
||||
_materials.clear();
|
||||
|
||||
_vertices.clear();
|
||||
_meshes.clear();
|
||||
|
|
|
@ -90,6 +90,11 @@ struct ScopeGuard
|
|||
}
|
||||
|
||||
private:
|
||||
// no copying allowed.
|
||||
ScopeGuard();
|
||||
ScopeGuard( const ScopeGuard & );
|
||||
ScopeGuard &operator = ( const ScopeGuard & );
|
||||
|
||||
T* obj;
|
||||
bool mdismiss;
|
||||
};
|
||||
|
|
|
@ -65,7 +65,6 @@ BlenderBMeshConverter::BlenderBMeshConverter( const Mesh* mesh ):
|
|||
BMesh( mesh ),
|
||||
triMesh( NULL )
|
||||
{
|
||||
AssertValidMesh( );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -143,9 +142,21 @@ void BlenderBMeshConverter::DestroyTriMesh( )
|
|||
void BlenderBMeshConverter::ConvertPolyToFaces( const MPoly& poly )
|
||||
{
|
||||
const MLoop* polyLoop = &BMesh->mloop[ poly.loopstart ];
|
||||
|
||||
if ( poly.totloop == 3 || poly.totloop == 4 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
|
@ -173,4 +184,20 @@ void BlenderBMeshConverter::AddFace( int v1, int v2, int v3, int v4 )
|
|||
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
|
||||
|
|
|
@ -80,6 +80,7 @@ namespace Assimp
|
|||
void DestroyTriMesh( );
|
||||
void ConvertPolyToFaces( const Blender::MPoly& poly );
|
||||
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;
|
||||
Blender::Mesh* triMesh;
|
||||
|
|
|
@ -659,11 +659,15 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
|
|||
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 );
|
||||
if ( BMeshConverter.ContainsBMesh( ) )
|
||||
{
|
||||
mesh = BMeshConverter.TriangulateBMesh( );
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef std::pair<const int,size_t> MyPair;
|
||||
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());
|
||||
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());
|
||||
out->mName = obj->id.name+2;
|
||||
|
|
|
@ -324,7 +324,7 @@ void BlenderTessellatorP2T::Copy3DVertices( const MLoop* polyLoop, int vertexCou
|
|||
aiMatrix4x4 BlenderTessellatorP2T::GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
@ -420,7 +420,7 @@ float BlenderTessellatorP2T::FindLargestMatrixElem( const aiMatrix3x3& mtx ) con
|
|||
{
|
||||
for ( int y = 0; y < 3; ++y )
|
||||
{
|
||||
result = p2tMax( fabs( mtx[ x ][ y ] ), result );
|
||||
result = p2tMax( std::fabs( mtx[ x ][ y ] ), result );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ namespace boost {
|
|||
};
|
||||
|
||||
// dummy
|
||||
list_elem& operator = (const list_elem& other) {
|
||||
list_elem& operator = (const list_elem& /*other*/) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -142,7 +142,7 @@ namespace boost {
|
|||
return me.me;
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// A very minimal implementation for up to 5 elements
|
||||
template <typename T0 = detail::nulltype,
|
||||
|
@ -278,6 +278,6 @@ namespace boost {
|
|||
tuple <> t;
|
||||
return t;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !! BOOST_TUPLE_INCLUDED
|
||||
|
|
|
@ -111,6 +111,7 @@ SET( Common_SRCS
|
|||
MemoryIOWrapper.h
|
||||
ParsingUtils.h
|
||||
StreamReader.h
|
||||
StreamWriter.h
|
||||
StringComparison.h
|
||||
SGSpatialSort.cpp
|
||||
SGSpatialSort.h
|
||||
|
@ -143,6 +144,7 @@ SET( Common_SRCS
|
|||
LogAux.h
|
||||
Bitmap.cpp
|
||||
Bitmap.h
|
||||
XMLTools.h
|
||||
)
|
||||
SOURCE_GROUP(Common FILES ${Common_SRCS})
|
||||
|
||||
|
@ -151,6 +153,8 @@ SET( 3DS_SRCS
|
|||
3DSHelper.h
|
||||
3DSLoader.cpp
|
||||
3DSLoader.h
|
||||
3DSExporter.h
|
||||
3DSExporter.cpp
|
||||
)
|
||||
SOURCE_GROUP(3DS FILES ${3DS_SRCS})
|
||||
|
||||
|
@ -168,6 +172,20 @@ SET( 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
|
||||
B3DImporter.cpp
|
||||
B3DImporter.h
|
||||
|
@ -612,7 +630,7 @@ SOURCE_GROUP( unzip FILES ${unzip_SRCS})
|
|||
|
||||
# VC2010 fixes
|
||||
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 )
|
||||
ADD_DEFINITIONS( -D_STDINT )
|
||||
endif( VC10_STDINT_FIX )
|
||||
|
@ -643,6 +661,8 @@ SET( assimp_src
|
|||
${3DS_SRCS}
|
||||
${AC_SRCS}
|
||||
${ASE_SRCS}
|
||||
${ASSBIN_SRCS}
|
||||
${ASSXML_SRCS}
|
||||
${B3D_SRCS}
|
||||
${BVH_SRCS}
|
||||
${Collada_SRCS}
|
||||
|
@ -705,6 +725,13 @@ ADD_LIBRARY( assimp ${assimp_src} )
|
|||
SET_PROPERTY(TARGET assimp PROPERTY DEBUG_POSTFIX ${ASSIMP_DEBUG_POSTFIX})
|
||||
|
||||
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
|
||||
VERSION ${ASSIMP_VERSION}
|
||||
SOVERSION ${ASSIMP_SOVERSION} # use full version
|
||||
|
@ -731,6 +758,11 @@ INSTALL( TARGETS assimp
|
|||
COMPONENT ${LIBASSIMP_COMPONENT})
|
||||
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)
|
||||
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)
|
||||
install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${ASSIMP_DEBUG_POSTFIX}.pdb
|
||||
|
|
|
@ -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
|
||||
// of vertices and no vertices are shared between faces. Sadly I don't know any quick test to
|
||||
// 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;
|
||||
|
||||
// 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& origTang = pMesh->mTangents[a];
|
||||
const aiVector3D& origBitang = pMesh->mBitangents[a];
|
||||
closeVertices.clear();
|
||||
closeVertices.resize( 0 );
|
||||
|
||||
// find all vertices close to that position
|
||||
vertexFinder->FindPositions( origPos, posEpsilon, verticesFound);
|
||||
|
|
|
@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "Bitmap.h"
|
||||
#include "fast_atof.h"
|
||||
#include "SceneCombiner.h"
|
||||
#include "XMLTools.h"
|
||||
|
||||
#include <ctime>
|
||||
#include <set>
|
||||
|
@ -93,6 +94,7 @@ void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* p
|
|||
} // end of namespace Assimp
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// 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)
|
||||
|
@ -140,7 +142,7 @@ void ColladaExporter::WriteFile()
|
|||
// useless Collada fu at the end, just in case we haven't had enough indirections, yet.
|
||||
mOutput << startstr << "<scene>" << endstr;
|
||||
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();
|
||||
mOutput << startstr << "</scene>" << endstr;
|
||||
PopTag();
|
||||
|
@ -236,12 +238,12 @@ void ColladaExporter::WriteHeader()
|
|||
if (!meta || !meta->Get("Author", value))
|
||||
mOutput << startstr << "<author>" << "Assimp" << "</author>" << endstr;
|
||||
else
|
||||
mOutput << startstr << "<author>" << value.C_Str() << "</author>" << endstr;
|
||||
mOutput << startstr << "<author>" << XMLEscape(value.C_Str()) << "</author>" << endstr;
|
||||
|
||||
if (!meta || !meta->Get("AuthoringTool", value))
|
||||
mOutput << startstr << "<authoring_tool>" << "Assimp Exporter" << "</authoring_tool>" << endstr;
|
||||
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 << "<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() )
|
||||
{
|
||||
mOutput << startstr << "<image id=\"" << pNameAdd << "\">" << endstr;
|
||||
mOutput << startstr << "<image id=\"" << XMLEscape(pNameAdd) << "\">" << endstr;
|
||||
PushTag();
|
||||
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 )
|
||||
{
|
||||
if( isalnum( *it) || *it == '_' || *it == '.' || *it == '/' || *it == '\\' )
|
||||
mOutput << *it;
|
||||
imageUrlEncoded << *it;
|
||||
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;
|
||||
PopTag();
|
||||
mOutput << startstr << "</image>" << endstr;
|
||||
|
@ -371,7 +377,7 @@ void ColladaExporter::WriteTextureColorEntry( const Surface& pSurface, const std
|
|||
}
|
||||
else
|
||||
{
|
||||
mOutput << startstr << "<texture texture=\"" << pImageName << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
|
||||
mOutput << startstr << "<texture texture=\"" << XMLEscape(pImageName) << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
|
||||
}
|
||||
PopTag();
|
||||
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( !pSurface.texture.empty() )
|
||||
{
|
||||
mOutput << startstr << "<newparam sid=\"" << pMatName << "-" << pTypeName << "-surface\">" << endstr;
|
||||
mOutput << startstr << "<newparam sid=\"" << XMLEscape(pMatName) << "-" << pTypeName << "-surface\">" << endstr;
|
||||
PushTag();
|
||||
mOutput << startstr << "<surface type=\"2D\">" << endstr;
|
||||
PushTag();
|
||||
mOutput << startstr << "<init_from>" << pMatName << "-" << pTypeName << "-image</init_from>" << endstr;
|
||||
mOutput << startstr << "<init_from>" << XMLEscape(pMatName) << "-" << pTypeName << "-image</init_from>" << endstr;
|
||||
PopTag();
|
||||
mOutput << startstr << "</surface>" << endstr;
|
||||
PopTag();
|
||||
mOutput << startstr << "</newparam>" << endstr;
|
||||
|
||||
mOutput << startstr << "<newparam sid=\"" << pMatName << "-" << pTypeName << "-sampler\">" << endstr;
|
||||
mOutput << startstr << "<newparam sid=\"" << XMLEscape(pMatName) << "-" << pTypeName << "-sampler\">" << endstr;
|
||||
PushTag();
|
||||
mOutput << startstr << "<sampler2D>" << endstr;
|
||||
PushTag();
|
||||
mOutput << startstr << "<source>" << pMatName << "-" << pTypeName << "-surface</source>" << endstr;
|
||||
mOutput << startstr << "<source>" << XMLEscape(pMatName) << "-" << pTypeName << "-surface</source>" << endstr;
|
||||
PopTag();
|
||||
mOutput << startstr << "</sampler2D>" << endstr;
|
||||
PopTag();
|
||||
|
@ -439,7 +445,7 @@ void ColladaExporter::WriteMaterials()
|
|||
name = "mat";
|
||||
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 ) {
|
||||
// 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.
|
||||
if( !isalnum( static_cast<uint8_t>(*it) ) ) {
|
||||
*it = '_';
|
||||
|
@ -510,7 +516,7 @@ void ColladaExporter::WriteMaterials()
|
|||
{
|
||||
const Material& mat = *it;
|
||||
// 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();
|
||||
mOutput << startstr << "<profile_COMMON>" << endstr;
|
||||
PushTag();
|
||||
|
@ -561,9 +567,9 @@ void ColladaExporter::WriteMaterials()
|
|||
for( std::vector<Material>::const_iterator it = materials.begin(); it != materials.end(); ++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();
|
||||
mOutput << startstr << "<instance_effect url=\"#" << mat.name << "-fx\"/>" << endstr;
|
||||
mOutput << startstr << "<instance_effect url=\"#" << XMLEscape(mat.name) << "-fx\"/>" << endstr;
|
||||
PopTag();
|
||||
mOutput << startstr << "</material>" << endstr;
|
||||
}
|
||||
|
@ -591,13 +597,14 @@ void ColladaExporter::WriteGeometryLibrary()
|
|||
void ColladaExporter::WriteGeometry( size_t 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 )
|
||||
return;
|
||||
|
||||
// opening tag
|
||||
mOutput << startstr << "<geometry id=\"" << idstr << "\" name=\"" << idstr << "_name\" >" << endstr;
|
||||
mOutput << startstr << "<geometry id=\"" << idstrEscaped << "\" name=\"" << idstrEscaped << "_name\" >" << endstr;
|
||||
PushTag();
|
||||
|
||||
mOutput << startstr << "<mesh>" << endstr;
|
||||
|
@ -627,20 +634,20 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
|
|||
}
|
||||
|
||||
// assemble vertex structure
|
||||
mOutput << startstr << "<vertices id=\"" << idstr << "-vertices" << "\">" << endstr;
|
||||
mOutput << startstr << "<vertices id=\"" << idstrEscaped << "-vertices" << "\">" << endstr;
|
||||
PushTag();
|
||||
mOutput << startstr << "<input semantic=\"POSITION\" source=\"#" << idstr << "-positions\" />" << endstr;
|
||||
mOutput << startstr << "<input semantic=\"POSITION\" source=\"#" << idstrEscaped << "-positions\" />" << endstr;
|
||||
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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
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();
|
||||
|
@ -660,7 +667,7 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
|
|||
{
|
||||
mOutput << startstr << "<lines count=\"" << countLines << "\" material=\"defaultMaterial\">" << endstr;
|
||||
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>";
|
||||
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;
|
||||
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>";
|
||||
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";
|
||||
|
||||
mOutput << startstr << "<source id=\"" << pIdString << "\" name=\"" << pIdString << "\">" << endstr;
|
||||
mOutput << startstr << "<source id=\"" << XMLEscape(pIdString) << "\" name=\"" << XMLEscape(pIdString) << "\">" << endstr;
|
||||
PushTag();
|
||||
|
||||
// source array
|
||||
mOutput << startstr << "<float_array id=\"" << arrayId << "\" count=\"" << pElementCount * floatsPerElement << "\"> ";
|
||||
mOutput << startstr << "<float_array id=\"" << XMLEscape(arrayId) << "\" count=\"" << pElementCount * floatsPerElement << "\"> ";
|
||||
PushTag();
|
||||
|
||||
if( pType == FloatType_TexCoord2 )
|
||||
|
@ -804,11 +811,11 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy
|
|||
// Writes the scene library
|
||||
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;
|
||||
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();
|
||||
|
||||
// start recursive write at the root node
|
||||
|
@ -833,7 +840,8 @@ void ColladaExporter::WriteNode(aiNode* pNode)
|
|||
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();
|
||||
|
||||
// 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 )
|
||||
continue;
|
||||
|
||||
mOutput << startstr << "<instance_geometry url=\"#" << GetMeshId( pNode->mMeshes[a]) << "\">" << endstr;
|
||||
mOutput << startstr << "<instance_geometry url=\"#" << XMLEscape(GetMeshId( pNode->mMeshes[a])) << "\">" << endstr;
|
||||
PushTag();
|
||||
mOutput << startstr << "<bind_material>" << endstr;
|
||||
PushTag();
|
||||
mOutput << startstr << "<technique_common>" << endstr;
|
||||
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();
|
||||
mOutput << startstr << "</technique_common>" << endstr;
|
||||
PopTag();
|
||||
|
|
|
@ -118,7 +118,6 @@ struct Camera
|
|||
float mZNear, mZFar;
|
||||
};
|
||||
|
||||
#define aiLightSource_AMBIENT 0xdeaddead
|
||||
#define ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET 1e9f
|
||||
|
||||
/** A collada light source. */
|
||||
|
|
|
@ -73,7 +73,7 @@ static const aiImporterDesc desc = {
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
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();
|
||||
mCameras.clear();
|
||||
mTextures.clear();
|
||||
mAnims.clear();
|
||||
|
||||
// parse the input file
|
||||
ColladaParser parser( pIOHandler, pFile);
|
||||
|
@ -307,10 +308,6 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
|
|||
continue;
|
||||
}
|
||||
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
|
||||
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 ....
|
||||
// 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);
|
||||
}
|
||||
else {
|
||||
|
@ -904,6 +901,8 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars
|
|||
pScene->mAnimations = new aiAnimation*[mAnims.size()];
|
||||
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
|
||||
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
|
||||
// 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
|
||||
// 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++);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -203,7 +203,7 @@ protected:
|
|||
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 */
|
||||
std::string FindNameForNode( const Collada::Node* pNode) const;
|
||||
std::string FindNameForNode( const Collada::Node* pNode);
|
||||
|
||||
protected:
|
||||
/** Filename, for a verbose error message */
|
||||
|
@ -235,6 +235,9 @@ protected:
|
|||
|
||||
bool noSkeletonMesh;
|
||||
bool ignoreUpDirection;
|
||||
|
||||
/** Used by FindNameForNode() to generate unique node names */
|
||||
unsigned int mNodeNameCounter;
|
||||
};
|
||||
|
||||
} // end of namespace Assimp
|
||||
|
|
|
@ -1163,6 +1163,19 @@ void ColladaParser::ReadEffectProfileCommon( Collada::Effect& pEffect)
|
|||
// 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 */
|
||||
else if( IsElement( "phong"))
|
||||
pEffect.mShadeType = Shade_Phong;
|
||||
|
@ -1854,14 +1867,15 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
|
|||
// read primitive count from the attribute
|
||||
int attrCount = GetAttribute( "count");
|
||||
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");
|
||||
SubMesh subgroup;
|
||||
if( attrMaterial > -1)
|
||||
subgroup.mMaterial = mReader->getAttributeValue( attrMaterial);
|
||||
subgroup.mNumFaces = numPrimitives;
|
||||
pMesh->mSubMeshes.push_back( subgroup);
|
||||
|
||||
// distinguish between polys and triangles
|
||||
std::string elementName = mReader->getNodeName();
|
||||
|
@ -1920,7 +1934,7 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
|
|||
if( !mReader->isEmptyElement())
|
||||
{
|
||||
// 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
|
||||
{
|
||||
|
@ -1935,6 +1949,14 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
|
|||
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
|
||||
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)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
// 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>
|
||||
size_t numPrimitives = pNumPrimitives;
|
||||
if( pPrimType == Prim_TriFans || pPrimType == Prim_Polygon)
|
||||
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->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
|
||||
size_t numPoints = 0;
|
||||
switch( pPrimType)
|
||||
{
|
||||
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;
|
||||
case Prim_Triangles:
|
||||
numPoints = 3;
|
||||
case Prim_Triangles:
|
||||
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;
|
||||
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;
|
||||
case Prim_TriFans:
|
||||
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;
|
||||
default:
|
||||
// LineStrip and TriStrip not supported due to expected index unmangling
|
||||
// LineStrip is not supported due to expected index unmangling
|
||||
ThrowException( "Unsupported primitive type.");
|
||||
break;
|
||||
}
|
||||
|
||||
// store the face size to later reconstruct the face from
|
||||
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...
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -177,9 +177,18 @@ protected:
|
|||
void ReadInputChannel( std::vector<Collada::InputChannel>& poChannels);
|
||||
|
||||
/** 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);
|
||||
|
||||
/** 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 */
|
||||
void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh);
|
||||
|
||||
|
|
|
@ -207,7 +207,7 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D
|
|||
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
|
||||
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,
|
||||
(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) {
|
||||
|
@ -215,7 +215,7 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D
|
|||
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
|
||||
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,
|
||||
(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) {
|
||||
|
@ -223,7 +223,7 @@ void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D
|
|||
for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) {
|
||||
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,
|
||||
(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
|
||||
|
|
|
@ -57,12 +57,15 @@ using namespace Assimp;
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
MakeLeftHandedProcess::MakeLeftHandedProcess()
|
||||
{}
|
||||
: BaseProcess() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
MakeLeftHandedProcess::~MakeLeftHandedProcess()
|
||||
{}
|
||||
MakeLeftHandedProcess::~MakeLeftHandedProcess() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// 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...
|
||||
|
||||
// continue for all children
|
||||
for( size_t a = 0; a < pNode->mNumChildren; ++a)
|
||||
ProcessNode( pNode->mChildren[a], pParentGlobalRotation * pNode->mTransformation);
|
||||
for( size_t a = 0; a < pNode->mNumChildren; ++a ) {
|
||||
ProcessNode( pNode->mChildren[ a ], pParentGlobalRotation * pNode->mTransformation );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -244,6 +248,10 @@ void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat)
|
|||
aiMaterial* mat = (aiMaterial*)_mat;
|
||||
for (unsigned int a = 0; a < mat->mNumProperties;++a) {
|
||||
aiMaterialProperty* prop = mat->mProperties[a];
|
||||
if( !prop ) {
|
||||
DefaultLogger::get()->debug( "Property is null" );
|
||||
continue;
|
||||
}
|
||||
|
||||
// UV transformation key?
|
||||
if (!::strcmp( prop->mKey.data, "$tex.uvtrafo")) {
|
||||
|
@ -263,11 +271,13 @@ void FlipUVsProcess::ProcessMesh( aiMesh* pMesh)
|
|||
{
|
||||
// mirror texture y coordinate
|
||||
for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) {
|
||||
if( !pMesh->HasTextureCoords( a))
|
||||
break;
|
||||
if( !pMesh->HasTextureCoords( a ) ) {
|
||||
break;
|
||||
}
|
||||
|
||||
for( unsigned int b = 0; b < pMesh->mNumVertices; b++)
|
||||
pMesh->mTextureCoords[a][b].y = 1.0f - pMesh->mTextureCoords[a][b].y;
|
||||
for( unsigned int b = 0; b < pMesh->mNumVertices; b++ ) {
|
||||
pMesh->mTextureCoords[ a ][ b ].y = 1.0f - pMesh->mTextureCoords[ a ][ b ].y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -111,8 +111,8 @@ void DeboneProcess::Execute( aiScene* pScene)
|
|||
|
||||
if(numSplits) {
|
||||
// we need to do something. Let's go.
|
||||
mSubMeshIndices.clear();
|
||||
mSubMeshIndices.resize(pScene->mNumMeshes);
|
||||
//mSubMeshIndices.clear(); // really needed?
|
||||
mSubMeshIndices.resize(pScene->mNumMeshes); // because we're doing it here anyway
|
||||
|
||||
// build a new array of meshes for the scene
|
||||
std::vector<aiMesh*> meshes;
|
||||
|
|
|
@ -56,52 +56,59 @@ namespace Assimp {
|
|||
class DefaultIOStream : public IOStream
|
||||
{
|
||||
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:
|
||||
DefaultIOStream ();
|
||||
DefaultIOStream (FILE* pFile, const std::string &strFilename);
|
||||
DefaultIOStream();
|
||||
DefaultIOStream(FILE* pFile, const std::string &strFilename);
|
||||
|
||||
public:
|
||||
/** Destructor public to allow simple deletion to close the file. */
|
||||
~DefaultIOStream ();
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Read from stream
|
||||
/// Read from stream
|
||||
size_t Read(void* pvBuffer,
|
||||
size_t pSize,
|
||||
size_t pCount);
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Write to stream
|
||||
/// Write to stream
|
||||
size_t Write(const void* pvBuffer,
|
||||
size_t pSize,
|
||||
size_t pCount);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Seek specific position
|
||||
/// Seek specific position
|
||||
aiReturn Seek(size_t pOffset,
|
||||
aiOrigin pOrigin);
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Get current seek position
|
||||
/// Get current seek position
|
||||
size_t Tell() const;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Get size of file
|
||||
/// Get size of file
|
||||
size_t FileSize() const;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Flush file contents
|
||||
/// Flush file contents
|
||||
void Flush();
|
||||
|
||||
private:
|
||||
//! File datastructure, using clib
|
||||
// File datastructure, using clib
|
||||
FILE* mFile;
|
||||
//! Filename
|
||||
// Filename
|
||||
std::string mFilename;
|
||||
|
||||
//! Cached file size
|
||||
// Cached file size
|
||||
mutable size_t cachedSize;
|
||||
};
|
||||
|
||||
|
|
|
@ -78,7 +78,10 @@ void ExportSceneObj(const char*,IOSystem*, const aiScene*);
|
|||
void ExportSceneSTL(const char*,IOSystem*, const aiScene*);
|
||||
void ExportSceneSTLBinary(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
|
||||
|
@ -90,7 +93,7 @@ Exporter::ExportFormatEntry gExporters[] =
|
|||
|
||||
#ifndef ASSIMP_BUILD_NO_FXILE_EXPORTER
|
||||
Exporter::ExportFormatEntry( "x", "X Files", "x", &ExportSceneXFile,
|
||||
aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs),
|
||||
aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs),
|
||||
#endif
|
||||
|
||||
#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
|
||||
|
@ -111,11 +114,23 @@ Exporter::ExportFormatEntry gExporters[] =
|
|||
Exporter::ExportFormatEntry( "ply", "Stanford Polygon Library", "ply" , &ExportScenePly,
|
||||
aiProcess_PreTransformVertices
|
||||
),
|
||||
Exporter::ExportFormatEntry( "plyb", "Stanford Polygon Library (binary)", "ply", &ExportScenePlyBinary,
|
||||
aiProcess_PreTransformVertices
|
||||
),
|
||||
#endif
|
||||
|
||||
//#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
|
||||
// ExportFormatEntry( "3ds", "Autodesk 3DS (legacy format)", "3ds" , &ExportScene3DS),
|
||||
//#endif
|
||||
#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
|
||||
Exporter::ExportFormatEntry( "3ds", "Autodesk 3DS (legacy)", "3ds" , &ExportScene3DS,
|
||||
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]))
|
||||
|
@ -443,6 +458,11 @@ const aiExportFormatDesc* Exporter :: GetExportFormatDescription( size_t pIndex
|
|||
if (pIndex >= GetExportFormatCount()) {
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace FBX {
|
|||
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)
|
||||
{
|
||||
const Scope& sc = GetRequiredScope(element);
|
||||
|
|
|
@ -55,14 +55,15 @@ namespace FBX {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
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)
|
||||
, type(type)
|
||||
, line(offset)
|
||||
, column(BINARY_MARKER)
|
||||
#ifdef DEBUG
|
||||
, contents(sbegin, static_cast<size_t>(send-sbegin))
|
||||
#endif
|
||||
{
|
||||
ai_assert(sbegin);
|
||||
ai_assert(send);
|
||||
|
@ -395,4 +396,4 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int le
|
|||
} // !FBX
|
||||
} // !Assimp
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -381,8 +381,6 @@ private:
|
|||
out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight();
|
||||
out_camera->mPosition = cam.Position();
|
||||
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());
|
||||
}
|
||||
|
||||
|
@ -499,15 +497,15 @@ private:
|
|||
bool is_id[3] = { true, true, true };
|
||||
|
||||
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]);
|
||||
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]);
|
||||
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]);
|
||||
is_id[0] = false;
|
||||
}
|
||||
|
@ -676,7 +674,7 @@ private:
|
|||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
|
@ -686,7 +684,7 @@ private:
|
|||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
|
@ -767,7 +765,6 @@ private:
|
|||
|
||||
// find user defined properties (3ds Max)
|
||||
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.
|
||||
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>& index_out_indices,
|
||||
std::vector<size_t>& count_out_indices,
|
||||
|
@ -2348,7 +2345,7 @@ private:
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
aiNodeAnim* GenerateScalingNodeAnim(const std::string& name,
|
||||
const Model& target,
|
||||
const Model& /*target*/,
|
||||
const std::vector<const AnimationCurveNode*>& curves,
|
||||
const LayerMap& layer_map,
|
||||
double& max_time,
|
||||
|
@ -2379,7 +2376,7 @@ private:
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
aiNodeAnim* GenerateTranslationNodeAnim(const std::string& name,
|
||||
const Model& target,
|
||||
const Model& /*target*/,
|
||||
const std::vector<const AnimationCurveNode*>& curves,
|
||||
const LayerMap& layer_map,
|
||||
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& minTime)
|
||||
{
|
||||
|
@ -2852,7 +2849,7 @@ private:
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
|
||||
const LayerMap& layers,
|
||||
const LayerMap& /*layers*/,
|
||||
double& maxTime,
|
||||
double& minTime)
|
||||
{
|
||||
|
@ -2870,7 +2867,7 @@ private:
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
|
||||
const LayerMap& layers,
|
||||
const LayerMap& /*layers*/,
|
||||
double& maxTime,
|
||||
double& minTime,
|
||||
Model::RotOrder order)
|
||||
|
|
|
@ -253,8 +253,8 @@ Document::Document(const Parser& parser, const ImportSettings& settings)
|
|||
: settings(settings)
|
||||
, parser(parser)
|
||||
{
|
||||
// cannot use array default initialization syntax because vc8 fails on it
|
||||
for (unsigned int i = 0; i < 7; ++i) {
|
||||
// Cannot use array default initialization syntax because vc8 fails on it
|
||||
for (unsigned int i = 0; i < sizeof(creationTimeStamp) / sizeof(creationTimeStamp[0]); ++i) {
|
||||
creationTimeStamp[i] = 0;
|
||||
}
|
||||
|
||||
|
@ -263,7 +263,7 @@ Document::Document(const Parser& parser, const ImportSettings& settings)
|
|||
|
||||
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,
|
||||
// though, since this may require valid connections.
|
||||
ReadObjects();
|
||||
|
@ -277,13 +277,18 @@ Document::~Document()
|
|||
BOOST_FOREACH(ObjectMap::value_type& v, objects) {
|
||||
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()
|
||||
{
|
||||
// read ID objects from "Objects" section
|
||||
// Read ID objects from "Objects" section
|
||||
const Scope& sc = parser.GetRootScope();
|
||||
const Element* const ehead = sc["FBXHeaderExtension"];
|
||||
if(!ehead || !ehead->Compound()) {
|
||||
|
@ -293,7 +298,7 @@ void Document::ReadHeader()
|
|||
const Scope& shead = *ehead->Compound();
|
||||
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
|
||||
if(fbxVersion < 7100) {
|
||||
DOMError("unsupported, old format version, supported are only FBX 2011, FBX 2012 and FBX 2013");
|
||||
|
|
|
@ -696,7 +696,7 @@ public:
|
|||
public:
|
||||
|
||||
/** Get the Skin attached to this geometry or NULL */
|
||||
const Skin* const DeformerSkin() const {
|
||||
const Skin* DeformerSkin() const {
|
||||
return skin;
|
||||
}
|
||||
|
||||
|
@ -1096,7 +1096,7 @@ public:
|
|||
return transformLink;
|
||||
}
|
||||
|
||||
const Model* const TargetNode() const {
|
||||
const Model* TargetNode() const {
|
||||
return node;
|
||||
}
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ bool FBXImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
|
|||
|
||||
else if ((!extension.length() || checkSig) && pIOHandler) {
|
||||
// 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 false;
|
||||
|
@ -179,6 +179,8 @@ void FBXImporter::InternReadFile( const std::string& pFile,
|
|||
|
||||
// convert the FBX DOM to aiScene
|
||||
ConvertToAssimpScene(pScene,doc);
|
||||
|
||||
std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
|
||||
}
|
||||
catch(std::exception&) {
|
||||
std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
|
||||
|
|
|
@ -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)
|
||||
,texture(0)
|
||||
,blendMode(BlendMode_Modulate)
|
||||
|
|
|
@ -466,8 +466,9 @@ void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D>& tangents_out,
|
|||
const std::string& MappingInformationType,
|
||||
const std::string& ReferenceInformationType)
|
||||
{
|
||||
const char * str = source.Elements().count( "Tangents" ) > 0 ? "Tangents" : "Tangent";
|
||||
ResolveVertexDataArray(tangents_out,source,MappingInformationType,ReferenceInformationType,
|
||||
"Tangent",
|
||||
str,
|
||||
"TangentIndex",
|
||||
vertices.size(),
|
||||
mapping_counts,
|
||||
|
@ -481,8 +482,9 @@ void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D>& binormals_ou
|
|||
const std::string& MappingInformationType,
|
||||
const std::string& ReferenceInformationType)
|
||||
{
|
||||
const char * str = source.Elements().count( "Binormals" ) > 0 ? "Binormals" : "Binormal";
|
||||
ResolveVertexDataArray(binormals_out,source,MappingInformationType,ReferenceInformationType,
|
||||
"Binormal",
|
||||
str,
|
||||
"BinormalIndex",
|
||||
vertices.size(),
|
||||
mapping_counts,
|
||||
|
|
|
@ -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) {
|
||||
ParseWarning(message,element->KeyToken());
|
||||
|
@ -103,7 +103,7 @@ namespace {
|
|||
DefaultLogger::get()->warn("FBX-Parser: " + message);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ParseError(const std::string& message, TokenPtr token)
|
||||
{
|
||||
|
@ -113,6 +113,18 @@ namespace {
|
|||
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 {
|
||||
|
@ -275,9 +287,7 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
|
|||
return 0L;
|
||||
}
|
||||
|
||||
ai_assert(t.end() - data == 9);
|
||||
|
||||
BE_NCONST uint64_t id = *reinterpret_cast<const uint64_t*>(data+1);
|
||||
BE_NCONST uint64_t id = SafeParse<uint64_t>(data+1, t.end());
|
||||
AI_SWAP8(id);
|
||||
return id;
|
||||
}
|
||||
|
@ -316,8 +326,7 @@ size_t ParseTokenAsDim(const Token& t, const char*& err_out)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ai_assert(t.end() - data == 9);
|
||||
BE_NCONST uint64_t id = *reinterpret_cast<const uint64_t*>(data+1);
|
||||
BE_NCONST uint64_t id = SafeParse<uint64_t>(data+1, t.end());
|
||||
AI_SWAP8(id);
|
||||
return static_cast<size_t>(id);
|
||||
}
|
||||
|
@ -364,24 +373,10 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out)
|
|||
}
|
||||
|
||||
if (data[0] == 'F') {
|
||||
// Actual size validation happens during Tokenization so
|
||||
// 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;
|
||||
return SafeParse<float>(data+1, t.end());
|
||||
}
|
||||
else {
|
||||
ai_assert(t.end() - data == sizeof(double) + 1);
|
||||
|
||||
// Same
|
||||
double out_double;
|
||||
::memcpy(&out_double, data+1, sizeof(double));
|
||||
return out_double;
|
||||
return static_cast<float>( SafeParse<double>(data+1, t.end()) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -416,8 +411,7 @@ int ParseTokenAsInt(const Token& t, const char*& err_out)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ai_assert(t.end() - data == 5);
|
||||
BE_NCONST int32_t ival = *reinterpret_cast<const int32_t*>(data+1);
|
||||
BE_NCONST int32_t ival = SafeParse<int32_t>(data+1, t.end());
|
||||
AI_SWAP4(ival);
|
||||
return static_cast<int>(ival);
|
||||
}
|
||||
|
@ -453,10 +447,8 @@ std::string ParseTokenAsString(const Token& t, const char*& err_out)
|
|||
return "";
|
||||
}
|
||||
|
||||
ai_assert(t.end() - data >= 5);
|
||||
|
||||
// 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_assert(t.end() - data == 5 + len);
|
||||
|
@ -494,7 +486,7 @@ void ReadBinaryDataArrayHead(const char*& data, const char* end, char& type, uin
|
|||
type = *data;
|
||||
|
||||
// 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);
|
||||
|
||||
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)
|
||||
void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const char* end,
|
||||
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 = *reinterpret_cast<const uint32_t*>(data);
|
||||
BE_NCONST uint32_t encmode = SafeParse<uint32_t>(data, end);
|
||||
AI_SWAP4(encmode);
|
||||
data += 4;
|
||||
|
||||
// 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);
|
||||
data += 4;
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ Property* ReadTypedProperty(const Element& element)
|
|||
else if (!strcmp(cs,"bool") || !strcmp(cs,"Bool")) {
|
||||
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]));
|
||||
}
|
||||
else if (!strcmp(cs,"ULongLong")) {
|
||||
|
@ -105,7 +105,7 @@ Property* ReadTypedProperty(const Element& element)
|
|||
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 NULL;
|
||||
|
|
|
@ -143,8 +143,7 @@ private:
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
inline T PropertyGet(const PropertyTable& in, const std::string& name,
|
||||
const T& defaultValue,
|
||||
bool ignoreTemplate = false)
|
||||
const T& defaultValue)
|
||||
{
|
||||
const Property* const prop = in.Get(name);
|
||||
if(!prop) {
|
||||
|
@ -164,8 +163,7 @@ inline T PropertyGet(const PropertyTable& in, const std::string& name,
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
inline T PropertyGet(const PropertyTable& in, const std::string& name,
|
||||
bool& result,
|
||||
bool ignoreTemplate = false)
|
||||
bool& result)
|
||||
{
|
||||
const Property* const prop = in.Get(name);
|
||||
if(!prop) {
|
||||
|
|
|
@ -58,14 +58,15 @@ namespace FBX {
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
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)
|
||||
, type(type)
|
||||
, line(line)
|
||||
, column(column)
|
||||
#ifdef DEBUG
|
||||
, contents(sbegin, static_cast<size_t>(send-sbegin))
|
||||
#endif
|
||||
{
|
||||
ai_assert(sbegin);
|
||||
ai_assert(send);
|
||||
|
|
|
@ -85,8 +85,7 @@ bool CompareBones(const aiMesh* orig, const aiMesh* inst)
|
|||
aiBone* oha = inst->mBones[i];
|
||||
|
||||
if (aha->mNumWeights != oha->mNumWeights ||
|
||||
aha->mOffsetMatrix != oha->mOffsetMatrix ||
|
||||
aha->mNumWeights != oha->mNumWeights) {
|
||||
aha->mOffsetMatrix != oha->mOffsetMatrix) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -174,7 +173,6 @@ void FindInstancesProcess::Execute( aiScene* pScene)
|
|||
|
||||
// use a constant epsilon for colors and UV coordinates
|
||||
static const float uvEpsilon = 10e-4f;
|
||||
|
||||
{
|
||||
unsigned int i, end = orig->GetNumUVChannels();
|
||||
for(i = 0; i < end; ++i) {
|
||||
|
@ -260,7 +258,7 @@ void FindInstancesProcess::Execute( aiScene* pScene)
|
|||
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());
|
||||
|
||||
// write to log
|
||||
|
|
|
@ -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) {
|
||||
return fabs(n-s)>epsilon;
|
||||
return std::fabs(n-s)>epsilon;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -149,8 +149,8 @@ bool FixInfacingNormalsProcess::ProcessMesh( aiMesh* pcMesh, unsigned int index)
|
|||
if (fDelta1_z < 0.05f * sqrtf( fDelta1_y * fDelta1_x ))return false;
|
||||
|
||||
// now compare the volumes of the bounding boxes
|
||||
if (::fabsf(fDelta0_x * fDelta1_yz) <
|
||||
::fabsf(fDelta1_x * fDelta1_y * fDelta1_z))
|
||||
if (std::fabs(fDelta0_x * fDelta1_yz) <
|
||||
std::fabs(fDelta1_x * fDelta1_y * fDelta1_z))
|
||||
{
|
||||
if (!DefaultLogger::isNullLogger())
|
||||
{
|
||||
|
|
|
@ -93,7 +93,7 @@ void GenVertexNormalsProcess::Execute( aiScene* pScene)
|
|||
bool bHas = false;
|
||||
for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
|
||||
{
|
||||
if(GenMeshVertexNormals( pScene->mMeshes[a],a))
|
||||
if(GenMeshVertexNormals( pScene->mMeshes[a],a))
|
||||
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
|
||||
// the effect, this one is the most straightforward one.
|
||||
else {
|
||||
const float fLimit = ::cos(configMaxAngle);
|
||||
const float fLimit = std::cos(configMaxAngle);
|
||||
for (unsigned int i = 0; i < pMesh->mNumVertices;++i) {
|
||||
// Get all vertices that share this one ...
|
||||
vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound);
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace Assimp {
|
|||
// ---------------------------------------------------------------------------
|
||||
/** The GenFaceNormalsProcess computes vertex normals for all vertizes
|
||||
*/
|
||||
class ASSIMP_API_WINONLY GenVertexNormalsProcess : public BaseProcess
|
||||
class ASSIMP_API GenVertexNormalsProcess : public BaseProcess
|
||||
{
|
||||
public:
|
||||
|
||||
|
|
|
@ -69,8 +69,8 @@ Intersect IntersectSegmentPlane(const IfcVector3& p,const IfcVector3& n, const I
|
|||
const IfcVector3 pdelta = e0 - p, seg = e1-e0;
|
||||
const IfcFloat dotOne = n*seg, dotTwo = -(n*pdelta);
|
||||
|
||||
if (fabs(dotOne) < 1e-6) {
|
||||
return fabs(dotTwo) < 1e-6f ? Intersect_LiesOnPlane : Intersect_No;
|
||||
if (std::fabs(dotOne) < 1e-6) {
|
||||
return std::fabs(dotTwo) < 1e-6f ? Intersect_LiesOnPlane : Intersect_No;
|
||||
}
|
||||
|
||||
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,
|
||||
const TempMesh& first_operand,
|
||||
ConversionData& conv)
|
||||
ConversionData& /*conv*/)
|
||||
{
|
||||
ai_assert(hs != NULL);
|
||||
|
||||
|
@ -210,7 +210,7 @@ bool IntersectsBoundaryProfile( const IfcVector3& e0, const IfcVector3& e1, cons
|
|||
// segment-segment intersection
|
||||
// solve b0 + b*s = e0 + e*t for (s,t)
|
||||
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)
|
||||
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 (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;
|
||||
|
@ -419,7 +419,7 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const IfcPolygonalBounded
|
|||
|
||||
#ifdef ASSIMP_BUILD_DEBUG
|
||||
if (isect == Intersect_Yes) {
|
||||
const IfcFloat f = fabs((isectpos - p)*n);
|
||||
const IfcFloat f = std::fabs((isectpos - p)*n);
|
||||
ai_assert(f < 1e-5);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -88,10 +88,10 @@ public:
|
|||
a *= conv.angle_scale;
|
||||
b *= conv.angle_scale;
|
||||
|
||||
a = fmod(a,static_cast<IfcFloat>( AI_MATH_TWO_PI ));
|
||||
b = fmod(b,static_cast<IfcFloat>( AI_MATH_TWO_PI ));
|
||||
a = std::fmod(a,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 );
|
||||
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 {
|
||||
u = -conv.angle_scale * u;
|
||||
return location + static_cast<IfcFloat>(entity.Radius)*(static_cast<IfcFloat>(::cos(u))*p[0] +
|
||||
static_cast<IfcFloat>(::sin(u))*p[1]);
|
||||
return location + static_cast<IfcFloat>(entity.Radius)*(static_cast<IfcFloat>(std::cos(u))*p[0] +
|
||||
static_cast<IfcFloat>(std::sin(u))*p[1]);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -153,8 +153,8 @@ public:
|
|||
// --------------------------------------------------
|
||||
IfcVector3 Eval(IfcFloat u) const {
|
||||
u = -conv.angle_scale * u;
|
||||
return location + static_cast<IfcFloat>(entity.SemiAxis1)*static_cast<IfcFloat>(::cos(u))*p[0] +
|
||||
static_cast<IfcFloat>(entity.SemiAxis2)*static_cast<IfcFloat>(::sin(u))*p[1];
|
||||
return location + static_cast<IfcFloat>(entity.SemiAxis1)*static_cast<IfcFloat>(std::cos(u))*p[0] +
|
||||
static_cast<IfcFloat>(entity.SemiAxis2)*static_cast<IfcFloat>(std::sin(u))*p[1];
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -486,7 +486,7 @@ public:
|
|||
IfcVector3 Eval(IfcFloat p) const {
|
||||
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) {
|
||||
return points.back();
|
||||
}
|
||||
|
@ -498,7 +498,7 @@ public:
|
|||
// --------------------------------------------------
|
||||
size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
|
||||
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()) {
|
||||
return true;
|
||||
//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;
|
||||
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);
|
||||
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];
|
||||
}
|
||||
|
||||
// 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 IfcFloat wrapdiff = (cv->Eval(range.first)-val).SquareLength();
|
||||
|
||||
|
|
|
@ -250,17 +250,17 @@ void ProcessRevolvedAreaSolid(const IfcRevolvedAreaSolid& solid, TempMesh& resul
|
|||
|
||||
bool has_area = solid.SweptArea->ProfileType == "AREA" && size>2;
|
||||
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) {
|
||||
result = meshout;
|
||||
}
|
||||
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;
|
||||
|
||||
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.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 (j = i+1; j < s-1; ++j) {
|
||||
nor = -((out[i]-any_point)^(out[j]-any_point));
|
||||
if(fabs(nor.Length()) > 1e-8f) {
|
||||
if(std::fabs(nor.Length()) > 1e-8f) {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -259,7 +259,7 @@ BoundingBox GetBoundingBox(const ClipperLib::Polygon& poly)
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void InsertWindowContours(const ContourVector& contours,
|
||||
const std::vector<TempOpening>& openings,
|
||||
const std::vector<TempOpening>& /*openings*/,
|
||||
TempMesh& curmesh)
|
||||
{
|
||||
// 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];
|
||||
|
||||
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;
|
||||
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;
|
||||
hit = true;
|
||||
}
|
||||
|
||||
if (fabs(v.y-bb.first.y)<epsilon) {
|
||||
if (std::fabs(v.y-bb.first.y)<epsilon) {
|
||||
edge.y = bb.first.y;
|
||||
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;
|
||||
hit = true;
|
||||
}
|
||||
|
@ -343,17 +343,17 @@ void InsertWindowContours(const ContourVector& contours,
|
|||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
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) ||
|
||||
(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) ||
|
||||
(fabs(bb.first.y - ibb.second.y) < epsilon && ibb.first.x <= bb.second.x && ibb.second.x >= bb.first.x);
|
||||
return (std::fabs(bb.second.x - ibb.first.x) < epsilon && bb.first.y <= ibb.second.y && bb.second.y >= ibb.first.y) ||
|
||||
(std::fabs(bb.first.x - ibb.second.x) < epsilon && ibb.first.y <= bb.second.y && ibb.second.y >= bb.first.y) ||
|
||||
(std::fabs(bb.second.y - ibb.first.y) < epsilon && bb.first.x <= ibb.second.x && bb.second.x >= ibb.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();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -631,14 +631,14 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
|
|||
// the higher absolute difference is big enough as to avoid
|
||||
// divisions by zero, the case 0/0 ~ infinity is detected and
|
||||
// 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;
|
||||
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.;
|
||||
}
|
||||
if (fabs(s1) == inf && fabs(n0_to_m1.x) < smalle) {
|
||||
if (std::fabs(s1) == inf && std::fabs(n0_to_m1.x) < smalle) {
|
||||
s1 = 0.;
|
||||
}
|
||||
}
|
||||
|
@ -646,10 +646,10 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
|
|||
s0 = n0_to_m0.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.;
|
||||
}
|
||||
if (fabs(s1) == inf && fabs(n0_to_m1.y) < smalle) {
|
||||
if (std::fabs(s1) == inf && std::fabs(n0_to_m1.y) < smalle) {
|
||||
s1 = 0.;
|
||||
}
|
||||
}
|
||||
|
@ -664,7 +664,7 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
|
|||
s0 = std::min(1.0,s0);
|
||||
s1 = std::min(1.0,s1);
|
||||
|
||||
if (fabs(s1-s0) < e) {
|
||||
if (std::fabs(s1-s0) < e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -755,7 +755,7 @@ void FindAdjacentContours(ContourVector::iterator current, const ContourVector&
|
|||
AI_FORCE_INLINE bool LikelyBorder(const IfcVector2& vdelta)
|
||||
{
|
||||
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)
|
||||
{
|
||||
vdelta.x = fabs(vdelta.x);
|
||||
vdelta.y = fabs(vdelta.y);
|
||||
return (fabs(vdelta.x-vdelta.y) < 0.8 * std::max(vdelta.x, vdelta.y));
|
||||
vdelta.x = std::fabs(vdelta.x);
|
||||
vdelta.y = std::fabs(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
|
||||
if (cit != cbegin) {
|
||||
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;
|
||||
}
|
||||
} */
|
||||
|
@ -1065,7 +1065,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh
|
|||
}
|
||||
#ifdef ASSIMP_BUILD_DEBUG
|
||||
const IfcFloat det = m.Determinant();
|
||||
ai_assert(fabs(det-1) < 1e-5);
|
||||
ai_assert(std::fabs(det-1) < 1e-5);
|
||||
#endif
|
||||
|
||||
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
|
||||
// epsilon
|
||||
// if(coord != -1.0f) {
|
||||
// assert(fabs(coord - vv.z) < 1e-3f);
|
||||
// assert(std::fabs(coord - vv.z) < 1e-3f);
|
||||
// }
|
||||
zcoord += vv.z;
|
||||
vmin = std::min(vv, vmin);
|
||||
|
@ -1125,7 +1125,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh
|
|||
const IfcVector3& vv = m * x;
|
||||
|
||||
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) {
|
||||
|
@ -1188,9 +1188,9 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
|
|||
bool is_2d_source = false;
|
||||
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
|
||||
if (fabs(norm_extrusion_dir * nor) > 0.9) {
|
||||
if (std::fabs(norm_extrusion_dir * nor) > 0.9) {
|
||||
profile_data = opening.profileMesh2D.get();
|
||||
is_2d_source = true;
|
||||
}
|
||||
|
@ -1200,7 +1200,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
|
|||
}
|
||||
else {
|
||||
// vertical extrusion
|
||||
if (fabs(norm_extrusion_dir * nor) > 0.9) {
|
||||
if (std::fabs(norm_extrusion_dir * nor) > 0.9) {
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
|
@ -1289,7 +1289,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
|
|||
ai_assert(!is_2d_source);
|
||||
const IfcVector2 area = vpmax-vpmin;
|
||||
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);
|
||||
|
||||
vpmax = vpmax2;
|
||||
|
@ -1301,7 +1301,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
|
|||
}
|
||||
|
||||
// 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)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -1310,7 +1310,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
|
|||
|
||||
// Skip over very small openings - these are likely projection errors
|
||||
// (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;
|
||||
}
|
||||
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
|
||||
// epsilon
|
||||
// if(coord != -1.0f) {
|
||||
// assert(fabs(coord - vv.z) < 1e-3f);
|
||||
// assert(std::fabs(coord - vv.z) < 1e-3f);
|
||||
// }
|
||||
|
||||
coord = vv.z;
|
||||
|
@ -1515,7 +1515,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
|
|||
BOOST_FOREACH(const TempOpening& t,openings) {
|
||||
const IfcVector3& outernor = nors[c++];
|
||||
const IfcFloat dot = nor * outernor;
|
||||
if (fabs(dot)<1.f-1e-6f) {
|
||||
if (std::fabs(dot)<1.f-1e-6f) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1529,7 +1529,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
|
|||
BOOST_FOREACH(const IfcVector3& xx, t.profileMesh->verts) {
|
||||
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) {
|
||||
first = false;
|
||||
if (dot > 0.f) {
|
||||
|
@ -1741,4 +1741,4 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
|
|||
#undef from_int64
|
||||
#undef one_vec
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -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>()) {
|
||||
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;
|
||||
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);
|
||||
|
|
|
@ -1045,7 +1045,7 @@ void IFC::GetSchema(EXPRESS::ConversionSchema& out)
|
|||
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;
|
||||
}
|
||||
|
@ -1253,7 +1253,7 @@ template <> size_t GenericFill<IfcPerformanceHistory>(const DB& db, const LIST&
|
|||
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;
|
||||
return base;
|
||||
|
@ -1715,7 +1715,7 @@ template <> size_t GenericFill<IfcPlateType>(const DB& db, const LIST& params, I
|
|||
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;
|
||||
return base;
|
||||
|
|
|
@ -278,7 +278,7 @@ void TempMesh::RemoveAdjacentDuplicates()
|
|||
// 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 ) {
|
||||
// v1 = v0;
|
||||
|
|
|
@ -220,7 +220,7 @@ struct FuzzyVectorCompare {
|
|||
|
||||
FuzzyVectorCompare(IfcFloat epsilon) : epsilon(epsilon) {}
|
||||
bool operator()(const IfcVector3& a, const IfcVector3& b) {
|
||||
return fabs((a-b).SquareLength()) < epsilon;
|
||||
return std::fabs((a-b).SquareLength()) < epsilon;
|
||||
}
|
||||
|
||||
const IfcFloat epsilon;
|
||||
|
|
46
code/IFF.h
46
code/IFF.h
|
@ -12,8 +12,6 @@
|
|||
namespace Assimp {
|
||||
namespace IFF {
|
||||
|
||||
#include "./../include/assimp/Compiler/pushpack1.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//! Describes an IFF chunk header
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -24,7 +22,7 @@ struct ChunkHeader
|
|||
|
||||
//! Length of the chunk data, in bytes
|
||||
uint32_t length;
|
||||
} PACK_STRUCT;
|
||||
};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -37,9 +35,7 @@ struct SubChunkHeader
|
|||
|
||||
//! Length of the chunk data, in bytes
|
||||
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) | \
|
||||
|
@ -52,28 +48,34 @@ struct SubChunkHeader
|
|||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//! Load a chunk header
|
||||
//! @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;
|
||||
AI_LSWAP4(head->length);
|
||||
AI_LSWAP4(head->type);
|
||||
outFile += sizeof(ChunkHeader);
|
||||
ChunkHeader head;
|
||||
::memcpy(&head.type, outFile, 4);
|
||||
outFile += 4;
|
||||
::memcpy(&head.length, outFile, 4);
|
||||
outFile += 4;
|
||||
AI_LSWAP4(head.length);
|
||||
AI_LSWAP4(head.type);
|
||||
return head;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//! Load a sub chunk header
|
||||
//! @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;
|
||||
AI_LSWAP2(head->length);
|
||||
AI_LSWAP4(head->type);
|
||||
outFile += sizeof(SubChunkHeader);
|
||||
SubChunkHeader head;
|
||||
::memcpy(&head.type, outFile, 4);
|
||||
outFile += 4;
|
||||
::memcpy(&head.length, outFile, 2);
|
||||
outFile += 2;
|
||||
AI_LSWAP2(head.length);
|
||||
AI_LSWAP4(head.type);
|
||||
return head;
|
||||
}
|
||||
|
||||
|
@ -84,14 +86,14 @@ inline SubChunkHeader* LoadSubChunk(uint8_t*& outFile)
|
|||
//! @param fileType Receives the type of the file
|
||||
//! @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);
|
||||
if(AI_IFF_FOURCC_FORM != head->type)
|
||||
ChunkHeader head = LoadChunk(outFile);
|
||||
if(AI_IFF_FOURCC_FORM != head.type)
|
||||
{
|
||||
return "The file is not an IFF file: FORM chunk is missing";
|
||||
}
|
||||
fileType = *((uint32_t*)(head+1));
|
||||
::memcpy(&fileType, outFile, 4);
|
||||
AI_LSWAP4(fileType);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -470,7 +470,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
|
|||
key.mTime = i * tdelta;
|
||||
|
||||
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 ...
|
||||
|
@ -533,8 +533,8 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
|
|||
aiVectorKey& key = anim->mPositionKeys[i];
|
||||
|
||||
const float dt = (i * in.speed * 0.001f );
|
||||
const float u = dt - floor(dt);
|
||||
const int idx = (int)floor(dt) % size;
|
||||
const float u = dt - std::floor(dt);
|
||||
const int idx = (int)std::floor(dt) % size;
|
||||
|
||||
// get the 4 current points to evaluate the spline
|
||||
const aiVector3D& p0 = in.splineKeys[ ClampSpline( idx - 1, size ) ].mValue;
|
||||
|
|
|
@ -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
|
||||
DefaultLogger::get()->info("Found a matching importer for this file format");
|
||||
pimpl->mProgressHandler->Update();
|
||||
pimpl->mProgressHandler->UpdateFileRead( 0, fileSize );
|
||||
|
||||
if (profiler) {
|
||||
profiler->BeginRegion("import");
|
||||
}
|
||||
|
||||
pimpl->mScene = imp->ReadFile( this, pFile, pimpl->mIOHandler);
|
||||
pimpl->mProgressHandler->Update();
|
||||
pimpl->mProgressHandler->UpdateFileRead( fileSize, fileSize );
|
||||
|
||||
if (profiler) {
|
||||
profiler->EndRegion("import");
|
||||
|
@ -678,7 +687,6 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
|
|||
ScenePreprocessor pre(pimpl->mScene);
|
||||
pre.ProcessScene();
|
||||
|
||||
pimpl->mProgressHandler->Update();
|
||||
if (profiler) {
|
||||
profiler->EndRegion("preprocess");
|
||||
}
|
||||
|
@ -768,6 +776,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
|
|||
for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
|
||||
|
||||
BaseProcess* process = pimpl->mPostProcessingSteps[a];
|
||||
pimpl->mProgressHandler->UpdatePostProcess( a, pimpl->mPostProcessingSteps.size() );
|
||||
if( process->IsActive( pFlags)) {
|
||||
|
||||
if (profiler) {
|
||||
|
@ -775,7 +784,6 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
|
|||
}
|
||||
|
||||
process->ExecuteOnScene ( this );
|
||||
pimpl->mProgressHandler->Update();
|
||||
|
||||
if (profiler) {
|
||||
profiler->EndRegion("postprocess");
|
||||
|
@ -803,6 +811,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
|
|||
}
|
||||
#endif // ! DEBUG
|
||||
}
|
||||
pimpl->mProgressHandler->UpdatePostProcess( pimpl->mPostProcessingSteps.size(), pimpl->mPostProcessingSteps.size() );
|
||||
|
||||
// update private scene flags
|
||||
if( pimpl->mScene )
|
||||
|
|
|
@ -166,6 +166,9 @@ corresponding preprocessor flag to selectively disable formats.
|
|||
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
|
||||
# include "FBXImporter.h"
|
||||
#endif
|
||||
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
|
||||
# include "AssbinLoader.h"
|
||||
#endif
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
|
@ -291,6 +294,9 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out)
|
|||
#if ( !defined ASSIMP_BUILD_NO_FBX_IMPORTER )
|
||||
out.push_back( new FBXImporter() );
|
||||
#endif
|
||||
#if ( !defined ASSIMP_BUILD_NO_ASSBIN_IMPORTER )
|
||||
out.push_back( new AssbinImporter() );
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -49,8 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
namespace Assimp
|
||||
{
|
||||
|
||||
class JoinVerticesTest;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** The JoinVerticesProcess unites identical vertices in all imported meshes.
|
||||
* 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
|
||||
* 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:
|
||||
|
||||
|
|
|
@ -58,30 +58,31 @@ void LWOImporter::LoadLWOBFile()
|
|||
while (running)
|
||||
{
|
||||
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");
|
||||
break;
|
||||
}
|
||||
uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
uint8_t* const next = mFileBuffer+head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
// vertex list
|
||||
case AI_LWO_PNTS:
|
||||
{
|
||||
if (!mCurLayer->mTempPoints.empty())
|
||||
DefaultLogger::get()->warn("LWO: PNTS chunk encountered twice");
|
||||
else LoadLWOPoints(head->length);
|
||||
else LoadLWOPoints(head.length);
|
||||
break;
|
||||
}
|
||||
// face list
|
||||
case AI_LWO_POLS:
|
||||
{
|
||||
|
||||
if (!mCurLayer->mFaces.empty())
|
||||
DefaultLogger::get()->warn("LWO: POLS chunk encountered twice");
|
||||
else LoadLWOBPolygons(head->length);
|
||||
else LoadLWOBPolygons(head.length);
|
||||
break;
|
||||
}
|
||||
// list of tags
|
||||
|
@ -89,14 +90,14 @@ void LWOImporter::LoadLWOBFile()
|
|||
{
|
||||
if (!mTags->empty())
|
||||
DefaultLogger::get()->warn("LWO: SRFS chunk encountered twice");
|
||||
else LoadLWOTags(head->length);
|
||||
else LoadLWOTags(head.length);
|
||||
break;
|
||||
}
|
||||
|
||||
// surface chunk
|
||||
case AI_LWO_SURF:
|
||||
{
|
||||
LoadLWOBSurface(head->length);
|
||||
LoadLWOBSurface(head.length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -137,14 +138,17 @@ void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& face
|
|||
{
|
||||
while (cursor < end && max--)
|
||||
{
|
||||
uint16_t numIndices = *cursor++;
|
||||
verts += numIndices;faces++;
|
||||
uint16_t numIndices;
|
||||
::memcpy(&numIndices, cursor++, 2);
|
||||
verts += numIndices;
|
||||
faces++;
|
||||
cursor += numIndices;
|
||||
int16_t surface = *cursor++;
|
||||
int16_t surface;
|
||||
::memcpy(&surface, cursor++, 2);
|
||||
if (surface < 0)
|
||||
{
|
||||
// there are detail polygons
|
||||
numIndices = *cursor++;
|
||||
::memcpy(&numIndices, cursor++, 2);
|
||||
CountVertsAndFacesLWOB(verts,faces,cursor,end,numIndices);
|
||||
}
|
||||
}
|
||||
|
@ -159,13 +163,22 @@ void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
|
|||
while (cursor < end && max--)
|
||||
{
|
||||
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];
|
||||
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())
|
||||
{
|
||||
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");
|
||||
int16_t surface = *cursor++;
|
||||
int16_t surface;
|
||||
::memcpy(&surface, cursor++, 2);
|
||||
if (surface < 0)
|
||||
{
|
||||
surface = -surface;
|
||||
|
||||
// there are detail polygons.
|
||||
const uint16_t numPolygons = *cursor++;
|
||||
if (cursor < end)CopyFaceIndicesLWOB(it,cursor,end,numPolygons);
|
||||
uint16_t numPolygons;
|
||||
::memcpy(&numPolygons, cursor++, 2);
|
||||
if (cursor < end)
|
||||
{
|
||||
CopyFaceIndicesLWOB(it,cursor,end,numPolygons);
|
||||
}
|
||||
}
|
||||
face.surfaceIndex = surface-1;
|
||||
}
|
||||
|
@ -235,7 +253,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
|
|||
if (mFileBuffer + 6 >= end)
|
||||
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.
|
||||
* 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
|
||||
* 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.");
|
||||
head->length = (uint16_t) (end - mFileBuffer);
|
||||
head.length = (uint16_t) (end - mFileBuffer);
|
||||
}
|
||||
|
||||
uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
uint8_t* const next = mFileBuffer+head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
// diffuse color
|
||||
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.g = GetU1() / 255.0f;
|
||||
surf.mColor.b = GetU1() / 255.0f;
|
||||
|
@ -264,35 +282,35 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
|
|||
// diffuse strength ...
|
||||
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;
|
||||
break;
|
||||
}
|
||||
// specular strength ...
|
||||
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;
|
||||
break;
|
||||
}
|
||||
// luminosity ...
|
||||
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;
|
||||
break;
|
||||
}
|
||||
// transparency
|
||||
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;
|
||||
break;
|
||||
}
|
||||
// surface flags
|
||||
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();
|
||||
if (flag & 0x4 ) surf.mMaximumSmoothAngle = 1.56207f;
|
||||
if (flag & 0x8 ) surf.mColorHighlights = 1.f;
|
||||
|
@ -302,14 +320,14 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
|
|||
// maximum smoothing angle
|
||||
case AI_LWO_SMAN:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4);
|
||||
surf.mMaximumSmoothAngle = fabs( GetF4() );
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SMAN,4);
|
||||
surf.mMaximumSmoothAngle = std::fabs( GetF4() );
|
||||
break;
|
||||
}
|
||||
// glossiness
|
||||
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();
|
||||
break;
|
||||
}
|
||||
|
@ -317,42 +335,42 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
|
|||
case AI_LWO_CTEX:
|
||||
{
|
||||
pTex = SetupNewTextureLWOB(surf.mColorTextures,
|
||||
head->length);
|
||||
head.length);
|
||||
break;
|
||||
}
|
||||
// diffuse texture
|
||||
case AI_LWO_DTEX:
|
||||
{
|
||||
pTex = SetupNewTextureLWOB(surf.mDiffuseTextures,
|
||||
head->length);
|
||||
head.length);
|
||||
break;
|
||||
}
|
||||
// specular texture
|
||||
case AI_LWO_STEX:
|
||||
{
|
||||
pTex = SetupNewTextureLWOB(surf.mSpecularTextures,
|
||||
head->length);
|
||||
head.length);
|
||||
break;
|
||||
}
|
||||
// bump texture
|
||||
case AI_LWO_BTEX:
|
||||
{
|
||||
pTex = SetupNewTextureLWOB(surf.mBumpTextures,
|
||||
head->length);
|
||||
head.length);
|
||||
break;
|
||||
}
|
||||
// transparency texture
|
||||
case AI_LWO_TTEX:
|
||||
{
|
||||
pTex = SetupNewTextureLWOB(surf.mOpacityTextures,
|
||||
head->length);
|
||||
head.length);
|
||||
break;
|
||||
}
|
||||
// texture path
|
||||
case AI_LWO_TIMG:
|
||||
{
|
||||
if (pTex) {
|
||||
GetS0(pTex->mFileName,head->length);
|
||||
GetS0(pTex->mFileName,head.length);
|
||||
}
|
||||
else DefaultLogger::get()->warn("LWOB: Unexpected TIMG chunk");
|
||||
break;
|
||||
|
@ -360,7 +378,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
|
|||
// texture strength
|
||||
case AI_LWO_TVAL:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TVAL,1);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TVAL,1);
|
||||
if (pTex) {
|
||||
pTex->mStrength = (float)GetU1()/ 255.f;
|
||||
}
|
||||
|
@ -370,7 +388,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
|
|||
// texture flags
|
||||
case AI_LWO_TFLG:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TFLG,2);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TFLG,2);
|
||||
|
||||
if (pTex)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
// for n elements, thus the EXPECTED complexity is O(nlogn)
|
||||
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) {
|
||||
const aiFace& face = *begin;
|
||||
|
@ -787,7 +787,8 @@ void LWOImporter::LoadLWO2Polygons(unsigned int length)
|
|||
CountVertsAndFacesLWO2(iNumVertices,iNumFaces,cursor,end);
|
||||
|
||||
// allocate the output array and copy face indices
|
||||
if (iNumFaces) {
|
||||
if (iNumFaces)
|
||||
{
|
||||
cursor = (uint16_t*)mFileBuffer;
|
||||
|
||||
mCurLayer->mFaces.resize(iNumFaces,LWO::Face(type));
|
||||
|
@ -802,13 +803,18 @@ void LWOImporter::CountVertsAndFacesLWO2(unsigned int& verts, unsigned int& face
|
|||
{
|
||||
while (cursor < end && max--)
|
||||
{
|
||||
AI_LSWAP2P(cursor);
|
||||
uint16_t numIndices = *cursor++;
|
||||
uint16_t numIndices;
|
||||
::memcpy(&numIndices, cursor++, 2);
|
||||
AI_LSWAP2(numIndices);
|
||||
numIndices &= 0x03FF;
|
||||
verts += numIndices;++faces;
|
||||
|
||||
verts += numIndices;
|
||||
++faces;
|
||||
|
||||
for(uint16_t i = 0; i < numIndices; i++)
|
||||
{
|
||||
ReadVSizedIntLWO2((uint8_t*&)cursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -817,10 +823,16 @@ void LWOImporter::CopyFaceIndicesLWO2(FaceList::iterator& it,
|
|||
uint16_t*& cursor,
|
||||
const uint16_t* const end)
|
||||
{
|
||||
while (cursor < end) {
|
||||
|
||||
LWO::Face& face = *it++;;
|
||||
if((face.mNumIndices = (*cursor++) & 0x03FF)) /* byte swapping has already been done */ {
|
||||
while (cursor < end)
|
||||
{
|
||||
LWO::Face& face = *it++;
|
||||
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];
|
||||
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)
|
||||
return;
|
||||
|
||||
while (mFileBuffer < end) {
|
||||
|
||||
while (mFileBuffer < end)
|
||||
{
|
||||
unsigned int i = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mFaceIDXOfs;
|
||||
unsigned int j = GetU2();
|
||||
|
||||
|
@ -1106,19 +1118,19 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
|
|||
// first - get the index of the clip
|
||||
clip.idx = GetU4();
|
||||
|
||||
IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
|
||||
switch (head->type)
|
||||
IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
|
||||
switch (head.type)
|
||||
{
|
||||
case AI_LWO_STIL:
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,STIL,1);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,STIL,1);
|
||||
|
||||
// "Normal" texture
|
||||
GetS0(clip.path,head->length);
|
||||
GetS0(clip.path,head.length);
|
||||
clip.type = Clip::STILL;
|
||||
break;
|
||||
|
||||
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.
|
||||
{
|
||||
uint8_t digits = GetU1(); mFileBuffer++;
|
||||
|
@ -1127,12 +1139,12 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
|
|||
|
||||
std::string s;
|
||||
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 << std::setw(digits) << offset + start;
|
||||
GetS0(s,head->length);
|
||||
GetS0(s,head.length);
|
||||
ss << s;
|
||||
clip.path = ss.str();
|
||||
clip.type = Clip::SEQ;
|
||||
|
@ -1148,7 +1160,7 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
|
|||
break;
|
||||
|
||||
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
|
||||
clip.type = Clip::REF;
|
||||
|
@ -1156,7 +1168,7 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
|
|||
break;
|
||||
|
||||
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());
|
||||
break;
|
||||
|
||||
|
@ -1194,17 +1206,17 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
|
|||
while (true)
|
||||
{
|
||||
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");
|
||||
|
||||
uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
uint8_t* const next = mFileBuffer+head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
// Type & representation of the envelope
|
||||
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
|
||||
|
||||
// Determine type of envelope
|
||||
|
@ -1214,20 +1226,20 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
|
|||
|
||||
// precondition
|
||||
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();
|
||||
break;
|
||||
|
||||
// postcondition
|
||||
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();
|
||||
break;
|
||||
|
||||
// keyframe
|
||||
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());
|
||||
LWO::Key& key = envelope.keys.back();
|
||||
|
@ -1240,7 +1252,7 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
|
|||
// interval interpolation
|
||||
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)
|
||||
DefaultLogger::get()->warn("LWO2: Unexpected SPAN chunk");
|
||||
else {
|
||||
|
@ -1286,22 +1298,22 @@ void LWOImporter::LoadLWO2File()
|
|||
while (true)
|
||||
{
|
||||
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");
|
||||
break;
|
||||
}
|
||||
uint8_t* const next = mFileBuffer+head->length;
|
||||
uint8_t* const next = mFileBuffer+head.length;
|
||||
unsigned int iUnnamed = 0;
|
||||
|
||||
if(!head->length) {
|
||||
if(!head.length) {
|
||||
mFileBuffer = next;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (head->type)
|
||||
switch (head.type)
|
||||
{
|
||||
// new layer
|
||||
case AI_LWO_LAYR:
|
||||
|
@ -1311,7 +1323,7 @@ void LWOImporter::LoadLWO2File()
|
|||
LWO::Layer& layer = mLayers->back();
|
||||
mCurLayer = &layer;
|
||||
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LAYR,16);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LAYR,16);
|
||||
|
||||
// layer index.
|
||||
layer.mIndex = GetU2();
|
||||
|
@ -1327,7 +1339,7 @@ void LWOImporter::LoadLWO2File()
|
|||
mCurLayer->mPivot.x = GetF4();
|
||||
mCurLayer->mPivot.y = 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 (layer.mName.empty()) {
|
||||
|
@ -1360,7 +1372,7 @@ void LWOImporter::LoadLWO2File()
|
|||
break;
|
||||
|
||||
unsigned int old = (unsigned int)mCurLayer->mTempPoints.size();
|
||||
LoadLWOPoints(head->length);
|
||||
LoadLWOPoints(head.length);
|
||||
mCurLayer->mPointIDXOfs = old;
|
||||
break;
|
||||
}
|
||||
|
@ -1379,7 +1391,7 @@ void LWOImporter::LoadLWO2File()
|
|||
|
||||
if (mCurLayer->mTempPoints.empty())
|
||||
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;
|
||||
}
|
||||
// face list
|
||||
|
@ -1389,7 +1401,7 @@ void LWOImporter::LoadLWO2File()
|
|||
break;
|
||||
|
||||
unsigned int old = (unsigned int)mCurLayer->mFaces.size();
|
||||
LoadLWO2Polygons(head->length);
|
||||
LoadLWO2Polygons(head.length);
|
||||
mCurLayer->mFaceIDXOfs = old;
|
||||
break;
|
||||
}
|
||||
|
@ -1401,7 +1413,7 @@ void LWOImporter::LoadLWO2File()
|
|||
|
||||
if (mCurLayer->mFaces.empty())
|
||||
DefaultLogger::get()->warn("LWO2: Unexpected PTAG");
|
||||
else LoadLWO2PolygonTags(head->length);
|
||||
else LoadLWO2PolygonTags(head.length);
|
||||
break;
|
||||
}
|
||||
// list of tags
|
||||
|
@ -1409,28 +1421,28 @@ void LWOImporter::LoadLWO2File()
|
|||
{
|
||||
if (!mTags->empty())
|
||||
DefaultLogger::get()->warn("LWO2: SRFS chunk encountered twice");
|
||||
else LoadLWOTags(head->length);
|
||||
else LoadLWOTags(head.length);
|
||||
break;
|
||||
}
|
||||
|
||||
// surface chunk
|
||||
case AI_LWO_SURF:
|
||||
{
|
||||
LoadLWO2Surface(head->length);
|
||||
LoadLWO2Surface(head.length);
|
||||
break;
|
||||
}
|
||||
|
||||
// clip chunk
|
||||
case AI_LWO_CLIP:
|
||||
{
|
||||
LoadLWO2Clip(head->length);
|
||||
LoadLWO2Clip(head.length);
|
||||
break;
|
||||
}
|
||||
|
||||
// envelope chunk
|
||||
case AI_LWO_ENVL:
|
||||
{
|
||||
LoadLWO2Envelope(head->length);
|
||||
LoadLWO2Envelope(head.length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -402,7 +402,9 @@ protected:
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
inline float LWOImporter::GetF4()
|
||||
{
|
||||
float f = *((float*)mFileBuffer);mFileBuffer += 4;
|
||||
float f;
|
||||
::memcpy(&f, mFileBuffer, 4);
|
||||
mFileBuffer += 4;
|
||||
AI_LSWAP4(f);
|
||||
return f;
|
||||
}
|
||||
|
@ -410,7 +412,9 @@ inline float LWOImporter::GetF4()
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
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);
|
||||
return f;
|
||||
}
|
||||
|
@ -418,7 +422,9 @@ inline uint32_t LWOImporter::GetU4()
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
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);
|
||||
return f;
|
||||
}
|
||||
|
|
|
@ -285,7 +285,7 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
|
|||
{
|
||||
float fGloss;
|
||||
if (mIsLWO2) {
|
||||
fGloss = pow( surf.mGlossiness*10.0f+2.0f, 2.0f);
|
||||
fGloss = std::pow( surf.mGlossiness*10.0f+2.0f, 2.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -527,13 +527,13 @@ void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
|
|||
while (true)
|
||||
{
|
||||
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");
|
||||
|
||||
uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
uint8_t* const next = mFileBuffer+head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
case AI_LWO_PROJ:
|
||||
tex.mapMode = (Texture::MappingMode)GetU2();
|
||||
|
@ -549,7 +549,7 @@ void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
|
|||
tex.mClipIdx = GetU2();
|
||||
break;
|
||||
case AI_LWO_VMAP:
|
||||
GetS0(tex.mUVChannelIndex,head->length);
|
||||
GetS0(tex.mUVChannelIndex,head.length);
|
||||
break;
|
||||
case AI_LWO_WRPH:
|
||||
tex.wrapAmountH = GetF4();
|
||||
|
@ -595,13 +595,13 @@ void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex )
|
|||
while (true)
|
||||
{
|
||||
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");
|
||||
|
||||
uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
uint8_t* const next = mFileBuffer+head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
case AI_LWO_CHAN:
|
||||
tex.type = GetU4();
|
||||
|
@ -698,20 +698,20 @@ void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* /*head*/, u
|
|||
while (true)
|
||||
{
|
||||
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");
|
||||
|
||||
uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
uint8_t* const next = mFileBuffer+head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
case AI_LWO_ENAB:
|
||||
shader.enabled = GetU2() ? true : false;
|
||||
break;
|
||||
|
||||
case AI_LWO_FUNC:
|
||||
GetS0( shader.functionName, head->length );
|
||||
GetS0( shader.functionName, head.length );
|
||||
}
|
||||
mFileBuffer = next;
|
||||
}
|
||||
|
@ -756,18 +756,18 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
|
|||
{
|
||||
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 surface chunk length");
|
||||
|
||||
uint8_t* const next = mFileBuffer+head->length;
|
||||
switch (head->type)
|
||||
uint8_t* const next = mFileBuffer+head.length;
|
||||
switch (head.type)
|
||||
{
|
||||
// diffuse color
|
||||
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.g = GetF4();
|
||||
surf.mColor.b = GetF4();
|
||||
|
@ -776,14 +776,14 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
|
|||
// diffuse strength ... hopefully
|
||||
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();
|
||||
break;
|
||||
}
|
||||
// specular strength ... hopefully
|
||||
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();
|
||||
break;
|
||||
}
|
||||
|
@ -794,21 +794,21 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
|
|||
if (surf.mTransparency == 10e10f)
|
||||
break;
|
||||
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,4);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TRAN,4);
|
||||
surf.mTransparency = GetF4();
|
||||
break;
|
||||
}
|
||||
// additive transparency
|
||||
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();
|
||||
break;
|
||||
}
|
||||
// wireframe mode
|
||||
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)
|
||||
surf.mWireframe = true;
|
||||
break;
|
||||
|
@ -816,49 +816,49 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
|
|||
// glossiness
|
||||
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();
|
||||
break;
|
||||
}
|
||||
// bump intensity
|
||||
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();
|
||||
break;
|
||||
}
|
||||
// color highlights
|
||||
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();
|
||||
break;
|
||||
}
|
||||
// index of refraction
|
||||
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();
|
||||
break;
|
||||
}
|
||||
// polygon sidedness
|
||||
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());
|
||||
break;
|
||||
}
|
||||
// maximum smoothing angle
|
||||
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() );
|
||||
break;
|
||||
}
|
||||
// vertex color channel to be applied to the surface
|
||||
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
|
||||
ReadVSizedIntLWO2(mFileBuffer); // skip envelope
|
||||
surf.mVCMapType = GetU4(); // type of the channel
|
||||
|
@ -870,18 +870,18 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
|
|||
// surface bock entry
|
||||
case AI_LWO_BLOK:
|
||||
{
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BLOK,4);
|
||||
LE_NCONST IFF::SubChunkHeader* head2 = IFF::LoadSubChunk(mFileBuffer);
|
||||
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,BLOK,4);
|
||||
IFF::SubChunkHeader head2 = IFF::LoadSubChunk(mFileBuffer);
|
||||
|
||||
switch (head2->type)
|
||||
switch (head2.type)
|
||||
{
|
||||
case AI_LWO_PROC:
|
||||
case AI_LWO_GRAD:
|
||||
case AI_LWO_IMAP:
|
||||
LoadLWO2TextureBlock(head2, head->length);
|
||||
LoadLWO2TextureBlock(&head2, head.length);
|
||||
break;
|
||||
case AI_LWO_SHDR:
|
||||
LoadLWO2ShaderBlock(head2, head->length);
|
||||
LoadLWO2ShaderBlock(&head2, head.length);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -464,7 +464,7 @@ std::string LWSImporter::FindLWOFile(const std::string& in)
|
|||
std::string tmp;
|
||||
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;
|
||||
|
||||
|
@ -480,12 +480,12 @@ std::string LWSImporter::FindLWOFile(const std::string& in)
|
|||
// <folder>\Scenes\<hh>\<*>.lws
|
||||
// where <hh> is optional.
|
||||
|
||||
std::string test = ".." + (io->getOsSeparator() + tmp);
|
||||
std::string test = std::string("..") + (io->getOsSeparator() + tmp);
|
||||
if (io->Exists(test)) {
|
||||
return test;
|
||||
}
|
||||
|
||||
test = ".." + (io->getOsSeparator() + test);
|
||||
test = std::string("..") + (io->getOsSeparator() + test);
|
||||
if (io->Exists(test)) {
|
||||
return test;
|
||||
}
|
||||
|
|
|
@ -131,10 +131,15 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
|
|||
|
||||
// and renormalize the weights
|
||||
float sum = 0.0f;
|
||||
for( std::vector<Weight>::const_iterator it = vit->begin(); it != vit->end(); ++it)
|
||||
sum += it->mWeight;
|
||||
for( std::vector<Weight>::iterator it = vit->begin(); it != vit->end(); ++it)
|
||||
it->mWeight /= sum;
|
||||
for( std::vector<Weight>::const_iterator it = vit->begin(); it != vit->end(); ++it ) {
|
||||
sum += it->mWeight;
|
||||
}
|
||||
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) {
|
||||
|
@ -157,18 +162,6 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
|
|||
const std::vector<aiVertexWeight>& bw = boneWeights[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() )
|
||||
{
|
||||
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
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -263,9 +263,9 @@ inline void LatLngNormalToVec3(uint16_t p_iNormal, float* p_afOut)
|
|||
lat *= 3.141926f/128.0f;
|
||||
lng *= 3.141926f/128.0f;
|
||||
|
||||
p_afOut[0] = cosf(lat) * sinf(lng);
|
||||
p_afOut[1] = sinf(lat) * sinf(lng);
|
||||
p_afOut[2] = cosf(lng);
|
||||
p_afOut[0] = std::cos(lat) * std::sin(lng);
|
||||
p_afOut[1] = std::sin(lat) * std::sin(lng);
|
||||
p_afOut[2] = std::cos(lng);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -259,7 +259,7 @@ inline void ConvertQuaternion (const aiVector3D& in, aiQuaternion& out) {
|
|||
|
||||
if (t < 0.0f)
|
||||
out.w = 0.0f;
|
||||
else out.w = sqrt (t);
|
||||
else out.w = std::sqrt (t);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -75,6 +75,7 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
|
|||
|
||||
} // end of namespace Assimp
|
||||
|
||||
static const std::string MaterialExt = ".mtl";
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ObjExporter :: ObjExporter(const char* _filename, const aiScene* pScene)
|
||||
|
@ -107,7 +108,7 @@ std::string ObjExporter :: GetMaterialLibName()
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
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);
|
||||
|
||||
|
@ -144,16 +145,16 @@ void ObjExporter :: WriteMaterialFile()
|
|||
|
||||
aiColor4D 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)) {
|
||||
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)) {
|
||||
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)) {
|
||||
mOutputMat << "ke " << c.r << " " << c.g << " " << c.b << endl;
|
||||
mOutputMat << "Ke " << c.r << " " << c.g << " " << c.b << endl;
|
||||
}
|
||||
|
||||
float o;
|
||||
|
@ -170,16 +171,19 @@ void ObjExporter :: WriteMaterialFile()
|
|||
|
||||
aiString 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)) {
|
||||
mOutputMat << "map_ka " << s.data << endl;
|
||||
mOutputMat << "map_Ka " << s.data << endl;
|
||||
}
|
||||
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)) {
|
||||
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)) {
|
||||
// implementations seem to vary here, so write both variants
|
||||
|
@ -199,7 +203,7 @@ void ObjExporter :: WriteGeometryFile()
|
|||
|
||||
// collect mesh geometry
|
||||
aiMatrix4x4 mBase;
|
||||
AddNode(pScene->mRootNode,mBase);
|
||||
AddNode(pScene->mRootNode, mBase);
|
||||
|
||||
// write vertex positions
|
||||
vpMap.getVectors(vp);
|
||||
|
@ -228,7 +232,9 @@ void ObjExporter :: WriteGeometryFile()
|
|||
// now write all mesh instances
|
||||
BOOST_FOREACH(const MeshInstance& m, meshes) {
|
||||
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;
|
||||
|
||||
BOOST_FOREACH(const Face& f, m.faces) {
|
||||
|
@ -243,11 +249,8 @@ void ObjExporter :: WriteGeometryFile()
|
|||
if (fv.vt) {
|
||||
mOutput << fv.vt;
|
||||
}
|
||||
if (f.kind == 'f') {
|
||||
mOutput << '/';
|
||||
if (fv.vn) {
|
||||
mOutput << fv.vn;
|
||||
}
|
||||
if (f.kind == 'f' && fv.vn) {
|
||||
mOutput << '/' << fv.vn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -258,14 +261,12 @@ void ObjExporter :: WriteGeometryFile()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec)
|
||||
{
|
||||
vecIndexMap::dataType::iterator vertIt = vecMap.find(vec);
|
||||
if(vertIt != vecMap.end()){// vertex already exists, so reference it
|
||||
vecIndexMap::dataType::iterator vertIt = vecMap.find(vec);
|
||||
// vertex already exists, so reference it
|
||||
if(vertIt != vecMap.end()){
|
||||
return vertIt->second;
|
||||
}
|
||||
vecMap[vec] = mNextIndex;
|
||||
|
@ -274,6 +275,7 @@ int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec)
|
|||
return ret;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ObjExporter::vecIndexMap::getVectors( std::vector<aiVector3D>& vecs )
|
||||
{
|
||||
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());
|
||||
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.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);
|
||||
|
||||
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{
|
||||
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;
|
||||
|
||||
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) {
|
||||
AddNode(nd->mChildren[i],mAbs);
|
||||
AddNode(nd->mChildren[i], mAbs);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
#endif // ASSIMP_BUILD_NO_OBJ_EXPORTER
|
||||
#endif // ASSIMP_BUILD_NO_EXPORT
|
||||
|
|
|
@ -62,7 +62,7 @@ static const aiImporterDesc desc = {
|
|||
|
||||
static const unsigned int ObjMinSize = 16;
|
||||
|
||||
namespace Assimp {
|
||||
namespace Assimp {
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -109,9 +109,7 @@ const aiImporterDesc* ObjFileImporter::GetInfo () const
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
// Obj-file import implementation
|
||||
void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
|
||||
{
|
||||
DefaultIOSystem io;
|
||||
|
||||
{
|
||||
// Read file into memory
|
||||
const std::string mode = "rb";
|
||||
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, mode));
|
||||
|
@ -139,7 +137,23 @@ void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
|
|||
{
|
||||
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
|
||||
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++ )
|
||||
{
|
||||
unsigned int meshId = pObject->m_Meshes[ i ];
|
||||
aiMesh *pMesh = new aiMesh;
|
||||
createTopology( pModel, pObject, meshId, pMesh );
|
||||
if ( pMesh->mNumVertices > 0 )
|
||||
{
|
||||
aiMesh *pMesh = createTopology( pModel, pObject, meshId );
|
||||
if( pMesh && pMesh->mNumFaces > 0 ) {
|
||||
MeshArray.push_back( pMesh );
|
||||
}
|
||||
else
|
||||
{
|
||||
delete pMesh;
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
|
||||
const ObjFile::Object* pData,
|
||||
unsigned int uiMeshIndex,
|
||||
aiMesh* pMesh )
|
||||
aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData,
|
||||
unsigned int uiMeshIndex )
|
||||
{
|
||||
// Checking preconditions
|
||||
ai_assert( NULL != pModel );
|
||||
if( NULL == pData ) {
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create faces
|
||||
ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ];
|
||||
ai_assert( NULL != pObjMesh );
|
||||
|
||||
pMesh->mNumFaces = 0;
|
||||
if( !pObjMesh ) {
|
||||
return NULL;
|
||||
}
|
||||
ai_assert( NULL != pObjMesh );
|
||||
aiMesh* pMesh = new aiMesh;
|
||||
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) {
|
||||
pMesh->mNumFaces += inp->m_pVertices->size() - 1;
|
||||
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->mPrimitiveTypes |= aiPrimitiveType_POINT;
|
||||
} else {
|
||||
++pMesh->mNumFaces;
|
||||
if (inp->m_pVertices->size() > 3) {
|
||||
pMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int uiIdxCount = 0u;
|
||||
unsigned int uiIdxCount( 0u );
|
||||
if ( pMesh->mNumFaces > 0 )
|
||||
{
|
||||
pMesh->mFaces = new aiFace[ pMesh->mNumFaces ];
|
||||
|
@ -305,7 +312,7 @@ void ObjFileImporter::createTopology(const ObjFile::Model* pModel,
|
|||
pMesh->mMaterialIndex = pObjMesh->m_uiMaterialIndex;
|
||||
}
|
||||
|
||||
unsigned int outIndex = 0;
|
||||
unsigned int outIndex( 0 );
|
||||
|
||||
// Copy all data from all stored meshes
|
||||
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
|
||||
createVertexArray(pModel, pData, uiMeshIndex, pMesh, uiIdxCount);
|
||||
|
||||
return pMesh;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -91,8 +91,8 @@ private:
|
|||
aiNode *pParent, aiScene* pScene, std::vector<aiMesh*> &MeshArray);
|
||||
|
||||
//! \brief Creates topology data like faces and meshes for the geometry.
|
||||
void createTopology(const ObjFile::Model* pModel, const ObjFile::Object* pData,
|
||||
unsigned int uiMeshIndex, aiMesh* pMesh);
|
||||
aiMesh *createTopology( const ObjFile::Model* pModel, const ObjFile::Object* pData,
|
||||
unsigned int uiMeshIndex );
|
||||
|
||||
//! \brief Creates vertices from model.
|
||||
void createVertexArray(const ObjFile::Model* pModel, const ObjFile::Object* pCurrentObject,
|
||||
|
|
|
@ -46,14 +46,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "ObjTools.h"
|
||||
#include "ObjFileData.h"
|
||||
#include "fast_atof.h"
|
||||
#include "ParsingUtils.h"
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
// Material specific token
|
||||
static const std::string DiffuseTexture = "map_kd";
|
||||
static const std::string AmbientTexture = "map_ka";
|
||||
static const std::string SpecularTexture = "map_ks";
|
||||
static const std::string DiffuseTexture = "map_Kd";
|
||||
static const std::string AmbientTexture = "map_Ka";
|
||||
static const std::string SpecularTexture = "map_Ks";
|
||||
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 BumpTexture2 = "map_Bump";
|
||||
static const std::string BumpTexture3 = "bump";
|
||||
|
@ -128,6 +130,7 @@ void ObjFileMtlImporter::load()
|
|||
{
|
||||
switch (*m_DataIt)
|
||||
{
|
||||
case 'k':
|
||||
case 'K':
|
||||
{
|
||||
++m_DataIt;
|
||||
|
@ -163,25 +166,27 @@ void ObjFileMtlImporter::load()
|
|||
}
|
||||
break;
|
||||
|
||||
case 'N': // Shineness
|
||||
case 'N':
|
||||
case 'n':
|
||||
{
|
||||
++m_DataIt;
|
||||
switch(*m_DataIt)
|
||||
switch(*m_DataIt)
|
||||
{
|
||||
case 's':
|
||||
case 's': // Specular exponent
|
||||
++m_DataIt;
|
||||
getFloatValue(m_pModel->m_pCurrentMaterial->shineness);
|
||||
break;
|
||||
case 'i': //Index Of refraction
|
||||
case 'i': // Index Of refraction
|
||||
++m_DataIt;
|
||||
getFloatValue(m_pModel->m_pCurrentMaterial->ior);
|
||||
break;
|
||||
case 'e': // New material
|
||||
createMaterial();
|
||||
break;
|
||||
}
|
||||
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'm': // Texture
|
||||
case 'b': // quick'n'dirty - for 'bump' sections
|
||||
|
@ -191,13 +196,6 @@ void ObjFileMtlImporter::load()
|
|||
}
|
||||
break;
|
||||
|
||||
case 'n': // New material name
|
||||
{
|
||||
createMaterial();
|
||||
m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
|
||||
}
|
||||
break;
|
||||
|
||||
case 'i': // Illumination model
|
||||
{
|
||||
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
||||
|
@ -221,15 +219,17 @@ void ObjFileMtlImporter::getColorRGBA( aiColor3D *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 );
|
||||
pColor->r = r;
|
||||
|
||||
m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, g );
|
||||
pColor->g = g;
|
||||
|
||||
m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, b );
|
||||
pColor->b = b;
|
||||
// we have to check if color is default 0 with only one token
|
||||
if( !IsLineEnd( *m_DataIt ) ) {
|
||||
m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, g );
|
||||
m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, b );
|
||||
}
|
||||
pColor->g = g;
|
||||
pColor->b = b;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
@ -253,7 +253,7 @@ void ObjFileMtlImporter::getFloatValue( float &value )
|
|||
void ObjFileMtlImporter::createMaterial()
|
||||
{
|
||||
std::string line( "" );
|
||||
while ( !isNewLine( *m_DataIt ) ) {
|
||||
while( !IsLineEnd( *m_DataIt ) ) {
|
||||
line += *m_DataIt;
|
||||
++m_DataIt;
|
||||
}
|
||||
|
@ -303,11 +303,7 @@ void ObjFileMtlImporter::getTexture() {
|
|||
// Opacity texture
|
||||
out = & m_pModel->m_pCurrentMaterial->textureOpacity;
|
||||
clampIndex = ObjFile::Material::TextureOpacityType;
|
||||
} else if (!ASSIMP_strincmp( pPtr,"map_ka",6)) {
|
||||
// Ambient texture
|
||||
out = & m_pModel->m_pCurrentMaterial->textureAmbient;
|
||||
clampIndex = ObjFile::Material::TextureAmbientType;
|
||||
} else if (!ASSIMP_strincmp(&(*m_DataIt),"map_emissive",6)) {
|
||||
} else if (!ASSIMP_strincmp( pPtr, EmmissiveTexture.c_str(), EmmissiveTexture.size())) {
|
||||
// Emissive texture
|
||||
out = & m_pModel->m_pCurrentMaterial->textureEmissive;
|
||||
clampIndex = ObjFile::Material::TextureEmissiveType;
|
||||
|
|
|
@ -113,8 +113,8 @@ void ObjFileParser::parseFile()
|
|||
getVector3(m_pModel->m_Vertices);
|
||||
} else if (*m_DataIt == 't') {
|
||||
// read in texture coordinate ( 2D or 3D )
|
||||
++m_DataIt;
|
||||
getVector( m_pModel->m_TextureCoord );
|
||||
++m_DataIt;
|
||||
getVector( m_pModel->m_TextureCoord );
|
||||
} else if (*m_DataIt == 'n') {
|
||||
// Read in normal vector definition
|
||||
++m_DataIt;
|
||||
|
@ -186,12 +186,12 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t length)
|
|||
{
|
||||
size_t index = 0;
|
||||
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;
|
||||
index++;
|
||||
if (index == length-1)
|
||||
break;
|
||||
if( index == length - 1 ) {
|
||||
break;
|
||||
}
|
||||
++m_DataIt;
|
||||
}
|
||||
|
||||
|
@ -233,12 +233,13 @@ void ObjFileParser::copyNextLine(char *pBuffer, size_t length)
|
|||
// -------------------------------------------------------------------
|
||||
void ObjFileParser::getVector( std::vector<aiVector3D> &point3d_array ) {
|
||||
size_t numComponents( 0 );
|
||||
DataArrayIt tmp( m_DataIt );
|
||||
const char* tmp( &m_DataIt[0] );
|
||||
while( !IsLineEnd( *tmp ) ) {
|
||||
if( *tmp == ' ' ) {
|
||||
++numComponents;
|
||||
if ( !SkipSpaces( &tmp ) ) {
|
||||
break;
|
||||
}
|
||||
tmp++;
|
||||
SkipToken( tmp );
|
||||
++numComponents;
|
||||
}
|
||||
float x, y, z;
|
||||
if( 2 == numComponents ) {
|
||||
|
@ -344,7 +345,7 @@ void ObjFileParser::getFace(aiPrimitiveType type)
|
|||
}
|
||||
iPos++;
|
||||
}
|
||||
else if ( isSeparator(*pPtr) )
|
||||
else if( IsSpaceOrNewLine( *pPtr ) )
|
||||
{
|
||||
iPos = 0;
|
||||
}
|
||||
|
@ -462,8 +463,9 @@ void ObjFileParser::getMaterialDesc()
|
|||
return;
|
||||
|
||||
char *pStart = &(*m_DataIt);
|
||||
while ( m_DataIt != m_DataItEnd && !isSeparator(*m_DataIt) )
|
||||
++m_DataIt;
|
||||
while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
|
||||
++m_DataIt;
|
||||
}
|
||||
|
||||
// Get name
|
||||
std::string strName(pStart, &(*m_DataIt));
|
||||
|
@ -517,12 +519,14 @@ void ObjFileParser::getMaterialLib()
|
|||
{
|
||||
// Translate tuple
|
||||
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
||||
if (m_DataIt == m_DataItEnd)
|
||||
return;
|
||||
if( m_DataIt == m_DataItEnd ) {
|
||||
return;
|
||||
}
|
||||
|
||||
char *pStart = &(*m_DataIt);
|
||||
while (m_DataIt != m_DataItEnd && !isNewLine(*m_DataIt))
|
||||
m_DataIt++;
|
||||
while( m_DataIt != m_DataItEnd && !IsLineEnd( *m_DataIt ) ) {
|
||||
++m_DataIt;
|
||||
}
|
||||
|
||||
// Check for existence
|
||||
const std::string strMatName(pStart, &(*m_DataIt));
|
||||
|
@ -550,13 +554,15 @@ void ObjFileParser::getNewMaterial()
|
|||
{
|
||||
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
||||
m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
|
||||
if ( m_DataIt == m_DataItEnd )
|
||||
return;
|
||||
if( m_DataIt == m_DataItEnd ) {
|
||||
return;
|
||||
}
|
||||
|
||||
char *pStart = &(*m_DataIt);
|
||||
std::string strMat( pStart, *m_DataIt );
|
||||
while ( m_DataIt != m_DataItEnd && isSeparator( *m_DataIt ) )
|
||||
m_DataIt++;
|
||||
while( m_DataIt != m_DataItEnd && IsSpaceOrNewLine( *m_DataIt ) ) {
|
||||
++m_DataIt;
|
||||
}
|
||||
std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat );
|
||||
if ( it == m_pModel->m_MaterialMap.end() )
|
||||
{
|
||||
|
@ -581,8 +587,9 @@ void ObjFileParser::getNewMaterial()
|
|||
int ObjFileParser::getMaterialIndex( const std::string &strMaterialName )
|
||||
{
|
||||
int mat_index = -1;
|
||||
if ( strMaterialName.empty() )
|
||||
return mat_index;
|
||||
if( strMaterialName.empty() ) {
|
||||
return mat_index;
|
||||
}
|
||||
for (size_t index = 0; index < m_pModel->m_MaterialLib.size(); ++index)
|
||||
{
|
||||
if ( strMaterialName == m_pModel->m_MaterialLib[ index ])
|
||||
|
@ -601,8 +608,9 @@ void ObjFileParser::getGroupName()
|
|||
std::string strGroupName;
|
||||
|
||||
m_DataIt = getName<DataArrayIt>(m_DataIt, m_DataItEnd, strGroupName);
|
||||
if ( isEndOfBuffer( m_DataIt, m_DataItEnd ) )
|
||||
return;
|
||||
if( isEndOfBuffer( m_DataIt, m_DataItEnd ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Change active group, if necessary
|
||||
if ( m_pModel->m_strActiveGroup != strGroupName )
|
||||
|
@ -653,11 +661,13 @@ void ObjFileParser::getGroupNumberAndResolution()
|
|||
void ObjFileParser::getObjectName()
|
||||
{
|
||||
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
|
||||
if (m_DataIt == m_DataItEnd)
|
||||
return;
|
||||
if( m_DataIt == m_DataItEnd ) {
|
||||
return;
|
||||
}
|
||||
char *pStart = &(*m_DataIt);
|
||||
while ( m_DataIt != m_DataItEnd && !isSeparator( *m_DataIt ) )
|
||||
++m_DataIt;
|
||||
while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
|
||||
++m_DataIt;
|
||||
}
|
||||
|
||||
std::string strObjectName(pStart, &(*m_DataIt));
|
||||
if (!strObjectName.empty())
|
||||
|
@ -678,8 +688,9 @@ void ObjFileParser::getObjectName()
|
|||
}
|
||||
|
||||
// Allocate a new object, if current one was not found before
|
||||
if ( NULL == m_pModel->m_pCurrent )
|
||||
createObject(strObjectName);
|
||||
if( NULL == m_pModel->m_pCurrent ) {
|
||||
createObject( strObjectName );
|
||||
}
|
||||
}
|
||||
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_Objects.push_back( m_pModel->m_pCurrent );
|
||||
|
||||
|
||||
createMesh();
|
||||
|
||||
if( m_pModel->m_pCurrentMaterial )
|
||||
|
|
|
@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#define OBJ_TOOLS_H_INC
|
||||
|
||||
#include "fast_atof.h"
|
||||
#include "ParsingUtils.h"
|
||||
|
||||
namespace Assimp
|
||||
{
|
||||
|
@ -68,28 +69,6 @@ inline bool isEndOfBuffer( char_t it, char_t 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
|
||||
* @param pBuffer Pointer to data 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 ) )
|
||||
{
|
||||
if ( !isSeparator( *pBuffer ) || isNewLine( *pBuffer ) )
|
||||
if( !IsSpaceOrNewLine( *pBuffer ) || IsLineEnd( *pBuffer ) )
|
||||
break;
|
||||
pBuffer++;
|
||||
}
|
||||
|
@ -117,7 +96,7 @@ inline Char_T getNextToken( Char_T pBuffer, Char_T pEnd )
|
|||
{
|
||||
while ( !isEndOfBuffer( pBuffer, pEnd ) )
|
||||
{
|
||||
if ( isSeparator( *pBuffer ) )
|
||||
if( IsSpaceOrNewLine( *pBuffer ) )
|
||||
break;
|
||||
pBuffer++;
|
||||
}
|
||||
|
@ -127,14 +106,14 @@ inline Char_T getNextToken( Char_T pBuffer, Char_T pEnd )
|
|||
/** @brief Skips a line
|
||||
* @param it Iterator set to current position
|
||||
* @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
|
||||
*/
|
||||
template<class char_t>
|
||||
inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine )
|
||||
{
|
||||
while ( !isEndOfBuffer( it, end ) && !isNewLine( *it ) )
|
||||
++it;
|
||||
inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine ) {
|
||||
while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) {
|
||||
++it;
|
||||
}
|
||||
if ( it != end )
|
||||
{
|
||||
++it;
|
||||
|
@ -157,15 +136,16 @@ template<class char_t>
|
|||
inline char_t getName( char_t it, char_t end, std::string &name )
|
||||
{
|
||||
name = "";
|
||||
if ( isEndOfBuffer( it, end ) )
|
||||
return end;
|
||||
if( isEndOfBuffer( it, end ) ) {
|
||||
return end;
|
||||
}
|
||||
|
||||
char *pStart = &( *it );
|
||||
while ( !isEndOfBuffer( it, end ) && !isNewLine( *it ) ) {
|
||||
while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) {
|
||||
++it;
|
||||
}
|
||||
|
||||
while(isEndOfBuffer( it, end ) || isNewLine( *it ) || isSeparator(*it)) {
|
||||
while( isEndOfBuffer( it, end ) || IsLineEnd( *it ) || IsSpaceOrNewLine( *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;
|
||||
it = getNextWord<char_t>( it, end );
|
||||
while ( !isSeparator( *it ) && !isEndOfBuffer( it, end ) )
|
||||
while( !IsSpaceOrNewLine( *it ) && !isEndOfBuffer( it, end ) )
|
||||
{
|
||||
pBuffer[index] = *it ;
|
||||
index++;
|
||||
|
@ -259,4 +239,4 @@ unsigned int tokenize( const string_type& str, std::vector<string_type>& tokens,
|
|||
|
||||
} // Namespace Assimp
|
||||
|
||||
#endif
|
||||
#endif // OBJ_TOOLS_H_INC
|
||||
|
|
|
@ -376,14 +376,14 @@ void OgreBinarySerializer::ReadMeshSkeletonLink(Mesh *mesh)
|
|||
mesh->skeletonRef = ReadLine();
|
||||
}
|
||||
|
||||
void OgreBinarySerializer::ReadMeshBounds(Mesh *mesh)
|
||||
void OgreBinarySerializer::ReadMeshBounds(Mesh * /*mesh*/)
|
||||
{
|
||||
// Skip bounds, not compatible with Assimp.
|
||||
// 2x float vec3 + 1x float sphere radius
|
||||
SkipBytes(sizeof(float) * 7);
|
||||
}
|
||||
|
||||
void OgreBinarySerializer::ReadMeshExtremes(Mesh *mesh)
|
||||
void OgreBinarySerializer::ReadMeshExtremes(Mesh * /*mesh*/)
|
||||
{
|
||||
// Skip extremes, not compatible with Assimp.
|
||||
size_t numBytes = m_currentLen - MSTREAM_OVERHEAD_SIZE;
|
||||
|
@ -534,7 +534,6 @@ void OgreBinarySerializer::ReadSubMeshTextureAlias(SubMesh *submesh)
|
|||
void OgreBinarySerializer::ReadSubMeshNames(Mesh *mesh)
|
||||
{
|
||||
uint16_t id = 0;
|
||||
uint16_t submeshIndex = 0;
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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.
|
||||
|
||||
|
@ -1055,7 +1054,7 @@ void OgreBinarySerializer::ReadSkeletonAnimation(Skeleton *skeleton)
|
|||
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>();
|
||||
Bone *bone = dest->parentSkeleton->BoneById(boneId);
|
||||
|
@ -1097,7 +1096,7 @@ void OgreBinarySerializer::ReadSkeletonAnimationKeyFrame(VertexAnimationTrack *d
|
|||
dest->transformKeyFrames.push_back(keyframe);
|
||||
}
|
||||
|
||||
void OgreBinarySerializer::ReadSkeletonAnimationLink(Skeleton *skeleton)
|
||||
void OgreBinarySerializer::ReadSkeletonAnimationLink(Skeleton * /*skeleton*/)
|
||||
{
|
||||
// Skip bounds, not compatible with Assimp.
|
||||
ReadLine(); // skeleton name
|
||||
|
|
|
@ -75,8 +75,8 @@ private:
|
|||
};
|
||||
|
||||
OgreBinarySerializer(MemoryStreamReader *reader, AssetMode mode) :
|
||||
m_reader(reader),
|
||||
m_currentLen(0),
|
||||
m_reader(reader),
|
||||
assetMode(mode)
|
||||
{
|
||||
}
|
||||
|
@ -301,11 +301,12 @@ enum MeshChunkId
|
|||
// unsigned short poseIndex
|
||||
// float influence
|
||||
// Optional submesh extreme vertex list chink
|
||||
M_TABLE_EXTREMES = 0xE000,
|
||||
M_TABLE_EXTREMES = 0xE000
|
||||
// unsigned short submesh_index;
|
||||
// float extremes [n_extremes][3];
|
||||
};
|
||||
|
||||
/*
|
||||
static std::string MeshHeaderToString(MeshChunkId id)
|
||||
{
|
||||
switch(id)
|
||||
|
@ -347,6 +348,7 @@ static std::string MeshHeaderToString(MeshChunkId id)
|
|||
}
|
||||
return "Unknown_MeshChunkId";
|
||||
}
|
||||
*/
|
||||
|
||||
enum SkeletonChunkId
|
||||
{
|
||||
|
@ -393,6 +395,7 @@ enum SkeletonChunkId
|
|||
// float scale : scale to apply to trans/scale keys
|
||||
};
|
||||
|
||||
/*
|
||||
static std::string SkeletonHeaderToString(SkeletonChunkId id)
|
||||
{
|
||||
switch(id)
|
||||
|
@ -409,6 +412,7 @@ static std::string SkeletonHeaderToString(SkeletonChunkId id)
|
|||
}
|
||||
return "Unknown_SkeletonChunkId";
|
||||
}
|
||||
*/
|
||||
} // Ogre
|
||||
} // Assimp
|
||||
|
||||
|
|
|
@ -108,10 +108,10 @@ void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Ass
|
|||
MemoryStreamReader reader(f);
|
||||
|
||||
// Import mesh
|
||||
boost::scoped_ptr<Mesh> mesh = OgreBinarySerializer::ImportMesh(&reader);
|
||||
boost::scoped_ptr<Mesh> mesh(OgreBinarySerializer::ImportMesh(&reader));
|
||||
|
||||
// Import skeleton
|
||||
OgreBinarySerializer::ImportSkeleton(pIOHandler, mesh);
|
||||
OgreBinarySerializer::ImportSkeleton(pIOHandler, mesh.get());
|
||||
|
||||
// Import mesh referenced materials
|
||||
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()));
|
||||
|
||||
// Import mesh
|
||||
boost::scoped_ptr<MeshXml> mesh = OgreXmlSerializer::ImportMesh(reader.get());
|
||||
boost::scoped_ptr<MeshXml> mesh(OgreXmlSerializer::ImportMesh(reader.get()));
|
||||
|
||||
// Import skeleton
|
||||
OgreXmlSerializer::ImportSkeleton(pIOHandler, mesh);
|
||||
OgreXmlSerializer::ImportSkeleton(pIOHandler, mesh.get());
|
||||
|
||||
// Import mesh referenced materials
|
||||
ReadMaterials(pFile, pIOHandler, pScene, mesh.get());
|
||||
|
|
|
@ -325,7 +325,7 @@ uint32_t VertexData::VertexSize(uint16_t source) const
|
|||
MemoryStream *VertexData::VertexBuffer(uint16_t source)
|
||||
{
|
||||
if (vertexBindings.find(source) != vertexBindings.end())
|
||||
return vertexBindings[source];
|
||||
return vertexBindings[source].get();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -404,9 +404,9 @@ size_t IndexData::FaceSize() const
|
|||
// Mesh
|
||||
|
||||
Mesh::Mesh() :
|
||||
sharedVertexData(0),
|
||||
skeleton(0),
|
||||
hasSkeletalAnimations(false)
|
||||
hasSkeletalAnimations(false),
|
||||
skeleton(NULL),
|
||||
sharedVertexData(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -712,8 +712,8 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent)
|
|||
// MeshXml
|
||||
|
||||
MeshXml::MeshXml() :
|
||||
sharedVertexData(0),
|
||||
skeleton(0)
|
||||
skeleton(0),
|
||||
sharedVertexData(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -797,8 +797,8 @@ void MeshXml::ConvertToAssimpScene(aiScene* dest)
|
|||
// 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(Skeleton *parent) :
|
||||
parentMesh(NULL),
|
||||
parentSkeleton(parent),
|
||||
parentMesh(0),
|
||||
length(0.0f),
|
||||
baseTime(-1.0f)
|
||||
{
|
||||
|
@ -963,6 +963,8 @@ aiAnimation *Animation::ConvertToAssimpAnimation()
|
|||
// Skeleton
|
||||
|
||||
Skeleton::Skeleton() :
|
||||
bones(),
|
||||
animations(),
|
||||
blendMode(ANIMBLEND_AVERAGE)
|
||||
{
|
||||
}
|
||||
|
@ -1103,7 +1105,7 @@ aiNode *Bone::ConvertToAssimpNode(Skeleton *skeleton, aiNode *parentNode)
|
|||
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();
|
||||
bone->mName = name;
|
||||
|
@ -1122,8 +1124,8 @@ aiBone *Bone::ConvertToAssimpBone(Skeleton *parent, const std::vector<aiVertexWe
|
|||
// VertexAnimationTrack
|
||||
|
||||
VertexAnimationTrack::VertexAnimationTrack() :
|
||||
target(0),
|
||||
type(VAT_NONE)
|
||||
type(VAT_NONE),
|
||||
target(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -47,22 +47,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
#include "OptimizeMeshes.h"
|
||||
#include "ProcessHelper.h"
|
||||
#include "SceneCombiner.h"
|
||||
|
||||
static const unsigned int NotSet = 0xffffffff;
|
||||
static const unsigned int DeadBeef = 0xdeadbeef;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Constructor to be privately used by Importer
|
||||
OptimizeMeshesProcess::OptimizeMeshesProcess()
|
||||
: pts (false)
|
||||
, max_verts (0xffffffff)
|
||||
, max_faces (0xffffffff)
|
||||
{}
|
||||
, max_verts( NotSet )
|
||||
, max_faces( NotSet ) {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Destructor, private as well
|
||||
OptimizeMeshesProcess::~OptimizeMeshesProcess()
|
||||
{}
|
||||
OptimizeMeshesProcess::~OptimizeMeshesProcess() {
|
||||
// empty
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// 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.
|
||||
if( 0 != (pFlags & aiProcess_OptimizeMeshes) ) {
|
||||
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 false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Setup properties for the postprocessing step
|
||||
// Setup properties for the post-processing step
|
||||
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_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;
|
||||
|
||||
// need to clear persistent members from previous runs
|
||||
merge_list.clear();
|
||||
output.clear();
|
||||
merge_list.resize( 0 );
|
||||
output.resize( 0 );
|
||||
|
||||
// ensure we have the right sizes
|
||||
merge_list.reserve(pScene->mNumMeshes);
|
||||
output.reserve(pScene->mNumMeshes);
|
||||
|
||||
// Prepare lookup tables
|
||||
meshes.resize(pScene->mNumMeshes);
|
||||
FindInstancedMeshes(pScene->mRootNode);
|
||||
if (max_verts == 0xdeadbeef) /* undo the magic hack */
|
||||
max_verts = 0xffffffff;
|
||||
if( max_verts == DeadBeef ) /* undo the magic hack */
|
||||
max_verts = NotSet;
|
||||
|
||||
// ... instanced meshes are immediately processed and added to the output list
|
||||
for (unsigned int i = 0, n = 0; i < pScene->mNumMeshes;++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++;
|
||||
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);
|
||||
if (!output.size()) {
|
||||
throw DeadlyImportError("OptimizeMeshes: No meshes remaining; there's definitely something wrong");
|
||||
}
|
||||
|
||||
meshes.clear();
|
||||
meshes.resize( 0 );
|
||||
ai_assert(output.size() <= num_old);
|
||||
|
||||
mScene->mNumMeshes = output.size();
|
||||
|
@ -142,8 +149,9 @@ void OptimizeMeshesProcess::Execute( aiScene* pScene)
|
|||
char tmp[512];
|
||||
::sprintf(tmp,"OptimizeMeshesProcess finished. Input meshes: %i, Output meshes: %i",num_old,pScene->mNumMeshes);
|
||||
DefaultLogger::get()->info(tmp);
|
||||
}
|
||||
else DefaultLogger::get()->debug("OptimizeMeshesProcess finished");
|
||||
} else {
|
||||
DefaultLogger::get()->debug( "OptimizeMeshesProcess finished" );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -157,7 +165,7 @@ void OptimizeMeshesProcess::ProcessNode( aiNode* pNode)
|
|||
im = meshes[im].output_id;
|
||||
}
|
||||
else {
|
||||
merge_list.clear();
|
||||
merge_list.resize( 0 );
|
||||
unsigned int verts = 0, faces = 0;
|
||||
|
||||
// Find meshes to merge with us
|
||||
|
@ -170,8 +178,9 @@ void OptimizeMeshesProcess::ProcessNode( aiNode* pNode)
|
|||
faces += mScene->mMeshes[am]->mNumFaces;
|
||||
|
||||
--pNode->mNumMeshes;
|
||||
for (unsigned int n = a; n < pNode->mNumMeshes; ++n)
|
||||
pNode->mMeshes[n] = pNode->mMeshes[n+1];
|
||||
for( unsigned int n = a; n < pNode->mNumMeshes; ++n ) {
|
||||
pNode->mMeshes[ n ] = pNode->mMeshes[ n + 1 ];
|
||||
}
|
||||
|
||||
--a;
|
||||
}
|
||||
|
@ -184,8 +193,7 @@ void OptimizeMeshesProcess::ProcessNode( aiNode* pNode)
|
|||
aiMesh* out;
|
||||
SceneCombiner::MergeMeshes(&out,0,merge_list.begin(),merge_list.end());
|
||||
output.push_back(out);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
output.push_back(mScene->mMeshes[im]);
|
||||
}
|
||||
im = output.size()-1;
|
||||
|
@ -193,8 +201,9 @@ void OptimizeMeshesProcess::ProcessNode( aiNode* pNode)
|
|||
}
|
||||
|
||||
|
||||
for (unsigned int i = 0; i < pNode->mNumChildren; ++i)
|
||||
ProcessNode(pNode->mChildren[i]);
|
||||
for( unsigned int i = 0; i < pNode->mNumChildren; ++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];
|
||||
|
||||
if ((0xffffffff != max_verts && verts+mb->mNumVertices > max_verts) ||
|
||||
(0xffffffff != max_faces && faces+mb->mNumFaces > max_faces)) {
|
||||
if ((NotSet != max_verts && verts+mb->mNumVertices > max_verts) ||
|
||||
(NotSet != max_faces && faces+mb->mNumFaces > max_faces)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -221,7 +230,7 @@ bool OptimizeMeshesProcess::CanJoin ( unsigned int a, unsigned int b, unsigned i
|
|||
return false;
|
||||
|
||||
// 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()) {
|
||||
// TODO
|
||||
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)
|
||||
{
|
||||
for (unsigned int i = 0; i < pNode->mNumMeshes;++i)
|
||||
++meshes[pNode->mMeshes[i]].instance_cnt;
|
||||
for( unsigned int i = 0; i < pNode->mNumMeshes; ++i ) {
|
||||
++meshes[ pNode->mMeshes[ i ] ].instance_cnt;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < pNode->mNumChildren; ++i)
|
||||
FindInstancedMeshes(pNode->mChildren[i]);
|
||||
for( unsigned int i = 0; i < pNode->mNumChildren; ++i ) {
|
||||
FindInstancedMeshes( pNode->mChildren[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
#endif // !! ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS
|
||||
|
|
|
@ -46,16 +46,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#define AI_PARSING_UTILS_H_INC
|
||||
|
||||
#include "StringComparison.h"
|
||||
|
||||
namespace Assimp {
|
||||
|
||||
// NOTE: the functions below are mostly intended as replacement for
|
||||
// std::upper, std::lower, std::isupper, std::islower, std::isspace.
|
||||
// we don't bother of locales. We don't want them. We want reliable
|
||||
// (i.e. identical) results across all locales.
|
||||
// NOTE: the functions below are mostly intended as replacement for
|
||||
// std::upper, std::lower, std::isupper, std::islower, std::isspace.
|
||||
// we don't bother of locales. We don't want them. We want reliable
|
||||
// (i.e. identical) results across all locales.
|
||||
|
||||
// The functions below accept any character type, but know only
|
||||
// about ASCII. However, UTF-32 is the only safe ASCII superset to
|
||||
// use since it doesn't have multibyte sequences.
|
||||
// The functions below accept any character type, but know only
|
||||
// about ASCII. However, UTF-32 is the only safe ASCII superset to
|
||||
// use since it doesn't have multi-byte sequences.
|
||||
|
||||
static const unsigned int BufferSize = 4096;
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
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;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
template <class char_t>
|
||||
AI_FORCE_INLINE char_t ToUpper( char_t in)
|
||||
{
|
||||
return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in-0x20) : in;
|
||||
AI_FORCE_INLINE char_t ToUpper( char_t in) {
|
||||
return (in >= (char_t)'a' && in <= (char_t)'z') ? (char_t)(in-0x20) : in;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
template <class char_t>
|
||||
AI_FORCE_INLINE bool IsUpper( char_t in)
|
||||
{
|
||||
return (in >= (char_t)'A' && in <= (char_t)'Z');
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
template <class char_t>
|
||||
AI_FORCE_INLINE bool IsLower( char_t in)
|
||||
{
|
||||
return (in >= (char_t)'a' && in <= (char_t)'z');
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
template <class char_t>
|
||||
AI_FORCE_INLINE bool IsSpace( char_t in)
|
||||
{
|
||||
return (in == (char_t)' ' || in == (char_t)'\t');
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
template <class char_t>
|
||||
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>
|
||||
AI_FORCE_INLINE bool IsSpaceOrNewLine( char_t in)
|
||||
{
|
||||
return IsSpace<char_t>(in) || IsLineEnd<char_t>(in);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
template <class char_t>
|
||||
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;
|
||||
return !IsLineEnd<char_t>(*in);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
template <class char_t>
|
||||
AI_FORCE_INLINE bool SkipSpaces( const char_t** inout)
|
||||
{
|
||||
return SkipSpaces<char_t>(*inout,inout);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
template <class char_t>
|
||||
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
|
||||
while (*in == (char_t)'\r' || *in == (char_t)'\n')in++;
|
||||
while( *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
|
||||
++in;
|
||||
}
|
||||
*out = in;
|
||||
return *in != (char_t)'\0';
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
template <class char_t>
|
||||
AI_FORCE_INLINE bool SkipLine( const char_t** inout)
|
||||
{
|
||||
return SkipLine<char_t>(*inout,inout);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
template <class char_t>
|
||||
AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out)
|
||||
{
|
||||
while (*in == (char_t)' ' || *in == (char_t)'\t' ||
|
||||
*in == (char_t)'\r' || *in == (char_t)'\n')in++;
|
||||
while( *in == ( char_t )' ' || *in == ( char_t )'\t' || *in == ( char_t )'\r' || *in == ( char_t )'\n' ) {
|
||||
++in;
|
||||
}
|
||||
*out = in;
|
||||
return *in != '\0';
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
template <class char_t>
|
||||
AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t** inout)
|
||||
{
|
||||
return SkipSpacesAndLineEnd<char_t>(*inout,inout);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
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* const end = _out+4096;
|
||||
while (!IsLineEnd( *buffer ) && _out < end)
|
||||
*_out++ = *buffer++;
|
||||
char* const end = _out + BufferSize;
|
||||
while( !IsLineEnd( *buffer ) && _out < end ) {
|
||||
*_out++ = *buffer++;
|
||||
}
|
||||
*_out = (char_t)'\0';
|
||||
|
||||
while (IsLineEnd( *buffer ) && '\0' != *buffer)++buffer;
|
||||
return true;
|
||||
while( IsLineEnd( *buffer ) && '\0' != *buffer ) {
|
||||
++buffer;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
template <class char_t>
|
||||
AI_FORCE_INLINE bool IsNumeric( char_t in)
|
||||
{
|
||||
return ( in >= '0' && in <= '9' ) || '-' == in || '+' == in;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
template <class char_t>
|
||||
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;
|
||||
return true;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len]))
|
||||
{
|
||||
if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len])) {
|
||||
in += len+1;
|
||||
return true;
|
||||
}
|
||||
|
@ -206,5 +235,9 @@ AI_FORCE_INLINE std::string GetNextToken(const char*& in)
|
|||
while (!IsSpaceOrNewLine(*in))++in;
|
||||
return std::string(cur,(size_t)(in-cur));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
} // ! namespace Assimp
|
||||
|
||||
#endif // ! AI_PARSING_UTILS_H_INC
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
#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)
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
PlyExporter :: PlyExporter(const char* _filename, const aiScene* pScene)
|
||||
PlyExporter::PlyExporter(const char* _filename, const aiScene* pScene, bool binary)
|
||||
: filename(_filename)
|
||||
, pScene(pScene)
|
||||
, endl("\n")
|
||||
|
@ -102,7 +116,16 @@ PlyExporter :: PlyExporter(const char* _filename, const aiScene* pScene)
|
|||
}
|
||||
|
||||
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"
|
||||
<< aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.'
|
||||
<< aiGetVersionRevision() << ")" << endl;
|
||||
|
@ -163,17 +186,29 @@ PlyExporter :: PlyExporter(const char* _filename, const aiScene* pScene)
|
|||
mOutput << "end_header" << endl;
|
||||
|
||||
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) {
|
||||
WriteMeshIndices(pScene->mMeshes[i],ofs);
|
||||
if (binary) {
|
||||
WriteMeshIndicesBinary(pScene->mMeshes[i], ofs);
|
||||
}
|
||||
else {
|
||||
WriteMeshIndices(pScene->mMeshes[i], ofs);
|
||||
}
|
||||
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) {
|
||||
mOutput <<
|
||||
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) {
|
||||
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
|
||||
|
|
|
@ -59,7 +59,7 @@ class PlyExporter
|
|||
{
|
||||
public:
|
||||
/// 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:
|
||||
|
||||
|
@ -71,6 +71,9 @@ private:
|
|||
void WriteMeshVerts(const aiMesh* m, unsigned int components);
|
||||
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:
|
||||
|
||||
const std::string filename;
|
||||
|
|
|
@ -182,7 +182,7 @@ PLY::ESemantic PLY::Property::ParseSemantic(const char* pCur,const char** pCurOu
|
|||
{
|
||||
eOut = PLY::EST_Opacity;
|
||||
}
|
||||
else if (TokenMatch(pCur,"specular_power",6))
|
||||
else if (TokenMatch(pCur,"specular_power",14))
|
||||
{
|
||||
eOut = PLY::EST_PhongPower;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
||||
b = sqrt(bb);
|
||||
c = sqrt(cc);
|
||||
theta = acos((bb + cc - aa) / (2 * b * c));
|
||||
b = std::sqrt(bb);
|
||||
c = std::sqrt(cc);
|
||||
theta = std::acos((bb + cc - aa) / (2 * b * c));
|
||||
|
||||
if (OnLeftSideOfLine2D(in[i],in[i+2],in[i+1])) {
|
||||
// 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)) +
|
||||
((-in[1].y + in[0].y) * (-in[1].y + in[0].y));
|
||||
|
||||
b = sqrt(bb);
|
||||
c = sqrt(cc);
|
||||
theta = acos((bb + cc - aa) / (2 * b * c));
|
||||
b = std::sqrt(bb);
|
||||
c = std::sqrt(cc);
|
||||
theta = std::acos((bb + cc - aa) / (2 * b * c));
|
||||
|
||||
//if (convex(in[npoints-2].x, in[npoints-2].y,
|
||||
// in[0].x, in[0].y,
|
||||
|
|
|
@ -73,11 +73,13 @@ static const aiImporterDesc desc = {
|
|||
|
||||
namespace Assimp {
|
||||
|
||||
/*
|
||||
static void getSupportedExtensions(std::vector<std::string> &supportedExtensions) {
|
||||
supportedExtensions.push_back( ".jpg" );
|
||||
supportedExtensions.push_back( ".png" );
|
||||
supportedExtensions.push_back( ".tga" );
|
||||
}
|
||||
*/
|
||||
|
||||
using namespace Q3BSP;
|
||||
|
||||
|
@ -628,7 +630,7 @@ aiFace *Q3BSPFileImporter::getNextFace( aiMesh *pMesh, unsigned int &rFaceIdx )
|
|||
bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *pModel,
|
||||
Q3BSP::Q3BSPZipArchive *pArchive, aiScene*,
|
||||
aiMaterial *pMatHelper, int textureId ) {
|
||||
if ( NULL == pArchive || NULL == pArchive || NULL == pMatHelper ) {
|
||||
if ( NULL == pArchive || NULL == pMatHelper ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -639,17 +641,17 @@ bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *pMode
|
|||
bool res = true;
|
||||
sQ3BSPTexture *pTexture = pModel->m_Textures[ textureId ];
|
||||
if ( !pTexture ) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> supportedExtensions;
|
||||
supportedExtensions.push_back( ".jpg" );
|
||||
supportedExtensions.push_back( ".png" );
|
||||
supportedExtensions.push_back( ".tga" );
|
||||
std::vector<std::string> supportedExtensions;
|
||||
supportedExtensions.push_back( ".jpg" );
|
||||
supportedExtensions.push_back( ".png" );
|
||||
supportedExtensions.push_back( ".tga" );
|
||||
std::string textureName, ext;
|
||||
if ( expandFile( pArchive, pTexture->strName, supportedExtensions, textureName, ext ) ) {
|
||||
IOStream *pTextureStream = pArchive->Open( textureName.c_str() );
|
||||
if ( !pTextureStream ) {
|
||||
if ( pTextureStream ) {
|
||||
size_t texSize = pTextureStream->FileSize();
|
||||
aiTexture *pTexture = new aiTexture;
|
||||
pTexture->mHeight = 0;
|
||||
|
|
|
@ -68,25 +68,25 @@ voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) {
|
|||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
aiOrigin assimp_origin;
|
||||
|
@ -115,7 +115,7 @@ int IOSystem2Unzip::close(voidpf opaque, voidpf stream) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int IOSystem2Unzip::testerror(voidpf opaque, voidpf stream) {
|
||||
int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -348,8 +348,8 @@ bool STLImporter::LoadBinaryFile()
|
|||
bool bIsMaterialise = false;
|
||||
|
||||
// search for an occurence of "COLOR=" in the header
|
||||
const char* sz2 = (const char*)mBuffer;
|
||||
const char* const szEnd = sz2+80;
|
||||
const unsigned char* sz2 = (const unsigned char*)mBuffer;
|
||||
const unsigned char* const szEnd = sz2+80;
|
||||
while (sz2 < szEnd) {
|
||||
|
||||
if ('C' == *sz2++ && 'O' == *sz2++ && 'L' == *sz2++ &&
|
||||
|
|
|
@ -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
|
||||
|
@ -1194,10 +1197,53 @@ void SceneCombiner::Copy (aiNode** _dest, const aiNode* src)
|
|||
// get a flat copy
|
||||
::memcpy(dest,src,sizeof(aiNode));
|
||||
|
||||
if (src->mMetaData) {
|
||||
Copy(&dest->mMetaData, src->mMetaData);
|
||||
}
|
||||
|
||||
// and reallocate all arrays
|
||||
GetArrayCopy( dest->mMeshes, dest->mNumMeshes );
|
||||
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
Loading…
Reference in New Issue