Merge remote-tracking branch 'upstream/master'

pull/1154/head
Denis Biryukov 2017-01-27 10:57:32 +03:00
commit d73a64b061
1211 changed files with 365066 additions and 226371 deletions

2
.coveralls.yml 100644
View File

@ -0,0 +1,2 @@
service_name: travis-pro
repo_token: GZXuNlublKFy7HAewHAZLk5ZwgipTFAOA

22
.editorconfig 100644
View File

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

8
.gitattributes vendored 100644
View File

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

51
.gitignore vendored
View File

@ -1,3 +1,4 @@
.idea
build build
.project .project
*.kdev4* *.kdev4*
@ -10,13 +11,14 @@ build
# Output # Output
bin/ bin/
lib/ lib/
contrib/
# Generated # Generated
assimp.pc assimp.pc
revision.h revision.h
contrib/zlib/zconf.h contrib/zlib/zconf.h
contrib/zlib/zlib.pc contrib/zlib/zlib.pc
include/assimp/config.h
# CMake # CMake
CMakeCache.txt CMakeCache.txt
@ -27,8 +29,55 @@ cmake_uninstall.cmake
assimp-config.cmake assimp-config.cmake
assimp-config-version.cmake assimp-config-version.cmake
# MakeFile
Makefile
code/Makefile
test/Makefile
test/headercheck/Makefile
tools/assimp_cmd/Makefile
# Tests # Tests
test/results test/results
# Python # Python
__pycache__ __pycache__
*.log
*.vcxproj
*.filters
*.tlog
Assimp.sdf
test/gtest/tmp/gtest-gitupdate.cmake
test/gtest/tmp/gtest-gitclone.cmake
test/gtest/tmp/gtest-cfgcmd.txt.in
test/gtest/tmp/gtest-cfgcmd.txt
test/gtest/src/gtest-stamp/gtest-download.cmake
test/gtest/src/gtest-stamp/gtest-configure.cmake
test/gtest/src/gtest-stamp/gtest-build.cmake
test/gtest/src/gtest-stamp/Debug/gtest-patch
*.cache
test/gtest/src/gtest-stamp/Debug/gtest-build
*.suo
*.lib
test/gtest/src/gtest-stamp/Debug/
tools/assimp_view/assimp_viewer.vcxproj.user
# Unix editor backups
*~
test/gtest/src/gtest-stamp/gtest-gitinfo.txt
test/gtest/src/gtest-stamp/gtest-gitclone-lastrun.txt
Assimp.opensdf
contrib/zlib/CTestTestfile.cmake
ipch/assimp_viewer-44bbbcd1/assimp_viewerd-ccc45335.ipch
bin64/assimp-vc140-mt.dll
bin64/assimp-vc140-mtd.dll
lib64/assimp-vc140-mt.exp
lib64/assimp-vc140-mtd.exp
lib64/assimp-vc140-mtd.ilk
lib64/assimp-vc140-mtd.pdb
bin64/assimp-vc120-mt.dll
bin64/assimp-vc120-mtd.dll
lib64/assimp-vc120-mtd.pdb
lib64/assimp-vc120-mtd.ilk
lib64/assimp-vc120-mtd.exp
lib64/assimp-vc120-mt.exp
xcuserdata

16
.travis.sh 100755
View File

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

View File

@ -1,11 +1,32 @@
before_install: before_install:
- sudo apt-get update -qq
- sudo apt-get install cmake
- sudo apt-get install cmake python3 - sudo apt-get install cmake python3
- if [ $LINUX ]; then sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; fi
- echo -e "#ifndef A_R_H_INC\n#define A_R_H_INC\n#define GitVersion ${TRAVIS_JOB_ID}\n#define GitBranch \"${TRAVIS_BRANCH}\"\n#endif // A_R_H_INC" > revision.h
# install latest LCOV (1.9 was failing)
- cd ${TRAVIS_BUILD_DIR}
- wget http://ftp.de.debian.org/debian/pool/main/l/lcov/lcov_1.11.orig.tar.gz
- tar xf lcov_1.11.orig.tar.gz
- sudo make -C lcov-1.11/ install
- gem install coveralls-lcov
- lcov --version
- g++ --version
branches:
only:
- master
env: env:
- TRAVIS_NO_EXPORT=YES global:
- TRAVIS_NO_EXPORT=NO - secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc="
- TRAVIS_STATIC_BUILD=ON - PV=r8e PLATF=linux-x86_64 NDK_HOME=${TRAVIS_BUILD_DIR}/android-ndk-${PV} PATH=${PATH}:${NDK_HOME}
- TRAVIS_STATIC_BUILD=OFF matrix:
- LINUX=1 TRAVIS_NO_EXPORT=YES ENABLE_COVERALLS=ON
- LINUX=1 TRAVIS_NO_EXPORT=NO ENABLE_COVERALLS=OFF
- LINUX=1 SHARED_BUILD=ON ENABLE_COVERALLS=OFF
- LINUX=1 SHARED_BUILD=OFF ENABLE_COVERALLS=OFF
- ANDROID=1
language: cpp language: cpp
@ -13,17 +34,31 @@ compiler:
- gcc - gcc
- clang - clang
script: install:
- cmake -G "Unix Makefiles" -DASSIMP_ENABLE_BOOST_WORKAROUND=YES -DASSIMP_NO_EXPORT=$TRAVIS_NO_EXPORT -STATIC_BUILD=$TRAVIS_STATIC_BUILD - if [ $ANDROID ]; then wget -c http://dl.google.com/android/ndk/android-ndk-${PV}-${PLATF}.tar.bz2 && tar xf android-ndk-${PV}-${PLATF}.tar.bz2 ; fi
- 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
before_script:
- cd ${TRAVIS_BUILD_DIR}
# init coverage to 0 (optional)
- lcov --directory . --zerocounters
script:
- export COVERALLS_SERVICE_NAME=travis-ci
- export COVERALLS_REPO_TOKEN=abc12345
- . ./.travis.sh
after_success:
- cd ${TRAVIS_BUILD_DIR}
- lcov --directory . --capture --output-file coverage.info
- lcov --remove coverage.info '/usr/*' 'contrib/*' 'test/*' --output-file coverage.info
- lcov --list coverage.info
- coveralls-lcov --source-encoding=ISO-8859-1 --repo-token=${COVERALLS_TOKEN} coverage.info
addons:
coverity_scan:
project:
name: "assimp/assimp"
notification_email: kim.kulling@googlemail.com
build_command_prepend: "cmake"
build_command: "make"
branch_pattern: coverity_scan

34
CHANGES
View File

@ -2,6 +2,40 @@
CHANGELOG CHANGELOG
---------------------------------------------------------------------- ----------------------------------------------------------------------
3.2.1 (2016-10-01)
FEATURES:
- Updated glTF exporter to meet 1.0 specification.
FIXES/HOUSEKEEPING:
- Fixed glTF Validator errors for exported glTF format.
ISSUES:
- Hard coded sampler setting for
- magFilter
- minFilter
- void* in ExportData for accessor max and min.
3.2.0 (2015-11-03)
FEATURES:
- OpenDDL-Parser is part of contrib-source.
- Experimental OpenGEX-support
- CI-check for linux and windows
- Coverity check added
- New regression testsuite.
FIXES/HOUSEKEEPING:
- Hundreds of bugfixes in all parts of the library
- Unified line endings
API COMPATIBILITY:
- Removed precompiled header to increase build speed for linux
3.1.1 (2014-06-15) 3.1.1 (2014-06-15)
FEATURES: FEATURES:

View File

@ -1,57 +1,188 @@
cmake_minimum_required( VERSION 2.6 ) # Open Asset Import Library (assimp)
# ----------------------------------------------------------------------
#
# Copyright (c) 2006-2016, 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.
#
#----------------------------------------------------------------------
SET(CMAKE_LEGACY_CYGWIN_WIN32 0) # Remove when CMake >= 2.8.4 is required
cmake_minimum_required( VERSION 2.8 )
PROJECT( Assimp ) PROJECT( Assimp )
# Define here the needed parameters # All supported options ###############################################
set (ASSIMP_VERSION_MAJOR 3) OPTION( BUILD_SHARED_LIBS
set (ASSIMP_VERSION_MINOR 1) "Build package with shared libraries."
set (ASSIMP_VERSION_PATCH 1) # subversion revision? ON
set (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}) )
set (ASSIMP_SOVERSION 3) OPTION( ASSIMP_DOUBLE_PRECISION
set (PROJECT_VERSION "${ASSIMP_VERSION}") "Set to ON to enable double precision processing"
OFF
)
OPTION( ASSIMP_OPT_BUILD_PACKAGES
"Set to ON to generate CPack configuration files and packaging targets"
OFF
)
OPTION( ASSIMP_ANDROID_JNIIOSYSTEM
"Android JNI IOSystem support is active"
OFF
)
OPTION( ASSIMP_NO_EXPORT
"Disable Assimp's export functionality."
OFF
)
OPTION( ASSIMP_BUILD_ZLIB
"Build your own zlib"
OFF
)
option( ASSIMP_BUILD_ASSIMP_TOOLS
"If the supplementary tools for Assimp are built in addition to the library."
ON
)
option ( ASSIMP_BUILD_SAMPLES
"If the official samples are built as well (needs Glut)."
OFF
)
OPTION ( ASSIMP_BUILD_TESTS
"If the test suite for Assimp is built in addition to the library."
ON
)
OPTION ( ASSIMP_COVERALLS
"Eańable this to measure test coverage."
OFF
)
set(ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources") IF(MSVC)
set (CMAKE_PREFIX_PATH "D:\\libs\\devil")
OPTION( ASSIMP_INSTALL_PDB
"Install MSVC debug files."
ON
)
ENDIF(MSVC)
IF(NOT BUILD_SHARED_LIBS)
SET(LINK_SEARCH_START_STATIC TRUE)
ENDIF(NOT BUILD_SHARED_LIBS)
# Define here the needed parameters
SET (ASSIMP_VERSION_MAJOR 3)
SET (ASSIMP_VERSION_MINOR 3)
SET (ASSIMP_VERSION_PATCH 1) # subversion revision?
SET (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH})
SET (ASSIMP_SOVERSION 3)
SET (PROJECT_VERSION "${ASSIMP_VERSION}")
SET(ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources")
# Needed for openddl_parser config, no use of c++11 at this moment
add_definitions( -DOPENDDL_NO_USE_CPP11 )
set_property( GLOBAL PROPERTY CXX_STANDARD 11 )
# Get the current working branch # Get the current working branch
execute_process( EXECUTE_PROCESS(
COMMAND git rev-parse --abbrev-ref HEAD COMMAND git rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_BRANCH OUTPUT_VARIABLE GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
) )
# Get the latest abbreviated commit hash of the working branch # Get the latest abbreviated commit hash of the working branch
execute_process( EXECUTE_PROCESS(
COMMAND git log -1 --format=%h COMMAND git log -1 --format=%h
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_HASH OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
) )
if(NOT GIT_COMMIT_HASH) IF(NOT GIT_COMMIT_HASH)
set(GIT_COMMIT_HASH 0) SET(GIT_COMMIT_HASH 0)
endif(NOT GIT_COMMIT_HASH) ENDIF(NOT GIT_COMMIT_HASH)
IF(ASSIMP_DOUBLE_PRECISION)
ADD_DEFINITIONS(-DASSIMP_DOUBLE_PRECISION)
ENDIF(ASSIMP_DOUBLE_PRECISION)
configure_file( configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/revision.h.in ${CMAKE_CURRENT_LIST_DIR}/revision.h.in
${CMAKE_CURRENT_BINARY_DIR}/revision.h ${CMAKE_CURRENT_BINARY_DIR}/revision.h
) )
include_directories(${CMAKE_CURRENT_BINARY_DIR}) configure_file(
${CMAKE_CURRENT_LIST_DIR}/include/assimp/config.h.in
${CMAKE_CURRENT_LIST_DIR}/include/assimp/config.h
)
option(ASSIMP_OPT_BUILD_PACKAGES "Set to ON to generate CPack configuration files and packaging targets" OFF) include_directories(
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" ) ./
set(LIBASSIMP_COMPONENT "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}" ) ${CMAKE_CURRENT_BINARY_DIR}
set(LIBASSIMP-DEV_COMPONENT "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}-dev" ) ${CMAKE_CURRENT_BINARY_DIR}/include
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")
if((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT CMAKE_COMPILER_IS_MINGW) SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" )
add_definitions(-fPIC) # this is a very important switch and some libraries seem now to have it.... SET(LIBASSIMP_COMPONENT "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}" )
SET(LIBASSIMP-DEV_COMPONENT "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}-dev" )
SET(CPACK_COMPONENTS_ALL assimp-bin ${LIBASSIMP_COMPONENT} ${LIBASSIMP-DEV_COMPONENT} assimp-dev)
SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names")
# Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit linux
IF( UNIX )
IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux
ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 )
ENDIF()
ENDIF()
IF((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT CMAKE_COMPILER_IS_MINGW)
IF (BUILD_SHARED_LIBS AND CMAKE_SIZEOF_VOID_P EQUAL 8) # -fPIC is only required for shared libs on 64 bit
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
ENDIF()
# hide all not-exported symbols # hide all not-exported symbols
add_definitions( -fvisibility=hidden -Wall ) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -Wall -std=c++0x" )
elseif(MSVC) ELSEIF(MSVC)
# enable multi-core compilation with MSVC # enable multi-core compilation with MSVC
add_definitions(/MP) add_compile_options(/MP)
ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -Wall -Wno-long-long -pedantic -std=c++11" )
ELSEIF( CMAKE_COMPILER_IS_MINGW )
SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall -Wno-long-long -pedantic -std=c++11" )
add_definitions( -U__STRICT_ANSI__ )
ENDIF()
if (ASSIMP_COVERALLS)
include(Coveralls)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
endif() endif()
INCLUDE (FindPkgConfig) INCLUDE (FindPkgConfig)
@ -70,27 +201,18 @@ IF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
ENDIF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR ) ENDIF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
# Cache these to allow the user to override them manually. # Cache these to allow the user to override them manually.
SET( ASSIMP_LIB_INSTALL_DIR "lib" CACHE PATH SET( ASSIMP_LIB_INSTALL_DIR "lib" CACHE STRING
"Path the built library files are installed to." ) "Path the built library files are installed to." )
SET( ASSIMP_INCLUDE_INSTALL_DIR "include" CACHE PATH SET( ASSIMP_INCLUDE_INSTALL_DIR "include" CACHE STRING
"Path the header files are installed to." ) "Path the header files are installed to." )
SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE PATH SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE STRING
"Path the tool executables are installed to." ) "Path the tool executables are installed to." )
option (ASSIMP_BUILD_STATIC_LIB "Build a static (.a) version of the library" OFF)
SET(ASSIMP_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfitx for lib, samples and tools") IF (CMAKE_BUILD_TYPE STREQUAL "Debug")
SET(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfix for lib, samples and tools")
# Allow the user to build a static library ELSE()
option ( BUILD_SHARED_LIBS "Build a shared version of the library" ON ) SET(CMAKE_DEBUG_POSTFIX "" CACHE STRING "Debug Postfix for lib, samples and tools")
IF ( ASSIMP_BUILD_STATIC_LIB ) ENDIF()
option ( BUILD_SHARED_LIBS "Build a shared version of the library" OFF )
ELSE ( ASSIMP_BUILD_STATIC_LIB )
option ( BUILD_SHARED_LIBS "Build a shared version of the library" ON )
ENDIF ( ASSIMP_BUILD_STATIC_LIB )
# Generate a pkg-config .pc for the Assimp library.
CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/assimp.pc.in" "${PROJECT_BINARY_DIR}/assimp.pc" @ONLY )
INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTALL_DIR}/pkgconfig/ COMPONENT ${LIBASSIMP-DEV_COMPONENT})
# Only generate this target if no higher-level project already has # Only generate this target if no higher-level project already has
IF (NOT TARGET uninstall) IF (NOT TARGET uninstall)
@ -99,74 +221,49 @@ IF (NOT TARGET uninstall)
add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
ENDIF() ENDIF()
# Globally enable Boost resp. the Boost workaround – it is also needed by the
# tools which include the Assimp headers.
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." )
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" "1.55" )
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 )
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIRS} )
ENDIF ( ASSIMP_ENABLE_BOOST_WORKAROUND )
# cmake configuration files # cmake configuration files
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT}) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT})
option ( ASSIMP_NO_EXPORT FIND_PACKAGE( DirectX )
"Disable Assimp's export functionality."
OFF IF( CMAKE_COMPILER_IS_GNUCXX )
) SET(LIBSTDC++_LIBRARIES -lstdc++)
ENDIF( CMAKE_COMPILER_IS_GNUCXX )
# Search for external dependencies, and build them from source if not found # Search for external dependencies, and build them from source if not found
# Search for zlib # Search for zlib
find_package(ZLIB) IF ( NOT ASSIMP_BUILD_ZLIB )
if( NOT ZLIB_FOUND ) find_package(ZLIB)
ENDIF( NOT ASSIMP_BUILD_ZLIB )
IF( NOT ZLIB_FOUND )
message(STATUS "compiling zlib from souces") message(STATUS "compiling zlib from souces")
include(CheckIncludeFile) include(CheckIncludeFile)
include(CheckTypeSize) include(CheckTypeSize)
include(CheckFunctionExists) include(CheckFunctionExists)
# compile from sources # compile from sources
add_subdirectory(contrib/zlib) add_subdirectory(contrib/zlib)
set(ZLIB_FOUND 1) SET(ZLIB_FOUND 1)
set(ZLIB_LIBRARIES zlibstatic) SET(ZLIB_LIBRARIES zlibstatic)
set(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib) SET(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib)
else(NOT ZLIB_FOUND) else(NOT ZLIB_FOUND)
ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB) ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB)
endif(NOT ZLIB_FOUND) SET(ZLIB_LIBRARIES_LINKED -lz)
ENDIF(NOT ZLIB_FOUND)
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
# Search for unzip # Search for unzip
if (PKG_CONFIG_FOUND) IF (PKG_CONFIG_FOUND)
PKG_CHECK_MODULES(UNZIP minizip) PKG_CHECK_MODULES(UNZIP minizip)
endif (PKG_CONFIG_FOUND) ENDIF (PKG_CONFIG_FOUND)
IF ( ASSIMP_NO_EXPORT ) IF ( ASSIMP_NO_EXPORT )
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_EXPORT) ADD_DEFINITIONS( -DASSIMP_BUILD_NO_EXPORT)
MESSAGE( STATUS "Build an import-only version of Assimp." ) MESSAGE( STATUS "Build an import-only version of Assimp." )
ENDIF( ASSIMP_NO_EXPORT ) ENDIF( ASSIMP_NO_EXPORT )
# if(CMAKE_CL_64)
# set(ASSIMP_BUILD_ARCHITECTURE "amd64")
# else(CMAKE_CL_64)
# set(ASSIMP_BUILD_ARCHITECTURE "x86")
# endif(CMAKE_CL_64)
SET ( ASSIMP_BUILD_ARCHITECTURE "" CACHE STRING SET ( ASSIMP_BUILD_ARCHITECTURE "" CACHE STRING
"describe the current architecture." "describe the current architecture."
) )
@ -186,22 +283,88 @@ ENDIF ( ASSIMP_BUILD_COMPILER STREQUAL "")
MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER ) MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER )
ADD_SUBDIRECTORY( code/ ) SET ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER OFF CACHE BOOL
option ( ASSIMP_BUILD_ASSIMP_TOOLS "Build the C4D importer, which relies on the non-free Melange SDK."
"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/ )
ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
option ( ASSIMP_BUILD_SAMPLES IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
"If the official samples are built as well (needs Glut)." IF ( MSVC )
OFF SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/includes")
)
# pick the correct prebuilt library
IF(MSVC14)
SET(C4D_LIB_POSTFIX "_2015")
ELSEIF(MSVC12)
SET(C4D_LIB_POSTFIX "_2013")
ELSEIF(MSVC11)
SET(C4D_LIB_POSTFIX "_2012")
ELSEIF(MSVC10)
SET(C4D_LIB_POSTFIX "_2010")
ELSE()
MESSAGE( FATAL_ERROR
"C4D is currently only supported with MSVC 10, 11, 12, 14"
)
ENDIF()
SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/libraries/win")
SET(C4D_DEBUG_LIBRARIES
"${C4D_LIB_BASE_PATH}/melangelib${C4D_LIB_POSTFIX}/melangelib_debug.lib"
"${C4D_LIB_BASE_PATH}/jpeglib${C4D_LIB_POSTFIX}/jpeglib_debug.lib"
)
SET(C4D_RELEASE_LIBRARIES
"${C4D_LIB_BASE_PATH}/melangelib${C4D_LIB_POSTFIX}/melangelib_release.lib"
"${C4D_LIB_BASE_PATH}/jpeglib${C4D_LIB_POSTFIX}/jpeglib_release.lib"
)
# winsock and winmm are necessary dependencies of melange (this is undocumented, but true.)
SET(C4D_EXTRA_LIBRARIES WSock32.lib Winmm.lib)
ELSE ()
MESSAGE( FATAL_ERROR
"C4D is currently only available on Windows with melange SDK installed in contrib/Melange"
)
ENDIF ( MSVC )
ELSE (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER )
ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
ADD_SUBDIRECTORY( code/ )
IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
IF ( WIN32 AND DirectX_D3DX9_LIBRARY )
option ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} )
IF ( ASSIMP_BUILD_ASSIMP_VIEW )
ADD_SUBDIRECTORY( tools/assimp_view/ )
ENDIF ( ASSIMP_BUILD_ASSIMP_VIEW )
ENDIF ( WIN32 AND DirectX_D3DX9_LIBRARY )
ADD_SUBDIRECTORY( tools/assimp_cmd/ )
# Check dependencies for assimp_qt_viewer.
# Why here? Maybe user do not want Qt viewer and have no Qt.
# Why assimp_qt_viewer/CMakeLists.txt still contain similar check?
# Because viewer can be build independently of Assimp.
FIND_PACKAGE(Qt5Widgets QUIET)
FIND_PACKAGE(DevIL QUIET)
FIND_PACKAGE(OpenGL QUIET)
IF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND)
ADD_SUBDIRECTORY( tools/assimp_qt_viewer/ )
ELSE()
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "")
IF (NOT Qt5_FOUND)
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} Qt5")
ENDIF (NOT Qt5_FOUND)
IF (NOT IL_FOUND)
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} DevIL")
ENDIF (NOT IL_FOUND)
IF (NOT OPENGL_FOUND)
SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} OpengGL")
ENDIF (NOT OPENGL_FOUND)
MESSAGE (WARNING "Build of assimp_qt_viewer is disabled. Unsatisfied dendencies: ${ASSIMP_QT_VIEWER_DEPENDENCIES}")
ENDIF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND)
ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
IF ( ASSIMP_BUILD_SAMPLES) IF ( ASSIMP_BUILD_SAMPLES)
IF ( WIN32 ) IF ( WIN32 )
@ -210,68 +373,87 @@ IF ( ASSIMP_BUILD_SAMPLES)
ADD_SUBDIRECTORY( samples/SimpleOpenGL/ ) ADD_SUBDIRECTORY( samples/SimpleOpenGL/ )
ENDIF ( ASSIMP_BUILD_SAMPLES ) ENDIF ( ASSIMP_BUILD_SAMPLES )
option ( ASSIMP_BUILD_TESTS
"If the test suite for Assimp is built in addition to the library."
ON
)
IF ( ASSIMP_BUILD_TESTS ) IF ( ASSIMP_BUILD_TESTS )
ADD_SUBDIRECTORY( test/ ) ADD_SUBDIRECTORY( test/ )
ENDIF ( ASSIMP_BUILD_TESTS ) ENDIF ( ASSIMP_BUILD_TESTS )
IF(MSVC) # Generate a pkg-config .pc for the Assimp library.
option ( ASSIMP_INSTALL_PDB CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/assimp.pc.in" "${PROJECT_BINARY_DIR}/assimp.pc" @ONLY )
"Install MSVC debug files." INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTALL_DIR}/pkgconfig/ COMPONENT ${LIBASSIMP-DEV_COMPONENT})
ON
)
ENDIF(MSVC)
if(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES) IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
# Packing information # Packing information
set(CPACK_PACKAGE_NAME "assimp{ASSIMP_VERSION_MAJOR}") SET(CPACK_PACKAGE_NAME "assimp{ASSIMP_VERSION_MAJOR}")
set(CPACK_PACKAGE_CONTACT "" CACHE STRING "Package maintainer and PGP signer.") SET(CPACK_PACKAGE_CONTACT "" CACHE STRING "Package maintainer and PGP signer.")
set(CPACK_PACKAGE_VENDOR "http://assimp.sourceforge.net/") SET(CPACK_PACKAGE_VENDOR "https://github.com/assimp")
set(CPACK_PACKAGE_DISPLAY_NAME "Assimp ${ASSIMP_VERSION}") SET(CPACK_PACKAGE_DISPLAY_NAME "Assimp ${ASSIMP_VERSION}")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY " - Open Asset Import Library ${ASSIMP_VERSION}") SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY " - Open Asset Import Library ${ASSIMP_VERSION}")
set(CPACK_PACKAGE_VERSION "${ASSIMP_VERSION}.${ASSIMP_PACKAGE_VERSION}" ) SET(CPACK_PACKAGE_VERSION "${ASSIMP_VERSION}.${ASSIMP_PACKAGE_VERSION}" )
set(CPACK_PACKAGE_VERSION_MAJOR "${ASSIMP_VERSION_MAJOR}") SET(CPACK_PACKAGE_VERSION_MAJOR "${ASSIMP_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${ASSIMP_VERSION_MINOR}") SET(CPACK_PACKAGE_VERSION_MINOR "${ASSIMP_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${ASSIMP_VERSION_PATCH}") SET(CPACK_PACKAGE_VERSION_PATCH "${ASSIMP_VERSION_PATCH}")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "assimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}") SET(CPACK_PACKAGE_INSTALL_DIRECTORY "assimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}")
#set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description") SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
string(TOUPPER ${LIBASSIMP_COMPONENT} "LIBASSIMP_COMPONENT_UPPER") string(TOUPPER ${LIBASSIMP_COMPONENT} "LIBASSIMP_COMPONENT_UPPER")
string(TOUPPER ${LIBASSIMP-DEV_COMPONENT} "LIBASSIMP-DEV_COMPONENT_UPPER") string(TOUPPER ${LIBASSIMP-DEV_COMPONENT} "LIBASSIMP-DEV_COMPONENT_UPPER")
set(CPACK_COMPONENT_ASSIMP-BIN_DISPLAY_NAME "tools") SET(CPACK_COMPONENT_ASSIMP-BIN_DISPLAY_NAME "tools")
set(CPACK_COMPONENT_ASSIMP-BIN_DEPENDS "${LIBASSIMP_COMPONENT}" ) SET(CPACK_COMPONENT_ASSIMP-BIN_DEPENDS "${LIBASSIMP_COMPONENT}" )
set(CPACK_COMPONENT_${LIBASSIMP_COMPONENT_UPPER}_DISPLAY_NAME "libraries") SET(CPACK_COMPONENT_${LIBASSIMP_COMPONENT_UPPER}_DISPLAY_NAME "libraries")
set(CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT_UPPER}_DISPLAY_NAME "common headers and installs") SET(CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT_UPPER}_DISPLAY_NAME "common headers and installs")
set(CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT_UPPER}_DEPENDS $ "{LIBASSIMP_COMPONENT}" ) SET(CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT_UPPER}_DEPENDS $ "{LIBASSIMP_COMPONENT}" )
set(CPACK_COMPONENT_ASSIMP-DEV_DISPLAY_NAME "${CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT}_DISPLAY_NAME}" ) SET(CPACK_COMPONENT_ASSIMP-DEV_DISPLAY_NAME "${CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT}_DISPLAY_NAME}" )
set(CPACK_COMPONENT_ASSIMP-DEV_DEPENDS "${LIBASSIMP-DEV_COMPONENT}" ) SET(CPACK_COMPONENT_ASSIMP-DEV_DEPENDS "${LIBASSIMP-DEV_COMPONENT}" )
set(CPACK_DEBIAN_BUILD_DEPENDS debhelper cmake libboost-dev libboost-thread-dev libboost-math-dev zlib1g-dev pkg-config) SET(CPACK_DEBIAN_BUILD_DEPENDS debhelper cmake zlib1g-dev pkg-config)
# debian # debian
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") SET(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
set(CPACK_DEBIAN_CMAKE_OPTIONS "-DBUILD_ASSIMP_SAMPLES:BOOL=${ASSIMP_BUILD_SAMPLES}") SET(CPACK_DEBIAN_CMAKE_OPTIONS "-DBUILD_ASSIMP_SAMPLES:BOOL=${ASSIMP_BUILD_SAMPLES}")
set(CPACK_DEBIAN_PACKAGE_SECTION "libs" ) SET(CPACK_DEBIAN_PACKAGE_SECTION "libs" )
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_COMPONENTS_ALL}") SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_COMPONENTS_ALL}")
set(CPACK_DEBIAN_PACKAGE_SUGGESTS) SET(CPACK_DEBIAN_PACKAGE_SUGGESTS)
set(CPACK_DEBIAN_PACKAGE_NAME "assimp") SET(CPACK_DEBIAN_PACKAGE_NAME "assimp")
set(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES contrib/cppunit-1.12.1 contrib/cppunit_note.txt contrib/zlib workspaces test doc obj samples packaging) SET(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES contrib/cppunit-1.12.1 contrib/cppunit_note.txt contrib/zlib workspaces test doc obj samples packaging)
set(CPACK_DEBIAN_PACKAGE_SOURCE_COPY svn export --force) SET(CPACK_DEBIAN_PACKAGE_SOURCE_COPY svn export --force)
set(CPACK_DEBIAN_CHANGELOG) SET(CPACK_DEBIAN_CHANGELOG)
execute_process(COMMAND lsb_release -is execute_process(COMMAND lsb_release -is
OUTPUT_VARIABLE _lsb_distribution OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE _lsb_distribution OUTPUT_STRIP_TRAILING_WHITESPACE
RESULT_VARIABLE _lsb_release_failed) RESULT_VARIABLE _lsb_release_failed)
set(CPACK_DEBIAN_DISTRIBUTION_NAME ${_lsb_distribution} CACHE STRING "Name of the distrubiton") SET(CPACK_DEBIAN_DISTRIBUTION_NAME ${_lsb_distribution} CACHE STRING "Name of the distrubiton")
string(TOLOWER ${CPACK_DEBIAN_DISTRIBUTION_NAME} CPACK_DEBIAN_DISTRIBUTION_NAME) STRING(TOLOWER ${CPACK_DEBIAN_DISTRIBUTION_NAME} CPACK_DEBIAN_DISTRIBUTION_NAME)
if( ${CPACK_DEBIAN_DISTRIBUTION_NAME} STREQUAL "ubuntu" ) IF( ${CPACK_DEBIAN_DISTRIBUTION_NAME} STREQUAL "ubuntu" )
set(CPACK_DEBIAN_DISTRIBUTION_RELEASES lucid maverick natty oneiric precise CACHE STRING "Release code-names of the distrubiton release") SET(CPACK_DEBIAN_DISTRIBUTION_RELEASES lucid maverick natty oneiric precise CACHE STRING "Release code-names of the distrubiton release")
endif() ENDIF()
set(DPUT_HOST "" CACHE STRING "PPA repository to upload the debian sources") SET(DPUT_HOST "" CACHE STRING "PPA repository to upload the debian sources")
include(CPack) include(CPack)
include(DebSourcePPA) include(DebSourcePPA)
endif() ENDIF()
if(WIN32)
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
SET(BIN_DIR "${PROJECT_SOURCE_DIR}/bin64/")
SET(LIB_DIR "${PROJECT_SOURCE_DIR}/lib64/")
elseif()
SET(BIN_DIR "${PROJECT_SOURCE_DIR}/bin32/")
SET(LIB_DIR "${PROJECT_SOURCE_DIR}/lib32/")
ENDIF()
if(MSVC12)
SET(ASSIMP_MSVC_VERSION "vc120")
elseif(MSVC14)
SET(ASSIMP_MSVC_VERSION "vc140")
ENDIF(MSVC12)
if(MSVC12 OR MSVC14)
add_custom_target(UpdateAssimpLibsDebugSymbolsAndDLLs COMMENT "Copying Assimp Libraries ..." VERBATIM)
add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.dll VERBATIM)
add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.exp VERBATIM)
add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.lib VERBATIM)
add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll ${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.dll VERBATIM)
add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.exp ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.exp VERBATIM)
add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk VERBATIM)
add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.lib ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.lib VERBATIM)
add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
ENDIF(MSVC12 OR MSVC14)
ENDIF (WIN32)

18
CREDITS
View File

@ -7,13 +7,13 @@ The following is a non-exhaustive list of all constributors over the years.
If you think your name should be listed here, drop us a line and we'll add you. If you think your name should be listed here, drop us a line and we'll add you.
- Alexander Gessler, - Alexander Gessler,
3DS-, BLEND-, ASE-, DXF-, HMP-, MDL-, MD2-, MD3-, MD5-, MDC-, NFF-, PLY-, STL-, RAW-, OFF-, MS3D-, Q3D- and LWO-Loader, Assimp-Viewer, assimp-cmd, -noboost, Website (Admin and Design). 3DS-, BLEND-, ASE-, DXF-, HMP-, MDL-, MD2-, MD3-, MD5-, MDC-, NFF-, PLY-, STL-, RAW-, OFF-, MS3D-, Q3D- and LWO-Loader, Assimp-Viewer, assimp-cmd, -noboost, Website (Design).
- Thomas Schulze, - Thomas Schulze,
X-, Collada-, BVH-Loader, Postprocessing framework. Data structure & Interface design, documentation. X-, Collada-, BVH-Loader, Postprocessing framework. Data structure & Interface design, documentation.
- Kim Kulling, - Kim Kulling,
Obj-Loader, Logging system, Scons-build environment, CMake build environment, Linux build. Obj-, Q3BSD-, OpenGEX-Loader, Logging system, CMake-build-environment, Linux-build, Website ( Admin ), Coverity ( Admin ), Glitter ( Admin ).
- R.Schmidt, - R.Schmidt,
Linux build, eclipse support. Linux build, eclipse support.
@ -30,7 +30,7 @@ Ogre Loader, VC2010 fixes and CMake fixes.
- Sebastian Hempel, - Sebastian Hempel,
PyAssimp (first version) PyAssimp (first version)
Compile-Bugfixes for mingw, add enviroment for static library support in make. Compile-Bugfixes for mingw, add environment for static library support in make.
- Jonathan Pokrass - Jonathan Pokrass
Supplied a bugfix concerning the scaling in the md3 loader. Supplied a bugfix concerning the scaling in the md3 loader.
@ -114,7 +114,7 @@ Contributes a fix for the configure script environment.
Contributed AssimpDelphi (/port/AssimpDelphi). Contributed AssimpDelphi (/port/AssimpDelphi).
- rdb - rdb
Contributes a bundle of fixes and improvments for the bsp-importer. Contributes a bundle of fixes and improvements for the bsp-importer.
- Mick P - Mick P
For contributing the De-bone postprocessing step and filing various bug reports. For contributing the De-bone postprocessing step and filing various bug reports.
@ -148,3 +148,13 @@ Bugfixes for uv-tanget calculation.
- Jonne Nauha - Jonne Nauha
Ogre Binary format support Ogre Binary format support
- Filip Wasil, Tieto Poland Sp. z o.o.
Android JNI asset extraction support
- Richard Steffen
Contributed ExportProperties interface
Contributed X File exporter
Contributed Step (stp) exporter

12
CodeConventions.md 100644
View File

@ -0,0 +1,12 @@
Open Asset Import Library Coding Conventions
==
If you want to participate as a developer in the **Open Asset Import Library** please read and respect the following coding conventions. This will ensure consistency throughout the codebase and help all the Open Asset Import Library users.
Spacing
==
* Use UNIX-style line endings (LF)
* Remove any trailing whitespace
* Expand tabs to 4 spaces

View File

@ -1,14 +0,0 @@
===============================================
The Asset-Importer-Library Coding conventions
===============================================
If you want to participate to the Asset-Importer_Library please have a look
onto these coding conventions and try to follow them. They are more or less
some kind of guide line to help others coming into the code and help all
the Asset-Importer-Library users.
Tab width
===========
The tab width shall be 4 spaces.

15
INSTALL
View File

@ -33,13 +33,12 @@ CMake is the preferred build system for Assimp. The minimum required version
is 2.6. If you don't have it yet, downloads for CMake can be found on is 2.6. If you don't have it yet, downloads for CMake can be found on
http://www.cmake.org/. http://www.cmake.org/.
Building Assimp with CMake is 'business as usual' if you've used CMake For Unix:
before. All steps can be done either on the command line / shell or
by using the CMake GUI tool, the choice is up to you.
First, invoke CMake to generate build files for a particular
toolchain (for standard GNU makefiles: cmake -G 'Unix Makefiles').
Afterwards, use the generated build files to perform the actual
build.
1. cmake CMakeLists.txt -G 'Unix Makefiles'
2. make
For Windows:
1. Open a command prompt
2. cmake CMakeLists.txt
2. Open your default IDE and build it

View File

@ -1,6 +1,6 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -76,9 +76,3 @@ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,18 +1,34 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
======== ==================================
Open Asset Import Library is a Open Source library designed to load various __3d file formats and convert them into a shared, in-memory format__. It supports more than __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. [![Linux Build Status](https://travis-ci.org/assimp/assimp.svg)](https://travis-ci.org/assimp/assimp)
[![Windows Build Status](https://ci.appveyor.com/api/projects/status/tmo433wax6u6cjp4?svg=true)](https://ci.appveyor.com/project/kimkulling/assimp)
<a href="https://scan.coverity.com/projects/5607">
<img alt="Coverity Scan Build Status"
src="https://scan.coverity.com/projects/5607/badge.svg"/>
</a>
[![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master)
<br>
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) APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS.
[open3mod](https://github.com/acgessler/open3mod) is an Open Source 3D model viewer based off Assimp's import and export abilities. Additionally, assimp features various __mesh post processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more.
This is the development trunk containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [assimp.sf.net](http://assimp.sf.net) or from *nix package repositories.
The current build status is:
Gitter chat: [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br>
__[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.__
Please check our Wiki as well: https://github.com/assimp/assimp/wiki
#### Supported file formats #### #### Supported file formats ####
The library provides importers for a lot of file formats, including: A full list [is here](http://assimp.org/main_features_formats.html).
__Importers__:
- 3DS - 3DS
- BLEND (Blender 3D) - BLEND (Blender)
- DAE/Collada - DAE/Collada
- FBX - FBX
- IFC-STEP - IFC-STEP
@ -29,6 +45,7 @@ The library provides importers for a lot of file formats, including:
- STL - STL
- X - X
- OBJ - OBJ
- OpenGEX
- SMD - SMD
- LWO - LWO
- LXO - LXO
@ -46,13 +63,15 @@ The library provides importers for a lot of file formats, including:
- Ogre Binary - Ogre Binary
- Ogre XML - Ogre XML
- Q3D - Q3D
- ASSBIN (Assimp scene serialization) - ASSBIN (Assimp custom format)
- glTF (partial)
- 3MF
Additionally, the following formats are also supported, but not part of the core library as they depend on proprietary libraries. Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default):
- C4D (https://github.com/acgessler/assimp-cinema4d) - C4D (https://github.com/acgessler/assimp-cinema4d)
Exporters include: __Exporters__:
- DAE (Collada) - DAE (Collada)
- STL - STL
@ -62,65 +81,63 @@ Exporters include:
- 3DS - 3DS
- JSON (for WebGl, via https://github.com/acgessler/assimp2json) - JSON (for WebGl, via https://github.com/acgessler/assimp2json)
- ASSBIN - ASSBIN
- STEP
- glTF (partial)
See [the full list here](http://assimp.sourceforge.net/main_features_formats.html). ### Building ###
Take a look into the `INSTALL` file. Our build system is CMake, if you used CMake before there is a good chance you know what to do.
### Ports ###
* [Android](port/AndroidJNI/README.md)
* [Python](port/PyAssimp/README.md)
* [.NET](port/AssimpNET/Readme.md)
* [Pascal](port/AssimpPascal/Readme.md)
* [Javascript (Alpha)](https://github.com/makc/assimp2json)
#### Repository structure #### #### Repository structure ####
Open Asset Import Library is implemented in C++. The directory structure is:
Open Asset Import Library is implemented in C++ (but provides both a C and a
C++ish interface). The directory structure is:
/bin Folder for binaries, only used on Windows
/code Source code /code Source code
/contrib Third-party libraries /contrib Third-party libraries
/doc Documentation (doxysource and pre-compiled docs) /doc Documentation (doxysource and pre-compiled docs)
/include Public header C and C++ header files /include Public header C and C++ header files
/lib Static library location for Windows
/obj Object file location for Windows
/scripts Scripts used to generate the loading code for some formats /scripts Scripts used to generate the loading code for some formats
/port Ports to other languages and scripts to maintain those. /port Ports to other languages and scripts to maintain those.
/test Unit- and regression tests, test suite of models /test Unit- and regression tests, test suite of models
/tools Tools (old assimp viewer, command line `assimp`) /tools Tools (old assimp viewer, command line `assimp`)
/samples A small number of samples to illustrate possible /samples A small number of samples to illustrate possible
use cases for Assimp use cases for Assimp
/workspaces Build enviroments for vc,xcode,... (deprecated, /workspaces Build environments for vc,xcode,... (deprecated,
CMake has superseeded all legacy build options!) CMake has superseeded all legacy build options!)
### Building ###
Take a look into the `INSTALL` file. Our build system is CMake, if you already used CMake before there is a good chance you know what to do.
### Where to get help ### ### Where to get help ###
For more information, visit [our website](http://assimp.org/). Or check out the `./doc`- folder, which contains the official documentation in HTML format.
For more information, visit [our website](http://assimp.sourceforge.net/). Or check out the `./doc`- folder, which contains the official documentation in HTML format.
(CHMs for Windows are included in some release packages and should be located right here in the root folder). (CHMs for Windows are included in some release packages and should be located right here in the root folder).
If the documentation doesn't solve your problems, If the docs don't solve your problem, ask on [StackOverflow](http://stackoverflow.com/questions/tagged/assimp?sort=newest). If you think you found a bug, please open an issue on Github.
[try our forums at SF.net](http://sourceforge.net/p/assimp/discussion/817654) or ask on
[StackOverflow](http://stackoverflow.com/questions/tagged/assimp?sort=newest).
For development discussions, there is also a mailing list, _assimp-discussions_ For development discussions, there is also a (very low-volume) mailing list, _assimp-discussions_
[(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions) [(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions)
### Contributing ### Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br>
### Contributing ###
Contributions to assimp are highly appreciated. The easiest way to get involved is to submit Contributions to assimp are highly appreciated. The easiest way to get involved is to submit
a pull request with your changes against the main repository's `master` branch. a pull request with your changes against the main repository's `master` branch.
### Donate ###
If you like assimp, consider buying us a beer (or two):
[Donate](http://sourceforge.net/donate/index.php?group_id=226462)
### License ### ### License ###
Our license is based on the modified, __3-clause BSD__-License.
Our license is based on the modified, __3-clause BSD__-License, which is very liberal.
An _informal_ summary is: do whatever you want, but include Assimp's license text with your product - An _informal_ summary is: do whatever you want, but include Assimp's license text with your product -
and don't sue us if our code doesn't work. Note that, unlike LGPLed code, you may link statically to Assimp. and don't sue us if our code doesn't work. Note that, unlike LGPLed code, you may link statically to Assimp.
For the legal details, see the `LICENSE` file. For the legal details, see the `LICENSE` file.
### Why this name ###
Sorry, we're germans :-), no english native speakers ...

42
appveyor.yml 100644
View File

@ -0,0 +1,42 @@
# AppVeyor file
# http://www.appveyor.com/docs/appveyor-yml
# clone directory
clone_folder: c:\projects\assimp
# branches to build
branches:
# whitelist
only:
- master
platform:
- x86
- x64
configuration:
- 14 2015
- 12 2013
#- MinGW
#- 10 2010 # only works for x86
init:
- if "%platform%" EQU "x64" ( for %%a in (2008 2010 MinGW) do ( if "%Configuration%"=="%%a" (echo "Skipping unsupported configuration" && exit /b 1 ) ) )
install:
# Make compiler command line tools available
- call c:\projects\assimp\scripts\appveyor\compiler_setup.bat
build_script:
- cd c:\projects\assimp
- if "%platform%" equ "x64" (cmake CMakeLists.txt -G "Visual Studio %Configuration% Win64")
- if "%platform%" equ "x86" (cmake CMakeLists.txt -G "Visual Studio %Configuration%")
- if "%platform%" equ "x64" (msbuild /m /p:Configuration=Release /p:Platform="x64" Assimp.sln)
- if "%platform%" equ "x86" (msbuild /m /p:Configuration=Release /p:Platform="Win32" Assimp.sln)
after_build:
- 7z a assimp.7z c:\projects\assimp\bin\release\* c:\projects\assimp\lib\release\*
artifacts:
- path: assimp.7z
name: assimp_lib

View File

@ -23,8 +23,16 @@ if( MSVC )
set(MSVC_PREFIX "vc80") set(MSVC_PREFIX "vc80")
elseif( MSVC90 ) elseif( MSVC90 )
set(MSVC_PREFIX "vc90") set(MSVC_PREFIX "vc90")
else() elseif( MSVC10 )
set(MSVC_PREFIX "vc100") set(MSVC_PREFIX "vc100")
elseif( MSVC11 )
set(MSVC_PREFIX "vc110")
elseif( MSVC12 )
set(MSVC_PREFIX "vc120")
elseif( MSVC14 )
set(MSVC_PREFIX "vc140")
else()
set(MSVC_PREFIX "vc150")
endif() endif()
set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" FORCE) set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" FORCE)
else() else()
@ -40,9 +48,7 @@ set( ASSIMP_LINK_FLAGS "" )
set( ASSIMP_LIBRARY_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_LIB_INSTALL_DIR@") set( ASSIMP_LIBRARY_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_LIB_INSTALL_DIR@")
set( ASSIMP_INCLUDE_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_INCLUDE_INSTALL_DIR@") set( ASSIMP_INCLUDE_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_INCLUDE_INSTALL_DIR@")
set( ASSIMP_LIBRARIES assimp${ASSIMP_LIBRARY_SUFFIX}) set( ASSIMP_LIBRARIES assimp${ASSIMP_LIBRARY_SUFFIX})
if (CMAKE_BUILD_TYPE EQUAL "DEBUG") set( ASSIMP_LIBRARIES ${ASSIMP_LIBRARIES}@CMAKE_DEBUG_POSTFIX@)
set( ASSIMP_LIBRARIES ${ASSIMP_LIBRARIES}D)
endif (CMAKE_BUILD_TYPE EQUAL "DEBUG")
# search for the boost version assimp was compiled with # search for the boost version assimp was compiled with
#set(Boost_USE_MULTITHREAD ON) #set(Boost_USE_MULTITHREAD ON)
@ -58,7 +64,7 @@ endif (CMAKE_BUILD_TYPE EQUAL "DEBUG")
# the boost version assimp was compiled with # the boost version assimp was compiled with
set( ASSIMP_Boost_VERSION "@Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@") set( ASSIMP_Boost_VERSION "@Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@")
# for compatibility wiht pkg-config # for compatibility with pkg-config
set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}") set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}")
set(ASSIMP_LDFLAGS_OTHER "${ASSIMP_LINK_FLAGS}") set(ASSIMP_LDFLAGS_OTHER "${ASSIMP_LINK_FLAGS}")

View File

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

View File

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

View File

@ -0,0 +1,126 @@
#
# The MIT License (MIT)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Copyright (C) 2014 Joakim Söderberg <joakim.soderberg@gmail.com>
#
set(_CMAKE_SCRIPT_PATH ${CMAKE_CURRENT_LIST_DIR}) # must be outside coveralls_setup() to get correct path
#
# Param _COVERAGE_SRCS A list of source files that coverage should be collected for.
# Param _COVERALLS_UPLOAD Upload the result to coveralls?
#
function(coveralls_setup _COVERAGE_SRCS _COVERALLS_UPLOAD)
if (ARGC GREATER 2)
set(_CMAKE_SCRIPT_PATH ${ARGN})
message(STATUS "Coveralls: Using alternate CMake script dir: ${_CMAKE_SCRIPT_PATH}")
endif()
if (NOT EXISTS "${_CMAKE_SCRIPT_PATH}/CoverallsClear.cmake")
message(FATAL_ERROR "Coveralls: Missing ${_CMAKE_SCRIPT_PATH}/CoverallsClear.cmake")
endif()
if (NOT EXISTS "${_CMAKE_SCRIPT_PATH}/CoverallsGenerateGcov.cmake")
message(FATAL_ERROR "Coveralls: Missing ${_CMAKE_SCRIPT_PATH}/CoverallsGenerateGcov.cmake")
endif()
# When passing a CMake list to an external process, the list
# will be converted from the format "1;2;3" to "1 2 3".
# This means the script we're calling won't see it as a list
# of sources, but rather just one long path. We remedy this
# by replacing ";" with "*" and then reversing that in the script
# that we're calling.
# http://cmake.3232098.n2.nabble.com/Passing-a-CMake-list-quot-as-is-quot-to-a-custom-target-td6505681.html
set(COVERAGE_SRCS_TMP ${_COVERAGE_SRCS})
set(COVERAGE_SRCS "")
foreach (COVERAGE_SRC ${COVERAGE_SRCS_TMP})
set(COVERAGE_SRCS "${COVERAGE_SRCS}*${COVERAGE_SRC}")
endforeach()
#message("Coverage sources: ${COVERAGE_SRCS}")
set(COVERALLS_FILE ${PROJECT_BINARY_DIR}/coveralls.json)
add_custom_target(coveralls_generate
# Zero the coverage counters.
COMMAND ${CMAKE_COMMAND} -DPROJECT_BINARY_DIR="${PROJECT_BINARY_DIR}" -P "${_CMAKE_SCRIPT_PATH}/CoverallsClear.cmake"
# Run regress tests.
COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure
# Generate Gcov and translate it into coveralls JSON.
# We do this by executing an external CMake script.
# (We don't want this to run at CMake generation time, but after compilation and everything has run).
COMMAND ${CMAKE_COMMAND}
-DCOVERAGE_SRCS="${COVERAGE_SRCS}" # TODO: This is passed like: "a b c", not "a;b;c"
-DCOVERALLS_OUTPUT_FILE="${COVERALLS_FILE}"
-DCOV_PATH="${PROJECT_BINARY_DIR}"
-DPROJECT_ROOT="${PROJECT_SOURCE_DIR}"
-P "${_CMAKE_SCRIPT_PATH}/CoverallsGenerateGcov.cmake"
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
COMMENT "Generating coveralls output..."
)
if (_COVERALLS_UPLOAD)
message("COVERALLS UPLOAD: ON")
find_program(CURL_EXECUTABLE curl)
if (NOT CURL_EXECUTABLE)
message(FATAL_ERROR "Coveralls: curl not found! Aborting")
endif()
add_custom_target(coveralls_upload
# Upload the JSON to coveralls.
COMMAND ${CURL_EXECUTABLE}
-S -F json_file=@${COVERALLS_FILE}
https://coveralls.io/api/v1/jobs
DEPENDS coveralls_generate
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
COMMENT "Uploading coveralls output...")
add_custom_target(coveralls DEPENDS coveralls_upload)
else()
message("COVERALLS UPLOAD: OFF")
add_custom_target(coveralls DEPENDS coveralls_generate)
endif()
endfunction()
macro(coveralls_turn_on_coverage)
if(NOT (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
AND (NOT "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang"))
message(FATAL_ERROR "Coveralls: Compiler ${CMAKE_C_COMPILER_ID} is not GNU gcc! Aborting... You can set this on the command line using CC=/usr/bin/gcc CXX=/usr/bin/g++ cmake <options> ..")
endif()
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
message(FATAL_ERROR "Coveralls: Code coverage results with an optimised (non-Debug) build may be misleading! Add -DCMAKE_BUILD_TYPE=Debug")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
endmacro()

View File

@ -0,0 +1,31 @@
#
# The MIT License (MIT)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Copyright (C) 2014 Joakim Söderberg <joakim.soderberg@gmail.com>
#
# do not follow symlinks in file(GLOB_RECURSE ...)
cmake_policy(SET CMP0009 NEW)
file(GLOB_RECURSE GCDA_FILES "${PROJECT_BINARY_DIR}/*.gcda")
if(NOT GCDA_FILES STREQUAL "")
file(REMOVE ${GCDA_FILES})
endif()

View File

@ -0,0 +1,482 @@
#
# The MIT License (MIT)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Copyright (C) 2014 Joakim Söderberg <joakim.soderberg@gmail.com>
#
# This is intended to be run by a custom target in a CMake project like this.
# 0. Compile program with coverage support.
# 1. Clear coverage data. (Recursively delete *.gcda in build dir)
# 2. Run the unit tests.
# 3. Run this script specifying which source files the coverage should be performed on.
#
# This script will then use gcov to generate .gcov files in the directory specified
# via the COV_PATH var. This should probably be the same as your cmake build dir.
#
# It then parses the .gcov files to convert them into the Coveralls JSON format:
# https://coveralls.io/docs/api
#
# Example for running as standalone CMake script from the command line:
# (Note it is important the -P is at the end...)
# $ cmake -DCOV_PATH=$(pwd)
# -DCOVERAGE_SRCS="catcierge_rfid.c;catcierge_timer.c"
# -P ../cmake/CoverallsGcovUpload.cmake
#
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
#
# Make sure we have the needed arguments.
#
if (NOT COVERALLS_OUTPUT_FILE)
message(FATAL_ERROR "Coveralls: No coveralls output file specified. Please set COVERALLS_OUTPUT_FILE")
endif()
if (NOT COV_PATH)
message(FATAL_ERROR "Coveralls: Missing coverage directory path where gcov files will be generated. Please set COV_PATH")
endif()
if (NOT COVERAGE_SRCS)
message(FATAL_ERROR "Coveralls: Missing the list of source files that we should get the coverage data for COVERAGE_SRCS")
endif()
if (NOT PROJECT_ROOT)
message(FATAL_ERROR "Coveralls: Missing PROJECT_ROOT.")
endif()
# Since it's not possible to pass a CMake list properly in the
# "1;2;3" format to an external process, we have replaced the
# ";" with "*", so reverse that here so we get it back into the
# CMake list format.
string(REGEX REPLACE "\\*" ";" COVERAGE_SRCS ${COVERAGE_SRCS})
if (NOT DEFINED ENV{GCOV})
find_program(GCOV_EXECUTABLE gcov)
else()
find_program(GCOV_EXECUTABLE $ENV{GCOV})
endif()
# convert all paths in COVERAGE_SRCS to absolute paths
set(COVERAGE_SRCS_TMP "")
foreach (COVERAGE_SRC ${COVERAGE_SRCS})
if (NOT "${COVERAGE_SRC}" MATCHES "^/")
set(COVERAGE_SRC ${PROJECT_ROOT}/${COVERAGE_SRC})
endif()
list(APPEND COVERAGE_SRCS_TMP ${COVERAGE_SRC})
endforeach()
set(COVERAGE_SRCS ${COVERAGE_SRCS_TMP})
unset(COVERAGE_SRCS_TMP)
if (NOT GCOV_EXECUTABLE)
message(FATAL_ERROR "gcov not found! Aborting...")
endif()
find_package(Git)
set(JSON_REPO_TEMPLATE
"{
\"head\": {
\"id\": \"\@GIT_COMMIT_HASH\@\",
\"author_name\": \"\@GIT_AUTHOR_NAME\@\",
\"author_email\": \"\@GIT_AUTHOR_EMAIL\@\",
\"committer_name\": \"\@GIT_COMMITTER_NAME\@\",
\"committer_email\": \"\@GIT_COMMITTER_EMAIL\@\",
\"message\": \"\@GIT_COMMIT_MESSAGE\@\"
},
\"branch\": \"@GIT_BRANCH@\",
\"remotes\": []
}"
)
# TODO: Fill in git remote data
if (GIT_FOUND)
# Branch.
execute_process(
COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
macro (git_log_format FORMAT_CHARS VAR_NAME)
execute_process(
COMMAND ${GIT_EXECUTABLE} log -1 --pretty=format:%${FORMAT_CHARS}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE ${VAR_NAME}
OUTPUT_STRIP_TRAILING_WHITESPACE
)
endmacro()
git_log_format(an GIT_AUTHOR_NAME)
git_log_format(ae GIT_AUTHOR_EMAIL)
git_log_format(cn GIT_COMMITTER_NAME)
git_log_format(ce GIT_COMMITTER_EMAIL)
git_log_format(B GIT_COMMIT_MESSAGE)
git_log_format(H GIT_COMMIT_HASH)
if(GIT_COMMIT_MESSAGE)
string(REPLACE "\n" "\\n" GIT_COMMIT_MESSAGE ${GIT_COMMIT_MESSAGE})
endif()
message("Git exe: ${GIT_EXECUTABLE}")
message("Git branch: ${GIT_BRANCH}")
message("Git author: ${GIT_AUTHOR_NAME}")
message("Git e-mail: ${GIT_AUTHOR_EMAIL}")
message("Git commiter name: ${GIT_COMMITTER_NAME}")
message("Git commiter e-mail: ${GIT_COMMITTER_EMAIL}")
message("Git commit hash: ${GIT_COMMIT_HASH}")
message("Git commit message: ${GIT_COMMIT_MESSAGE}")
string(CONFIGURE ${JSON_REPO_TEMPLATE} JSON_REPO_DATA)
else()
set(JSON_REPO_DATA "{}")
endif()
############################# Macros #########################################
#
# This macro converts from the full path format gcov outputs:
#
# /path/to/project/root/build/#path#to#project#root#subdir#the_file.c.gcov
#
# to the original source file path the .gcov is for:
#
# /path/to/project/root/subdir/the_file.c
#
macro(get_source_path_from_gcov_filename _SRC_FILENAME _GCOV_FILENAME)
# /path/to/project/root/build/#path#to#project#root#subdir#the_file.c.gcov
# ->
# #path#to#project#root#subdir#the_file.c.gcov
get_filename_component(_GCOV_FILENAME_WEXT ${_GCOV_FILENAME} NAME)
# #path#to#project#root#subdir#the_file.c.gcov -> /path/to/project/root/subdir/the_file.c
string(REGEX REPLACE "\\.gcov$" "" SRC_FILENAME_TMP ${_GCOV_FILENAME_WEXT})
string(REGEX REPLACE "\#" "/" SRC_FILENAME_TMP ${SRC_FILENAME_TMP})
set(${_SRC_FILENAME} "${SRC_FILENAME_TMP}")
endmacro()
##############################################################################
# Get the coverage data.
file(GLOB_RECURSE GCDA_FILES "${COV_PATH}/*.gcda")
message("GCDA files:")
# Get a list of all the object directories needed by gcov
# (The directories the .gcda files and .o files are found in)
# and run gcov on those.
foreach(GCDA ${GCDA_FILES})
message("Process: ${GCDA}")
message("------------------------------------------------------------------------------")
get_filename_component(GCDA_DIR ${GCDA} PATH)
#
# The -p below refers to "Preserve path components",
# This means that the generated gcov filename of a source file will
# keep the original files entire filepath, but / is replaced with #.
# Example:
#
# /path/to/project/root/build/CMakeFiles/the_file.dir/subdir/the_file.c.gcda
# ------------------------------------------------------------------------------
# File '/path/to/project/root/subdir/the_file.c'
# Lines executed:68.34% of 199
# /path/to/project/root/subdir/the_file.c:creating '#path#to#project#root#subdir#the_file.c.gcov'
#
# If -p is not specified then the file is named only "the_file.c.gcov"
#
execute_process(
COMMAND ${GCOV_EXECUTABLE} -p -o ${GCDA_DIR} ${GCDA}
WORKING_DIRECTORY ${COV_PATH}
)
endforeach()
# TODO: Make these be absolute path
file(GLOB ALL_GCOV_FILES ${COV_PATH}/*.gcov)
# Get only the filenames to use for filtering.
#set(COVERAGE_SRCS_NAMES "")
#foreach (COVSRC ${COVERAGE_SRCS})
# get_filename_component(COVSRC_NAME ${COVSRC} NAME)
# message("${COVSRC} -> ${COVSRC_NAME}")
# list(APPEND COVERAGE_SRCS_NAMES "${COVSRC_NAME}")
#endforeach()
#
# Filter out all but the gcov files we want.
#
# We do this by comparing the list of COVERAGE_SRCS filepaths that the
# user wants the coverage data for with the paths of the generated .gcov files,
# so that we only keep the relevant gcov files.
#
# Example:
# COVERAGE_SRCS =
# /path/to/project/root/subdir/the_file.c
#
# ALL_GCOV_FILES =
# /path/to/project/root/build/#path#to#project#root#subdir#the_file.c.gcov
# /path/to/project/root/build/#path#to#project#root#subdir#other_file.c.gcov
#
# Result should be:
# GCOV_FILES =
# /path/to/project/root/build/#path#to#project#root#subdir#the_file.c.gcov
#
set(GCOV_FILES "")
#message("Look in coverage sources: ${COVERAGE_SRCS}")
message("\nFilter out unwanted GCOV files:")
message("===============================")
set(COVERAGE_SRCS_REMAINING ${COVERAGE_SRCS})
foreach (GCOV_FILE ${ALL_GCOV_FILES})
#
# /path/to/project/root/build/#path#to#project#root#subdir#the_file.c.gcov
# ->
# /path/to/project/root/subdir/the_file.c
get_source_path_from_gcov_filename(GCOV_SRC_PATH ${GCOV_FILE})
file(RELATIVE_PATH GCOV_SRC_REL_PATH "${PROJECT_ROOT}" "${GCOV_SRC_PATH}")
# Is this in the list of source files?
# TODO: We want to match against relative path filenames from the source file root...
list(FIND COVERAGE_SRCS ${GCOV_SRC_PATH} WAS_FOUND)
if (NOT WAS_FOUND EQUAL -1)
message("YES: ${GCOV_FILE}")
list(APPEND GCOV_FILES ${GCOV_FILE})
# We remove it from the list, so we don't bother searching for it again.
# Also files left in COVERAGE_SRCS_REMAINING after this loop ends should
# have coverage data generated from them (no lines are covered).
list(REMOVE_ITEM COVERAGE_SRCS_REMAINING ${GCOV_SRC_PATH})
else()
message("NO: ${GCOV_FILE}")
endif()
endforeach()
# TODO: Enable setting these
set(JSON_SERVICE_NAME "travis-ci")
set(JSON_SERVICE_JOB_ID $ENV{TRAVIS_JOB_ID})
set(JSON_REPO_TOKEN $ENV{COVERALLS_REPO_TOKEN})
set(JSON_TEMPLATE
"{
\"repo_token\": \"\@JSON_REPO_TOKEN\@\",
\"service_name\": \"\@JSON_SERVICE_NAME\@\",
\"service_job_id\": \"\@JSON_SERVICE_JOB_ID\@\",
\"source_files\": \@JSON_GCOV_FILES\@,
\"git\": \@JSON_REPO_DATA\@
}"
)
set(SRC_FILE_TEMPLATE
"{
\"name\": \"\@GCOV_SRC_REL_PATH\@\",
\"source_digest\": \"\@GCOV_CONTENTS_MD5\@\",
\"coverage\": \@GCOV_FILE_COVERAGE\@
}"
)
message("\nGenerate JSON for files:")
message("=========================")
set(JSON_GCOV_FILES "[")
# Read the GCOV files line by line and get the coverage data.
foreach (GCOV_FILE ${GCOV_FILES})
get_source_path_from_gcov_filename(GCOV_SRC_PATH ${GCOV_FILE})
file(RELATIVE_PATH GCOV_SRC_REL_PATH "${PROJECT_ROOT}" "${GCOV_SRC_PATH}")
# The new coveralls API doesn't need the entire source (Yay!)
# However, still keeping that part for now. Will cleanup in the future.
file(MD5 "${GCOV_SRC_PATH}" GCOV_CONTENTS_MD5)
message("MD5: ${GCOV_SRC_PATH} = ${GCOV_CONTENTS_MD5}")
# Loads the gcov file as a list of lines.
# (We first open the file and replace all occurences of [] with _
# because CMake will fail to parse a line containing unmatched brackets...
# also the \ to escaped \n in macros screws up things.)
# https://public.kitware.com/Bug/view.php?id=15369
file(READ ${GCOV_FILE} GCOV_CONTENTS)
string(REPLACE "[" "_" GCOV_CONTENTS "${GCOV_CONTENTS}")
string(REPLACE "]" "_" GCOV_CONTENTS "${GCOV_CONTENTS}")
string(REPLACE "\\" "_" GCOV_CONTENTS "${GCOV_CONTENTS}")
# Remove file contents to avoid encoding issues (cmake 2.8 has no ENCODING option)
string(REGEX REPLACE "([^:]*):([^:]*):([^\n]*)\n" "\\1:\\2: \n" GCOV_CONTENTS "${GCOV_CONTENTS}")
file(WRITE ${GCOV_FILE}_tmp "${GCOV_CONTENTS}")
file(STRINGS ${GCOV_FILE}_tmp GCOV_LINES)
list(LENGTH GCOV_LINES LINE_COUNT)
# Instead of trying to parse the source from the
# gcov file, simply read the file contents from the source file.
# (Parsing it from the gcov is hard because C-code uses ; in many places
# which also happens to be the same as the CMake list delimeter).
file(READ ${GCOV_SRC_PATH} GCOV_FILE_SOURCE)
string(REPLACE "\\" "\\\\" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
string(REGEX REPLACE "\"" "\\\\\"" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
string(REPLACE "\t" "\\\\t" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
string(REPLACE "\r" "\\\\r" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
string(REPLACE "\n" "\\\\n" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
# According to http://json.org/ these should be escaped as well.
# Don't know how to do that in CMake however...
#string(REPLACE "\b" "\\\\b" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
#string(REPLACE "\f" "\\\\f" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
#string(REGEX REPLACE "\u([a-fA-F0-9]{4})" "\\\\u\\1" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")
# We want a json array of coverage data as a single string
# start building them from the contents of the .gcov
set(GCOV_FILE_COVERAGE "[")
set(GCOV_LINE_COUNT 1) # Line number for the .gcov.
set(DO_SKIP 0)
foreach (GCOV_LINE ${GCOV_LINES})
#message("${GCOV_LINE}")
# Example of what we're parsing:
# Hitcount |Line | Source
# " 8: 26: if (!allowed || (strlen(allowed) == 0))"
string(REGEX REPLACE
"^([^:]*):([^:]*):(.*)$"
"\\1;\\2;\\3"
RES
"${GCOV_LINE}")
# Check if we should exclude lines using the Lcov syntax.
string(REGEX MATCH "LCOV_EXCL_START" START_SKIP "${GCOV_LINE}")
string(REGEX MATCH "LCOV_EXCL_END" END_SKIP "${GCOV_LINE}")
string(REGEX MATCH "LCOV_EXCL_LINE" LINE_SKIP "${GCOV_LINE}")
set(RESET_SKIP 0)
if (LINE_SKIP AND NOT DO_SKIP)
set(DO_SKIP 1)
set(RESET_SKIP 1)
endif()
if (START_SKIP)
set(DO_SKIP 1)
message("${GCOV_LINE_COUNT}: Start skip")
endif()
if (END_SKIP)
set(DO_SKIP 0)
endif()
list(LENGTH RES RES_COUNT)
if (RES_COUNT GREATER 2)
list(GET RES 0 HITCOUNT)
list(GET RES 1 LINE)
list(GET RES 2 SOURCE)
string(STRIP ${HITCOUNT} HITCOUNT)
string(STRIP ${LINE} LINE)
# Lines with 0 line numbers are metadata and can be ignored.
if (NOT ${LINE} EQUAL 0)
if (DO_SKIP)
set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}null, ")
else()
# Translate the hitcount into valid JSON values.
if (${HITCOUNT} STREQUAL "#####" OR ${HITCOUNT} STREQUAL "=====")
set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}0, ")
elseif (${HITCOUNT} STREQUAL "-")
set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}null, ")
else()
set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}${HITCOUNT}, ")
endif()
endif()
endif()
else()
message(WARNING "Failed to properly parse line (RES_COUNT = ${RES_COUNT}) ${GCOV_FILE}:${GCOV_LINE_COUNT}\n-->${GCOV_LINE}")
endif()
if (RESET_SKIP)
set(DO_SKIP 0)
endif()
math(EXPR GCOV_LINE_COUNT "${GCOV_LINE_COUNT}+1")
endforeach()
message("${GCOV_LINE_COUNT} of ${LINE_COUNT} lines read!")
# Advanced way of removing the trailing comma in the JSON array.
# "[1, 2, 3, " -> "[1, 2, 3"
string(REGEX REPLACE ",[ ]*$" "" GCOV_FILE_COVERAGE ${GCOV_FILE_COVERAGE})
# Append the trailing ] to complete the JSON array.
set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}]")
# Generate the final JSON for this file.
message("Generate JSON for file: ${GCOV_SRC_REL_PATH}...")
string(CONFIGURE ${SRC_FILE_TEMPLATE} FILE_JSON)
set(JSON_GCOV_FILES "${JSON_GCOV_FILES}${FILE_JSON}, ")
endforeach()
# Loop through all files we couldn't find any coverage for
# as well, and generate JSON for those as well with 0% coverage.
foreach(NOT_COVERED_SRC ${COVERAGE_SRCS_REMAINING})
# Set variables for json replacement
set(GCOV_SRC_PATH ${NOT_COVERED_SRC})
file(MD5 "${GCOV_SRC_PATH}" GCOV_CONTENTS_MD5)
file(RELATIVE_PATH GCOV_SRC_REL_PATH "${PROJECT_ROOT}" "${GCOV_SRC_PATH}")
# Loads the source file as a list of lines.
file(STRINGS ${NOT_COVERED_SRC} SRC_LINES)
set(GCOV_FILE_COVERAGE "[")
set(GCOV_FILE_SOURCE "")
foreach (SOURCE ${SRC_LINES})
set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}null, ")
string(REPLACE "\\" "\\\\" SOURCE "${SOURCE}")
string(REGEX REPLACE "\"" "\\\\\"" SOURCE "${SOURCE}")
string(REPLACE "\t" "\\\\t" SOURCE "${SOURCE}")
string(REPLACE "\r" "\\\\r" SOURCE "${SOURCE}")
set(GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}${SOURCE}\\n")
endforeach()
# Remove trailing comma, and complete JSON array with ]
string(REGEX REPLACE ",[ ]*$" "" GCOV_FILE_COVERAGE ${GCOV_FILE_COVERAGE})
set(GCOV_FILE_COVERAGE "${GCOV_FILE_COVERAGE}]")
# Generate the final JSON for this file.
message("Generate JSON for non-gcov file: ${NOT_COVERED_SRC}...")
string(CONFIGURE ${SRC_FILE_TEMPLATE} FILE_JSON)
set(JSON_GCOV_FILES "${JSON_GCOV_FILES}${FILE_JSON}, ")
endforeach()
# Get rid of trailing comma.
string(REGEX REPLACE ",[ ]*$" "" JSON_GCOV_FILES ${JSON_GCOV_FILES})
set(JSON_GCOV_FILES "${JSON_GCOV_FILES}]")
# Generate the final complete JSON!
message("Generate final JSON...")
string(CONFIGURE ${JSON_TEMPLATE} JSON)
file(WRITE "${COVERALLS_OUTPUT_FILE}" "${JSON}")
message("###########################################################################")
message("Generated coveralls JSON containing coverage data:")
message("${COVERALLS_OUTPUT_FILE}")
message("###########################################################################")

View File

@ -35,6 +35,7 @@ if(WIN32) # The only platform it makes sense to check for DirectX SDK
"C:/Program Files (x86)/Microsoft DirectX SDK*" "C:/Program Files (x86)/Microsoft DirectX SDK*"
"C:/apps/Microsoft DirectX SDK*" "C:/apps/Microsoft DirectX SDK*"
"C:/Program Files/Microsoft DirectX SDK*" "C:/Program Files/Microsoft DirectX SDK*"
"C:/Program Files (x86)/Windows Kits/8.1"
"$ENV{ProgramFiles}/Microsoft DirectX SDK*" "$ENV{ProgramFiles}/Microsoft DirectX SDK*"
) )
create_search_paths(DirectX) create_search_paths(DirectX)

View File

@ -127,6 +127,7 @@ MACRO(findpkg_framework fwk)
/System/Library/Frameworks /System/Library/Frameworks
/Network/Library/Frameworks /Network/Library/Frameworks
/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/System/Library/Frameworks/ /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/System/Library/Frameworks/
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/System/Library/Frameworks/
) )
FOREACH(dir ${${fwk}_FRAMEWORK_PATH}) FOREACH(dir ${${fwk}_FRAMEWORK_PATH})
SET(fwkpath ${dir}/${fwk}.framework) SET(fwkpath ${dir}/${fwk}.framework)

View File

@ -0,0 +1,20 @@
# Try to find real time libraries
# Once done, this will define
#
# RT_FOUND - system has rt library
# RT_LIBRARIES - rt libraries directory
#
# Source: https://gitlab.cern.ch/dss/eos/commit/44070e575faaa46bd998708ef03eedb381506ff0
#
if(RT_LIBRARIES)
set(RT_FIND_QUIETLY TRUE)
endif(RT_LIBRARIES)
find_library(RT_LIBRARY rt)
set(RT_LIBRARIES ${RT_LIBRARY})
# handle the QUIETLY and REQUIRED arguments and set
# RT_FOUND to TRUE if all listed variables are TRUE
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(rt DEFAULT_MSG RT_LIBRARY)
mark_as_advanced(RT_LIBRARY)

View File

@ -1,25 +1,81 @@
FIND_PATH( if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(ASSIMP_ARCHITECTURE "64")
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
set(ASSIMP_ARCHITECTURE "32")
endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
if(WIN32)
set(ASSIMP_ROOT_DIR CACHE PATH "ASSIMP root directory")
# Find path of each library
find_path(ASSIMP_INCLUDE_DIR
NAMES
assimp/anim.h
HINTS
${ASSIMP_ROOT_DIR}/include
)
if(MSVC12)
set(ASSIMP_MSVC_VERSION "vc120")
elseif(MSVC14)
set(ASSIMP_MSVC_VERSION "vc140")
endif(MSVC12)
if(MSVC12 OR MSVC14)
find_path(ASSIMP_LIBRARY_DIR
NAMES
assimp-${ASSIMP_MSVC_VERSION}-mt.lib
HINTS
${ASSIMP_ROOT_DIR}/lib${ASSIMP_ARCHITECTURE}
)
find_library(ASSIMP_LIBRARY_RELEASE assimp-${ASSIMP_MSVC_VERSION}-mt.lib PATHS ${ASSIMP_LIBRARY_DIR})
find_library(ASSIMP_LIBRARY_DEBUG assimp-${ASSIMP_MSVC_VERSION}-mtd.lib PATHS ${ASSIMP_LIBRARY_DIR})
set(ASSIMP_LIBRARY
optimized ${ASSIMP_LIBRARY_RELEASE}
debug ${ASSIMP_LIBRARY_DEBUG}
)
set(ASSIMP_LIBRARIES "ASSIMP_LIBRARY_RELEASE" "ASSIMP_LIBRARY_DEBUG")
FUNCTION(ASSIMP_COPY_BINARIES TargetDirectory)
ADD_CUSTOM_TARGET(AssimpCopyBinaries
COMMAND ${CMAKE_COMMAND} -E copy ${ASSIMP_ROOT_DIR}/bin${ASSIMP_ARCHITECTURE}/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll ${TargetDirectory}/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll
COMMAND ${CMAKE_COMMAND} -E copy ${ASSIMP_ROOT_DIR}/bin${ASSIMP_ARCHITECTURE}/assimp-${ASSIMP_MSVC_VERSION}-mt.dll ${TargetDirectory}/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.dll
COMMENT "Copying Assimp binaries to '${TargetDirectory}'"
VERBATIM)
ENDFUNCTION(ASSIMP_COPY_BINARIES)
endif()
else(WIN32)
find_path(
assimp_INCLUDE_DIRS assimp_INCLUDE_DIRS
NAMES postprocess.h scene.h version.h config.h cimport.h NAMES postprocess.h scene.h version.h config.h cimport.h
PATHS /usr/local/include/ PATHS /usr/local/include/
) )
FIND_LIBRARY( find_library(
assimp_LIBRARIES assimp_LIBRARIES
NAMES assimp NAMES assimp
PATHS /usr/local/lib/ PATHS /usr/local/lib/
) )
IF (assimp_INCLUDE_DIRS AND assimp_LIBRARIES) if (assimp_INCLUDE_DIRS AND assimp_LIBRARIES)
SET(assimp_FOUND TRUE) SET(assimp_FOUND TRUE)
ENDIF (assimp_INCLUDE_DIRS AND assimp_LIBRARIES) ENDIF (assimp_INCLUDE_DIRS AND assimp_LIBRARIES)
IF (assimp_FOUND) if (assimp_FOUND)
IF (NOT assimp_FIND_QUIETLY) if (NOT assimp_FIND_QUIETLY)
MESSAGE(STATUS "Found asset importer library: ${assimp_LIBRARIES}") message(STATUS "Found asset importer library: ${assimp_LIBRARIES}")
ENDIF (NOT assimp_FIND_QUIETLY) endif (NOT assimp_FIND_QUIETLY)
ELSE (assimp_FOUND) else (assimp_FOUND)
IF (assimp_FIND_REQUIRED) if (assimp_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find asset importer library") message(FATAL_ERROR "Could not find asset importer library")
ENDIF (assimp_FIND_REQUIRED) endif (assimp_FIND_REQUIRED)
ENDIF (assimp_FOUND) endif (assimp_FOUND)
endif(WIN32)

View File

@ -0,0 +1,16 @@
# this one sets internal to crosscompile (in theory)
SET(CMAKE_SYSTEM_NAME Windows)
# the minimalistic settings
SET(CMAKE_C_COMPILER "/usr/bin/x86_64-w64-mingw32-gcc")
SET(CMAKE_CXX_COMPILER "/usr/bin/x86_64-w64-mingw32-g++")
SET(CMAKE_RC_COMPILER "/usr/bin/x86_64-w64-mingw32-windres")
# where is the target (so called staging) environment
SET(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32)
# search for programs in the build host directories (default BOTH)
#SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

View File

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

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
@ -41,12 +41,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the 3ds importer class */ /** @file Implementation of the 3ds importer class */
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
// internal headers // internal headers
#include "3DSLoader.h" #include "3DSLoader.h"
#include "TargetAnimation.h" #include "TargetAnimation.h"
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include "StringComparison.h"
#include <memory>
#include <cctype>
using namespace Assimp; using namespace Assimp;
@ -65,8 +70,9 @@ void Discreet3DSImporter::ReplaceDefaultMaterial()
for (unsigned int i = 0; i < mScene->mMaterials.size();++i) for (unsigned int i = 0; i < mScene->mMaterials.size();++i)
{ {
std::string s = mScene->mMaterials[i].mName; std::string s = mScene->mMaterials[i].mName;
for (std::string::iterator it = s.begin(); it != s.end(); ++it) for ( std::string::iterator it = s.begin(); it != s.end(); ++it ) {
*it = ::tolower(*it); *it = static_cast< char >( ::tolower( *it ) );
}
if (std::string::npos == s.find("default"))continue; if (std::string::npos == s.find("default"))continue;
@ -191,7 +197,7 @@ void CopyTexture(aiMaterial& mat, D3DS::Texture& texture, aiTextureType type)
// Setup the texture blend factor // Setup the texture blend factor
if (is_not_qnan(texture.mTextureBlend)) if (is_not_qnan(texture.mTextureBlend))
mat.AddProperty<float>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0)); mat.AddProperty<ai_real>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
// Setup the texture mapping mode // Setup the texture mapping mode
mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0)); mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0));
@ -201,14 +207,14 @@ void CopyTexture(aiMaterial& mat, D3DS::Texture& texture, aiTextureType type)
// FIXME: this is not really correct ... // FIXME: this is not really correct ...
if (texture.mMapMode == aiTextureMapMode_Mirror) if (texture.mMapMode == aiTextureMapMode_Mirror)
{ {
texture.mScaleU *= 2.f; texture.mScaleU *= 2.0;
texture.mScaleV *= 2.f; texture.mScaleV *= 2.0;
texture.mOffsetU /= 2.f; texture.mOffsetU /= 2.0;
texture.mOffsetV /= 2.f; texture.mOffsetV /= 2.0;
} }
// Setup texture UV transformations // Setup texture UV transformations
mat.AddProperty<float>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0)); mat.AddProperty<ai_real>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -259,10 +265,10 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
} }
// Opacity // Opacity
mat.AddProperty<float>( &oldMat.mTransparency,1,AI_MATKEY_OPACITY); mat.AddProperty<ai_real>( &oldMat.mTransparency,1,AI_MATKEY_OPACITY);
// Bump height scaling // Bump height scaling
mat.AddProperty<float>( &oldMat.mBumpHeight,1,AI_MATKEY_BUMPSCALING); mat.AddProperty<ai_real>( &oldMat.mBumpHeight,1,AI_MATKEY_BUMPSCALING);
// Two sided rendering? // Two sided rendering?
if (oldMat.mTwoSided) if (oldMat.mTwoSided)
@ -353,7 +359,7 @@ void Discreet3DSImporter::ConvertMeshes(aiScene* pcOut)
// we need to split all meshes by their materials // we need to split all meshes by their materials
for (std::vector<D3DS::Mesh>::iterator i = mScene->mMeshes.begin(); i != mScene->mMeshes.end();++i) { for (std::vector<D3DS::Mesh>::iterator i = mScene->mMeshes.begin(); i != mScene->mMeshes.end();++i) {
boost::scoped_array< std::vector<unsigned int> > aiSplit(new std::vector<unsigned int>[mScene->mMaterials.size()]); std::unique_ptr< std::vector<unsigned int>[] > aiSplit(new std::vector<unsigned int>[mScene->mMaterials.size()]);
name.length = ASSIMP_itoa10(name.data,num++); name.length = ASSIMP_itoa10(name.data,num++);
@ -396,7 +402,7 @@ void Discreet3DSImporter::ConvertMeshes(aiScene* pcOut)
} }
for (unsigned int q = 0, base = 0; q < aiSplit[p].size();++q) for (unsigned int q = 0, base = 0; q < aiSplit[p].size();++q)
{ {
register unsigned int index = aiSplit[p][q]; unsigned int index = aiSplit[p][q];
aiFace& face = meshOut->mFaces[q]; aiFace& face = meshOut->mFaces[q];
face.mIndices = new unsigned int[3]; face.mIndices = new unsigned int[3];
@ -658,14 +664,14 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,
nda->mRotationKeys = new aiQuatKey[nda->mNumRotationKeys]; nda->mRotationKeys = new aiQuatKey[nda->mNumRotationKeys];
// Rotations are quaternion offsets // Rotations are quaternion offsets
aiQuaternion abs; aiQuaternion abs1;
for (unsigned int n = 0; n < nda->mNumRotationKeys;++n) for (unsigned int n = 0; n < nda->mNumRotationKeys;++n)
{ {
const aiQuatKey& q = pcIn->aRotationKeys[n]; const aiQuatKey& q = pcIn->aRotationKeys[n];
abs = (n ? abs * q.mValue : q.mValue); abs1 = (n ? abs1 * q.mValue : q.mValue);
nda->mRotationKeys[n].mTime = q.mTime; nda->mRotationKeys[n].mTime = q.mTime;
nda->mRotationKeys[n].mValue = abs.Normalize(); nda->mRotationKeys[n].mValue = abs1.Normalize();
} }
} }
@ -684,7 +690,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,
pcOut->mChildren = new aiNode*[pcIn->mChildren.size()]; pcOut->mChildren = new aiNode*[pcIn->mChildren.size()];
// Recursively process all children // Recursively process all children
const unsigned int size = pcIn->mChildren.size(); const unsigned int size = static_cast<unsigned int>(pcIn->mChildren.size());
for (unsigned int i = 0; i < size;++i) for (unsigned int i = 0; i < size;++i)
{ {
pcOut->mChildren[i] = new aiNode(); pcOut->mChildren[i] = new aiNode();
@ -736,7 +742,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut)
DefaultLogger::get()->warn("No hierarchy information has been found in the file. "); DefaultLogger::get()->warn("No hierarchy information has been found in the file. ");
pcOut->mRootNode->mNumChildren = pcOut->mNumMeshes + pcOut->mRootNode->mNumChildren = pcOut->mNumMeshes +
mScene->mCameras.size() + mScene->mLights.size(); static_cast<unsigned int>(mScene->mCameras.size() + mScene->mLights.size());
pcOut->mRootNode->mChildren = new aiNode* [ pcOut->mRootNode->mNumChildren ]; pcOut->mRootNode->mChildren = new aiNode* [ pcOut->mRootNode->mNumChildren ];
pcOut->mRootNode->mName.Set("<3DSDummyRoot>"); pcOut->mRootNode->mName.Set("<3DSDummyRoot>");
@ -752,7 +758,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut)
pcNode->mNumMeshes = 1; pcNode->mNumMeshes = 1;
// Build a name for the node // Build a name for the node
pcNode->mName.length = sprintf(pcNode->mName.data,"3DSMesh_%i",i); pcNode->mName.length = ai_snprintf(pcNode->mName.data, MAXLEN, "3DSMesh_%u",i);
} }
// Build dummy nodes for all cameras // Build dummy nodes for all cameras

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -38,18 +38,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER #ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
#include "3DSExporter.h" #include "3DSExporter.h"
#include "3DSLoader.h" #include "3DSLoader.h"
#include "3DSHelper.h"
#include "SceneCombiner.h" #include "SceneCombiner.h"
#include "SplitLargeMeshes.h" #include "SplitLargeMeshes.h"
#include "StringComparison.h"
#include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/Exporter.hpp>
#include <memory>
using namespace Assimp; using namespace Assimp;
namespace Assimp { namespace Assimp {
using namespace D3DS;
namespace { namespace {
@ -81,7 +87,7 @@ namespace {
const std::size_t chunk_size = head_pos - chunk_start_pos; const std::size_t chunk_size = head_pos - chunk_start_pos;
writer.SetCurrentPos(chunk_start_pos + SIZE_OFFSET); writer.SetCurrentPos(chunk_start_pos + SIZE_OFFSET);
writer.PutU4(chunk_size); writer.PutU4(static_cast<uint32_t>(chunk_size));
writer.SetCurrentPos(head_pos); writer.SetCurrentPos(head_pos);
} }
@ -144,9 +150,9 @@ namespace {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Worker function for exporting a scene to 3DS. Prototyped and registered in Exporter.cpp // Worker function for exporting a scene to 3DS. Prototyped and registered in Exporter.cpp
void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene) void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
{ {
boost::shared_ptr<IOStream> outfile (pIOSystem->Open(pFile, "wb")); std::shared_ptr<IOStream> outfile (pIOSystem->Open(pFile, "wb"));
if(!outfile) { if(!outfile) {
throw DeadlyExportError("Could not open output .3ds file: " + std::string(pFile)); throw DeadlyExportError("Could not open output .3ds file: " + std::string(pFile));
} }
@ -160,7 +166,7 @@ void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScen
// in |Exporter::ExportFormatEntry|. // in |Exporter::ExportFormatEntry|.
aiScene* scenecopy_tmp; aiScene* scenecopy_tmp;
SceneCombiner::CopyScene(&scenecopy_tmp,pScene); SceneCombiner::CopyScene(&scenecopy_tmp,pScene);
std::auto_ptr<aiScene> scenecopy(scenecopy_tmp); std::unique_ptr<aiScene> scenecopy(scenecopy_tmp);
SplitLargeMeshesProcess_Triangle tri_splitter; SplitLargeMeshesProcess_Triangle tri_splitter;
tri_splitter.SetLimit(0xffff); tri_splitter.SetLimit(0xffff);
@ -177,7 +183,7 @@ void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScen
} // end of namespace Assimp } // end of namespace Assimp
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
Discreet3DSExporter:: Discreet3DSExporter(boost::shared_ptr<IOStream> outfile, const aiScene* scene) Discreet3DSExporter:: Discreet3DSExporter(std::shared_ptr<IOStream> outfile, const aiScene* scene)
: scene(scene) : scene(scene)
, writer(outfile) , writer(outfile)
{ {
@ -188,8 +194,8 @@ Discreet3DSExporter:: Discreet3DSExporter(boost::shared_ptr<IOStream> outfile, c
{ {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJMESH); ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJMESH);
WriteMeshes();
WriteMaterials(); WriteMaterials();
WriteMeshes();
{ {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MASTER_SCALE); ChunkWriter chunk(writer, Discreet3DS::CHUNK_MASTER_SCALE);
@ -294,7 +300,7 @@ void Discreet3DSExporter::WriteMaterials()
WriteColor(color); WriteColor(color);
} }
aiShadingMode shading_mode; aiShadingMode shading_mode = aiShadingMode_Flat;
if (mat.Get(AI_MATKEY_SHADING_MODEL, shading_mode) == AI_SUCCESS) { if (mat.Get(AI_MATKEY_SHADING_MODEL, shading_mode) == AI_SUCCESS) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHADING); ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHADING);
@ -320,6 +326,7 @@ void Discreet3DSExporter::WriteMaterials()
break; break;
default: default:
shading_mode_out = Discreet3DS::Flat;
ai_assert(false); ai_assert(false);
}; };
writer.PutU2(static_cast<uint16_t>(shading_mode_out)); writer.PutU2(static_cast<uint16_t>(shading_mode_out));
@ -360,7 +367,7 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type
aiTextureMapMode map_mode[2] = { aiTextureMapMode map_mode[2] = {
aiTextureMapMode_Wrap, aiTextureMapMode_Wrap aiTextureMapMode_Wrap, aiTextureMapMode_Wrap
}; };
float blend = 1.0f; ai_real blend = 1.0;
if (mat.GetTexture(type, 0, &path, NULL, NULL, &blend, NULL, map_mode) != AI_SUCCESS || !path.length) { if (mat.GetTexture(type, 0, &path, NULL, NULL, &blend, NULL, map_mode) != AI_SUCCESS || !path.length) {
return; return;
} }
@ -555,6 +562,12 @@ void Discreet3DSExporter::WritePercentChunk(float f) {
writer.PutF4(f); writer.PutF4(f);
} }
// ------------------------------------------------------------------------------------------------
void Discreet3DSExporter::WritePercentChunk(double f) {
ChunkWriter chunk(writer, Discreet3DS::CHUNK_PERCENTD);
writer.PutF8(f);
}
#endif // ASSIMP_BUILD_NO_3DS_EXPORTER #endif // ASSIMP_BUILD_NO_3DS_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT #endif // ASSIMP_BUILD_NO_EXPORT

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -45,11 +45,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_3DSEXPORTER_H_INC #define AI_3DSEXPORTER_H_INC
#include <map> #include <map>
#include <memory>
#include "StreamWriter.h" #include "StreamWriter.h"
#include "./../include/assimp/material.h"
struct aiScene; struct aiScene;
struct aiNode; struct aiNode;
struct aiMaterial;
struct aiMesh;
namespace Assimp namespace Assimp
{ {
@ -60,7 +64,7 @@ namespace Assimp
class Discreet3DSExporter class Discreet3DSExporter
{ {
public: public:
Discreet3DSExporter(boost::shared_ptr<IOStream> outfile, const aiScene* pScene); Discreet3DSExporter(std::shared_ptr<IOStream> outfile, const aiScene* pScene);
private: private:
@ -76,6 +80,7 @@ private:
void WriteString(const aiString& s); void WriteString(const aiString& s);
void WriteColor(const aiColor3D& color); void WriteColor(const aiColor3D& color);
void WritePercentChunk(float f); void WritePercentChunk(float f);
void WritePercentChunk(double f);
private: private:

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -46,6 +46,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SpatialSort.h" #include "SpatialSort.h"
#include "SmoothingGroups.h" #include "SmoothingGroups.h"
#include "StringUtils.h"
#include "qnan.h"
#include "./../include/assimp/material.h"
#include "./../include/assimp/camera.h"
#include "./../include/assimp/light.h"
#include "./../include/assimp/anim.h"
#include <stdio.h> //sprintf
namespace Assimp { namespace Assimp {
namespace D3DS { namespace D3DS {
@ -122,6 +129,7 @@ public:
CHUNK_PERCENTW = 0x0030, // int2 percentage CHUNK_PERCENTW = 0x0030, // int2 percentage
CHUNK_PERCENTF = 0x0031, // float4 percentage CHUNK_PERCENTF = 0x0031, // float4 percentage
CHUNK_PERCENTD = 0x0032, // float8 percentage
// ******************************************************************** // ********************************************************************
// Prj master chunk // Prj master chunk
@ -320,29 +328,30 @@ struct Texture
{ {
//! Default constructor //! Default constructor
Texture() Texture()
: mOffsetU (0.0f) : mOffsetU (0.0)
, mOffsetV (0.0f) , mOffsetV (0.0)
, mScaleU (1.0f) , mScaleU (1.0)
, mScaleV (1.0f) , mScaleV (1.0)
, mRotation (0.0f) , mRotation (0.0)
, mMapMode (aiTextureMapMode_Wrap) , mMapMode (aiTextureMapMode_Wrap)
, bPrivate()
, iUVSrc (0) , iUVSrc (0)
{ {
mTextureBlend = get_qnan(); mTextureBlend = get_qnan();
} }
//! Specifies the blend factor for the texture //! Specifies the blend factor for the texture
float mTextureBlend; ai_real mTextureBlend;
//! Specifies the filename of the texture //! Specifies the filename of the texture
std::string mMapName; std::string mMapName;
//! Specifies texture coordinate offsets/scaling/rotations //! Specifies texture coordinate offsets/scaling/rotations
float mOffsetU; ai_real mOffsetU;
float mOffsetV; ai_real mOffsetV;
float mScaleU; ai_real mScaleU;
float mScaleV; ai_real mScaleV;
float mRotation; ai_real mRotation;
//! Specifies the mapping mode to be used for the texture //! Specifies the mapping mode to be used for the texture
aiTextureMapMode mMapMode; aiTextureMapMode mMapMode;
@ -360,19 +369,18 @@ struct Material
{ {
//! Default constructor. Builds a default name for the material //! Default constructor. Builds a default name for the material
Material() Material()
: : mDiffuse ( ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 0.6 ) ) // FIX ... we won't want object to be black
mDiffuse (0.6f,0.6f,0.6f), // FIX ... we won't want object to be black , mSpecularExponent ( ai_real( 0.0 ) )
mSpecularExponent (0.0f), , mShininessStrength ( ai_real( 1.0 ) )
mShininessStrength (1.0f), , mShading(Discreet3DS::Gouraud)
mShading(Discreet3DS::Gouraud), , mTransparency ( ai_real( 1.0 ) )
mTransparency (1.0f), , mBumpHeight ( ai_real( 1.0 ) )
mBumpHeight (1.0f), , mTwoSided (false)
mTwoSided (false)
{ {
static int iCnt = 0; static int iCnt = 0;
char szTemp[128]; char szTemp[128];
sprintf(szTemp,"UNNAMED_%i",iCnt++); ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
mName = szTemp; mName = szTemp;
} }
@ -381,9 +389,9 @@ struct Material
//! Diffuse color of the material //! Diffuse color of the material
aiColor3D mDiffuse; aiColor3D mDiffuse;
//! Specular exponent //! Specular exponent
float mSpecularExponent; ai_real mSpecularExponent;
//! Shininess strength, in percent //! Shininess strength, in percent
float mShininessStrength; ai_real mShininessStrength;
//! Specular color of the material //! Specular color of the material
aiColor3D mSpecular; aiColor3D mSpecular;
//! Ambient color of the material //! Ambient color of the material
@ -391,7 +399,7 @@ struct Material
//! Shading type to be used //! Shading type to be used
Discreet3DS::shadetype3ds mShading; Discreet3DS::shadetype3ds mShading;
//! Opacity of the material //! Opacity of the material
float mTransparency; ai_real mTransparency;
//! Diffuse texture channel //! Diffuse texture channel
Texture sTexDiffuse; Texture sTexDiffuse;
//! Opacity texture channel //! Opacity texture channel
@ -407,7 +415,7 @@ struct Material
//! Shininess texture channel //! Shininess texture channel
Texture sTexShininess; Texture sTexShininess;
//! Scaling factor for the bump values //! Scaling factor for the bump values
float mBumpHeight; ai_real mBumpHeight;
//! Emissive color //! Emissive color
aiColor3D mEmissive; aiColor3D mEmissive;
//! Ambient texture channel //! Ambient texture channel
@ -428,7 +436,7 @@ struct Mesh : public MeshWithSmoothingGroups<D3DS::Face>
// Generate a default name for the mesh // Generate a default name for the mesh
char szTemp[128]; char szTemp[128];
::sprintf(szTemp,"UNNAMED_%i",iCnt++); ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
mName = szTemp; mName = szTemp;
} }
@ -451,7 +459,7 @@ struct Mesh : public MeshWithSmoothingGroups<D3DS::Face>
struct aiFloatKey struct aiFloatKey
{ {
double mTime; ///< The time of this key double mTime; ///< The time of this key
float mValue; ///< The value of this key ai_real mValue; ///< The value of this key
#ifdef __cplusplus #ifdef __cplusplus
@ -468,7 +476,7 @@ struct aiFloatKey
{return mTime < o.mTime;} {return mTime < o.mTime;}
bool operator > (const aiFloatKey& o) const bool operator > (const aiFloatKey& o) const
{return mTime < o.mTime;} {return mTime > o.mTime;}
#endif #endif
}; };
@ -477,18 +485,18 @@ struct aiFloatKey
/** Helper structure to represent a 3ds file node */ /** Helper structure to represent a 3ds file node */
struct Node struct Node
{ {
Node() Node():
mParent(NULL)
: mHierarchyPos (0) , mInstanceNumber(0)
, mHierarchyPos (0)
, mHierarchyIndex (0) , mHierarchyIndex (0)
, mInstanceCount (1) , mInstanceCount (1)
{ {
static int iCnt = 0; static int iCnt = 0;
// Generate a default name for the node // Generate a default name for the node
char szTemp[128]; char szTemp[128];
::sprintf(szTemp,"UNNAMED_%i",iCnt++); ::ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
mName = szTemp; mName = szTemp;
aRotationKeys.reserve (20); aRotationKeys.reserve (20);

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
@ -45,11 +45,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* http://www.the-labs.com/Blender/3DS-details.html * http://www.the-labs.com/Blender/3DS-details.html
*/ */
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
// internal headers // internal headers
#include "3DSLoader.h" #include "3DSLoader.h"
#include "Macros.h"
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include "StringComparison.h"
using namespace Assimp; using namespace Assimp;
@ -81,8 +86,8 @@ static const aiImporterDesc desc = {
int chunkSize = chunk.Size-sizeof(Discreet3DS::Chunk); \ int chunkSize = chunk.Size-sizeof(Discreet3DS::Chunk); \
if(chunkSize <= 0) \ if(chunkSize <= 0) \
continue; \ continue; \
const int oldReadLimit = stream->GetReadLimit(); \ const unsigned int oldReadLimit = stream->SetReadLimit( \
stream->SetReadLimit(stream->GetCurrentPos() + chunkSize); \ stream->GetCurrentPos() + chunkSize); \
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -98,6 +103,14 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
Discreet3DSImporter::Discreet3DSImporter() Discreet3DSImporter::Discreet3DSImporter()
: stream(),
mLastNodeIndex(),
mCurrentNode(),
mRootNode(),
mScene(),
mMasterScale(),
bHasBG(),
bIsPrj()
{} {}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -169,18 +182,21 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile,
ParseMainChunk(); ParseMainChunk();
// Process all meshes in the file. First check whether all // Process all meshes in the file. First check whether all
// face indices haev valid values. The generate our // face indices have valid values. The generate our
// internal verbose representation. Finally compute normal // internal verbose representation. Finally compute normal
// vectors from the smoothing groups we read from the // vectors from the smoothing groups we read from the
// file. // file.
for (std::vector<D3DS::Mesh>::iterator i = mScene->mMeshes.begin(), for (auto &mesh : mScene->mMeshes) {
end = mScene->mMeshes.end(); i != end;++i) { if (mesh.mFaces.size() > 0 && mesh.mPositions.size() == 0) {
CheckIndices(*i); delete mScene;
MakeUnique (*i); throw DeadlyImportError("3DS file contains faces but no vertices: " + pFile);
ComputeNormalsWithSmoothingsGroups<D3DS::Face>(*i); }
CheckIndices(mesh);
MakeUnique (mesh);
ComputeNormalsWithSmoothingsGroups<D3DS::Face>(mesh);
} }
// Replace all occurences of the default material with a // Replace all occurrences of the default material with a
// valid material. Generate it if no material containing // valid material. Generate it if no material containing
// DEFAULT in its name has been found in the file // DEFAULT in its name has been found in the file
ReplaceDefaultMaterial(); ReplaceDefaultMaterial();
@ -442,20 +458,20 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num)
camera->mLookAt.x = stream->GetF4() - camera->mPosition.x; camera->mLookAt.x = stream->GetF4() - camera->mPosition.x;
camera->mLookAt.y = stream->GetF4() - camera->mPosition.y; camera->mLookAt.y = stream->GetF4() - camera->mPosition.y;
camera->mLookAt.z = stream->GetF4() - camera->mPosition.z; camera->mLookAt.z = stream->GetF4() - camera->mPosition.z;
float len = camera->mLookAt.Length(); ai_real len = camera->mLookAt.Length();
if (len < 1e-5f) { if (len < 1e-5) {
// There are some files with lookat == position. Don't know why or whether it's ok or not. // There are some files with lookat == position. Don't know why or whether it's ok or not.
DefaultLogger::get()->error("3DS: Unable to read proper camera look-at vector"); DefaultLogger::get()->error("3DS: Unable to read proper camera look-at vector");
camera->mLookAt = aiVector3D(0.f,1.f,0.f); camera->mLookAt = aiVector3D(0.0,1.0,0.0);
} }
else camera->mLookAt /= len; else camera->mLookAt /= len;
// And finally - the camera rotation angle, in counter clockwise direction // And finally - the camera rotation angle, in counter clockwise direction
const float angle = AI_DEG_TO_RAD( stream->GetF4() ); const ai_real angle = AI_DEG_TO_RAD( stream->GetF4() );
aiQuaternion quat(camera->mLookAt,angle); aiQuaternion quat(camera->mLookAt,angle);
camera->mUp = quat.GetMatrix() * aiVector3D(0.f,1.f,0.f); camera->mUp = quat.GetMatrix() * aiVector3D(0.0,1.0,0.0);
// Read the lense angle // Read the lense angle
camera->mHorizontalFOV = AI_DEG_TO_RAD ( stream->GetF4() ); camera->mHorizontalFOV = AI_DEG_TO_RAD ( stream->GetF4() );
@ -663,7 +679,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
if ( pcNode) if ( pcNode)
{ {
// if the source is not a CHUNK_TRACKINFO block it wont be an object instance // if the source is not a CHUNK_TRACKINFO block it won't be an object instance
if (parent != Discreet3DS::CHUNK_TRACKINFO) if (parent != Discreet3DS::CHUNK_TRACKINFO)
{ {
mCurrentNode = pcNode; mCurrentNode = pcNode;
@ -944,6 +960,9 @@ void Discreet3DSImporter::ParseFaceChunk()
// This is the list of smoothing groups - a bitfield for every face. // This is the list of smoothing groups - a bitfield for every face.
// Up to 32 smoothing groups assigned to a single face. // Up to 32 smoothing groups assigned to a single face.
unsigned int num = chunkSize/4, m = 0; unsigned int num = chunkSize/4, m = 0;
if (num > mMesh.mFaces.size()) {
throw DeadlyImportError("3DS: More smoothing groups than faces");
}
for (std::vector<D3DS::Face>::iterator i = mMesh.mFaces.begin(); m != num;++i, ++m) { for (std::vector<D3DS::Face>::iterator i = mMesh.mFaces.begin(); m != num;++i, ++m) {
// nth bit is set for nth smoothing group // nth bit is set for nth smoothing group
(*i).iSmoothGroup = stream->GetI4(); (*i).iSmoothGroup = stream->GetI4();
@ -1148,13 +1167,14 @@ void Discreet3DSImporter::ParseMaterialChunk()
case Discreet3DS::CHUNK_MAT_TRANSPARENCY: case Discreet3DS::CHUNK_MAT_TRANSPARENCY:
{ {
// This is the material's transparency // This is the material's transparency
float* pcf = &mScene->mMaterials.back().mTransparency; ai_real* pcf = &mScene->mMaterials.back().mTransparency;
*pcf = ParsePercentageChunk(); *pcf = ParsePercentageChunk();
// NOTE: transparency, not opacity // NOTE: transparency, not opacity
if (is_qnan(*pcf)) if (is_qnan(*pcf))
*pcf = 1.0f; *pcf = ai_real( 1.0 );
else *pcf = 1.0f - *pcf * (float)0xFFFF / 100.0f; else
*pcf = ai_real( 1.0 ) - *pcf * (ai_real)0xFFFF / ai_real( 100.0 );
} }
break; break;
@ -1170,30 +1190,32 @@ void Discreet3DSImporter::ParseMaterialChunk()
case Discreet3DS::CHUNK_MAT_SHININESS: case Discreet3DS::CHUNK_MAT_SHININESS:
{ // This is the shininess of the material { // This is the shininess of the material
float* pcf = &mScene->mMaterials.back().mSpecularExponent; ai_real* pcf = &mScene->mMaterials.back().mSpecularExponent;
*pcf = ParsePercentageChunk(); *pcf = ParsePercentageChunk();
if (is_qnan(*pcf)) if (is_qnan(*pcf))
*pcf = 0.0f; *pcf = 0.0;
else *pcf *= (float)0xFFFF; else *pcf *= (ai_real)0xFFFF;
} }
break; break;
case Discreet3DS::CHUNK_MAT_SHININESS_PERCENT: case Discreet3DS::CHUNK_MAT_SHININESS_PERCENT:
{ // This is the shininess strength of the material { // This is the shininess strength of the material
float* pcf = &mScene->mMaterials.back().mShininessStrength; ai_real* pcf = &mScene->mMaterials.back().mShininessStrength;
*pcf = ParsePercentageChunk(); *pcf = ParsePercentageChunk();
if (is_qnan(*pcf)) if (is_qnan(*pcf))
*pcf = 0.0f; *pcf = ai_real( 0.0 );
else *pcf *= (float)0xffff / 100.0f; else
*pcf *= (ai_real)0xffff / ai_real( 100.0 );
} }
break; break;
case Discreet3DS::CHUNK_MAT_SELF_ILPCT: case Discreet3DS::CHUNK_MAT_SELF_ILPCT:
{ // This is the self illumination strength of the material { // This is the self illumination strength of the material
float f = ParsePercentageChunk(); ai_real f = ParsePercentageChunk();
if (is_qnan(f)) if (is_qnan(f))
f = 0.0f; f = ai_real( 0.0 );
else f *= (float)0xFFFF / 100.0f; else
f *= (ai_real)0xFFFF / ai_real( 100.0 );
mScene->mMaterials.back().mEmissive = aiColor3D(f,f,f); mScene->mMaterials.back().mEmissive = aiColor3D(f,f,f);
} }
break; break;
@ -1251,6 +1273,11 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
break; break;
case Discreet3DS::CHUNK_PERCENTD:
// Manually parse the blend factor
pcOut->mTextureBlend = ai_real( stream->GetF8() );
break;
case Discreet3DS::CHUNK_PERCENTF: case Discreet3DS::CHUNK_PERCENTF:
// Manually parse the blend factor // Manually parse the blend factor
pcOut->mTextureBlend = stream->GetF4(); pcOut->mTextureBlend = stream->GetF4();
@ -1258,7 +1285,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
case Discreet3DS::CHUNK_PERCENTW: case Discreet3DS::CHUNK_PERCENTW:
// Manually parse the blend factor // Manually parse the blend factor
pcOut->mTextureBlend = (float)((uint16_t)stream->GetI2()) / 100.0f; pcOut->mTextureBlend = (ai_real)((uint16_t)stream->GetI2()) / ai_real( 100.0 );
break; break;
case Discreet3DS::CHUNK_MAT_MAP_USCALE: case Discreet3DS::CHUNK_MAT_MAP_USCALE:
@ -1317,7 +1344,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Read a percentage chunk // Read a percentage chunk
float Discreet3DSImporter::ParsePercentageChunk() ai_real Discreet3DSImporter::ParsePercentageChunk()
{ {
Discreet3DS::Chunk chunk; Discreet3DS::Chunk chunk;
ReadChunk(&chunk); ReadChunk(&chunk);
@ -1325,19 +1352,18 @@ float Discreet3DSImporter::ParsePercentageChunk()
if (Discreet3DS::CHUNK_PERCENTF == chunk.Flag) if (Discreet3DS::CHUNK_PERCENTF == chunk.Flag)
return stream->GetF4(); return stream->GetF4();
else if (Discreet3DS::CHUNK_PERCENTW == chunk.Flag) else if (Discreet3DS::CHUNK_PERCENTW == chunk.Flag)
return (float)((uint16_t)stream->GetI2()) / (float)0xFFFF; return (ai_real)((uint16_t)stream->GetI2()) / (ai_real)0xFFFF;
return get_qnan(); return get_qnan();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Read a color chunk. If a percentage chunk is found instead it is read as a grayscale color // Read a color chunk. If a percentage chunk is found instead it is read as a grayscale color
void Discreet3DSImporter::ParseColorChunk(aiColor3D* out, void Discreet3DSImporter::ParseColorChunk( aiColor3D* out, bool acceptPercent )
bool acceptPercent)
{ {
ai_assert(out != NULL); ai_assert(out != NULL);
// error return value // error return value
const float qnan = get_qnan(); const ai_real qnan = get_qnan();
static const aiColor3D clrError = aiColor3D(qnan,qnan,qnan); static const aiColor3D clrError = aiColor3D(qnan,qnan,qnan);
Discreet3DS::Chunk chunk; Discreet3DS::Chunk chunk;
@ -1353,7 +1379,7 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D* out,
bGamma = true; bGamma = true;
case Discreet3DS::CHUNK_RGBF: case Discreet3DS::CHUNK_RGBF:
if (sizeof(float) * 3 > diff) { if (sizeof(ai_real) * 3 > diff) {
*out = clrError; *out = clrError;
return; return;
} }
@ -1365,13 +1391,16 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D* out,
case Discreet3DS::CHUNK_LINRGBB: case Discreet3DS::CHUNK_LINRGBB:
bGamma = true; bGamma = true;
case Discreet3DS::CHUNK_RGBB: case Discreet3DS::CHUNK_RGBB:
if (sizeof(char) * 3 > diff) { {
if ( sizeof( char ) * 3 > diff ) {
*out = clrError; *out = clrError;
return; return;
} }
out->r = (float)(uint8_t)stream->GetI1() / 255.0f; const ai_real invVal = ai_real( 1.0 ) / ai_real( 255.0 );
out->g = (float)(uint8_t)stream->GetI1() / 255.0f; out->r = ( ai_real ) ( uint8_t ) stream->GetI1() * invVal;
out->b = (float)(uint8_t)stream->GetI1() / 255.0f; out->g = ( ai_real ) ( uint8_t ) stream->GetI1() * invVal;
out->b = ( ai_real ) ( uint8_t ) stream->GetI1() * invVal;
}
break; break;
// Percentage chunks are accepted, too. // Percentage chunks are accepted, too.
@ -1385,7 +1414,7 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D* out,
case Discreet3DS::CHUNK_PERCENTW: case Discreet3DS::CHUNK_PERCENTW:
if (acceptPercent && 1 <= diff) { if (acceptPercent && 1 <= diff) {
out->g = out->b = out->r = (float)(uint8_t)stream->GetI1() / 255.0f; out->g = out->b = out->r = (ai_real)(uint8_t)stream->GetI1() / ai_real( 255.0 );
break; break;
} }
*out = clrError; *out = clrError;

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -46,12 +46,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_3DSIMPORTER_H_INC #define AI_3DSIMPORTER_H_INC
#include "BaseImporter.h" #include "BaseImporter.h"
#include "../include/assimp/types.h" #include <assimp/types.h>
#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
struct aiNode;
#include "3DSHelper.h" #include "3DSHelper.h"
#include "StreamReader.h"
struct aiNode;
namespace Assimp { namespace Assimp {
@ -117,7 +119,7 @@ protected:
* chunk behind afterwards. If no percentage chunk is found * chunk behind afterwards. If no percentage chunk is found
* QNAN is returned. * QNAN is returned.
*/ */
float ParsePercentageChunk(); ai_real ParsePercentageChunk();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Parse a color chunk. mCurrent will point to the next /** Parse a color chunk. mCurrent will point to the next
@ -263,7 +265,7 @@ protected:
aiColor3D mClrAmbient; aiColor3D mClrAmbient;
/** Master scaling factor of the scene */ /** Master scaling factor of the scene */
float mMasterScale; ai_real mMasterScale;
/** Path to the background image of the scene */ /** Path to the background image of the scene */
std::string mBackgroundImage; std::string mBackgroundImage;

View File

@ -4,7 +4,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
@ -42,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the AC3D importer class */ /** @file Implementation of the AC3D importer class */
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_AC_IMPORTER #ifndef ASSIMP_BUILD_NO_AC_IMPORTER
@ -51,6 +51,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ParsingUtils.h" #include "ParsingUtils.h"
#include "fast_atof.h" #include "fast_atof.h"
#include "Subdivision.h" #include "Subdivision.h"
#include "Importer.h"
#include "BaseImporter.h"
#include <assimp/Importer.hpp>
#include <assimp/light.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/material.h>
#include <assimp/scene.h>
#include <assimp/config.h>
#include <assimp/IOSystem.hpp>
#include <memory>
using namespace Assimp; using namespace Assimp;
@ -79,6 +89,9 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// read a string (may be enclosed in double quotation marks). buffer must point to " // read a string (may be enclosed in double quotation marks). buffer must point to "
#define AI_AC_GET_STRING(out) \ #define AI_AC_GET_STRING(out) \
if (*buffer == '\0') { \
throw DeadlyImportError("AC3D: Unexpected EOF in string"); \
} \
++buffer; \ ++buffer; \
const char* sz = buffer; \ const char* sz = buffer; \
while ('\"' != *buffer) \ while ('\"' != *buffer) \
@ -119,6 +132,15 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
AC3DImporter::AC3DImporter() AC3DImporter::AC3DImporter()
: buffer(),
configSplitBFCull(),
configEvalSubdivision(),
mNumMeshes(),
mLights(),
lights(),
groups(),
polys(),
worlds()
{ {
// nothing to be done here // nothing to be done here
} }
@ -189,7 +211,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
// Generate a default name for both the light source and the node // Generate a default name for both the light source and the node
// FIXME - what's the right way to print a size_t? Is 'zu' universally available? stick with the safe version. // FIXME - what's the right way to print a size_t? Is 'zu' universally available? stick with the safe version.
light->mName.length = ::sprintf(light->mName.data,"ACLight_%i",static_cast<unsigned int>(mLights->size())-1); light->mName.length = ::ai_snprintf(light->mName.data, MAXLEN, "ACLight_%i",static_cast<unsigned int>(mLights->size())-1);
obj.name = std::string( light->mName.data ); obj.name = std::string( light->mName.data );
DefaultLogger::get()->debug("AC3D: Light source encountered"); DefaultLogger::get()->debug("AC3D: Light source encountered");
@ -274,6 +296,9 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
SkipSpaces(&buffer); SkipSpaces(&buffer);
unsigned int t = strtoul10(buffer,&buffer); unsigned int t = strtoul10(buffer,&buffer);
if (t >= AI_MAX_ALLOC(aiVector3D)) {
throw DeadlyImportError("AC3D: Too many vertices, would run out of memory");
}
obj.vertices.reserve(t); obj.vertices.reserve(t);
for (unsigned int i = 0; i < t;++i) for (unsigned int i = 0; i < t;++i)
{ {
@ -327,8 +352,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
{ {
if(!GetNextLine()) if(!GetNextLine())
{ {
DefaultLogger::get()->error("AC3D: Unexpected EOF: surface is incomplete"); throw DeadlyImportError("AC3D: Unexpected EOF: surface is incomplete");
break;
} }
if (TokenMatch(buffer,"mat",3)) if (TokenMatch(buffer,"mat",3))
{ {
@ -489,7 +513,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
for (it = object.surfaces.begin(); it != end; ++it) for (it = object.surfaces.begin(); it != end; ++it)
{ {
register unsigned int idx = (*it).mat; unsigned int idx = (*it).mat;
if (idx >= needMat.size()) if (idx >= needMat.size())
{ {
DefaultLogger::get()->error("AC3D: material index is out of range"); DefaultLogger::get()->error("AC3D: material index is out of range");
@ -563,9 +587,19 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
// allocate storage for vertices and normals // allocate storage for vertices and normals
mesh->mNumFaces = (*cit).first; mesh->mNumFaces = (*cit).first;
if (mesh->mNumFaces == 0) {
throw DeadlyImportError("AC3D: No faces");
} else if (mesh->mNumFaces > AI_MAX_ALLOC(aiFace)) {
throw DeadlyImportError("AC3D: Too many faces, would run out of memory");
}
aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces]; aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
mesh->mNumVertices = (*cit).second; mesh->mNumVertices = (*cit).second;
if (mesh->mNumVertices == 0) {
throw DeadlyImportError("AC3D: No vertices");
} else if (mesh->mNumVertices > AI_MAX_ALLOC(aiVector3D)) {
throw DeadlyImportError("AC3D: Too many vertices, would run out of memory");
}
aiVector3D* vertices = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; aiVector3D* vertices = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
unsigned int cur = 0; unsigned int cur = 0;
@ -598,6 +632,9 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
face.mIndices[i] = cur++; face.mIndices[i] = cur++;
// copy vertex positions // copy vertex positions
if (static_cast<unsigned>(vertices - mesh->mVertices) >= mesh->mNumVertices) {
throw DeadlyImportError("AC3D: Invalid number of vertices");
}
*vertices = object.vertices[entry.first] + object.translation; *vertices = object.vertices[entry.first] + object.translation;
@ -617,7 +654,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
it2 = (*it).entries.begin(); it2 = (*it).entries.begin();
// either a closed or an unclosed line // either a closed or an unclosed line
register unsigned int tmp = (unsigned int)(*it).entries.size(); unsigned int tmp = (unsigned int)(*it).entries.size();
if (0x2 == type)--tmp; if (0x2 == type)--tmp;
for (unsigned int m = 0; m < tmp;++m) for (unsigned int m = 0; m < tmp;++m)
{ {
@ -629,6 +666,10 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
face.mIndices[1] = cur++; face.mIndices[1] = cur++;
// copy vertex positions // copy vertex positions
if (it2 == (*it).entries.end() ) {
throw DeadlyImportError("AC3D: Bad line");
}
ai_assert((*it2).first < object.vertices.size());
*vertices++ = object.vertices[(*it2).first]; *vertices++ = object.vertices[(*it2).first];
// copy texture coordinates // copy texture coordinates
@ -667,7 +708,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
// collect all meshes using the same material group. // collect all meshes using the same material group.
if (object.subDiv) { if (object.subDiv) {
if (configEvalSubdivision) { if (configEvalSubdivision) {
boost::scoped_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE)); std::unique_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE));
DefaultLogger::get()->info("AC3D: Evaluating subdivision surface: "+object.name); DefaultLogger::get()->info("AC3D: Evaluating subdivision surface: "+object.name);
std::vector<aiMesh*> cpy(meshes.size()-oldm,NULL); std::vector<aiMesh*> cpy(meshes.size()-oldm,NULL);
@ -692,18 +733,18 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
switch (object.type) switch (object.type)
{ {
case Object::Group: case Object::Group:
node->mName.length = ::sprintf(node->mName.data,"ACGroup_%i",groups++); node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACGroup_%i",groups++);
break; break;
case Object::Poly: case Object::Poly:
node->mName.length = ::sprintf(node->mName.data,"ACPoly_%i",polys++); node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACPoly_%i",polys++);
break; break;
case Object::Light: case Object::Light:
node->mName.length = ::sprintf(node->mName.data,"ACLight_%i",lights++); node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACLight_%i",lights++);
break; break;
// there shouldn't be more than one world, but we don't care // there shouldn't be more than one world, but we don't care
case Object::World: case Object::World:
node->mName.length = ::sprintf(node->mName.data,"ACWorld_%i",worlds++); node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACWorld_%i",worlds++);
break; break;
} }
} }
@ -746,7 +787,7 @@ void AC3DImporter::SetupProperties(const Importer* pImp)
void AC3DImporter::InternReadFile( const std::string& pFile, void AC3DImporter::InternReadFile( const std::string& pFile,
aiScene* pScene, IOSystem* pIOHandler) aiScene* pScene, IOSystem* pIOHandler)
{ {
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
// Check whether we can read from the file // Check whether we can read from the file
if( file.get() == NULL) if( file.get() == NULL)
@ -843,7 +884,7 @@ void AC3DImporter::InternReadFile( const std::string& pFile,
// copy meshes // copy meshes
if (meshes.empty()) if (meshes.empty())
{ {
throw DeadlyImportError("An unknown error occured during converting"); throw DeadlyImportError("An unknown error occurred during converting");
} }
pScene->mNumMeshes = (unsigned int)meshes.size(); pScene->mNumMeshes = (unsigned int)meshes.size();
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -47,7 +47,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector> #include <vector>
#include "BaseImporter.h" #include "BaseImporter.h"
#include "../include/assimp/types.h" #include <assimp/types.h>
struct aiNode;
struct aiMesh;
struct aiMaterial;
struct aiLight;
namespace Assimp { namespace Assimp {
@ -124,6 +130,7 @@ public:
, surfaces() , surfaces()
, numRefs (0) , numRefs (0)
, subDiv (0) , subDiv (0)
, crease()
{} {}
// Type description // Type description

View File

@ -0,0 +1,704 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2016, 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 AMFImporter.cpp
/// \brief AMF-format files importer for Assimp: main algorithm implementation.
/// \date 2016
/// \author smal.root@gmail.com
#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
// Header files, Assimp.
#include "AMFImporter.hpp"
#include "AMFImporter_Macro.hpp"
#include "fast_atof.h"
#include "DefaultIOSystem.h"
// Header files, stdlib.
#include <memory>
#include <string>
namespace Assimp
{
/// \var aiImporterDesc AMFImporter::Description
/// Conastant which hold importer description
const aiImporterDesc AMFImporter::Description = {
"Additive manufacturing file format(AMF) Importer",
"smalcom",
"",
"See documentation in source code. Chapter: Limitations.",
aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental,
0,
0,
0,
0,
"amf"
};
void AMFImporter::Clear()
{
mNodeElement_Cur = nullptr;
mUnit.clear();
mMaterial_Converted.clear();
mTexture_Converted.clear();
// Delete all elements
if(mNodeElement_List.size())
{
for(CAMFImporter_NodeElement* ne: mNodeElement_List) { delete ne; }
mNodeElement_List.clear();
}
}
AMFImporter::~AMFImporter()
{
if(mReader != nullptr) delete mReader;
// Clear() is accounting if data already is deleted. So, just check again if all data is deleted.
Clear();
}
/*********************************************************************************************************************************************/
/************************************************************ Functions: find set ************************************************************/
/*********************************************************************************************************************************************/
bool AMFImporter::Find_NodeElement(const std::string& pID, const CAMFImporter_NodeElement::EType pType, CAMFImporter_NodeElement** pNodeElement) const
{
for(CAMFImporter_NodeElement* ne: mNodeElement_List)
{
if((ne->ID == pID) && (ne->Type == pType))
{
if(pNodeElement != nullptr) *pNodeElement = ne;
return true;
}
}// for(CAMFImporter_NodeElement* ne: mNodeElement_List)
return false;
}
bool AMFImporter::Find_ConvertedNode(const std::string& pID, std::list<aiNode*>& pNodeList, aiNode** pNode) const
{
aiString node_name(pID.c_str());
for(aiNode* node: pNodeList)
{
if(node->mName == node_name)
{
if(pNode != nullptr) *pNode = node;
return true;
}
}// for(aiNode* node: pNodeList)
return false;
}
bool AMFImporter::Find_ConvertedMaterial(const std::string& pID, const SPP_Material** pConvertedMaterial) const
{
for(const SPP_Material& mat: mMaterial_Converted)
{
if(mat.ID == pID)
{
if(pConvertedMaterial != nullptr) *pConvertedMaterial = &mat;
return true;
}
}// for(const SPP_Material& mat: mMaterial_Converted)
return false;
}
/*********************************************************************************************************************************************/
/************************************************************ Functions: throw set ***********************************************************/
/*********************************************************************************************************************************************/
void AMFImporter::Throw_CloseNotFound(const std::string& pNode)
{
throw DeadlyImportError("Close tag for node <" + pNode + "> not found. Seems file is corrupt.");
}
void AMFImporter::Throw_IncorrectAttr(const std::string& pAttrName)
{
throw DeadlyImportError("Node <" + std::string(mReader->getNodeName()) + "> has incorrect attribute \"" + pAttrName + "\".");
}
void AMFImporter::Throw_IncorrectAttrValue(const std::string& pAttrName)
{
throw DeadlyImportError("Attribute \"" + pAttrName + "\" in node <" + std::string(mReader->getNodeName()) + "> has incorrect value.");
}
void AMFImporter::Throw_MoreThanOnceDefined(const std::string& pNodeType, const std::string& pDescription)
{
throw DeadlyImportError("\"" + pNodeType + "\" node can be used only once in " + mReader->getNodeName() + ". Description: " + pDescription);
}
void AMFImporter::Throw_ID_NotFound(const std::string& pID) const
{
throw DeadlyImportError("Not found node with name \"" + pID + "\".");
}
/*********************************************************************************************************************************************/
/************************************************************* Functions: XML set ************************************************************/
/*********************************************************************************************************************************************/
void AMFImporter::XML_CheckNode_MustHaveChildren()
{
if(mReader->isEmptyElement()) throw DeadlyImportError(std::string("Node <") + mReader->getNodeName() + "> must have children.");
}
void AMFImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName)
{
static const size_t Uns_Skip_Len = 3;
const char* Uns_Skip[Uns_Skip_Len] = { "composite", "edge", "normal" };
static bool skipped_before[Uns_Skip_Len] = { false, false, false };
std::string nn(mReader->getNodeName());
bool found = false;
bool close_found = false;
size_t sk_idx;
for(sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++)
{
if(nn != Uns_Skip[sk_idx]) continue;
found = true;
if(mReader->isEmptyElement())
{
close_found = true;
goto casu_cres;
}
while(mReader->read())
{
if((mReader->getNodeType() == irr::io::EXN_ELEMENT_END) && (nn == mReader->getNodeName()))
{
close_found = true;
goto casu_cres;
}
}
}// for(sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++)
casu_cres:
if(!found) throw DeadlyImportError("Unknown node \"" + nn + "\" in " + pParentNodeName + ".");
if(!close_found) Throw_CloseNotFound(nn);
if(!skipped_before[sk_idx])
{
skipped_before[sk_idx] = true;
LogWarning("Skipping node \"" + nn + "\" in " + pParentNodeName + ".");
}
}
bool AMFImporter::XML_SearchNode(const std::string& pNodeName)
{
while(mReader->read())
{
if((mReader->getNodeType() == irr::io::EXN_ELEMENT) && XML_CheckNode_NameEqual(pNodeName)) return true;
}
return false;
}
bool AMFImporter::XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx)
{
std::string val(mReader->getAttributeValue(pAttrIdx));
if((val == "false") || (val == "0"))
return false;
else if((val == "true") || (val == "1"))
return true;
else
throw DeadlyImportError("Bool attribute value can contain \"false\"/\"0\" or \"true\"/\"1\" not the \"" + val + "\"");
}
float AMFImporter::XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx)
{
std::string val;
float tvalf;
ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), val);
fast_atoreal_move(val.c_str(), tvalf, false);
return tvalf;
}
uint32_t AMFImporter::XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx)
{
return strtoul10(mReader->getAttributeValue(pAttrIdx));
}
float AMFImporter::XML_ReadNode_GetVal_AsFloat()
{
std::string val;
float tvalf;
if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. No data, seems file is corrupt.");
if(mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. Invalid type of XML element, seems file is corrupt.");
ParseHelper_FixTruncatedFloatString(mReader->getNodeData(), val);
fast_atoreal_move(val.c_str(), tvalf, false);
return tvalf;
}
uint32_t AMFImporter::XML_ReadNode_GetVal_AsU32()
{
if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. No data, seems file is corrupt.");
if(mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. Invalid type of XML element, seems file is corrupt.");
return strtoul10(mReader->getNodeData());
}
void AMFImporter::XML_ReadNode_GetVal_AsString(std::string& pValue)
{
if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsString. No data, seems file is corrupt.");
if(mReader->getNodeType() != irr::io::EXN_TEXT)
throw DeadlyImportError("XML_ReadNode_GetVal_AsString. Invalid type of XML element, seems file is corrupt.");
pValue = mReader->getNodeData();
}
/*********************************************************************************************************************************************/
/************************************************************ Functions: parse set ***********************************************************/
/*********************************************************************************************************************************************/
void AMFImporter::ParseHelper_Node_Enter(CAMFImporter_NodeElement* pNode)
{
mNodeElement_Cur->Child.push_back(pNode);// add new element to current element child list.
mNodeElement_Cur = pNode;// switch current element to new one.
}
void AMFImporter::ParseHelper_Node_Exit()
{
// check if we can walk up.
if(mNodeElement_Cur != nullptr) mNodeElement_Cur = mNodeElement_Cur->Parent;
}
void AMFImporter::ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString)
{
size_t instr_len;
pOutString.clear();
instr_len = strlen(pInStr);
if(!instr_len) return;
pOutString.reserve(instr_len * 3 / 2);
// check and correct floats in format ".x". Must be "x.y".
if(pInStr[0] == '.') pOutString.push_back('0');
pOutString.push_back(pInStr[0]);
for(size_t ci = 1; ci < instr_len; ci++)
{
if((pInStr[ci] == '.') && ((pInStr[ci - 1] == ' ') || (pInStr[ci - 1] == '-') || (pInStr[ci - 1] == '+') || (pInStr[ci - 1] == '\t')))
{
pOutString.push_back('0');
pOutString.push_back('.');
}
else
{
pOutString.push_back(pInStr[ci]);
}
}
}
static bool ParseHelper_Decode_Base64_IsBase64(const char pChar)
{
return (isalnum(pChar) || (pChar == '+') || (pChar == '/'));
}
void AMFImporter::ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector<uint8_t>& pOutputData) const
{
// With help from
// René Nyffenegger http://www.adp-gmbh.ch/cpp/common/base64.html
const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
uint8_t tidx = 0;
uint8_t arr4[4], arr3[3];
// check input data
if(pInputBase64.size() % 4) throw DeadlyImportError("Base64-encoded data must have size multiply of four.");
// prepare output place
pOutputData.clear();
pOutputData.reserve(pInputBase64.size() / 4 * 3);
for(size_t in_len = pInputBase64.size(), in_idx = 0; (in_len > 0) && (pInputBase64[in_idx] != '='); in_len--)
{
if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx]))
{
arr4[tidx++] = pInputBase64[in_idx++];
if(tidx == 4)
{
for(tidx = 0; tidx < 4; tidx++) arr4[tidx] = (uint8_t)base64_chars.find(arr4[tidx]);
arr3[0] = (arr4[0] << 2) + ((arr4[1] & 0x30) >> 4);
arr3[1] = ((arr4[1] & 0x0F) << 4) + ((arr4[2] & 0x3C) >> 2);
arr3[2] = ((arr4[2] & 0x03) << 6) + arr4[3];
for(tidx = 0; tidx < 3; tidx++) pOutputData.push_back(arr3[tidx]);
tidx = 0;
}// if(tidx == 4)
}// if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx]))
else
{
in_idx++;
}// if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx])) else
}
if(tidx)
{
for(uint8_t i = tidx; i < 4; i++) arr4[i] = 0;
for(uint8_t i = 0; i < 4; i++) arr4[i] = (uint8_t)(base64_chars.find(arr4[i]));
arr3[0] = (arr4[0] << 2) + ((arr4[1] & 0x30) >> 4);
arr3[1] = ((arr4[1] & 0x0F) << 4) + ((arr4[2] & 0x3C) >> 2);
arr3[2] = ((arr4[2] & 0x03) << 6) + arr4[3];
for(uint8_t i = 0; i < (tidx - 1); i++) pOutputData.push_back(arr3[i]);
}
}
void AMFImporter::ParseFile(const std::string& pFile, IOSystem* pIOHandler)
{
irr::io::IrrXMLReader* OldReader = mReader;// store current XMLreader.
std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
// Check whether we can read from the file
if(file.get() == NULL) throw DeadlyImportError("Failed to open AMF file " + pFile + ".");
// generate a XML reader for it
std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(file.get()));
mReader = irr::io::createIrrXMLReader(mIOWrapper.get());
if(!mReader) throw DeadlyImportError("Failed to create XML reader for file" + pFile + ".");
//
// start reading
// search for root tag <amf>
if(XML_SearchNode("amf"))
ParseNode_Root();
else
throw DeadlyImportError("Root node \"amf\" not found.");
delete mReader;
// restore old XMLreader
mReader = OldReader;
}
// <amf
// unit="" - The units to be used. May be "inch", "millimeter", "meter", "feet", or "micron".
// version="" - Version of file format.
// >
// </amf>
// Root XML element.
// Multi elements - No.
void AMFImporter::ParseNode_Root()
{
std::string unit, version;
CAMFImporter_NodeElement *ne( nullptr );
// Read attributes for node <amf>.
MACRO_ATTRREAD_LOOPBEG;
MACRO_ATTRREAD_CHECK_RET("unit", unit, mReader->getAttributeValue);
MACRO_ATTRREAD_CHECK_RET("version", version, mReader->getAttributeValue);
MACRO_ATTRREAD_LOOPEND_WSKIP;
// Check attributes
if(!mUnit.empty())
{
if((mUnit != "inch") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) Throw_IncorrectAttrValue("unit");
}
// create root node element.
ne = new CAMFImporter_NodeElement_Root(nullptr);
mNodeElement_Cur = ne;// set first "current" element
// and assign attribute's values
((CAMFImporter_NodeElement_Root*)ne)->Unit = unit;
((CAMFImporter_NodeElement_Root*)ne)->Version = version;
// Check for child nodes
if(!mReader->isEmptyElement())
{
MACRO_NODECHECK_LOOPBEGIN("amf");
if(XML_CheckNode_NameEqual("object")) { ParseNode_Object(); continue; }
if(XML_CheckNode_NameEqual("material")) { ParseNode_Material(); continue; }
if(XML_CheckNode_NameEqual("texture")) { ParseNode_Texture(); continue; }
if(XML_CheckNode_NameEqual("constellation")) { ParseNode_Constellation(); continue; }
if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
MACRO_NODECHECK_LOOPEND("amf");
mNodeElement_Cur = ne;// force restore "current" element
}// if(!mReader->isEmptyElement())
mNodeElement_List.push_back(ne);// add to node element list because its a new object in graph.
}
// <constellation
// id="" - The Object ID of the new constellation being defined.
// >
// </constellation>
// A collection of objects or constellations with specific relative locations.
// Multi elements - Yes.
// Parent element - <amf>.
void AMFImporter::ParseNode_Constellation()
{
std::string id;
CAMFImporter_NodeElement* ne( nullptr );
// Read attributes for node <constellation>.
MACRO_ATTRREAD_LOOPBEG;
MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
MACRO_ATTRREAD_LOOPEND;
// create and if needed - define new grouping object.
ne = new CAMFImporter_NodeElement_Constellation(mNodeElement_Cur);
CAMFImporter_NodeElement_Constellation& als = *((CAMFImporter_NodeElement_Constellation*)ne);// alias for convenience
if(!id.empty()) als.ID = id;
// Check for child nodes
if(!mReader->isEmptyElement())
{
ParseHelper_Node_Enter(ne);
MACRO_NODECHECK_LOOPBEGIN("constellation");
if(XML_CheckNode_NameEqual("instance")) { ParseNode_Instance(); continue; }
if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
MACRO_NODECHECK_LOOPEND("constellation");
ParseHelper_Node_Exit();
}// if(!mReader->isEmptyElement())
else
{
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
}// if(!mReader->isEmptyElement()) else
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
}
// <instance
// objectid="" - The Object ID of the new constellation being defined.
// >
// </instance>
// A collection of objects or constellations with specific relative locations.
// Multi elements - Yes.
// Parent element - <amf>.
void AMFImporter::ParseNode_Instance()
{
std::string objectid;
CAMFImporter_NodeElement* ne( nullptr );
// Read attributes for node <constellation>.
MACRO_ATTRREAD_LOOPBEG;
MACRO_ATTRREAD_CHECK_RET("objectid", objectid, mReader->getAttributeValue);
MACRO_ATTRREAD_LOOPEND;
// used object id must be defined, check that.
if(objectid.empty()) throw DeadlyImportError("\"objectid\" in <instance> must be defined.");
// create and define new grouping object.
ne = new CAMFImporter_NodeElement_Instance(mNodeElement_Cur);
CAMFImporter_NodeElement_Instance& als = *((CAMFImporter_NodeElement_Instance*)ne);// alias for convenience
als.ObjectID = objectid;
// Check for child nodes
if(!mReader->isEmptyElement())
{
bool read_flag[6] = { false, false, false, false, false, false };
als.Delta.Set(0, 0, 0);
als.Rotation.Set(0, 0, 0);
ParseHelper_Node_Enter(ne);
MACRO_NODECHECK_LOOPBEGIN("instance");
MACRO_NODECHECK_READCOMP_F("deltax", read_flag[0], als.Delta.x);
MACRO_NODECHECK_READCOMP_F("deltay", read_flag[1], als.Delta.y);
MACRO_NODECHECK_READCOMP_F("deltaz", read_flag[2], als.Delta.z);
MACRO_NODECHECK_READCOMP_F("rx", read_flag[3], als.Rotation.x);
MACRO_NODECHECK_READCOMP_F("ry", read_flag[4], als.Rotation.y);
MACRO_NODECHECK_READCOMP_F("rz", read_flag[5], als.Rotation.z);
MACRO_NODECHECK_LOOPEND("instance");
ParseHelper_Node_Exit();
// also convert degrees to radians.
als.Rotation.x = AI_MATH_PI_F * als.Rotation.x / 180.0f;
als.Rotation.y = AI_MATH_PI_F * als.Rotation.y / 180.0f;
als.Rotation.z = AI_MATH_PI_F * als.Rotation.z / 180.0f;
}// if(!mReader->isEmptyElement())
else
{
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
}// if(!mReader->isEmptyElement()) else
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
}
// <object
// id="" - A unique ObjectID for the new object being defined.
// >
// </object>
// An object definition.
// Multi elements - Yes.
// Parent element - <amf>.
void AMFImporter::ParseNode_Object()
{
std::string id;
CAMFImporter_NodeElement* ne( nullptr );
// Read attributes for node <object>.
MACRO_ATTRREAD_LOOPBEG;
MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
MACRO_ATTRREAD_LOOPEND;
// create and if needed - define new geometry object.
ne = new CAMFImporter_NodeElement_Object(mNodeElement_Cur);
CAMFImporter_NodeElement_Object& als = *((CAMFImporter_NodeElement_Object*)ne);// alias for convenience
if(!id.empty()) als.ID = id;
// Check for child nodes
if(!mReader->isEmptyElement())
{
bool col_read = false;
ParseHelper_Node_Enter(ne);
MACRO_NODECHECK_LOOPBEGIN("object");
if(XML_CheckNode_NameEqual("color"))
{
// Check if color already defined for object.
if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <object>.");
// read data and set flag about it
ParseNode_Color();
col_read = true;
continue;
}
if(XML_CheckNode_NameEqual("mesh")) { ParseNode_Mesh(); continue; }
if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
MACRO_NODECHECK_LOOPEND("object");
ParseHelper_Node_Exit();
}// if(!mReader->isEmptyElement())
else
{
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
}// if(!mReader->isEmptyElement()) else
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
}
// <metadata
// type="" - The type of the attribute.
// >
// </metadata>
// Specify additional information about an entity.
// Multi elements - Yes.
// Parent element - <amf>, <object>, <volume>, <material>, <vertex>.
//
// Reserved types are:
// "Name" - The alphanumeric label of the entity, to be used by the interpreter if interacting with the user.
// "Description" - A description of the content of the entity
// "URL" - A link to an external resource relating to the entity
// "Author" - Specifies the name(s) of the author(s) of the entity
// "Company" - Specifying the company generating the entity
// "CAD" - specifies the name of the originating CAD software and version
// "Revision" - specifies the revision of the entity
// "Tolerance" - specifies the desired manufacturing tolerance of the entity in entity's unit system
// "Volume" - specifies the total volume of the entity, in the entity's unit system, to be used for verification (object and volume only)
void AMFImporter::ParseNode_Metadata()
{
std::string type, value;
CAMFImporter_NodeElement* ne( nullptr );
// read attribute
MACRO_ATTRREAD_LOOPBEG;
MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
MACRO_ATTRREAD_LOOPEND;
// and value of node.
value = mReader->getNodeData();
// Create node element and assign read data.
ne = new CAMFImporter_NodeElement_Metadata(mNodeElement_Cur);
((CAMFImporter_NodeElement_Metadata*)ne)->Type = type;
((CAMFImporter_NodeElement_Metadata*)ne)->Value = value;
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
}
/*********************************************************************************************************************************************/
/******************************************************** Functions: BaseImporter set ********************************************************/
/*********************************************************************************************************************************************/
bool AMFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool pCheckSig) const
{
const std::string extension = GetExtension(pFile);
if ( extension == "amf" ) {
return true;
}
if(!extension.length() || pCheckSig)
{
const char* tokens[] = { "<amf" };
return SearchFileHeaderForToken( pIOHandler, pFile, tokens, 1 );
}
return false;
}
void AMFImporter::GetExtensionList(std::set<std::string>& pExtensionList)
{
pExtensionList.insert("amf");
}
const aiImporterDesc* AMFImporter::GetInfo () const
{
return &Description;
}
void AMFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
{
Clear();// delete old graph.
ParseFile(pFile, pIOHandler);
Postprocess_BuildScene(pScene);
// scene graph is ready, exit.
}
}// namespace Assimp
#endif // !ASSIMP_BUILD_NO_AMF_IMPORTER

View File

@ -0,0 +1,563 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2016, 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 AMFImporter.hpp
/// \brief AMF-format files importer for Assimp.
/// \date 2016
/// \author smal.root@gmail.com
// Thanks to acorn89 for support.
#pragma once
#ifndef INCLUDED_AI_AMF_IMPORTER_H
#define INCLUDED_AI_AMF_IMPORTER_H
#include "AMFImporter_Node.hpp"
// Header files, Assimp.
#include "assimp/DefaultLogger.hpp"
#include "assimp/importerdesc.h"
#include "assimp/ProgressHandler.hpp"
#include "assimp/types.h"
#include "BaseImporter.h"
#include "irrXMLWrapper.h"
// Header files, stdlib.
#include <set>
namespace Assimp
{
/// \class AMFImporter
/// Class that holding scene graph which include: geometry, metadata, materials etc.
///
/// Implementing features.
///
/// Limitations.
///
/// 1. When for texture mapping used set of source textures (r, g, b, a) not only one then attribute "tiled" for all set will be true if it true in any of
/// source textures.
/// Example. Triangle use for texture mapping three textures. Two of them has "tiled" set to false and one - set to true. In scene all three textures
/// will be tiled.
///
/// Unsupported features:
/// 1. Node <composite>, formulas in <composite> and <color>. For implementing this feature can be used expression parser "muParser" like in project
/// "amf_tools".
/// 2. Attribute "profile" in node <color>.
/// 3. Curved geometry: <edge>, <normal> and children nodes of them.
/// 4. Attributes: "unit" and "version" in <amf> read but do nothing.
/// 5. <metadata> stored only for root node <amf>.
/// 6. Color averaging of vertices for which <triangle>'s set different colors.
///
/// Supported nodes:
/// General:
/// <amf>; <constellation>; <instance> and children <deltax>, <deltay>, <deltaz>, <rx>, <ry>, <rz>; <metadata>;
///
/// Geometry:
/// <object>; <mesh>; <vertices>; <vertex>; <coordinates> and children <x>, <y>, <z>; <volume>; <triangle> and children <v1>, <v2>, <v3>;
///
/// Material:
/// <color> and children <r>, <g>, <b>, <a>; <texture>; <material>;
/// two variants of texture coordinates:
/// new - <texmap> and children <utex1>, <utex2>, <utex3>, <vtex1>, <vtex2>, <vtex3>
/// old - <map> and children <u1>, <u2>, <u3>, <v1>, <v2>, <v3>
///
class AMFImporter : public BaseImporter
{
/***********************************************/
/******************** Types ********************/
/***********************************************/
private:
struct SPP_Material;// forward declaration
/// \struct SPP_Composite
/// Data type for postprocessing step. More suitable container for part of material's composition.
struct SPP_Composite
{
SPP_Material* Material;///< Pointer to material - part of composition.
std::string Formula;///< Formula for calculating ratio of \ref Material.
};
/// \struct SPP_Material
/// Data type for postprocessing step. More suitable container for material.
struct SPP_Material
{
std::string ID;///< Material ID.
std::list<CAMFImporter_NodeElement_Metadata*> Metadata;///< Metadata of material.
CAMFImporter_NodeElement_Color* Color;///< Color of material.
std::list<SPP_Composite> Composition;///< List of child materials if current material is composition of few another.
/// \fn aiColor4D GetColor(const float pX, const float pY, const float pZ) const
/// Return color calculated for specified coordinate.
/// \param [in] pX - "x" coordinate.
/// \param [in] pY - "y" coordinate.
/// \param [in] pZ - "z" coordinate.
/// \return calculated color.
aiColor4D GetColor(const float pX, const float pY, const float pZ) const;
};
/// \struct SPP_Texture
/// Data type for post-processing step. More suitable container for texture.
struct SPP_Texture
{
std::string ID;
size_t Width, Height, Depth;
bool Tiled;
char FormatHint[ 9 ];// 8 for string + 1 for terminator.
uint8_t *Data;
};
/// \struct SComplexFace
/// Data type for post-processing step. Contain face data.
struct SComplexFace
{
aiFace Face;///< Face vertices.
const CAMFImporter_NodeElement_Color* Color;///< Face color. Equal to nullptr if color is not set for the face.
const CAMFImporter_NodeElement_TexMap* TexMap;///< Face texture mapping data. Equal to nullptr if texture mapping is not set for the face.
};
/***********************************************/
/****************** Constants ******************/
/***********************************************/
private:
static const aiImporterDesc Description;
/***********************************************/
/****************** Variables ******************/
/***********************************************/
private:
CAMFImporter_NodeElement* mNodeElement_Cur;///< Current element.
std::list<CAMFImporter_NodeElement*> mNodeElement_List;///< All elements of scene graph.
irr::io::IrrXMLReader* mReader;///< Pointer to XML-reader object
std::string mUnit;
std::list<SPP_Material> mMaterial_Converted;///< List of converted materials for postprocessing step.
std::list<SPP_Texture> mTexture_Converted;///< List of converted textures for postprocessing step.
/***********************************************/
/****************** Functions ******************/
/***********************************************/
private:
/// \fn AMFImporter(const AMFImporter& pScene)
/// Disabled copy constructor.
AMFImporter(const AMFImporter& pScene);
/// \fn AMFImporter& operator=(const AMFImporter& pScene)
/// Disabled assign operator.
AMFImporter& operator=(const AMFImporter& pScene);
/// \fn void Clear()
/// Clear all temporary data.
void Clear();
/***********************************************/
/************* Functions: find set *************/
/***********************************************/
/// \fn bool Find_NodeElement(const std::string& pID, const CAMFImporter_NodeElement::EType pType, aiNode** pNode) const
/// Find specified node element in node elements list ( \ref mNodeElement_List).
/// \param [in] pID - ID(name) of requested node element.
/// \param [in] pType - type of node element.
/// \param [out] pNode - pointer to pointer to item found.
/// \return true - if the node element is found, else - false.
bool Find_NodeElement(const std::string& pID, const CAMFImporter_NodeElement::EType pType, CAMFImporter_NodeElement** pNodeElement) const;
/// \fn bool Find_ConvertedNode(const std::string& pID, std::list<aiNode*>& pNodeList, aiNode** pNode) const
/// Find requested aiNode in node list.
/// \param [in] pID - ID(name) of requested node.
/// \param [in] pNodeList - list of nodes where to find the node.
/// \param [out] pNode - pointer to pointer to item found.
/// \return true - if the node is found, else - false.
bool Find_ConvertedNode(const std::string& pID, std::list<aiNode*>& pNodeList, aiNode** pNode) const;
/// \fn bool Find_ConvertedMaterial(const std::string& pID, const SPP_Material** pConvertedMaterial) const
/// Find material in list for converted materials. Use at postprocessing step.
/// \param [in] pID - material ID.
/// \param [out] pConvertedMaterial - pointer to found converted material (\ref SPP_Material).
/// \return true - if the material is found, else - false.
bool Find_ConvertedMaterial(const std::string& pID, const SPP_Material** pConvertedMaterial) const;
/// \fn bool Find_ConvertedTexture(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A, uint32_t* pConvertedTextureIndex = nullptr) const
/// Find texture in list of converted textures. Use at postprocessing step,
/// \param [in] pID_R - ID of source "red" texture.
/// \param [in] pID_G - ID of source "green" texture.
/// \param [in] pID_B - ID of source "blue" texture.
/// \param [in] pID_A - ID of source "alpha" texture. Use empty string to find RGB-texture.
/// \param [out] pConvertedTextureIndex - pointer where index in list of found texture will be written. If equivalent to nullptr then nothing will be
/// written.
/// \return true - if the texture is found, else - false.
bool Find_ConvertedTexture(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A,
uint32_t* pConvertedTextureIndex = nullptr) const;
/***********************************************/
/********* Functions: postprocess set **********/
/***********************************************/
/// \fn void PostprocessHelper_CreateMeshDataArray(const CAMFImporter_NodeElement_Mesh& pNodeElement, std::vector<aiVector3D>& pVertexCoordinateArray, std::vector<CAMFImporter_NodeElement_Color*>& pVertexColorArray) const
/// Get data stored in <vertices> and place it to arrays.
/// \param [in] pNodeElement - reference to node element which kept <object> data.
/// \param [in] pVertexCoordinateArray - reference to vertices coordinates kept in <vertices>.
/// \param [in] pVertexColorArray - reference to vertices colors for all <vertex's. If color for vertex is not set then corresponding member of array
/// contain nullptr.
void PostprocessHelper_CreateMeshDataArray(const CAMFImporter_NodeElement_Mesh& pNodeElement, std::vector<aiVector3D>& pVertexCoordinateArray,
std::vector<CAMFImporter_NodeElement_Color*>& pVertexColorArray) const;
/// \fn size_t PostprocessHelper_GetTextureID_Or_Create(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A)
/// Return converted texture ID which related to specified source textures ID's. If converted texture does not exist then it will be created and ID on new
/// converted texture will be returned. Convertion: set of textures from \ref CAMFImporter_NodeElement_Texture to one \ref SPP_Texture and place it
/// to converted textures list.
/// Any of source ID's can be absent(empty string) or even one ID only specified. But at least one ID must be specified.
/// \param [in] pID_R - ID of source "red" texture.
/// \param [in] pID_G - ID of source "green" texture.
/// \param [in] pID_B - ID of source "blue" texture.
/// \param [in] pID_A - ID of source "alpha" texture.
/// \return index of the texture in array of the converted textures.
size_t PostprocessHelper_GetTextureID_Or_Create(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A);
/// \fn void PostprocessHelper_SplitFacesByTextureID(std::list<SComplexFace>& pInputList, std::list<std::list<SComplexFace> > pOutputList_Separated)
/// Separate input list by texture IDs. This step is needed because aiMesh can contain mesh which is use only one texture (or set: diffuse, bump etc).
/// \param [in] pInputList - input list with faces. Some of them can contain color or texture mapping, or both of them, or nothing. Will be cleared after
/// processing.
/// \param [out] pOutputList_Separated - output list of the faces lists. Separated faces list by used texture IDs. Will be cleared before processing.
void PostprocessHelper_SplitFacesByTextureID(std::list<SComplexFace>& pInputList, std::list<std::list<SComplexFace> >& pOutputList_Separated);
/// \fn void Postprocess_AddMetadata(const std::list<CAMFImporter_NodeElement_Metadata*>& pMetadataList, aiNode& pSceneNode) const
/// Check if child elements of node element is metadata and add it to scene node.
/// \param [in] pMetadataList - reference to list with collected metadata.
/// \param [out] pSceneNode - scene node in which metadata will be added.
void Postprocess_AddMetadata(const std::list<CAMFImporter_NodeElement_Metadata*>& pMetadataList, aiNode& pSceneNode) const;
/// \fn void Postprocess_BuildNodeAndObject(const CAMFImporter_NodeElement_Object& pNodeElement, std::list<aiMesh*>& pMeshList, aiNode** pSceneNode)
/// To create aiMesh and aiNode for it from <object>.
/// \param [in] pNodeElement - reference to node element which kept <object> data.
/// \param [out] pMeshList - reference to a list with all aiMesh of the scene.
/// \param [out] pSceneNode - pointer to place where new aiNode will be created.
void Postprocess_BuildNodeAndObject(const CAMFImporter_NodeElement_Object& pNodeElement, std::list<aiMesh*>& pMeshList, aiNode** pSceneNode);
/// \fn void Postprocess_BuildMeshSet(const CAMFImporter_NodeElement_Mesh& pNodeElement, const std::vector<aiVector3D>& pVertexCoordinateArray, const std::vector<CAMFImporter_NodeElement_Color*>& pVertexColorArray, const CAMFImporter_NodeElement_Color* pObjectColor, std::list<aiMesh*>& pMeshList, aiNode& pSceneNode)
/// Create mesh for every <volume> in <mesh>.
/// \param [in] pNodeElement - reference to node element which kept <mesh> data.
/// \param [in] pVertexCoordinateArray - reference to vertices coordinates for all <volume>'s.
/// \param [in] pVertexColorArray - reference to vertices colors for all <volume>'s. If color for vertex is not set then corresponding member of array
/// contain nullptr.
/// \param [in] pObjectColor - pointer to colors for <object>. If color is not set then argument contain nullptr.
/// \param [in] pMaterialList - reference to a list with defined materials.
/// \param [out] pMeshList - reference to a list with all aiMesh of the scene.
/// \param [out] pSceneNode - reference to aiNode which will own new aiMesh's.
void Postprocess_BuildMeshSet(const CAMFImporter_NodeElement_Mesh& pNodeElement, const std::vector<aiVector3D>& pVertexCoordinateArray,
const std::vector<CAMFImporter_NodeElement_Color*>& pVertexColorArray, const CAMFImporter_NodeElement_Color* pObjectColor,
std::list<aiMesh*>& pMeshList, aiNode& pSceneNode);
/// \fn void Postprocess_BuildMaterial(const CAMFImporter_NodeElement_Material& pMaterial)
/// Convert material from \ref CAMFImporter_NodeElement_Material to \ref SPP_Material.
/// \param [in] pMaterial - source CAMFImporter_NodeElement_Material.
void Postprocess_BuildMaterial(const CAMFImporter_NodeElement_Material& pMaterial);
/// \fn void Postprocess_BuildConstellation(CAMFImporter_NodeElement_Constellation& pConstellation, std::list<aiNode*>& pNodeList) const
/// Create and add to aiNode's list new part of scene graph defined by <constellation>.
/// \param [in] pConstellation - reference to <constellation> node.
/// \param [out] pNodeList - reference to aiNode's list.
void Postprocess_BuildConstellation(CAMFImporter_NodeElement_Constellation& pConstellation, std::list<aiNode*>& pNodeList) const;
/// \fn void Postprocess_BuildScene()
/// Build Assimp scene graph in aiScene from collected data.
/// \param [out] pScene - pointer to aiScene where tree will be built.
void Postprocess_BuildScene(aiScene* pScene);
/***********************************************/
/************* Functions: throw set ************/
/***********************************************/
/// \fn void Throw_CloseNotFound(const std::string& pNode)
/// Call that function when close tag of node not found and exception must be raised.
/// E.g.:
/// <amf>
/// <object>
/// </amf> <!--- object not closed --->
/// \throw DeadlyImportError.
/// \param [in] pNode - node name in which exception happened.
void Throw_CloseNotFound(const std::string& pNode);
/// \fn void Throw_IncorrectAttr(const std::string& pAttrName)
/// Call that function when attribute name is incorrect and exception must be raised.
/// \param [in] pAttrName - attribute name.
/// \throw DeadlyImportError.
void Throw_IncorrectAttr(const std::string& pAttrName);
/// \fn void Throw_IncorrectAttrValue(const std::string& pAttrName)
/// Call that function when attribute value is incorrect and exception must be raised.
/// \param [in] pAttrName - attribute name.
/// \throw DeadlyImportError.
void Throw_IncorrectAttrValue(const std::string& pAttrName);
/// \fn void Throw_MoreThanOnceDefined(const std::string& pNode, const std::string& pDescription)
/// Call that function when some type of nodes are defined twice or more when must be used only once and exception must be raised.
/// E.g.:
/// <object>
/// <color>... <!--- color defined --->
/// <color>... <!--- color defined again --->
/// </object>
/// \throw DeadlyImportError.
/// \param [in] pNodeType - type of node which defined one more time.
/// \param [in] pDescription - message about error. E.g. what the node defined while exception raised.
void Throw_MoreThanOnceDefined(const std::string& pNodeType, const std::string& pDescription);
/// \fn void Throw_ID_NotFound(const std::string& pID) const
/// Call that function when referenced element ID are not found in graph and exception must be raised.
/// \param [in] pID - ID of of element which not found.
/// \throw DeadlyImportError.
void Throw_ID_NotFound(const std::string& pID) const;
/***********************************************/
/************** Functions: LOG set *************/
/***********************************************/
/// \fn void LogInfo(const std::string& pMessage)
/// Short variant for calling \ref DefaultLogger::get()->info()
void LogInfo(const std::string& pMessage) { DefaultLogger::get()->info(pMessage); }
/// \fn void LogWarning(const std::string& pMessage)
/// Short variant for calling \ref DefaultLogger::get()->warn()
void LogWarning(const std::string& pMessage) { DefaultLogger::get()->warn(pMessage); }
/// \fn void LogError(const std::string& pMessage)
/// Short variant for calling \ref DefaultLogger::get()->error()
void LogError(const std::string& pMessage) { DefaultLogger::get()->error(pMessage); }
/***********************************************/
/************** Functions: XML set *************/
/***********************************************/
/// \fn void XML_CheckNode_MustHaveChildren()
/// Check if current node have children: <node>...</node>. If not then exception will throwed.
void XML_CheckNode_MustHaveChildren();
/// \fn bool XML_CheckNode_NameEqual(const std::string& pNodeName)
/// Chek if current node name is equal to pNodeName.
/// \param [in] pNodeName - name for checking.
/// return true if current node name is equal to pNodeName, else - false.
bool XML_CheckNode_NameEqual(const std::string& pNodeName) { return mReader->getNodeName() == pNodeName; }
/// \fn void XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName)
/// Skip unsupported node and report about that. Depend on node name can be skipped begin tag of node all whole node.
/// \param [in] pParentNodeName - parent node name. Used for reporting.
void XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName);
/// \fn bool XML_SearchNode(const std::string& pNodeName)
/// Search for specified node in file. XML file read pointer(mReader) will point to found node or file end after search is end.
/// \param [in] pNodeName - requested node name.
/// return true - if node is found, else - false.
bool XML_SearchNode(const std::string& pNodeName);
/// \fn bool XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx)
/// Read attribute value.
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
/// \return read data.
bool XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx);
/// \fn float XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx)
/// Read attribute value.
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
/// \return read data.
float XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx);
/// \fn uint32_t XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx)
/// Read attribute value.
/// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set).
/// \return read data.
uint32_t XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx);
/// \fn float XML_ReadNode_GetVal_AsFloat()
/// Read node value.
/// \return read data.
float XML_ReadNode_GetVal_AsFloat();
/// \fn uint32_t XML_ReadNode_GetVal_AsU32()
/// Read node value.
/// \return read data.
uint32_t XML_ReadNode_GetVal_AsU32();
/// \fn void XML_ReadNode_GetVal_AsString(std::string& pValue)
/// Read node value.
/// \return read data.
void XML_ReadNode_GetVal_AsString(std::string& pValue);
/***********************************************/
/******** Functions: parse set private *********/
/***********************************************/
/// \fn void ParseHelper_Node_Enter(CAMFImporter_NodeElement* pNode)
/// Make pNode as current and enter deeper for parsing child nodes. At end \ref ParseHelper_Node_Exit must be called.
/// \param [in] pNode - new current node.
void ParseHelper_Node_Enter(CAMFImporter_NodeElement* pNode);
/// \fn void ParseHelper_Group_End()
/// This function must be called when exiting from grouping node. \ref ParseHelper_Group_Begin.
void ParseHelper_Node_Exit();
/// \fn void ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString)
/// Attribute values of floating point types can take form ".x"(without leading zero). irrXMLReader can not read this form of values and it
/// must be converted to right form - "0.xxx".
/// \param [in] pInStr - pointer to input string which can contain incorrect form of values.
/// \param [out[ pOutString - output string with right form of values.
void ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString);
/// \fn void ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector<uint8_t>& pOutputData) const
/// Decode Base64-encoded data.
/// \param [in] pInputBase64 - reference to input Base64-encoded string.
/// \param [out] pOutputData - reference to output array for decoded data.
void ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector<uint8_t>& pOutputData) const;
/// \fn void ParseNode_Root()
/// Parse <AMF> node of the file.
void ParseNode_Root();
/******** Functions: top nodes *********/
/// \fn void ParseNode_Constellation()
/// Parse <constellation> node of the file.
void ParseNode_Constellation();
/// \fn void ParseNode_Constellation()
/// Parse <instance> node of the file.
void ParseNode_Instance();
/// \fn void ParseNode_Material()
/// Parse <material> node of the file.
void ParseNode_Material();
/// \fn void ParseNode_Metadata()
/// Parse <metadata> node.
void ParseNode_Metadata();
/// \fn void ParseNode_Object()
/// Parse <object> node of the file.
void ParseNode_Object();
/// \fn void ParseNode_Texture()
/// Parse <texture> node of the file.
void ParseNode_Texture();
/******** Functions: geometry nodes *********/
/// \fn void ParseNode_Coordinates()
/// Parse <coordinates> node of the file.
void ParseNode_Coordinates();
/// \fn void ParseNode_Edge()
/// Parse <edge> node of the file.
void ParseNode_Edge();
/// \fn void ParseNode_Mesh()
/// Parse <mesh> node of the file.
void ParseNode_Mesh();
/// \fn void ParseNode_Triangle()
/// Parse <triangle> node of the file.
void ParseNode_Triangle();
/// \fn void ParseNode_Vertex()
/// Parse <vertex> node of the file.
void ParseNode_Vertex();
/// \fn void ParseNode_Vertices()
/// Parse <vertices> node of the file.
void ParseNode_Vertices();
/// \fn void ParseNode_Volume()
/// Parse <volume> node of the file.
void ParseNode_Volume();
/******** Functions: material nodes *********/
/// \fn void ParseNode_Color()
/// Parse <color> node of the file.
void ParseNode_Color();
/// \fn void ParseNode_TexMap(const bool pUseOldName = false)
/// Parse <texmap> of <map> node of the file.
/// \param [in] pUseOldName - if true then use old name of node(and children) - <map>, instead of new name - <texmap>.
void ParseNode_TexMap(const bool pUseOldName = false);
public:
/// \fn AMFImporter()
/// Default constructor.
AMFImporter()
: mNodeElement_Cur(nullptr), mReader(nullptr)
{}
/// \fn ~AMFImporter()
/// Default destructor.
~AMFImporter();
/***********************************************/
/******** Functions: parse set, public *********/
/***********************************************/
/// \fn void ParseFile(const std::string& pFile, IOSystem* pIOHandler)
/// Parse AMF file and fill scene graph. The function has no return value. Result can be found by analyzing the generated graph.
/// Also exception can be throwed if trouble will found.
/// \param [in] pFile - name of file to be parsed.
/// \param [in] pIOHandler - pointer to IO helper object.
void ParseFile(const std::string& pFile, IOSystem* pIOHandler);
/***********************************************/
/********* Functions: BaseImporter set *********/
/***********************************************/
bool CanRead(const std::string& pFile, IOSystem* pIOHandler, bool pCheckSig) const;
void GetExtensionList(std::set<std::string>& pExtensionList);
void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
const aiImporterDesc* GetInfo ()const;
};// class AMFImporter
}// namespace Assimp
#endif // INCLUDED_AI_AMF_IMPORTER_H

View File

@ -0,0 +1,355 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2016, 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 AMFImporter_Geometry.cpp
/// \brief Parsing data from geometry nodes.
/// \date 2016
/// \author smal.root@gmail.com
#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
#include "AMFImporter.hpp"
#include "AMFImporter_Macro.hpp"
namespace Assimp
{
// <mesh>
// </mesh>
// A 3D mesh hull.
// Multi elements - Yes.
// Parent element - <object>.
void AMFImporter::ParseNode_Mesh()
{
CAMFImporter_NodeElement* ne;
// create new mesh object.
ne = new CAMFImporter_NodeElement_Mesh(mNodeElement_Cur);
// Check for child nodes
if(!mReader->isEmptyElement())
{
bool vert_read = false;
ParseHelper_Node_Enter(ne);
MACRO_NODECHECK_LOOPBEGIN("mesh");
if(XML_CheckNode_NameEqual("vertices"))
{
// Check if data already defined.
if(vert_read) Throw_MoreThanOnceDefined("vertices", "Only one vertices set can be defined for <mesh>.");
// read data and set flag about it
ParseNode_Vertices();
vert_read = true;
continue;
}
if(XML_CheckNode_NameEqual("volume")) { ParseNode_Volume(); continue; }
MACRO_NODECHECK_LOOPEND("mesh");
ParseHelper_Node_Exit();
}// if(!mReader->isEmptyElement())
else
{
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
}// if(!mReader->isEmptyElement()) else
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
}
// <vertices>
// </vertices>
// The list of vertices to be used in defining triangles.
// Multi elements - No.
// Parent element - <mesh>.
void AMFImporter::ParseNode_Vertices()
{
CAMFImporter_NodeElement* ne;
// create new mesh object.
ne = new CAMFImporter_NodeElement_Vertices(mNodeElement_Cur);
// Check for child nodes
if(!mReader->isEmptyElement())
{
ParseHelper_Node_Enter(ne);
MACRO_NODECHECK_LOOPBEGIN("vertices");
if(XML_CheckNode_NameEqual("vertex")) { ParseNode_Vertex(); continue; }
MACRO_NODECHECK_LOOPEND("vertices");
ParseHelper_Node_Exit();
}// if(!mReader->isEmptyElement())
else
{
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
}// if(!mReader->isEmptyElement()) else
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
}
// <vertex>
// </vertex>
// A vertex to be referenced in triangles.
// Multi elements - Yes.
// Parent element - <vertices>.
void AMFImporter::ParseNode_Vertex()
{
CAMFImporter_NodeElement* ne;
// create new mesh object.
ne = new CAMFImporter_NodeElement_Vertex(mNodeElement_Cur);
// Check for child nodes
if(!mReader->isEmptyElement())
{
bool col_read = false;
bool coord_read = false;
ParseHelper_Node_Enter(ne);
MACRO_NODECHECK_LOOPBEGIN("vertex");
if(XML_CheckNode_NameEqual("color"))
{
// Check if data already defined.
if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <vertex>.");
// read data and set flag about it
ParseNode_Color();
col_read = true;
continue;
}
if(XML_CheckNode_NameEqual("coordinates"))
{
// Check if data already defined.
if(coord_read) Throw_MoreThanOnceDefined("coordinates", "Only one coordinates set can be defined for <vertex>.");
// read data and set flag about it
ParseNode_Coordinates();
coord_read = true;
continue;
}
if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
MACRO_NODECHECK_LOOPEND("vertex");
ParseHelper_Node_Exit();
}// if(!mReader->isEmptyElement())
else
{
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
}// if(!mReader->isEmptyElement()) else
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
}
// <coordinates>
// </coordinates>
// Specifies the 3D location of this vertex.
// Multi elements - No.
// Parent element - <vertex>.
//
// Children elements:
// <x>, <y>, <z>
// Multi elements - No.
// X, Y, or Z coordinate, respectively, of a vertex position in space.
void AMFImporter::ParseNode_Coordinates()
{
CAMFImporter_NodeElement* ne;
// create new color object.
ne = new CAMFImporter_NodeElement_Coordinates(mNodeElement_Cur);
CAMFImporter_NodeElement_Coordinates& als = *((CAMFImporter_NodeElement_Coordinates*)ne);// alias for convenience
// Check for child nodes
if(!mReader->isEmptyElement())
{
bool read_flag[3] = { false, false, false };
ParseHelper_Node_Enter(ne);
MACRO_NODECHECK_LOOPBEGIN("coordinates");
MACRO_NODECHECK_READCOMP_F("x", read_flag[0], als.Coordinate.x);
MACRO_NODECHECK_READCOMP_F("y", read_flag[1], als.Coordinate.y);
MACRO_NODECHECK_READCOMP_F("z", read_flag[2], als.Coordinate.z);
MACRO_NODECHECK_LOOPEND("coordinates");
ParseHelper_Node_Exit();
// check that all components was defined
if((read_flag[0] && read_flag[1] && read_flag[2]) == 0) throw DeadlyImportError("Not all coordinate's components are defined.");
}// if(!mReader->isEmptyElement())
else
{
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
}// if(!mReader->isEmptyElement()) else
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
}
// <volume
// materialid="" - Which material to use.
// type="" - What this volume describes can be “region” or “support”. If none specified, “object” is assumed. If support, then the geometric
// requirements 1-8 listed in section 5 do not need to be maintained.
// >
// </volume>
// Defines a volume from the established vertex list.
// Multi elements - Yes.
// Parent element - <mesh>.
void AMFImporter::ParseNode_Volume()
{
std::string materialid;
std::string type;
CAMFImporter_NodeElement* ne;
// Read attributes for node <color>.
MACRO_ATTRREAD_LOOPBEG;
MACRO_ATTRREAD_CHECK_RET("materialid", materialid, mReader->getAttributeValue);
MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
MACRO_ATTRREAD_LOOPEND;
// create new object.
ne = new CAMFImporter_NodeElement_Volume(mNodeElement_Cur);
// and assign read data
((CAMFImporter_NodeElement_Volume*)ne)->MaterialID = materialid;
((CAMFImporter_NodeElement_Volume*)ne)->Type = type;
// Check for child nodes
if(!mReader->isEmptyElement())
{
bool col_read = false;
ParseHelper_Node_Enter(ne);
MACRO_NODECHECK_LOOPBEGIN("volume");
if(XML_CheckNode_NameEqual("color"))
{
// Check if data already defined.
if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <volume>.");
// read data and set flag about it
ParseNode_Color();
col_read = true;
continue;
}
if(XML_CheckNode_NameEqual("triangle")) { ParseNode_Triangle(); continue; }
if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
MACRO_NODECHECK_LOOPEND("volume");
ParseHelper_Node_Exit();
}// if(!mReader->isEmptyElement())
else
{
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
}// if(!mReader->isEmptyElement()) else
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
}
// <triangle>
// </triangle>
// Defines a 3D triangle from three vertices, according to the right-hand rule (counter-clockwise when looking from the outside).
// Multi elements - Yes.
// Parent element - <volume>.
//
// Children elements:
// <v1>, <v2>, <v3>
// Multi elements - No.
// Index of the desired vertices in a triangle or edge.
void AMFImporter::ParseNode_Triangle()
{
CAMFImporter_NodeElement* ne;
// create new color object.
ne = new CAMFImporter_NodeElement_Triangle(mNodeElement_Cur);
CAMFImporter_NodeElement_Triangle& als = *((CAMFImporter_NodeElement_Triangle*)ne);// alias for convenience
// Check for child nodes
if(!mReader->isEmptyElement())
{
bool col_read = false, tex_read = false;
bool read_flag[3] = { false, false, false };
ParseHelper_Node_Enter(ne);
MACRO_NODECHECK_LOOPBEGIN("triangle");
if(XML_CheckNode_NameEqual("color"))
{
// Check if data already defined.
if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <triangle>.");
// read data and set flag about it
ParseNode_Color();
col_read = true;
continue;
}
if(XML_CheckNode_NameEqual("texmap"))// new name of node: "texmap".
{
// Check if data already defined.
if(tex_read) Throw_MoreThanOnceDefined("texmap", "Only one texture coordinate can be defined for <triangle>.");
// read data and set flag about it
ParseNode_TexMap();
tex_read = true;
continue;
}
else if(XML_CheckNode_NameEqual("map"))// old name of node: "map".
{
// Check if data already defined.
if(tex_read) Throw_MoreThanOnceDefined("map", "Only one texture coordinate can be defined for <triangle>.");
// read data and set flag about it
ParseNode_TexMap(true);
tex_read = true;
continue;
}
MACRO_NODECHECK_READCOMP_U32("v1", read_flag[0], als.V[0]);
MACRO_NODECHECK_READCOMP_U32("v2", read_flag[1], als.V[1]);
MACRO_NODECHECK_READCOMP_U32("v3", read_flag[2], als.V[2]);
MACRO_NODECHECK_LOOPEND("triangle");
ParseHelper_Node_Exit();
// check that all components was defined
if((read_flag[0] && read_flag[1] && read_flag[2]) == 0) throw DeadlyImportError("Not all vertices of the triangle are defined.");
}// if(!mReader->isEmptyElement())
else
{
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
}// if(!mReader->isEmptyElement()) else
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
}
}// namespace Assimp
#endif // !ASSIMP_BUILD_NO_AMF_IMPORTER

View File

@ -0,0 +1,164 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2016, 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 AMFImporter_Macro.hpp
/// \brief Useful macrodefines.
/// \date 2016
/// \author smal.root@gmail.com
#pragma once
#ifndef AMFIMPORTER_MACRO_HPP_INCLUDED
#define AMFIMPORTER_MACRO_HPP_INCLUDED
/// \def MACRO_ATTRREAD_LOOPBEG
/// Begin of loop that read attributes values.
#define MACRO_ATTRREAD_LOOPBEG \
for(int idx = 0, idx_end = mReader->getAttributeCount(); idx < idx_end; idx++) \
{ \
std::string an(mReader->getAttributeName(idx));
/// \def MACRO_ATTRREAD_LOOPEND
/// End of loop that read attributes values.
#define MACRO_ATTRREAD_LOOPEND \
Throw_IncorrectAttr(an); \
}
/// \def MACRO_ATTRREAD_LOOPEND_WSKIP
/// End of loop that read attributes values. Difference from \ref MACRO_ATTRREAD_LOOPEND in that: current macro skip unknown attributes, but
/// \ref MACRO_ATTRREAD_LOOPEND throw an exception.
#define MACRO_ATTRREAD_LOOPEND_WSKIP \
continue; \
}
/// \def MACRO_ATTRREAD_CHECK_REF
/// Check curent attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then
/// "continue" will called.
/// \param [in] pAttrName - attribute name.
/// \param [out] pVarName - output variable name.
/// \param [in] pFunction - function which read attribute value and write it to pVarName.
#define MACRO_ATTRREAD_CHECK_REF(pAttrName, pVarName, pFunction) \
if(an == pAttrName) \
{ \
pFunction(idx, pVarName); \
continue; \
}
/// \def MACRO_ATTRREAD_CHECK_RET
/// Check curent attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction.
/// If result was read then "continue" will called.
/// \param [in] pAttrName - attribute name.
/// \param [out] pVarName - output variable name.
/// \param [in] pFunction - function which read attribute value and write it to pVarName.
#define MACRO_ATTRREAD_CHECK_RET(pAttrName, pVarName, pFunction) \
if(an == pAttrName) \
{ \
pVarName = pFunction(idx); \
continue; \
}
/// \def MACRO_NODECHECK_LOOPBEGIN(pNodeName)
/// Begin of loop of parsing child nodes. Do not add ';' at end.
/// \param [in] pNodeName - current node name.
#define MACRO_NODECHECK_LOOPBEGIN(pNodeName) \
do { \
bool close_found = false; \
\
while(mReader->read()) \
{ \
if(mReader->getNodeType() == irr::io::EXN_ELEMENT) \
{
/// \def MACRO_NODECHECK_LOOPEND(pNodeName)
/// End of loop of parsing child nodes.
/// \param [in] pNodeName - current node name.
#define MACRO_NODECHECK_LOOPEND(pNodeName) \
XML_CheckNode_SkipUnsupported(pNodeName); \
}/* if(mReader->getNodeType() == irr::io::EXN_ELEMENT) */ \
else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) \
{ \
if(XML_CheckNode_NameEqual(pNodeName)) \
{ \
close_found = true; \
\
break; \
} \
}/* else if(mReader->getNodeType() == irr::io::EXN_ELEMENT_END) */ \
}/* while(mReader->read()) */ \
\
if(!close_found) Throw_CloseNotFound(pNodeName); \
\
} while(false)
/// \def MACRO_NODECHECK_READCOMP_F
/// Check curent node name and if it equal to requested then read value. Result write to output variable of type "float".
/// If result was read then "continue" will called. Also check if node data already read then raise exception.
/// \param [in] pNodeName - node name.
/// \param [in, out] pReadFlag - read flag.
/// \param [out] pVarName - output variable name.
#define MACRO_NODECHECK_READCOMP_F(pNodeName, pReadFlag, pVarName) \
if(XML_CheckNode_NameEqual(pNodeName)) \
{ \
/* Check if field already read before. */ \
if(pReadFlag) Throw_MoreThanOnceDefined(pNodeName, "Only one component can be defined."); \
/* Read color component and assign it to object. */ \
pVarName = XML_ReadNode_GetVal_AsFloat(); \
pReadFlag = true; \
continue; \
}
/// \def MACRO_NODECHECK_READCOMP_U32
/// Check curent node name and if it equal to requested then read value. Result write to output variable of type "uint32_t".
/// If result was read then "continue" will called. Also check if node data already read then raise exception.
/// \param [in] pNodeName - node name.
/// \param [in, out] pReadFlag - read flag.
/// \param [out] pVarName - output variable name.
#define MACRO_NODECHECK_READCOMP_U32(pNodeName, pReadFlag, pVarName) \
if(XML_CheckNode_NameEqual(pNodeName)) \
{ \
/* Check if field already read before. */ \
if(pReadFlag) Throw_MoreThanOnceDefined(pNodeName, "Only one component can be defined."); \
/* Read color component and assign it to object. */ \
pVarName = XML_ReadNode_GetVal_AsU32(); \
pReadFlag = true; \
continue; \
}
#endif // AMFIMPORTER_MACRO_HPP_INCLUDED

View File

@ -0,0 +1,309 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2016, 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 AMFImporter_Material.cpp
/// \brief Parsing data from material nodes.
/// \date 2016
/// \author smal.root@gmail.com
#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
#include "AMFImporter.hpp"
#include "AMFImporter_Macro.hpp"
namespace Assimp
{
// <color
// profile="" - The ICC color space used to interpret the three color channels <r>, <g> and <b>.
// >
// </color>
// A color definition.
// Multi elements - No.
// Parent element - <material>, <object>, <volume>, <vertex>, <triangle>.
//
// "profile" can be one of "sRGB", "AdobeRGB", "Wide-Gamut-RGB", "CIERGB", "CIELAB", or "CIEXYZ".
// Children elements:
// <r>, <g>, <b>, <a>
// Multi elements - No.
// Red, Greed, Blue and Alpha (transparency) component of a color in sRGB space, values ranging from 0 to 1. The
// values can be specified as constants, or as a formula depending on the coordinates.
void AMFImporter::ParseNode_Color()
{
std::string profile;
CAMFImporter_NodeElement* ne;
// Read attributes for node <color>.
MACRO_ATTRREAD_LOOPBEG;
MACRO_ATTRREAD_CHECK_RET("profile", profile, mReader->getAttributeValue);
MACRO_ATTRREAD_LOOPEND;
// create new color object.
ne = new CAMFImporter_NodeElement_Color(mNodeElement_Cur);
CAMFImporter_NodeElement_Color& als = *((CAMFImporter_NodeElement_Color*)ne);// alias for convenience
als.Profile = profile;
// Check for child nodes
if(!mReader->isEmptyElement())
{
bool read_flag[4] = { false, false, false, false };
ParseHelper_Node_Enter(ne);
MACRO_NODECHECK_LOOPBEGIN("color");
MACRO_NODECHECK_READCOMP_F("r", read_flag[0], als.Color.r);
MACRO_NODECHECK_READCOMP_F("g", read_flag[1], als.Color.g);
MACRO_NODECHECK_READCOMP_F("b", read_flag[2], als.Color.b);
MACRO_NODECHECK_READCOMP_F("a", read_flag[3], als.Color.a);
MACRO_NODECHECK_LOOPEND("color");
ParseHelper_Node_Exit();
// check that all components was defined
if(!(read_flag[0] && read_flag[1] && read_flag[2])) throw DeadlyImportError("Not all color components are defined.");
// check if <a> is absent. Then manualy add "a == 1".
if(!read_flag[3]) als.Color.a = 1;
}// if(!mReader->isEmptyElement())
else
{
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
}// if(!mReader->isEmptyElement()) else
als.Composed = false;
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
}
// <material
// id="" - A unique material id. material ID "0" is reserved to denote no material (void) or sacrificial material.
// >
// </material>
// An available material.
// Multi elements - Yes.
// Parent element - <amf>.
void AMFImporter::ParseNode_Material()
{
std::string id;
CAMFImporter_NodeElement* ne;
// Read attributes for node <color>.
MACRO_ATTRREAD_LOOPBEG;
MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
MACRO_ATTRREAD_LOOPEND;
// create new object.
ne = new CAMFImporter_NodeElement_Material(mNodeElement_Cur);
// and assign read data
((CAMFImporter_NodeElement_Material*)ne)->ID = id;
// Check for child nodes
if(!mReader->isEmptyElement())
{
bool col_read = false;
ParseHelper_Node_Enter(ne);
MACRO_NODECHECK_LOOPBEGIN("material");
if(XML_CheckNode_NameEqual("color"))
{
// Check if data already defined.
if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <material>.");
// read data and set flag about it
ParseNode_Color();
col_read = true;
continue;
}
if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
MACRO_NODECHECK_LOOPEND("material");
ParseHelper_Node_Exit();
}// if(!mReader->isEmptyElement())
else
{
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
}// if(!mReader->isEmptyElement()) else
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
}
// <texture
// id="" - Assigns a unique texture id for the new texture.
// width="" - Width (horizontal size, x) of the texture, in pixels.
// height="" - Height (lateral size, y) of the texture, in pixels.
// depth="" - Depth (vertical size, z) of the texture, in pixels.
// type="" - Encoding of the data in the texture. Currently allowed values are "grayscale" only. In grayscale mode, each pixel is represented by one byte
// in the range of 0-255. When the texture is referenced using the tex function, these values are converted into a single floating point number in the
// range of 0-1 (see Annex 2). A full color graphics will typically require three textures, one for each of the color channels. A graphic involving
// transparency may require a fourth channel.
// tiled="" - If true then texture repeated when UV-coordinates is greater than 1.
// >
// </triangle>
// Specifies an texture data to be used as a map. Lists a sequence of Base64 values specifying values for pixels from left to right then top to bottom,
// then layer by layer.
// Multi elements - Yes.
// Parent element - <amf>.
void AMFImporter::ParseNode_Texture()
{
std::string id;
uint32_t width = 0;
uint32_t height = 0;
uint32_t depth = 1;
std::string type;
bool tiled = false;
std::string enc64_data;
CAMFImporter_NodeElement* ne;
// Read attributes for node <color>.
MACRO_ATTRREAD_LOOPBEG;
MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
MACRO_ATTRREAD_CHECK_RET("width", width, XML_ReadNode_GetAttrVal_AsU32);
MACRO_ATTRREAD_CHECK_RET("height", height, XML_ReadNode_GetAttrVal_AsU32);
MACRO_ATTRREAD_CHECK_RET("depth", depth, XML_ReadNode_GetAttrVal_AsU32);
MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
MACRO_ATTRREAD_CHECK_RET("tiled", tiled, XML_ReadNode_GetAttrVal_AsBool);
MACRO_ATTRREAD_LOOPEND;
// create new texture object.
ne = new CAMFImporter_NodeElement_Texture(mNodeElement_Cur);
CAMFImporter_NodeElement_Texture& als = *((CAMFImporter_NodeElement_Texture*)ne);// alias for convenience
// Check for child nodes
if(!mReader->isEmptyElement()) XML_ReadNode_GetVal_AsString(enc64_data);
// check that all components was defined
if(id.empty()) throw DeadlyImportError("ID for texture must be defined.");
if(width < 1) Throw_IncorrectAttrValue("width");
if(height < 1) Throw_IncorrectAttrValue("height");
if(depth < 1) Throw_IncorrectAttrValue("depth");
if(type != "grayscale") Throw_IncorrectAttrValue("type");
if(enc64_data.empty()) throw DeadlyImportError("Texture data not defined.");
// copy data
als.ID = id;
als.Width = width;
als.Height = height;
als.Depth = depth;
als.Tiled = tiled;
ParseHelper_Decode_Base64(enc64_data, als.Data);
// check data size
if((width * height * depth) != als.Data.size()) throw DeadlyImportError("Texture has incorrect data size.");
mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
}
// <texmap
// rtexid="" - Texture ID for red color component.
// gtexid="" - Texture ID for green color component.
// btexid="" - Texture ID for blue color component.
// atexid="" - Texture ID for alpha color component. Optional.
// >
// </texmap>, old name: <map>
// Specifies texture coordinates for triangle.
// Multi elements - No.
// Parent element - <triangle>.
// Children elements:
// <utex1>, <utex2>, <utex3>, <vtex1>, <vtex2>, <vtex3>. Old name: <u1>, <u2>, <u3>, <v1>, <v2>, <v3>.
// Multi elements - No.
// Texture coordinates for every vertex of triangle.
void AMFImporter::ParseNode_TexMap(const bool pUseOldName)
{
std::string rtexid, gtexid, btexid, atexid;
CAMFImporter_NodeElement* ne;
// Read attributes for node <color>.
MACRO_ATTRREAD_LOOPBEG;
MACRO_ATTRREAD_CHECK_RET("rtexid", rtexid, mReader->getAttributeValue);
MACRO_ATTRREAD_CHECK_RET("gtexid", gtexid, mReader->getAttributeValue);
MACRO_ATTRREAD_CHECK_RET("btexid", btexid, mReader->getAttributeValue);
MACRO_ATTRREAD_CHECK_RET("atexid", atexid, mReader->getAttributeValue);
MACRO_ATTRREAD_LOOPEND;
// create new texture coordinates object.
ne = new CAMFImporter_NodeElement_TexMap(mNodeElement_Cur);
CAMFImporter_NodeElement_TexMap& als = *((CAMFImporter_NodeElement_TexMap*)ne);// alias for convenience
// check data
if(rtexid.empty() && gtexid.empty() && btexid.empty()) throw DeadlyImportError("ParseNode_TexMap. At least one texture ID must be defined.");
// Check for children nodes
XML_CheckNode_MustHaveChildren();
// read children nodes
bool read_flag[6] = { false, false, false, false, false, false };
ParseHelper_Node_Enter(ne);
if(!pUseOldName)
{
MACRO_NODECHECK_LOOPBEGIN("texmap");
MACRO_NODECHECK_READCOMP_F("utex1", read_flag[0], als.TextureCoordinate[0].x);
MACRO_NODECHECK_READCOMP_F("utex2", read_flag[1], als.TextureCoordinate[1].x);
MACRO_NODECHECK_READCOMP_F("utex3", read_flag[2], als.TextureCoordinate[2].x);
MACRO_NODECHECK_READCOMP_F("vtex1", read_flag[3], als.TextureCoordinate[0].y);
MACRO_NODECHECK_READCOMP_F("vtex2", read_flag[4], als.TextureCoordinate[1].y);
MACRO_NODECHECK_READCOMP_F("vtex3", read_flag[5], als.TextureCoordinate[2].y);
MACRO_NODECHECK_LOOPEND("texmap");
}
else
{
MACRO_NODECHECK_LOOPBEGIN("map");
MACRO_NODECHECK_READCOMP_F("u1", read_flag[0], als.TextureCoordinate[0].x);
MACRO_NODECHECK_READCOMP_F("u2", read_flag[1], als.TextureCoordinate[1].x);
MACRO_NODECHECK_READCOMP_F("u3", read_flag[2], als.TextureCoordinate[2].x);
MACRO_NODECHECK_READCOMP_F("v1", read_flag[3], als.TextureCoordinate[0].y);
MACRO_NODECHECK_READCOMP_F("v2", read_flag[4], als.TextureCoordinate[1].y);
MACRO_NODECHECK_READCOMP_F("v3", read_flag[5], als.TextureCoordinate[2].y);
MACRO_NODECHECK_LOOPEND("map");
}// if(!pUseOldName) else
ParseHelper_Node_Exit();
// check that all components was defined
if(!(read_flag[0] && read_flag[1] && read_flag[2] && read_flag[3] && read_flag[4] && read_flag[5]))
throw DeadlyImportError("Not all texture coordinates are defined.");
// copy attributes data
als.TextureID_R = rtexid;
als.TextureID_G = gtexid;
als.TextureID_B = btexid;
als.TextureID_A = atexid;
mNodeElement_List.push_back(ne);// add to node element list because its a new object in graph.
}
}// namespace Assimp
#endif // !ASSIMP_BUILD_NO_AMF_IMPORTER

View File

@ -0,0 +1,423 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2016, 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 AMFImporter_Node.hpp
/// \brief Elements of scene graph.
/// \date 2016
/// \author smal.root@gmail.com
#pragma once
#ifndef INCLUDED_AI_AMF_IMPORTER_NODE_H
#define INCLUDED_AI_AMF_IMPORTER_NODE_H
// Header files, stdlib.
#include <list>
#include <string>
#include <vector>
// Header files, Assimp.
#include "assimp/types.h"
#include "assimp/scene.h"
/// \class CAMFImporter_NodeElement
/// Base class for elements of nodes.
class CAMFImporter_NodeElement
{
/***********************************************/
/******************** Types ********************/
/***********************************************/
public:
/// \enum EType
/// Define what data type contain node element.
enum EType
{
ENET_Color, ///< Color element: <color>.
ENET_Constellation,///< Grouping element: <constellation>.
ENET_Coordinates, ///< Coordinates element: <coordinates>.
ENET_Edge, ///< Edge element: <edge>.
ENET_Instance, ///< Grouping element: <constellation>.
ENET_Material, ///< Material element: <material>.
ENET_Metadata, ///< Metadata element: <metadata>.
ENET_Mesh, ///< Metadata element: <mesh>.
ENET_Object, ///< Element which hold object: <object>.
ENET_Root, ///< Root element: <amf>.
ENET_Triangle, ///< Triangle element: <triangle>.
ENET_TexMap, ///< Texture coordinates element: <texmap> or <map>.
ENET_Texture, ///< Texture element: <texture>.
ENET_Vertex, ///< Vertex element: <vertex>.
ENET_Vertices, ///< Vertex element: <vertices>.
ENET_Volume, ///< Volume element: <volume>.
ENET_Invalid ///< Element has invalid type and possible contain invalid data.
};
/***********************************************/
/****************** Constants ******************/
/***********************************************/
public:
const EType Type;///< Type of element.
/***********************************************/
/****************** Variables ******************/
/***********************************************/
public:
std::string ID;///< ID of element.
CAMFImporter_NodeElement* Parent;///< Parrent element. If nullptr then this node is root.
std::list<CAMFImporter_NodeElement*> Child;///< Child elements.
/***********************************************/
/****************** Functions ******************/
/***********************************************/
private:
/// \fn CAMFImporter_NodeElement(const CAMFImporter_NodeElement& pNodeElement)
/// Disabled copy constructor.
CAMFImporter_NodeElement(const CAMFImporter_NodeElement& pNodeElement);
/// \fn CAMFImporter_NodeElement& operator=(const CAMFImporter_NodeElement& pNodeElement)
/// Disabled assign operator.
CAMFImporter_NodeElement& operator=(const CAMFImporter_NodeElement& pNodeElement);
/// \fn CAMFImporter_NodeElement()
/// Disabled default constructor.
CAMFImporter_NodeElement();
protected:
/// \fn CAMFImporter_NodeElement(const EType pType, CAMFImporter_NodeElement* pParent)
/// In constructor inheritor must set element type.
/// \param [in] pType - element type.
/// \param [in] pParent - parent element.
CAMFImporter_NodeElement(const EType pType, CAMFImporter_NodeElement* pParent)
: Type(pType), Parent(pParent)
{}
};// class IAMFImporter_NodeElement
/// \struct CAMFImporter_NodeElement_Constellation
/// A collection of objects or constellations with specific relative locations.
struct CAMFImporter_NodeElement_Constellation : public CAMFImporter_NodeElement
{
/// \fn CAMFImporter_NodeElement_Constellation(CAMFImporter_NodeElement* pParent)
/// Constructor.
/// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Constellation(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Constellation, pParent)
{}
};// struct CAMFImporter_NodeElement_Constellation
/// \struct CAMFImporter_NodeElement_Instance
/// Part of constellation.
struct CAMFImporter_NodeElement_Instance : public CAMFImporter_NodeElement
{
/****************** Variables ******************/
std::string ObjectID;///< ID of object for instanciation.
/// \var Delta - The distance of translation in the x, y, or z direction, respectively, in the referenced object's coordinate system, to
/// create an instance of the object in the current constellation.
aiVector3D Delta;
/// \var Rotation - The rotation, in degrees, to rotate the referenced object about its x, y, and z axes, respectively, to create an
/// instance of the object in the current constellation. Rotations shall be executed in order of x first, then y, then z.
aiVector3D Rotation;
/****************** Functions ******************/
/// \fn CAMFImporter_NodeElement_Instance(CAMFImporter_NodeElement* pParent)
/// Constructor.
/// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Instance(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Instance, pParent)
{}
};// struct CAMFImporter_NodeElement_Instance
/// \struct CAMFImporter_NodeElement_Metadata
/// Structure that define metadata node.
struct CAMFImporter_NodeElement_Metadata : public CAMFImporter_NodeElement
{
/****************** Variables ******************/
std::string Type;///< Type of "Value".
std::string Value;///< Value.
/****************** Functions ******************/
/// \fn CAMFImporter_NodeElement_Metadata(CAMFImporter_NodeElement* pParent)
/// Constructor.
/// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Metadata(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Metadata, pParent)
{}
};// struct CAMFImporter_NodeElement_Metadata
/// \struct CAMFImporter_NodeElement_Root
/// Structure that define root node.
struct CAMFImporter_NodeElement_Root : public CAMFImporter_NodeElement
{
/****************** Variables ******************/
std::string Unit;///< The units to be used. May be "inch", "millimeter", "meter", "feet", or "micron".
std::string Version;///< Version of format.
/****************** Functions ******************/
/// \fn CAMFImporter_NodeElement_Root(CAMFImporter_NodeElement* pParent)
/// Constructor.
/// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Root(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Root, pParent)
{}
};// struct CAMFImporter_NodeElement_Root
/// \struct CAMFImporter_NodeElement_Color
/// Structure that define object node.
struct CAMFImporter_NodeElement_Color : public CAMFImporter_NodeElement
{
/****************** Variables ******************/
bool Composed;///< Type of color stored: if true then look for formula in \ref Color_Composed[4], else - in \ref Color.
std::string Color_Composed[4];///< By components formulas of composed color. [0..3] => RGBA.
aiColor4D Color;///< Constant color.
std::string Profile;///< The ICC color space used to interpret the three color channels <r>, <g> and <b>..
/****************** Functions ******************/
/// \fn CAMFImporter_NodeElement_Color(CAMFImporter_NodeElement* pParent)
/// Constructor.
/// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Color(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Color, pParent)
{}
};// struct CAMFImporter_NodeElement_Color
/// \struct CAMFImporter_NodeElement_Material
/// Structure that define material node.
struct CAMFImporter_NodeElement_Material : public CAMFImporter_NodeElement
{
/// \fn CAMFImporter_NodeElement_Material(CAMFImporter_NodeElement* pParent)
/// Constructor.
/// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Material(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Material, pParent)
{}
};// struct CAMFImporter_NodeElement_Material
/// \struct CAMFImporter_NodeElement_Object
/// Structure that define object node.
struct CAMFImporter_NodeElement_Object : public CAMFImporter_NodeElement
{
/// \fn CAMFImporter_NodeElement_Object(CAMFImporter_NodeElement* pParent)
/// Constructor.
/// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Object(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Object, pParent)
{}
};// struct CAMFImporter_NodeElement_Object
/// \struct CAMFImporter_NodeElement_Mesh
/// Structure that define mesh node.
struct CAMFImporter_NodeElement_Mesh : public CAMFImporter_NodeElement
{
/// \fn CAMFImporter_NodeElement_Mesh(CAMFImporter_NodeElement* pParent)
/// Constructor.
/// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Mesh(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Mesh, pParent)
{}
};// struct CAMFImporter_NodeElement_Mesh
/// \struct CAMFImporter_NodeElement_Vertex
/// Structure that define vertex node.
struct CAMFImporter_NodeElement_Vertex : public CAMFImporter_NodeElement
{
/// \fn CAMFImporter_NodeElement_Vertex(CAMFImporter_NodeElement* pParent)
/// Constructor.
/// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Vertex(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Vertex, pParent)
{}
};// struct CAMFImporter_NodeElement_Vertex
/// \struct CAMFImporter_NodeElement_Edge
/// Structure that define edge node.
struct CAMFImporter_NodeElement_Edge : public CAMFImporter_NodeElement
{
/// \fn CAMFImporter_NodeElement_Edge(CAMFImporter_NodeElement* pParent)
/// Constructor.
/// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Edge(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Edge, pParent)
{}
};// struct CAMFImporter_NodeElement_Vertex
/// \struct CAMFImporter_NodeElement_Vertices
/// Structure that define vertices node.
struct CAMFImporter_NodeElement_Vertices : public CAMFImporter_NodeElement
{
/// \fn CAMFImporter_NodeElement_Vertices(CAMFImporter_NodeElement* pParent)
/// Constructor.
/// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Vertices(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Vertices, pParent)
{}
};// struct CAMFImporter_NodeElement_Vertices
/// \struct CAMFImporter_NodeElement_Volume
/// Structure that define volume node.
struct CAMFImporter_NodeElement_Volume : public CAMFImporter_NodeElement
{
/****************** Variables ******************/
std::string MaterialID;///< Which material to use.
std::string Type;///< What this volume describes can be “region” or “support”. If none specified, “object” is assumed.
/****************** Functions ******************/
/// \fn CAMFImporter_NodeElement_Volume(CAMFImporter_NodeElement* pParent)
/// Constructor.
/// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Volume(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Volume, pParent)
{}
};// struct CAMFImporter_NodeElement_Volume
/// \struct CAMFImporter_NodeElement_Coordinates
/// Structure that define coordinates node.
struct CAMFImporter_NodeElement_Coordinates : public CAMFImporter_NodeElement
{
/****************** Variables ******************/
aiVector3D Coordinate;///< Coordinate.
/****************** Functions ******************/
/// \fn CAMFImporter_NodeElement_Coordinates(CAMFImporter_NodeElement* pParent)
/// Constructor.
/// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Coordinates(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Coordinates, pParent)
{}
};// struct CAMFImporter_NodeElement_Coordinates
/// \struct CAMFImporter_NodeElement_TexMap
/// Structure that define texture coordinates node.
struct CAMFImporter_NodeElement_TexMap : public CAMFImporter_NodeElement
{
/****************** Variables ******************/
aiVector3D TextureCoordinate[3];///< Texture coordinates.
std::string TextureID_R;///< Texture ID for red color component.
std::string TextureID_G;///< Texture ID for green color component.
std::string TextureID_B;///< Texture ID for blue color component.
std::string TextureID_A;///< Texture ID for alpha color component.
/****************** Functions ******************/
/// \fn CAMFImporter_NodeElement_TexMap(CAMFImporter_NodeElement* pParent)
/// Constructor.
/// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_TexMap(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_TexMap, pParent)
{}
};// struct CAMFImporter_NodeElement_TexMap
/// \struct CAMFImporter_NodeElement_Triangle
/// Structure that define triangle node.
struct CAMFImporter_NodeElement_Triangle : public CAMFImporter_NodeElement
{
/****************** Variables ******************/
size_t V[3];///< Triangle vertices.
/****************** Functions ******************/
/// \fn CAMFImporter_NodeElement_Triangle(CAMFImporter_NodeElement* pParent)
/// Constructor.
/// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Triangle(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Triangle, pParent)
{}
};// struct CAMFImporter_NodeElement_Triangle
/// \struct CAMFImporter_NodeElement_Texture
/// Structure that define texture node.
struct CAMFImporter_NodeElement_Texture : public CAMFImporter_NodeElement
{
/****************** Variables ******************/
size_t Width, Height, Depth;///< Size of the texture.
std::vector<uint8_t> Data;///< Data of the texture.
bool Tiled;
/****************** Functions ******************/
/// \fn CAMFImporter_NodeElement_Texture(CAMFImporter_NodeElement* pParent)
/// Constructor.
/// \param [in] pParent - pointer to parent node.
CAMFImporter_NodeElement_Texture(CAMFImporter_NodeElement* pParent)
: CAMFImporter_NodeElement(ENET_Texture, pParent)
{}
};// struct CAMFImporter_NodeElement_Texture
#endif // INCLUDED_AI_AMF_IMPORTER_NODE_H

View File

@ -0,0 +1,966 @@
/*
---------------------------------------------------------------------------
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
Copyright (c) 2006-2016, 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 AMFImporter_Postprocess.cpp
/// \brief Convert built scenegraph and objects to Assimp scenegraph.
/// \date 2016
/// \author smal.root@gmail.com
#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
#include "AMFImporter.hpp"
// Header files, Assimp.
#include "SceneCombiner.h"
#include "StandardShapes.h"
#include "StringUtils.h"
// Header files, stdlib.
#include <algorithm>
#include <iterator>
namespace Assimp
{
aiColor4D AMFImporter::SPP_Material::GetColor(const float pX, const float pY, const float pZ) const
{
aiColor4D tcol;
// Check if stored data are supported.
if(Composition.size() != 0)
{
throw DeadlyImportError("IME. GetColor for composition");
}
else if(Color->Composed)
{
throw DeadlyImportError("IME. GetColor, composed color");
}
else
{
tcol = Color->Color;
}
// Check if default color must be used
if((tcol.r == 0) && (tcol.g == 0) && (tcol.b == 0) && (tcol.a == 0))
{
tcol.r = 0.5f;
tcol.g = 0.5f;
tcol.b = 0.5f;
tcol.a = 1;
}
return tcol;
}
void AMFImporter::PostprocessHelper_CreateMeshDataArray(const CAMFImporter_NodeElement_Mesh& pNodeElement, std::vector<aiVector3D>& pVertexCoordinateArray,
std::vector<CAMFImporter_NodeElement_Color*>& pVertexColorArray) const
{
CAMFImporter_NodeElement_Vertices* vn = nullptr;
size_t col_idx;
// All data stored in "vertices", search for it.
for(CAMFImporter_NodeElement* ne_child: pNodeElement.Child)
{
if(ne_child->Type == CAMFImporter_NodeElement::ENET_Vertices) vn = (CAMFImporter_NodeElement_Vertices*)ne_child;
}
// If "vertices" not found then no work for us.
if(vn == nullptr) return;
pVertexCoordinateArray.reserve(vn->Child.size());// all coordinates stored as child and we need to reserve space for future push_back's.
pVertexColorArray.resize(vn->Child.size());// colors count equal vertices count.
col_idx = 0;
// Inside vertices collect all data and place to arrays
for(CAMFImporter_NodeElement* vn_child: vn->Child)
{
// vertices, colors
if(vn_child->Type == CAMFImporter_NodeElement::ENET_Vertex)
{
// by default clear color for current vertex
pVertexColorArray[col_idx] = nullptr;
for(CAMFImporter_NodeElement* vtx: vn_child->Child)
{
if(vtx->Type == CAMFImporter_NodeElement::ENET_Coordinates)
{
pVertexCoordinateArray.push_back(((CAMFImporter_NodeElement_Coordinates*)vtx)->Coordinate);
continue;
}
if(vtx->Type == CAMFImporter_NodeElement::ENET_Color)
{
pVertexColorArray[col_idx] = (CAMFImporter_NodeElement_Color*)vtx;
continue;
}
}// for(CAMFImporter_NodeElement* vtx: vn_child->Child)
col_idx++;
}// if(vn_child->Type == CAMFImporter_NodeElement::ENET_Vertex)
}// for(CAMFImporter_NodeElement* vn_child: vn->Child)
}
size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B,
const std::string& pID_A)
{
size_t TextureConverted_Index;
std::string TextureConverted_ID;
// check input data
if(pID_R.empty() && pID_G.empty() && pID_B.empty() && pID_A.empty())
throw DeadlyImportError("PostprocessHelper_GetTextureID_Or_Create. At least one texture ID must be defined.");
// Create ID
TextureConverted_ID = pID_R + "_" + pID_G + "_" + pID_B + "_" + pID_A;
// Check if texture specified by set of IDs is converted already.
TextureConverted_Index = 0;
for(const SPP_Texture& tex_convd: mTexture_Converted)
{
if(tex_convd.ID == TextureConverted_ID)
return TextureConverted_Index;
else
TextureConverted_Index++;
}
//
// Converted texture not found, create it.
//
CAMFImporter_NodeElement_Texture* src_texture[4]{nullptr};
std::vector<CAMFImporter_NodeElement_Texture*> src_texture_4check;
SPP_Texture converted_texture;
{// find all specified source textures
CAMFImporter_NodeElement* t_tex;
// R
if(!pID_R.empty())
{
if(!Find_NodeElement(pID_R, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_R);
src_texture[0] = (CAMFImporter_NodeElement_Texture*)t_tex;
src_texture_4check.push_back((CAMFImporter_NodeElement_Texture*)t_tex);
}
else
{
src_texture[0] = nullptr;
}
// G
if(!pID_G.empty())
{
if(!Find_NodeElement(pID_G, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_G);
src_texture[1] = (CAMFImporter_NodeElement_Texture*)t_tex;
src_texture_4check.push_back((CAMFImporter_NodeElement_Texture*)t_tex);
}
else
{
src_texture[1] = nullptr;
}
// B
if(!pID_B.empty())
{
if(!Find_NodeElement(pID_B, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_B);
src_texture[2] = (CAMFImporter_NodeElement_Texture*)t_tex;
src_texture_4check.push_back((CAMFImporter_NodeElement_Texture*)t_tex);
}
else
{
src_texture[2] = nullptr;
}
// A
if(!pID_A.empty())
{
if(!Find_NodeElement(pID_A, CAMFImporter_NodeElement::ENET_Texture, &t_tex)) Throw_ID_NotFound(pID_A);
src_texture[3] = (CAMFImporter_NodeElement_Texture*)t_tex;
src_texture_4check.push_back((CAMFImporter_NodeElement_Texture*)t_tex);
}
else
{
src_texture[3] = nullptr;
}
}// END: find all specified source textures
// check that all textures has same size
if(src_texture_4check.size() > 1)
{
for (size_t i = 0, i_e = (src_texture_4check.size() - 1); i < i_e; i++)
{
if((src_texture_4check[i]->Width != src_texture_4check[i + 1]->Width) || (src_texture_4check[i]->Height != src_texture_4check[i + 1]->Height) ||
(src_texture_4check[i]->Depth != src_texture_4check[i + 1]->Depth))
{
throw DeadlyImportError("PostprocessHelper_GetTextureID_Or_Create. Source texture must has the same size.");
}
}
}// if(src_texture_4check.size() > 1)
// set texture attributes
converted_texture.Width = src_texture_4check[0]->Width;
converted_texture.Height = src_texture_4check[0]->Height;
converted_texture.Depth = src_texture_4check[0]->Depth;
// if one of source texture is tiled then converted texture is tiled too.
converted_texture.Tiled = false;
for(uint8_t i = 0; i < src_texture_4check.size(); i++) converted_texture.Tiled |= src_texture_4check[i]->Tiled;
// Create format hint.
strcpy(converted_texture.FormatHint, "rgba0000");// copy initial string.
if(!pID_R.empty()) converted_texture.FormatHint[4] = '8';
if(!pID_G.empty()) converted_texture.FormatHint[5] = '8';
if(!pID_B.empty()) converted_texture.FormatHint[6] = '8';
if(!pID_A.empty()) converted_texture.FormatHint[7] = '8';
//
// Сopy data of textures.
//
size_t tex_size = 0;
size_t step = 0;
size_t off_g = 0;
size_t off_b = 0;
// Calculate size of the target array and rule how data will be copied.
if(!pID_R.empty()) { tex_size += src_texture[0]->Data.size(); step++, off_g++, off_b++; }
if(!pID_G.empty()) { tex_size += src_texture[1]->Data.size(); step++, off_b++; }
if(!pID_B.empty()) { tex_size += src_texture[2]->Data.size(); step++; }
if(!pID_A.empty()) { tex_size += src_texture[3]->Data.size(); step++; }
// Create target array.
converted_texture.Data = new uint8_t[tex_size];
// And copy data
auto CopyTextureData = [&](const std::string& pID, const size_t pOffset, const size_t pStep, const uint8_t pSrcTexNum) -> void
{
if(!pID.empty())
{
for(size_t idx_target = pOffset, idx_src = 0; idx_target < tex_size; idx_target += pStep, idx_src++)
converted_texture.Data[idx_target] = src_texture[pSrcTexNum]->Data.at(idx_src);
}
};// auto CopyTextureData = [&](const size_t pOffset, const size_t pStep, const uint8_t pSrcTexNum) -> void
CopyTextureData(pID_R, 0, step, 0);
CopyTextureData(pID_G, off_g, step, 1);
CopyTextureData(pID_B, off_b, step, 2);
CopyTextureData(pID_A, step - 1, step, 3);
// Store new converted texture ID
converted_texture.ID = TextureConverted_ID;
// Store new converted texture
mTexture_Converted.push_back(converted_texture);
return TextureConverted_Index;
}
void AMFImporter::PostprocessHelper_SplitFacesByTextureID(std::list<SComplexFace>& pInputList, std::list<std::list<SComplexFace> >& pOutputList_Separated)
{
auto texmap_is_equal = [](const CAMFImporter_NodeElement_TexMap* pTexMap1, const CAMFImporter_NodeElement_TexMap* pTexMap2) -> bool
{
if((pTexMap1 == nullptr) && (pTexMap2 == nullptr)) return true;
if(pTexMap1 == nullptr) return false;
if(pTexMap2 == nullptr) return false;
if(pTexMap1->TextureID_R != pTexMap2->TextureID_R) return false;
if(pTexMap1->TextureID_G != pTexMap2->TextureID_G) return false;
if(pTexMap1->TextureID_B != pTexMap2->TextureID_B) return false;
if(pTexMap1->TextureID_A != pTexMap2->TextureID_A) return false;
return true;
};
pOutputList_Separated.clear();
if(pInputList.size() == 0) return;
do
{
SComplexFace face_start = pInputList.front();
std::list<SComplexFace> face_list_cur;
for(std::list<SComplexFace>::iterator it = pInputList.begin(), it_end = pInputList.end(); it != it_end;)
{
if(texmap_is_equal(face_start.TexMap, it->TexMap))
{
auto it_old = it;
it++;
face_list_cur.push_back(*it_old);
pInputList.erase(it_old);
}
else
{
it++;
}
}
if(face_list_cur.size() > 0) pOutputList_Separated.push_back(face_list_cur);
} while(pInputList.size() > 0);
}
void AMFImporter::Postprocess_AddMetadata(const std::list<CAMFImporter_NodeElement_Metadata*>& metadataList, aiNode& sceneNode) const
{
if ( !metadataList.empty() )
{
if(sceneNode.mMetaData != nullptr) throw DeadlyImportError("Postprocess. MetaData member in node are not nullptr. Something went wrong.");
// copy collected metadata to output node.
sceneNode.mMetaData = aiMetadata::Alloc( static_cast<unsigned int>(metadataList.size()) );
size_t meta_idx( 0 );
for(const CAMFImporter_NodeElement_Metadata& metadata: metadataList)
{
sceneNode.mMetaData->Set(static_cast<unsigned int>(meta_idx++), metadata.Type, aiString(metadata.Value));
}
}// if(!metadataList.empty())
}
void AMFImporter::Postprocess_BuildNodeAndObject(const CAMFImporter_NodeElement_Object& pNodeElement, std::list<aiMesh*>& pMeshList, aiNode** pSceneNode)
{
CAMFImporter_NodeElement_Color* object_color = nullptr;
// create new aiNode and set name as <object> has.
*pSceneNode = new aiNode;
(*pSceneNode)->mName = pNodeElement.ID;
// read mesh and color
for(const CAMFImporter_NodeElement* ne_child: pNodeElement.Child)
{
std::vector<aiVector3D> vertex_arr;
std::vector<CAMFImporter_NodeElement_Color*> color_arr;
// color for object
if(ne_child->Type == CAMFImporter_NodeElement::ENET_Color) object_color = (CAMFImporter_NodeElement_Color*)ne_child;
if(ne_child->Type == CAMFImporter_NodeElement::ENET_Mesh)
{
// Create arrays from children of mesh: vertices.
PostprocessHelper_CreateMeshDataArray(*((CAMFImporter_NodeElement_Mesh*)ne_child), vertex_arr, color_arr);
// Use this arrays as a source when creating every aiMesh
Postprocess_BuildMeshSet(*((CAMFImporter_NodeElement_Mesh*)ne_child), vertex_arr, color_arr, object_color, pMeshList, **pSceneNode);
}
}// for(const CAMFImporter_NodeElement* ne_child: pNodeElement)
}
void AMFImporter::Postprocess_BuildMeshSet(const CAMFImporter_NodeElement_Mesh& pNodeElement, const std::vector<aiVector3D>& pVertexCoordinateArray,
const std::vector<CAMFImporter_NodeElement_Color*>& pVertexColorArray,
const CAMFImporter_NodeElement_Color* pObjectColor, std::list<aiMesh*>& pMeshList, aiNode& pSceneNode)
{
std::list<unsigned int> mesh_idx;
// all data stored in "volume", search for it.
for(const CAMFImporter_NodeElement* ne_child: pNodeElement.Child)
{
const CAMFImporter_NodeElement_Color* ne_volume_color = nullptr;
const SPP_Material* cur_mat = nullptr;
if(ne_child->Type == CAMFImporter_NodeElement::ENET_Volume)
{
/******************* Get faces *******************/
const CAMFImporter_NodeElement_Volume* ne_volume = reinterpret_cast<const CAMFImporter_NodeElement_Volume*>(ne_child);
std::list<SComplexFace> complex_faces_list;// List of the faces of the volume.
std::list<std::list<SComplexFace> > complex_faces_toplist;// List of the face list for every mesh.
// check if volume use material
if(!ne_volume->MaterialID.empty())
{
if(!Find_ConvertedMaterial(ne_volume->MaterialID, &cur_mat)) Throw_ID_NotFound(ne_volume->MaterialID);
}
// inside "volume" collect all data and place to arrays or create new objects
for(const CAMFImporter_NodeElement* ne_volume_child: ne_volume->Child)
{
// color for volume
if(ne_volume_child->Type == CAMFImporter_NodeElement::ENET_Color)
{
ne_volume_color = reinterpret_cast<const CAMFImporter_NodeElement_Color*>(ne_volume_child);
}
else if(ne_volume_child->Type == CAMFImporter_NodeElement::ENET_Triangle)// triangles, triangles colors
{
const CAMFImporter_NodeElement_Triangle& tri_al = *reinterpret_cast<const CAMFImporter_NodeElement_Triangle*>(ne_volume_child);
SComplexFace complex_face;
// initialize pointers
complex_face.Color = nullptr;
complex_face.TexMap = nullptr;
// get data from triangle children: color, texture coordinates.
if(tri_al.Child.size())
{
for(const CAMFImporter_NodeElement* ne_triangle_child: tri_al.Child)
{
if(ne_triangle_child->Type == CAMFImporter_NodeElement::ENET_Color)
complex_face.Color = reinterpret_cast<const CAMFImporter_NodeElement_Color*>(ne_triangle_child);
else if(ne_triangle_child->Type == CAMFImporter_NodeElement::ENET_TexMap)
complex_face.TexMap = reinterpret_cast<const CAMFImporter_NodeElement_TexMap*>(ne_triangle_child);
}
}// if(tri_al.Child.size())
// create new face and store it.
complex_face.Face.mNumIndices = 3;
complex_face.Face.mIndices = new unsigned int[3];
complex_face.Face.mIndices[0] = static_cast<unsigned int>(tri_al.V[0]);
complex_face.Face.mIndices[1] = static_cast<unsigned int>(tri_al.V[1]);
complex_face.Face.mIndices[2] = static_cast<unsigned int>(tri_al.V[2]);
complex_faces_list.push_back(complex_face);
}
}// for(const CAMFImporter_NodeElement* ne_volume_child: ne_volume->Child)
/**** Split faces list: one list per mesh ****/
PostprocessHelper_SplitFacesByTextureID(complex_faces_list, complex_faces_toplist);
/***** Create mesh for every faces list ******/
for(std::list<SComplexFace>& face_list_cur: complex_faces_toplist)
{
auto VertexIndex_GetMinimal = [](const std::list<SComplexFace>& pFaceList, const size_t* pBiggerThan) -> size_t
{
size_t rv;
if(pBiggerThan != nullptr)
{
bool found = false;
for(const SComplexFace& face: pFaceList)
{
for(size_t idx_vert = 0; idx_vert < face.Face.mNumIndices; idx_vert++)
{
if(face.Face.mIndices[idx_vert] > *pBiggerThan)
{
rv = face.Face.mIndices[idx_vert];
found = true;
break;
}
}
if(found) break;
}
if(!found) return *pBiggerThan;
}
else
{
rv = pFaceList.front().Face.mIndices[0];
}// if(pBiggerThan != nullptr) else
for(const SComplexFace& face: pFaceList)
{
for(size_t vi = 0; vi < face.Face.mNumIndices; vi++)
{
if(face.Face.mIndices[vi] < rv)
{
if(pBiggerThan != nullptr)
{
if(face.Face.mIndices[vi] > *pBiggerThan) rv = face.Face.mIndices[vi];
}
else
{
rv = face.Face.mIndices[vi];
}
}
}
}// for(const SComplexFace& face: pFaceList)
return rv;
};// auto VertexIndex_GetMinimal = [](const std::list<SComplexFace>& pFaceList, const size_t* pBiggerThan) -> size_t
auto VertexIndex_Replace = [](std::list<SComplexFace>& pFaceList, const size_t pIdx_From, const size_t pIdx_To) -> void
{
for(const SComplexFace& face: pFaceList)
{
for(size_t vi = 0; vi < face.Face.mNumIndices; vi++)
{
if(face.Face.mIndices[vi] == pIdx_From) face.Face.mIndices[vi] = static_cast<unsigned int>(pIdx_To);
}
}
};// auto VertexIndex_Replace = [](std::list<SComplexFace>& pFaceList, const size_t pIdx_From, const size_t pIdx_To) -> void
auto Vertex_CalculateColor = [&](const size_t pIdx) -> aiColor4D
{
// Color priorities(In descending order):
// 1. triangle color;
// 2. vertex color;
// 3. volume color;
// 4. object color;
// 5. material;
// 6. default - invisible coat.
//
// Fill vertices colors in color priority list above that's points from 1 to 6.
if((pIdx < pVertexColorArray.size()) && (pVertexColorArray[pIdx] != nullptr))// check for vertex color
{
if(pVertexColorArray[pIdx]->Composed)
throw DeadlyImportError("IME: vertex color composed");
else
return pVertexColorArray[pIdx]->Color;
}
else if(ne_volume_color != nullptr)// check for volume color
{
if(ne_volume_color->Composed)
throw DeadlyImportError("IME: volume color composed");
else
return ne_volume_color->Color;
}
else if(pObjectColor != nullptr)// check for object color
{
if(pObjectColor->Composed)
throw DeadlyImportError("IME: object color composed");
else
return pObjectColor->Color;
}
else if(cur_mat != nullptr)// check for material
{
return cur_mat->GetColor(pVertexCoordinateArray.at(pIdx).x, pVertexCoordinateArray.at(pIdx).y, pVertexCoordinateArray.at(pIdx).z);
}
else// set default color.
{
return {0, 0, 0, 0};
}// if((vi < pVertexColorArray.size()) && (pVertexColorArray[vi] != nullptr)) else
};// auto Vertex_CalculateColor = [&](const size_t pIdx) -> aiColor4D
aiMesh* tmesh = new aiMesh;
tmesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;// Only triangles is supported by AMF.
//
// set geometry and colors (vertices)
//
// copy faces/triangles
tmesh->mNumFaces = static_cast<unsigned int>(face_list_cur.size());
tmesh->mFaces = new aiFace[tmesh->mNumFaces];
// Create vertices list and optimize indices. Optimisation mean following.In AMF all volumes use one big list of vertices. And one volume
// can use only part of vertices list, for example: vertices list contain few thousands of vertices and volume use vertices 1, 3, 10.
// Do you need all this thousands of garbage? Of course no. So, optimisation step transformate sparse indices set to continuous.
size_t VertexCount_Max = tmesh->mNumFaces * 3;// 3 - triangles.
std::vector<aiVector3D> vert_arr, texcoord_arr;
std::vector<aiColor4D> col_arr;
vert_arr.reserve(VertexCount_Max * 2);// "* 2" - see below TODO.
col_arr.reserve(VertexCount_Max * 2);
{// fill arrays
size_t vert_idx_from, vert_idx_to;
// first iteration.
vert_idx_to = 0;
vert_idx_from = VertexIndex_GetMinimal(face_list_cur, nullptr);
vert_arr.push_back(pVertexCoordinateArray.at(vert_idx_from));
col_arr.push_back(Vertex_CalculateColor(vert_idx_from));
if(vert_idx_from != vert_idx_to) VertexIndex_Replace(face_list_cur, vert_idx_from, vert_idx_to);
// rest iterations
do
{
vert_idx_from = VertexIndex_GetMinimal(face_list_cur, &vert_idx_to);
if(vert_idx_from == vert_idx_to) break;// all indices are transferred,
vert_arr.push_back(pVertexCoordinateArray.at(vert_idx_from));
col_arr.push_back(Vertex_CalculateColor(vert_idx_from));
vert_idx_to++;
if(vert_idx_from != vert_idx_to) VertexIndex_Replace(face_list_cur, vert_idx_from, vert_idx_to);
} while(true);
}// fill arrays. END.
//
// check if triangle colors are used and create additional faces if needed.
//
for(const SComplexFace& face_cur: face_list_cur)
{
if(face_cur.Color != nullptr)
{
aiColor4D face_color;
size_t vert_idx_new = vert_arr.size();
if(face_cur.Color->Composed)
throw DeadlyImportError("IME: face color composed");
else
face_color = face_cur.Color->Color;
for(size_t idx_ind = 0; idx_ind < face_cur.Face.mNumIndices; idx_ind++)
{
vert_arr.push_back(vert_arr.at(face_cur.Face.mIndices[idx_ind]));
col_arr.push_back(face_color);
face_cur.Face.mIndices[idx_ind] = static_cast<unsigned int>(vert_idx_new++);
}
}// if(face_cur.Color != nullptr)
}// for(const SComplexFace& face_cur: face_list_cur)
//
// if texture is used then copy texture coordinates too.
//
if(face_list_cur.front().TexMap != nullptr)
{
size_t idx_vert_new = vert_arr.size();
///TODO: clean unused vertices. "* 2": in certain cases - mesh full of triangle colors - vert_arr will contain duplicated vertices for
/// colored triangles and initial vertices (for colored vertices) which in real became unused. This part need more thinking about
/// optimisation.
bool* idx_vert_used;
idx_vert_used = new bool[VertexCount_Max * 2];
for(size_t i = 0, i_e = VertexCount_Max * 2; i < i_e; i++) idx_vert_used[i] = false;
// This ID's will be used when set materials ID in scene.
tmesh->mMaterialIndex = static_cast<unsigned int>(PostprocessHelper_GetTextureID_Or_Create(face_list_cur.front().TexMap->TextureID_R,
face_list_cur.front().TexMap->TextureID_G,
face_list_cur.front().TexMap->TextureID_B,
face_list_cur.front().TexMap->TextureID_A));
texcoord_arr.resize(VertexCount_Max * 2);
for(const SComplexFace& face_cur: face_list_cur)
{
for(size_t idx_ind = 0; idx_ind < face_cur.Face.mNumIndices; idx_ind++)
{
const size_t idx_vert = face_cur.Face.mIndices[idx_ind];
if(!idx_vert_used[idx_vert])
{
texcoord_arr.at(idx_vert) = face_cur.TexMap->TextureCoordinate[idx_ind];
idx_vert_used[idx_vert] = true;
}
else if(texcoord_arr.at(idx_vert) != face_cur.TexMap->TextureCoordinate[idx_ind])
{
// in that case one vertex is shared with many texture coordinates. We need to duplicate vertex with another texture
// coordinates.
vert_arr.push_back(vert_arr.at(idx_vert));
col_arr.push_back(col_arr.at(idx_vert));
texcoord_arr.at(idx_vert_new) = face_cur.TexMap->TextureCoordinate[idx_ind];
face_cur.Face.mIndices[idx_ind] = static_cast<unsigned int>(idx_vert_new++);
}
}// for(size_t idx_ind = 0; idx_ind < face_cur.Face.mNumIndices; idx_ind++)
}// for(const SComplexFace& face_cur: face_list_cur)
delete [] idx_vert_used;
// shrink array
texcoord_arr.resize(idx_vert_new);
}// if(face_list_cur.front().TexMap != nullptr)
//
// copy collected data to mesh
//
tmesh->mNumVertices = static_cast<unsigned int>(vert_arr.size());
tmesh->mVertices = new aiVector3D[tmesh->mNumVertices];
tmesh->mColors[0] = new aiColor4D[tmesh->mNumVertices];
tmesh->mFaces = new aiFace[face_list_cur.size()];
memcpy(tmesh->mVertices, vert_arr.data(), tmesh->mNumVertices * sizeof(aiVector3D));
memcpy(tmesh->mColors[0], col_arr.data(), tmesh->mNumVertices * sizeof(aiColor4D));
if(texcoord_arr.size() > 0)
{
tmesh->mTextureCoords[0] = new aiVector3D[tmesh->mNumVertices];
memcpy(tmesh->mTextureCoords[0], texcoord_arr.data(), tmesh->mNumVertices * sizeof(aiVector3D));
tmesh->mNumUVComponents[0] = 2;// U and V stored in "x", "y" of aiVector3D.
}
size_t idx_face = 0;
for(const SComplexFace& face_cur: face_list_cur) tmesh->mFaces[idx_face++] = face_cur.Face;
// store new aiMesh
mesh_idx.push_back(static_cast<unsigned int>(pMeshList.size()));
pMeshList.push_back(tmesh);
}// for(const std::list<SComplexFace>& face_list_cur: complex_faces_toplist)
}// if(ne_child->Type == CAMFImporter_NodeElement::ENET_Volume)
}// for(const CAMFImporter_NodeElement* ne_child: pNodeElement.Child)
// if meshes was created then assign new indices with current aiNode
if(mesh_idx.size() > 0)
{
std::list<unsigned int>::const_iterator mit = mesh_idx.begin();
pSceneNode.mNumMeshes = static_cast<unsigned int>(mesh_idx.size());
pSceneNode.mMeshes = new unsigned int[pSceneNode.mNumMeshes];
for(size_t i = 0; i < pSceneNode.mNumMeshes; i++) pSceneNode.mMeshes[i] = *mit++;
}// if(mesh_idx.size() > 0)
}
void AMFImporter::Postprocess_BuildMaterial(const CAMFImporter_NodeElement_Material& pMaterial)
{
SPP_Material new_mat;
new_mat.ID = pMaterial.ID;
for(const CAMFImporter_NodeElement* mat_child: pMaterial.Child)
{
if(mat_child->Type == CAMFImporter_NodeElement::ENET_Color)
{
new_mat.Color = (CAMFImporter_NodeElement_Color*)mat_child;
}
else if(mat_child->Type == CAMFImporter_NodeElement::ENET_Metadata)
{
new_mat.Metadata.push_back((CAMFImporter_NodeElement_Metadata*)mat_child);
}
}// for(const CAMFImporter_NodeElement* mat_child; pMaterial.Child)
// place converted material to special list
mMaterial_Converted.push_back(new_mat);
}
void AMFImporter::Postprocess_BuildConstellation(CAMFImporter_NodeElement_Constellation& pConstellation, std::list<aiNode*>& pNodeList) const
{
aiNode* con_node;
std::list<aiNode*> ch_node;
// We will build next hierarchy:
// aiNode as parent (<constellation>) for set of nodes as a children
// |- aiNode for transformation (<instance> -> <delta...>, <r...>) - aiNode for pointing to object ("objectid")
// ...
// \_ aiNode for transformation (<instance> -> <delta...>, <r...>) - aiNode for pointing to object ("objectid")
con_node = new aiNode;
con_node->mName = pConstellation.ID;
// Walk through children and search for instances of another objects, constellations.
for(const CAMFImporter_NodeElement* ne: pConstellation.Child)
{
aiMatrix4x4 tmat;
aiNode* t_node;
aiNode* found_node;
if(ne->Type == CAMFImporter_NodeElement::ENET_Metadata) continue;
if(ne->Type != CAMFImporter_NodeElement::ENET_Instance) throw DeadlyImportError("Only <instance> nodes can be in <constellation>.");
// create alias for conveniance
CAMFImporter_NodeElement_Instance& als = *((CAMFImporter_NodeElement_Instance*)ne);
// find referenced object
if(!Find_ConvertedNode(als.ObjectID, pNodeList, &found_node)) Throw_ID_NotFound(als.ObjectID);
// create node for apllying transformation
t_node = new aiNode;
t_node->mParent = con_node;
// apply transformation
aiMatrix4x4::Translation(als.Delta, tmat), t_node->mTransformation *= tmat;
aiMatrix4x4::RotationX(als.Rotation.x, tmat), t_node->mTransformation *= tmat;
aiMatrix4x4::RotationY(als.Rotation.y, tmat), t_node->mTransformation *= tmat;
aiMatrix4x4::RotationZ(als.Rotation.z, tmat), t_node->mTransformation *= tmat;
// create array for one child node
t_node->mNumChildren = 1;
t_node->mChildren = new aiNode*[t_node->mNumChildren];
SceneCombiner::Copy(&t_node->mChildren[0], found_node);
t_node->mChildren[0]->mParent = t_node;
ch_node.push_back(t_node);
}// for(const CAMFImporter_NodeElement* ne: pConstellation.Child)
// copy found aiNode's as children
if(ch_node.size() == 0) throw DeadlyImportError("<constellation> must have at least one <instance>.");
size_t ch_idx = 0;
con_node->mNumChildren = static_cast<unsigned int>(ch_node.size());
con_node->mChildren = new aiNode*[con_node->mNumChildren];
for(aiNode* node: ch_node) con_node->mChildren[ch_idx++] = node;
// and place "root" of <constellation> node to node list
pNodeList.push_back(con_node);
}
void AMFImporter::Postprocess_BuildScene(aiScene* pScene)
{
std::list<aiNode*> node_list;
std::list<aiMesh*> mesh_list;
std::list<CAMFImporter_NodeElement_Metadata*> meta_list;
//
// Because for AMF "material" is just complex colors mixing so aiMaterial will not be used.
// For building aiScene we are must to do few steps:
// at first creating root node for aiScene.
pScene->mRootNode = new aiNode;
pScene->mRootNode->mParent = nullptr;
pScene->mFlags |= AI_SCENE_FLAGS_ALLOW_SHARED;
// search for root(<amf>) element
CAMFImporter_NodeElement* root_el = nullptr;
for(CAMFImporter_NodeElement* ne: mNodeElement_List)
{
if(ne->Type != CAMFImporter_NodeElement::ENET_Root) continue;
root_el = ne;
break;
}// for(const CAMFImporter_NodeElement* ne: mNodeElement_List)
// Check if root element are found.
if(root_el == nullptr) throw DeadlyImportError("Root(<amf>) element not found.");
// after that walk through children of root and collect data. Five types of nodes can be placed at top level - in <amf>: <object>, <material>, <texture>,
// <constellation> and <metadata>. But at first we must read <material> and <texture> because they will be used in <object>. <metadata> can be read
// at any moment.
//
// 1. <material>
// 2. <texture> will be converted later when processing triangles list. \sa Postprocess_BuildMeshSet
for(const CAMFImporter_NodeElement* root_child: root_el->Child)
{
if(root_child->Type == CAMFImporter_NodeElement::ENET_Material) Postprocess_BuildMaterial(*((CAMFImporter_NodeElement_Material*)root_child));
}
// After "appearance" nodes we must read <object> because it will be used in <constellation> -> <instance>.
//
// 3. <object>
for(const CAMFImporter_NodeElement* root_child: root_el->Child)
{
if(root_child->Type == CAMFImporter_NodeElement::ENET_Object)
{
aiNode* tnode = nullptr;
// for <object> mesh and node must be built: object ID assigned to aiNode name and will be used in future for <instance>
Postprocess_BuildNodeAndObject(*((CAMFImporter_NodeElement_Object*)root_child), mesh_list, &tnode);
if(tnode != nullptr) node_list.push_back(tnode);
}
}// for(const CAMFImporter_NodeElement* root_child: root_el->Child)
// And finally read rest of nodes.
//
for(const CAMFImporter_NodeElement* root_child: root_el->Child)
{
// 4. <constellation>
if(root_child->Type == CAMFImporter_NodeElement::ENET_Constellation)
{
// <object> and <constellation> at top of self abstraction use aiNode. So we can use only aiNode list for creating new aiNode's.
Postprocess_BuildConstellation(*((CAMFImporter_NodeElement_Constellation*)root_child), node_list);
}
// 5, <metadata>
if(root_child->Type == CAMFImporter_NodeElement::ENET_Metadata) meta_list.push_back((CAMFImporter_NodeElement_Metadata*)root_child);
}// for(const CAMFImporter_NodeElement* root_child: root_el->Child)
// at now we can add collected metadata to root node
Postprocess_AddMetadata(meta_list, *pScene->mRootNode);
//
// Check constellation children
//
// As said in specification:
// "When multiple objects and constellations are defined in a single file, only the top level objects and constellations are available for printing."
// What that means? For example: if some object is used in constellation then you must show only constellation but not original object.
// And at this step we are checking that relations.
nl_clean_loop:
if(node_list.size() > 1)
{
// walk through all nodes
for(std::list<aiNode*>::iterator nl_it = node_list.begin(); nl_it != node_list.end(); nl_it++)
{
// and try to find them in another top nodes.
std::list<aiNode*>::const_iterator next_it = nl_it;
next_it++;
for(; next_it != node_list.end(); next_it++)
{
if((*next_it)->FindNode((*nl_it)->mName) != nullptr)
{
// if current top node(nl_it) found in another top node then erase it from node_list and restart search loop.
node_list.erase(nl_it);
goto nl_clean_loop;
}
}// for(; next_it != node_list.end(); next_it++)
}// for(std::list<aiNode*>::const_iterator nl_it = node_list.begin(); nl_it != node_list.end(); nl_it++)
}
//
// move created objects to aiScene
//
//
// Nodes
if(node_list.size() > 0)
{
std::list<aiNode*>::const_iterator nl_it = node_list.begin();
pScene->mRootNode->mNumChildren = static_cast<unsigned int>(node_list.size());
pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren];
for(size_t i = 0; i < pScene->mRootNode->mNumChildren; i++)
{
// Objects and constellation that must be showed placed at top of hierarchy in <amf> node. So all aiNode's in node_list must have
// mRootNode only as parent.
(*nl_it)->mParent = pScene->mRootNode;
pScene->mRootNode->mChildren[i] = *nl_it++;
}
}// if(node_list.size() > 0)
//
// Meshes
if(mesh_list.size() > 0)
{
std::list<aiMesh*>::const_iterator ml_it = mesh_list.begin();
pScene->mNumMeshes = static_cast<unsigned int>(mesh_list.size());
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
for(size_t i = 0; i < pScene->mNumMeshes; i++) pScene->mMeshes[i] = *ml_it++;
}// if(mesh_list.size() > 0)
//
// Textures
pScene->mNumTextures = static_cast<unsigned int>(mTexture_Converted.size());
if(pScene->mNumTextures > 0)
{
size_t idx;
idx = 0;
pScene->mTextures = new aiTexture*[pScene->mNumTextures];
for(const SPP_Texture& tex_convd: mTexture_Converted)
{
pScene->mTextures[idx] = new aiTexture;
pScene->mTextures[idx]->mWidth = static_cast<unsigned int>(tex_convd.Width);
pScene->mTextures[idx]->mHeight = static_cast<unsigned int>(tex_convd.Height);
pScene->mTextures[idx]->pcData = (aiTexel*)tex_convd.Data;
// texture format description.
strcpy(pScene->mTextures[idx]->achFormatHint, tex_convd.FormatHint);
idx++;
}// for(const SPP_Texture& tex_convd: mTexture_Converted)
// Create materials for embedded textures.
idx = 0;
pScene->mNumMaterials = static_cast<unsigned int>(mTexture_Converted.size());
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
for(const SPP_Texture& tex_convd: mTexture_Converted)
{
const aiString texture_id(AI_EMBEDDED_TEXNAME_PREFIX + to_string(idx));
const int mode = aiTextureOp_Multiply;
const int repeat = tex_convd.Tiled ? 1 : 0;
pScene->mMaterials[idx] = new aiMaterial;
pScene->mMaterials[idx]->AddProperty(&texture_id, AI_MATKEY_TEXTURE_DIFFUSE(0));
pScene->mMaterials[idx]->AddProperty(&mode, 1, AI_MATKEY_TEXOP_DIFFUSE(0));
pScene->mMaterials[idx]->AddProperty(&repeat, 1, AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0));
pScene->mMaterials[idx]->AddProperty(&repeat, 1, AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0));
idx++;
}
}// if(pScene->mNumTextures > 0)
}// END: after that walk through children of root and collect data
}// namespace Assimp
#endif // !ASSIMP_BUILD_NO_AMF_IMPORTER

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the ASE importer class * @brief Implementation of the ASE importer class
*/ */
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_ASE_IMPORTER #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
// internal headers // internal headers
@ -51,6 +50,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "StringComparison.h" #include "StringComparison.h"
#include "SkeletonMeshBuilder.h" #include "SkeletonMeshBuilder.h"
#include "TargetAnimation.h" #include "TargetAnimation.h"
#include <assimp/Importer.hpp>
#include <assimp/IOSystem.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
#include <memory>
// utilities // utilities
#include "fast_atof.h" #include "fast_atof.h"
@ -74,7 +79,11 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
ASEImporter::ASEImporter() ASEImporter::ASEImporter()
: noSkeletonMesh() : mParser(),
mBuffer(),
pcScene(),
configRecomputeNormals(),
noSkeletonMesh()
{} {}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -121,7 +130,7 @@ void ASEImporter::SetupProperties(const Importer* pImp)
void ASEImporter::InternReadFile( const std::string& pFile, void ASEImporter::InternReadFile( const std::string& pFile,
aiScene* pScene, IOSystem* pIOHandler) aiScene* pScene, IOSystem* pIOHandler)
{ {
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
// Check whether we can read from the file // Check whether we can read from the file
if( file.get() == NULL) { if( file.get() == NULL) {
@ -216,17 +225,13 @@ void ASEImporter::InternReadFile( const std::string& pFile,
+ mParser->m_vCameras.size() + mParser->m_vDummies.size()); + mParser->m_vCameras.size() + mParser->m_vDummies.size());
// Lights // Lights
for (std::vector<ASE::Light>::iterator it = mParser->m_vLights.begin(), for (auto &light : mParser->m_vLights)nodes.push_back(&light);
end = mParser->m_vLights.end();it != end; ++it)nodes.push_back(&(*it));
// Cameras // Cameras
for (std::vector<ASE::Camera>::iterator it = mParser->m_vCameras.begin(), for (auto &camera : mParser->m_vCameras)nodes.push_back(&camera);
end = mParser->m_vCameras.end();it != end; ++it)nodes.push_back(&(*it));
// Meshes // Meshes
for (std::vector<ASE::Mesh>::iterator it = mParser->m_vMeshes.begin(), for (auto &mesh : mParser->m_vMeshes)nodes.push_back(&mesh);
end = mParser->m_vMeshes.end();it != end; ++it)nodes.push_back(&(*it));
// Dummies // Dummies
for (std::vector<ASE::Dummy>::iterator it = mParser->m_vDummies.begin(), for (auto &dummy : mParser->m_vDummies)nodes.push_back(&dummy);
end = mParser->m_vDummies.end();it != end; ++it)nodes.push_back(&(*it));
// build the final node graph // build the final node graph
BuildNodes(nodes); BuildNodes(nodes);
@ -648,8 +653,8 @@ void ASEImporter::BuildNodes(std::vector<BaseNode*>& nodes) {
ch->mParent = root; ch->mParent = root;
// Change the transformation matrix of all nodes // Change the transformation matrix of all nodes
for (std::vector<BaseNode*>::iterator it = nodes.begin(), end = nodes.end();it != end; ++it) { for (BaseNode *node : nodes) {
aiMatrix4x4& m = (*it)->mTransform; aiMatrix4x4& m = node->mTransform;
m.Transpose(); // row-order vs column-order m.Transpose(); // row-order vs column-order
} }
@ -814,10 +819,10 @@ void CopyASETexture(aiMaterial& mat, ASE::Texture& texture, aiTextureType type)
// Setup the texture blend factor // Setup the texture blend factor
if (is_not_qnan(texture.mTextureBlend)) if (is_not_qnan(texture.mTextureBlend))
mat.AddProperty<float>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0)); mat.AddProperty<ai_real>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
// Setup texture UV transformations // Setup texture UV transformations
mat.AddProperty<float>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0)); mat.AddProperty<ai_real>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -860,7 +865,7 @@ void ASEImporter::ConvertMaterial(ASE::Material& mat)
} }
// opacity // opacity
mat.pcInstance->AddProperty<float>( &mat.mTransparency,1,AI_MATKEY_OPACITY); mat.pcInstance->AddProperty<ai_real>( &mat.mTransparency,1,AI_MATKEY_OPACITY);
// Two sided rendering? // Two sided rendering?
if (mat.mTwoSided) if (mat.mTwoSided)

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -45,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_ASELOADER_H_INCLUDED #define AI_ASELOADER_H_INCLUDED
#include "BaseImporter.h" #include "BaseImporter.h"
#include "../include/assimp/types.h" #include <assimp/types.h>
struct aiNode; struct aiNode;
#include "ASEParser.h" #include "ASEParser.h"

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
@ -25,8 +25,8 @@ conditions are met:
derived from this software without specific prior derived from this software without specific prior
written permission of the assimp team. written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
@ -43,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the ASE parser class * @brief Implementation of the ASE parser class
*/ */
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_ASE_IMPORTER #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
// internal headers // internal headers
@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "ASELoader.h" #include "ASELoader.h"
#include "MaterialSystem.h" #include "MaterialSystem.h"
#include "fast_atof.h" #include "fast_atof.h"
#include <assimp/DefaultLogger.hpp>
using namespace Assimp; using namespace Assimp;
using namespace Assimp::ASE; using namespace Assimp::ASE;
@ -142,9 +143,9 @@ void Parser::LogWarning(const char* szWarn)
char szTemp[1024]; char szTemp[1024];
#if _MSC_VER >= 1400 #if _MSC_VER >= 1400
sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn); sprintf_s(szTemp, "Line %u: %s",iLineNumber,szWarn);
#else #else
snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn); ai_snprintf(szTemp,1024,"Line %u: %s",iLineNumber,szWarn);
#endif #endif
// output the warning to the logger ... // output the warning to the logger ...
@ -158,9 +159,9 @@ void Parser::LogInfo(const char* szWarn)
char szTemp[1024]; char szTemp[1024];
#if _MSC_VER >= 1400 #if _MSC_VER >= 1400
sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn); sprintf_s(szTemp,"Line %u: %s",iLineNumber,szWarn);
#else #else
snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn); ai_snprintf(szTemp,1024,"Line %u: %s",iLineNumber,szWarn);
#endif #endif
// output the information to the logger ... // output the information to the logger ...
@ -168,15 +169,15 @@ void Parser::LogInfo(const char* szWarn)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Parser::LogError(const char* szWarn) AI_WONT_RETURN void Parser::LogError(const char* szWarn)
{ {
ai_assert(NULL != szWarn); ai_assert(NULL != szWarn);
char szTemp[1024]; char szTemp[1024];
#if _MSC_VER >= 1400 #if _MSC_VER >= 1400
sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn); sprintf_s(szTemp,"Line %u: %s",iLineNumber,szWarn);
#else #else
snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn); ai_snprintf(szTemp,1024,"Line %u: %s",iLineNumber,szWarn);
#endif #endif
// throw an exception // throw an exception
@ -430,7 +431,7 @@ void Parser::ParseLV1SoftSkinBlock()
ParseString(bone,"*MESH_SOFTSKINVERTS.Bone"); ParseString(bone,"*MESH_SOFTSKINVERTS.Bone");
// Find the bone in the mesh's list // Find the bone in the mesh's list
std::pair<int,float> me; std::pair<int,ai_real> me;
me.first = -1; me.first = -1;
for (unsigned int n = 0; n < curMesh->mBones.size();++n) for (unsigned int n = 0; n < curMesh->mBones.size();++n)
@ -617,12 +618,13 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
if (TokenMatch(filePtr,"MATERIAL_TRANSPARENCY",21)) if (TokenMatch(filePtr,"MATERIAL_TRANSPARENCY",21))
{ {
ParseLV4MeshFloat(mat.mTransparency); ParseLV4MeshFloat(mat.mTransparency);
mat.mTransparency = 1.0f - mat.mTransparency;continue; mat.mTransparency = ai_real( 1.0 ) - mat.mTransparency;
continue;
} }
// material self illumination // material self illumination
if (TokenMatch(filePtr,"MATERIAL_SELFILLUM",18)) if (TokenMatch(filePtr,"MATERIAL_SELFILLUM",18))
{ {
float f = 0.0f; ai_real f = 0.0;
ParseLV4MeshFloat(f); ParseLV4MeshFloat(f);
mat.mEmissive.r = f; mat.mEmissive.r = f;
@ -824,7 +826,7 @@ bool Parser::ParseString(std::string& out,const char* szName)
if (!SkipSpaces(&filePtr)) if (!SkipSpaces(&filePtr))
{ {
sprintf(szBuffer,"Unable to parse %s block: Unexpected EOL",szName); ai_snprintf(szBuffer, 1024, "Unable to parse %s block: Unexpected EOL",szName);
LogWarning(szBuffer); LogWarning(szBuffer);
return false; return false;
} }
@ -832,7 +834,7 @@ bool Parser::ParseString(std::string& out,const char* szName)
if ('\"' != *filePtr) if ('\"' != *filePtr)
{ {
sprintf(szBuffer,"Unable to parse %s block: Strings are expected " ai_snprintf(szBuffer, 1024, "Unable to parse %s block: Strings are expected "
"to be enclosed in double quotation marks",szName); "to be enclosed in double quotation marks",szName);
LogWarning(szBuffer); LogWarning(szBuffer);
return false; return false;
@ -844,7 +846,7 @@ bool Parser::ParseString(std::string& out,const char* szName)
if ('\"' == *sz)break; if ('\"' == *sz)break;
else if ('\0' == *sz) else if ('\0' == *sz)
{ {
sprintf(szBuffer,"Unable to parse %s block: Strings are expected to " ai_snprintf(szBuffer, 1024, "Unable to parse %s block: Strings are expected to "
"be enclosed in double quotation marks but EOF was reached before " "be enclosed in double quotation marks but EOF was reached before "
"a closing quotation mark was encountered",szName); "a closing quotation mark was encountered",szName);
LogWarning(szBuffer); LogWarning(szBuffer);
@ -1133,7 +1135,7 @@ void Parser::ParseLV3ScaleAnimationBlock(ASE::Animation& anim)
bool b = false; bool b = false;
// For the moment we're just reading the three floats - // For the moment we're just reading the three floats -
// we ignore the ádditional information for bezier's and TCBs // we ignore the additional information for bezier's and TCBs
// simple scaling keyframe // simple scaling keyframe
if (TokenMatch(filePtr,"CONTROL_SCALE_SAMPLE" ,20)) if (TokenMatch(filePtr,"CONTROL_SCALE_SAMPLE" ,20))
@ -1179,7 +1181,7 @@ void Parser::ParseLV3PosAnimationBlock(ASE::Animation& anim)
bool b = false; bool b = false;
// For the moment we're just reading the three floats - // For the moment we're just reading the three floats -
// we ignore the ádditional information for bezier's and TCBs // we ignore the additional information for bezier's and TCBs
// simple scaling keyframe // simple scaling keyframe
if (TokenMatch(filePtr,"CONTROL_POS_SAMPLE" ,18)) if (TokenMatch(filePtr,"CONTROL_POS_SAMPLE" ,18))
@ -1225,7 +1227,7 @@ void Parser::ParseLV3RotAnimationBlock(ASE::Animation& anim)
bool b = false; bool b = false;
// For the moment we're just reading the floats - // For the moment we're just reading the floats -
// we ignore the ádditional information for bezier's and TCBs // we ignore the additional information for bezier's and TCBs
// simple scaling keyframe // simple scaling keyframe
if (TokenMatch(filePtr,"CONTROL_ROT_SAMPLE" ,18)) if (TokenMatch(filePtr,"CONTROL_ROT_SAMPLE" ,18))
@ -1250,7 +1252,7 @@ void Parser::ParseLV3RotAnimationBlock(ASE::Animation& anim)
{ {
anim.akeyRotations.push_back(aiQuatKey()); anim.akeyRotations.push_back(aiQuatKey());
aiQuatKey& key = anim.akeyRotations.back(); aiQuatKey& key = anim.akeyRotations.back();
aiVector3D v;float f; aiVector3D v;ai_real f;
ParseLV4MeshFloatTriple(&v.x,iIndex); ParseLV4MeshFloatTriple(&v.x,iIndex);
ParseLV4MeshFloat(f); ParseLV4MeshFloat(f);
key.mTime = (double)iIndex; key.mTime = (double)iIndex;
@ -1462,31 +1464,30 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
continue; continue;
} }
// another mesh UV channel ... // another mesh UV channel ...
if (TokenMatch(filePtr,"MESH_MAPPINGCHANNEL" ,19)) if (TokenMatch(filePtr,"MESH_MAPPINGCHANNEL" ,19)) {
{ unsigned int iIndex( 0 );
unsigned int iIndex = 0;
ParseLV4MeshLong(iIndex); ParseLV4MeshLong(iIndex);
if ( 0 == iIndex ) {
if (iIndex < 2) LogWarning( "Mapping channel has an invalid index. Skipping UV channel" );
{ // skip it ...
LogWarning("Mapping channel has an invalid index. Skipping UV channel"); SkipSection();
} else {
if ( iIndex < 2 ) {
LogWarning( "Mapping channel has an invalid index. Skipping UV channel" );
// skip it ... // skip it ...
SkipSection(); SkipSection();
} }
if (iIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS) if ( iIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS ) {
{ LogWarning( "Too many UV channels specified. Skipping channel .." );
LogWarning("Too many UV channels specified. Skipping channel ..");
// skip it ... // skip it ...
SkipSection(); SkipSection();
} } else {
else
{
// parse the mapping channel // parse the mapping channel
ParseLV3MappingChannel(iIndex-1,mesh); ParseLV3MappingChannel( iIndex - 1, mesh );
} }
continue; continue;
} }
}
// mesh animation keyframe. Not supported // mesh animation keyframe. Not supported
if (TokenMatch(filePtr,"MESH_ANIMATION" ,14)) if (TokenMatch(filePtr,"MESH_ANIMATION" ,14))
{ {
@ -1525,7 +1526,7 @@ void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh& mesh)
continue; continue;
} }
// Number of bones // Number of bones
if (TokenMatch(filePtr,"MESH_NUMBONE" ,11)) if (TokenMatch(filePtr,"MESH_NUMBONE" ,12))
{ {
ParseLV4MeshLong(iNumBones); ParseLV4MeshLong(iNumBones);
continue; continue;
@ -1559,7 +1560,7 @@ void Parser::ParseLV4MeshBones(unsigned int iNumBones,ASE::Mesh& mesh)
++filePtr; ++filePtr;
// Mesh bone with name ... // Mesh bone with name ...
if (TokenMatch(filePtr,"MESH_BONE_NAME" ,16)) if (TokenMatch(filePtr,"MESH_BONE_NAME" ,14))
{ {
// parse an index ... // parse an index ...
if(SkipSpaces(&filePtr)) if(SkipSpaces(&filePtr))
@ -1603,7 +1604,7 @@ void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices,ASE::Mesh& mesh
} }
// --- ignored // --- ignored
float afVert[3]; ai_real afVert[3];
ParseLV4MeshFloatTriple(afVert); ParseLV4MeshFloatTriple(afVert);
std::pair<int,float> pairOut; std::pair<int,float> pairOut;
@ -2101,7 +2102,7 @@ void Parser::ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut
ParseLV4MeshLongTriple(apOut); ParseLV4MeshLongTriple(apOut);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut) void Parser::ParseLV4MeshFloatTriple(ai_real* apOut, unsigned int& rIndexOut)
{ {
ai_assert(NULL != apOut); ai_assert(NULL != apOut);
@ -2112,7 +2113,7 @@ void Parser::ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut)
ParseLV4MeshFloatTriple(apOut); ParseLV4MeshFloatTriple(apOut);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshFloatTriple(float* apOut) void Parser::ParseLV4MeshFloatTriple(ai_real* apOut)
{ {
ai_assert(NULL != apOut); ai_assert(NULL != apOut);
@ -2120,19 +2121,19 @@ void Parser::ParseLV4MeshFloatTriple(float* apOut)
ParseLV4MeshFloat(apOut[i]); ParseLV4MeshFloat(apOut[i]);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshFloat(float& fOut) void Parser::ParseLV4MeshFloat(ai_real& fOut)
{ {
// skip spaces and tabs // skip spaces and tabs
if(!SkipSpaces(&filePtr)) if(!SkipSpaces(&filePtr))
{ {
// LOG // LOG
LogWarning("Unable to parse float: unexpected EOL [#1]"); LogWarning("Unable to parse float: unexpected EOL [#1]");
fOut = 0.0f; fOut = 0.0;
++iLineNumber; ++iLineNumber;
return; return;
} }
// parse the first float // parse the first float
filePtr = fast_atoreal_move<float>(filePtr,fOut); filePtr = fast_atoreal_move<ai_real>(filePtr,fOut);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Parser::ParseLV4MeshLong(unsigned int& iOut) void Parser::ParseLV4MeshLong(unsigned int& iOut)

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -43,15 +43,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_ASEFILEHELPER_H_INC #ifndef AI_ASEFILEHELPER_H_INC
#define AI_ASEFILEHELPER_H_INC #define AI_ASEFILEHELPER_H_INC
// STL/CRT headers
#include <string>
#include <vector>
#include <list>
// public ASSIMP headers // public ASSIMP headers
#include "../include/assimp/types.h" #include <assimp/types.h>
#include "../include/assimp/mesh.h" #include <assimp/mesh.h>
#include "../include/assimp/anim.h" #include <assimp/anim.h>
// for some helper routines like IsSpace() // for some helper routines like IsSpace()
#include "ParsingUtils.h" #include "ParsingUtils.h"
@ -133,12 +128,12 @@ struct Bone
// Generate a default name for the bone // Generate a default name for the bone
char szTemp[128]; char szTemp[128];
::sprintf(szTemp,"UNNAMED_%i",iCnt++); ::ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
mName = szTemp; mName = szTemp;
} }
//! Construction from an existing name //! Construction from an existing name
Bone( const std::string& name) explicit Bone( const std::string& name)
: mName (name) : mName (name)
{} {}
@ -216,18 +211,18 @@ struct BaseNode
enum Type {Light, Camera, Mesh, Dummy} mType; enum Type {Light, Camera, Mesh, Dummy} mType;
//! Constructor. Creates a default name for the node //! Constructor. Creates a default name for the node
BaseNode(Type _mType) explicit BaseNode(Type _mType)
: mType (_mType) : mType (_mType)
, mProcessed (false) , mProcessed (false)
{ {
// generate a default name for the node // generate a default name for the node
static int iCnt = 0; static int iCnt = 0;
char szTemp[128]; // should be sufficiently large char szTemp[128]; // should be sufficiently large
::sprintf(szTemp,"UNNAMED_%i",iCnt++); ::ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
mName = szTemp; mName = szTemp;
// Set mTargetPosition to qnan // Set mTargetPosition to qnan
const float qnan = get_qnan(); const ai_real qnan = get_qnan();
mTargetPosition.x = qnan; mTargetPosition.x = qnan;
} }
@ -322,9 +317,9 @@ struct Light : public BaseNode
LightType mLightType; LightType mLightType;
aiColor3D mColor; aiColor3D mColor;
float mIntensity; ai_real mIntensity;
float mAngle; // in degrees ai_real mAngle; // in degrees
float mFalloff; ai_real mFalloff;
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -347,7 +342,7 @@ struct Camera : public BaseNode
{ {
} }
float mFOV, mNear, mFar; ai_real mFOV, mNear, mFar;
CameraType mCameraType; CameraType mCameraType;
}; };
@ -549,13 +544,13 @@ private:
//! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...) //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...)
//! \param apOut Output buffer (3 floats) //! \param apOut Output buffer (3 floats)
//! \param rIndexOut Output index //! \param rIndexOut Output index
void ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut); void ParseLV4MeshFloatTriple(ai_real* apOut, unsigned int& rIndexOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *MESH_VERT block in a file //! Parse a *MESH_VERT block in a file
//! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...) //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...)
//! \param apOut Output buffer (3 floats) //! \param apOut Output buffer (3 floats)
void ParseLV4MeshFloatTriple(float* apOut); void ParseLV4MeshFloatTriple(ai_real* apOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a *MESH_TFACE block in a file //! Parse a *MESH_TFACE block in a file
@ -573,7 +568,7 @@ private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a single float element //! Parse a single float element
//! \param fOut Output float //! \param fOut Output float
void ParseLV4MeshFloat(float& fOut); void ParseLV4MeshFloat(ai_real& fOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a single int element //! Parse a single int element
@ -602,14 +597,14 @@ private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Output an error to the logger //! Output an error to the logger
//! \param szWarn Error message //! \param szWarn Error message
void LogError(const char* szWarn); AI_WONT_RETURN void LogError(const char* szWarn) AI_WONT_RETURN_SUFFIX;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
//! Parse a string, enclosed in double quotation marks //! Parse a string, enclosed in double quotation marks
//! \param out Output string //! \param out Output string
//! \param szName Name of the enclosing element -> used in error //! \param szName Name of the enclosing element -> used in error
//! messages. //! messages.
//! \return false if an error occured //! \return false if an error occurred
bool ParseString(std::string& out,const char* szName); bool ParseString(std::string& out,const char* szName);
public: public:

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -40,10 +40,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file AssbinExporter.cpp /** @file AssbinExporter.cpp
* ASSBIN exporter main code * ASSBIN exporter main code
*/ */
#include "AssimpPCH.h"
#include "assbin_chunks.h" #include "assbin_chunks.h"
#include "./../include/assimp/version.h" #include <assimp/version.h>
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
#include <assimp/Exporter.hpp>
#include "ProcessHelper.h" #include "ProcessHelper.h"
#include "Exceptional.h"
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB #ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h> # include <zlib.h>
@ -99,7 +102,7 @@ inline size_t Write<unsigned int>(IOStream * stream, const unsigned int& w)
template <> template <>
inline size_t Write<uint16_t>(IOStream * stream, const uint16_t& w) inline size_t Write<uint16_t>(IOStream * stream, const uint16_t& w)
{ {
BOOST_STATIC_ASSERT(sizeof(uint16_t)==2); static_assert(sizeof(uint16_t)==2, "sizeof(uint16_t)==2");
stream->Write(&w,2,1); stream->Write(&w,2,1);
return 2; return 2;
} }
@ -109,7 +112,7 @@ inline size_t Write<uint16_t>(IOStream * stream, const uint16_t& w)
template <> template <>
inline size_t Write<float>(IOStream * stream, const float& f) inline size_t Write<float>(IOStream * stream, const float& f)
{ {
BOOST_STATIC_ASSERT(sizeof(float)==4); static_assert(sizeof(float)==4, "sizeof(float)==4");
stream->Write(&f,4,1); stream->Write(&f,4,1);
return 4; return 4;
} }
@ -119,7 +122,7 @@ inline size_t Write<float>(IOStream * stream, const float& f)
template <> template <>
inline size_t Write<double>(IOStream * stream, const double& f) inline size_t Write<double>(IOStream * stream, const double& f)
{ {
BOOST_STATIC_ASSERT(sizeof(double)==8); static_assert(sizeof(double)==8, "sizeof(double)==8");
stream->Write(&f,8,1); stream->Write(&f,8,1);
return 8; return 8;
} }
@ -273,13 +276,13 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
if (buffer) delete[] buffer; if (buffer) delete[] buffer;
} }
void * GetBufferPointer() { return buffer; }; void * GetBufferPointer() { return buffer; }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
virtual size_t Read(void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) { return 0; }; 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 aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) { return aiReturn_FAILURE; }
virtual size_t Tell() const { return cursor; }; virtual size_t Tell() const { return cursor; }
virtual void Flush() { }; virtual void Flush() { }
virtual size_t FileSize() const virtual size_t FileSize() const
{ {
@ -468,7 +471,7 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
uint32_t tmp = f.mNumIndices; uint32_t tmp = f.mNumIndices;
hash = SuperFastHash(reinterpret_cast<const char*>(&tmp),sizeof tmp,hash); hash = SuperFastHash(reinterpret_cast<const char*>(&tmp),sizeof tmp,hash);
for (unsigned int i = 0; i < f.mNumIndices; ++i) { for (unsigned int i = 0; i < f.mNumIndices; ++i) {
BOOST_STATIC_ASSERT(AI_MAX_VERTICES <= 0xffffffff); static_assert(AI_MAX_VERTICES <= 0xffffffff, "AI_MAX_VERTICES <= 0xffffffff");
tmp = static_cast<uint32_t>( f.mIndices[i] ); tmp = static_cast<uint32_t>( f.mIndices[i] );
hash = SuperFastHash(reinterpret_cast<const char*>(&tmp),sizeof tmp,hash); hash = SuperFastHash(reinterpret_cast<const char*>(&tmp),sizeof tmp,hash);
} }
@ -482,7 +485,7 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
for (unsigned int i = 0; i < mesh->mNumFaces;++i) { for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
const aiFace& f = mesh->mFaces[i]; const aiFace& f = mesh->mFaces[i];
BOOST_STATIC_ASSERT(AI_MAX_FACE_INDICES <= 0xffff); static_assert(AI_MAX_FACE_INDICES <= 0xffff, "AI_MAX_FACE_INDICES <= 0xffff");
Write<uint16_t>(&chunk,f.mNumIndices); Write<uint16_t>(&chunk,f.mNumIndices);
for (unsigned int a = 0; a < f.mNumIndices;++a) { for (unsigned int a = 0; a < f.mNumIndices;++a) {
@ -698,7 +701,7 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
#if _MSC_VER >= 1400 #if _MSC_VER >= 1400
sprintf_s(s,"ASSIMP.binary-dump.%s",asctime(p)); sprintf_s(s,"ASSIMP.binary-dump.%s",asctime(p));
#else #else
snprintf(s,64,"ASSIMP.binary-dump.%s",asctime(p)); ai_snprintf(s,64,"ASSIMP.binary-dump.%s",asctime(p));
#endif #endif
out->Write( s, 44, 1 ); out->Write( s, 44, 1 );
// == 44 bytes // == 44 bytes
@ -734,7 +737,7 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
AssbinChunkWriter uncompressedStream( NULL, 0 ); AssbinChunkWriter uncompressedStream( NULL, 0 );
WriteBinaryScene( &uncompressedStream, pScene ); WriteBinaryScene( &uncompressedStream, pScene );
uLongf uncompressedSize = uncompressedStream.Tell(); uLongf uncompressedSize = static_cast<uLongf>(uncompressedStream.Tell());
uLongf compressedSize = (uLongf)(uncompressedStream.Tell() * 1.001 + 12.); uLongf compressedSize = (uLongf)(uncompressedStream.Tell() * 1.001 + 12.);
uint8_t* compressedBuffer = new uint8_t[ compressedSize ]; uint8_t* compressedBuffer = new uint8_t[ compressedSize ];
@ -754,7 +757,7 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
} }
}; };
void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene) void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
{ {
AssbinExport exporter; AssbinExport exporter;
exporter.WriteBinaryDump( pFile, pIOSystem, pScene ); exporter.WriteBinaryDump( pFile, pIOSystem, pScene );

View File

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

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
@ -45,17 +45,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* see assbin_chunks.h * see assbin_chunks.h
*/ */
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER #ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
// internal headers // internal headers
#include "AssbinLoader.h" #include "AssbinLoader.h"
#include "assbin_chunks.h" #include "assbin_chunks.h"
#include "MemoryIOWrapper.h" #include "MemoryIOWrapper.h"
#include <assimp/mesh.h>
#include <assimp/anim.h>
#include <assimp/scene.h>
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB #ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h> # include <zlib.h>
#else #else
# include "../contrib/zlib/zlib.h" # include <contrib/zlib/zlib.h>
#endif #endif
using namespace Assimp; using namespace Assimp;
@ -138,6 +141,7 @@ aiString Read<aiString>(IOStream * stream)
aiString s; aiString s;
stream->Read(&s.length,4,1); stream->Read(&s.length,4,1);
stream->Read(s.data,s.length,1); stream->Read(s.data,s.length,1);
s.data[s.length] = 0;
return s; return s;
} }
@ -194,7 +198,8 @@ template <typename T> void ReadBounds( IOStream * stream, T* /*p*/, unsigned int
void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node ) void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node )
{ {
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AINODE); uint32_t chunkID = Read<uint32_t>(stream);
ai_assert(chunkID == ASSBIN_CHUNK_AINODE);
/*uint32_t size =*/ Read<uint32_t>(stream); /*uint32_t size =*/ Read<uint32_t>(stream);
*node = new aiNode(); *node = new aiNode();
@ -225,7 +230,8 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node )
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b ) void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b )
{ {
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIBONE ); uint32_t chunkID = Read<uint32_t>(stream);
ai_assert(chunkID == ASSBIN_CHUNK_AIBONE);
/*uint32_t size =*/ Read<uint32_t>(stream); /*uint32_t size =*/ Read<uint32_t>(stream);
b->mName = Read<aiString>(stream); b->mName = Read<aiString>(stream);
@ -248,7 +254,8 @@ void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b )
void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh )
{ {
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIMESH); uint32_t chunkID = Read<uint32_t>(stream);
ai_assert(chunkID == ASSBIN_CHUNK_AIMESH);
/*uint32_t size =*/ Read<uint32_t>(stream); /*uint32_t size =*/ Read<uint32_t>(stream);
mesh->mPrimitiveTypes = Read<unsigned int>(stream); mesh->mPrimitiveTypes = Read<unsigned int>(stream);
@ -343,7 +350,7 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh )
for (unsigned int i = 0; i < mesh->mNumFaces;++i) { for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
aiFace& f = mesh->mFaces[i]; aiFace& f = mesh->mFaces[i];
BOOST_STATIC_ASSERT(AI_MAX_FACE_INDICES <= 0xffff); static_assert(AI_MAX_FACE_INDICES <= 0xffff, "AI_MAX_FACE_INDICES <= 0xffff");
f.mNumIndices = Read<uint16_t>(stream); f.mNumIndices = Read<uint16_t>(stream);
f.mIndices = new unsigned int[f.mNumIndices]; f.mIndices = new unsigned int[f.mNumIndices];
@ -372,7 +379,8 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh )
void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop) void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop)
{ {
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIMATERIALPROPERTY); uint32_t chunkID = Read<uint32_t>(stream);
ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIALPROPERTY);
/*uint32_t size =*/ Read<uint32_t>(stream); /*uint32_t size =*/ Read<uint32_t>(stream);
prop->mKey = Read<aiString>(stream); prop->mKey = Read<aiString>(stream);
@ -388,7 +396,8 @@ void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialPro
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat) void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat)
{ {
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIMATERIAL); uint32_t chunkID = Read<uint32_t>(stream);
ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIAL);
/*uint32_t size =*/ Read<uint32_t>(stream); /*uint32_t size =*/ Read<uint32_t>(stream);
mat->mNumAllocated = mat->mNumProperties = Read<unsigned int>(stream); mat->mNumAllocated = mat->mNumProperties = Read<unsigned int>(stream);
@ -409,7 +418,8 @@ void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat)
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd) void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd)
{ {
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AINODEANIM); uint32_t chunkID = Read<uint32_t>(stream);
ai_assert(chunkID == ASSBIN_CHUNK_AINODEANIM);
/*uint32_t size =*/ Read<uint32_t>(stream); /*uint32_t size =*/ Read<uint32_t>(stream);
nd->mNodeName = Read<aiString>(stream); nd->mNodeName = Read<aiString>(stream);
@ -457,7 +467,8 @@ void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd)
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim ) void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim )
{ {
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AIANIMATION); uint32_t chunkID = Read<uint32_t>(stream);
ai_assert(chunkID == ASSBIN_CHUNK_AIANIMATION);
/*uint32_t size =*/ Read<uint32_t>(stream); /*uint32_t size =*/ Read<uint32_t>(stream);
anim->mName = Read<aiString> (stream); anim->mName = Read<aiString> (stream);
@ -477,7 +488,8 @@ void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim )
void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex) void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex)
{ {
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AITEXTURE); uint32_t chunkID = Read<uint32_t>(stream);
ai_assert(chunkID == ASSBIN_CHUNK_AITEXTURE);
/*uint32_t size =*/ Read<uint32_t>(stream); /*uint32_t size =*/ Read<uint32_t>(stream);
tex->mWidth = Read<unsigned int>(stream); tex->mWidth = Read<unsigned int>(stream);
@ -500,7 +512,8 @@ void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex)
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l ) void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l )
{ {
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AILIGHT); uint32_t chunkID = Read<uint32_t>(stream);
ai_assert(chunkID == ASSBIN_CHUNK_AILIGHT);
/*uint32_t size =*/ Read<uint32_t>(stream); /*uint32_t size =*/ Read<uint32_t>(stream);
l->mName = Read<aiString>(stream); l->mName = Read<aiString>(stream);
@ -526,7 +539,8 @@ void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l )
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam ) void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam )
{ {
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AICAMERA); uint32_t chunkID = Read<uint32_t>(stream);
ai_assert(chunkID == ASSBIN_CHUNK_AICAMERA);
/*uint32_t size =*/ Read<uint32_t>(stream); /*uint32_t size =*/ Read<uint32_t>(stream);
cam->mName = Read<aiString>(stream); cam->mName = Read<aiString>(stream);
@ -541,7 +555,8 @@ void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam )
void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
{ {
ai_assert( Read<uint32_t>(stream) == ASSBIN_CHUNK_AISCENE); uint32_t chunkID = Read<uint32_t>(stream);
ai_assert(chunkID == ASSBIN_CHUNK_AISCENE);
/*uint32_t size =*/ Read<uint32_t>(stream); /*uint32_t size =*/ Read<uint32_t>(stream);
scene->mFlags = Read<unsigned int>(stream); scene->mFlags = Read<unsigned int>(stream);
@ -644,7 +659,7 @@ void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
if (compressed) if (compressed)
{ {
uLongf uncompressedSize = Read<uint32_t>(stream); uLongf uncompressedSize = Read<uint32_t>(stream);
uLongf compressedSize = stream->FileSize() - stream->Tell(); uLongf compressedSize = static_cast<uLongf>(stream->FileSize() - stream->Tell());
unsigned char * compressedData = new unsigned char[ compressedSize ]; unsigned char * compressedData = new unsigned char[ compressedSize ];
stream->Read( compressedData, 1, compressedSize ); stream->Read( compressedData, 1, compressedSize );

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -46,7 +46,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define AI_ASSBINIMPORTER_H_INC #define AI_ASSBINIMPORTER_H_INC
#include "BaseImporter.h" #include "BaseImporter.h"
#include "../include/assimp/types.h" #include <assimp/types.h>
struct aiMesh;
struct aiNode;
struct aiBone;
struct aiMaterial;
struct aiMaterialProperty;
struct aiNodeAnim;
struct aiAnimation;
struct aiTexture;
struct aiLight;
struct aiCamera;
#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER #ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
@ -42,17 +42,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the Plain-C API * @brief Implementation of the Plain-C API
*/ */
#include "AssimpPCH.h" #include <assimp/cimport.h>
#include "../include/assimp/cimport.h" #include <assimp/LogStream.hpp>
#include <assimp/DefaultLogger.hpp>
#include <assimp/Importer.hpp>
#include <assimp/importerdesc.h>
#include <assimp/scene.h>
#include "GenericProperty.h" #include "GenericProperty.h"
#include "CInterfaceIOWrapper.h" #include "CInterfaceIOWrapper.h"
#include "Importer.h" #include "Importer.h"
#include "Exceptional.h"
#include "ScenePrivate.h"
#include "BaseImporter.h"
#include <list>
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
# include <boost/thread/thread.hpp> # include <thread>
# include <boost/thread/mutex.hpp> # include <mutex>
#endif #endif
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
using namespace Assimp; using namespace Assimp;
@ -84,12 +92,18 @@ namespace Assimp
/** Verbose logging active or not? */ /** Verbose logging active or not? */
static aiBool gVerboseLogging = false; static aiBool gVerboseLogging = false;
}
/** will return all registered importers. */
void GetImporterInstanceList(std::vector< BaseImporter* >& out);
/** will delete all registered importers. */
void DeleteImporterInstanceList(std::vector< BaseImporter* >& out);
} // namespace assimp
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
/** Global mutex to manage the access to the logstream map */ /** Global mutex to manage the access to the log-stream map */
static boost::mutex gLogStreamMutex; static std::mutex gLogStreamMutex;
#endif #endif
@ -98,14 +112,14 @@ static boost::mutex gLogStreamMutex;
class LogToCallbackRedirector : public LogStream class LogToCallbackRedirector : public LogStream
{ {
public: public:
LogToCallbackRedirector(const aiLogStream& s) explicit LogToCallbackRedirector(const aiLogStream& s)
: stream (s) { : stream (s) {
ai_assert(NULL != s.callback); ai_assert(NULL != s.callback);
} }
~LogToCallbackRedirector() { ~LogToCallbackRedirector() {
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
boost::mutex::scoped_lock lock(gLogStreamMutex); std::lock_guard<std::mutex> lock(gLogStreamMutex);
#endif #endif
// (HACK) Check whether the 'stream.user' pointer points to a // (HACK) Check whether the 'stream.user' pointer points to a
// custom LogStream allocated by #aiGetPredefinedLogStream. // custom LogStream allocated by #aiGetPredefinedLogStream.
@ -136,7 +150,7 @@ void ReportSceneNotFoundError()
DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. " DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. "
"The C-API does not accept scenes produced by the C++ API and vice versa"); "The C-API does not accept scenes produced by the C++ API and vice versa");
assert(false); ai_assert(false);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -216,7 +230,8 @@ const aiScene* aiImportFileFromMemoryWithProperties(
const char* pHint, const char* pHint,
const aiPropertyStore* props) const aiPropertyStore* props)
{ {
ai_assert(NULL != pBuffer && 0 != pLength); ai_assert( NULL != pBuffer );
ai_assert( 0 != pLength );
const aiScene* scene = NULL; const aiScene* scene = NULL;
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
@ -305,10 +320,38 @@ ASSIMP_API const aiScene* aiApplyPostProcessing(const aiScene* pScene,
return sc; return sc;
} }
// ------------------------------------------------------------------------------------------------
ASSIMP_API const aiScene *aiApplyCustomizedPostProcessing( const aiScene *scene,
BaseProcess* process,
bool requestValidation ) {
const aiScene* sc( NULL );
ASSIMP_BEGIN_EXCEPTION_REGION();
// find the importer associated with this data
const ScenePrivateData* priv = ScenePriv( scene );
if ( NULL == priv || NULL == priv->mOrigImporter ) {
ReportSceneNotFoundError();
return NULL;
}
sc = priv->mOrigImporter->ApplyCustomizedPostProcessing( process, requestValidation );
if ( !sc ) {
aiReleaseImport( scene );
return NULL;
}
ASSIMP_END_EXCEPTION_REGION( const aiScene* );
return sc;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void CallbackToLogRedirector (const char* msg, char* dt) void CallbackToLogRedirector (const char* msg, char* dt)
{ {
ai_assert(NULL != msg && NULL != dt); ai_assert( NULL != msg );
ai_assert( NULL != dt );
LogStream* s = (LogStream*)dt; LogStream* s = (LogStream*)dt;
s->write(msg); s->write(msg);
@ -340,7 +383,7 @@ ASSIMP_API void aiAttachLogStream( const aiLogStream* stream )
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
boost::mutex::scoped_lock lock(gLogStreamMutex); std::lock_guard<std::mutex> lock(gLogStreamMutex);
#endif #endif
LogStream* lg = new LogToCallbackRedirector(*stream); LogStream* lg = new LogToCallbackRedirector(*stream);
@ -359,9 +402,9 @@ ASSIMP_API aiReturn aiDetachLogStream( const aiLogStream* stream)
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
boost::mutex::scoped_lock lock(gLogStreamMutex); std::lock_guard<std::mutex> lock(gLogStreamMutex);
#endif #endif
// find the logstream associated with this data // find the log-stream associated with this data
LogStreamMap::iterator it = gActiveLogStreams.find( *stream); LogStreamMap::iterator it = gActiveLogStreams.find( *stream);
// it should be there... else the user is playing fools with us // it should be there... else the user is playing fools with us
if( it == gActiveLogStreams.end()) { if( it == gActiveLogStreams.end()) {
@ -384,14 +427,20 @@ ASSIMP_API void aiDetachAllLogStreams(void)
{ {
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
#ifndef ASSIMP_BUILD_SINGLETHREADED #ifndef ASSIMP_BUILD_SINGLETHREADED
boost::mutex::scoped_lock lock(gLogStreamMutex); std::lock_guard<std::mutex> lock(gLogStreamMutex);
#endif #endif
Logger *logger( DefaultLogger::get() );
if ( NULL == logger ) {
return;
}
for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) { for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) {
DefaultLogger::get()->detatchStream( it->second ); logger->detatchStream( it->second );
delete it->second; delete it->second;
} }
gActiveLogStreams.clear(); gActiveLogStreams.clear();
DefaultLogger::kill(); DefaultLogger::kill();
ASSIMP_END_EXCEPTION_REGION(void); ASSIMP_END_EXCEPTION_REGION(void);
} }
@ -411,6 +460,20 @@ const char* aiGetErrorString()
return gLastErrorString.c_str(); return gLastErrorString.c_str();
} }
// -----------------------------------------------------------------------------------------------
// Return the description of a importer given its index
const aiImporterDesc* aiGetImportFormatDescription( size_t pIndex)
{
return Importer().GetImporterInfo(pIndex);
}
// -----------------------------------------------------------------------------------------------
// Return the number of importers
size_t aiGetImportFormatCount(void)
{
return Importer().GetImporterCount();
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns the error text of the last failed import process. // Returns the error text of the last failed import process.
aiBool aiIsExtensionSupported(const char* szExtension) aiBool aiIsExtensionSupported(const char* szExtension)
@ -465,7 +528,6 @@ ASSIMP_API aiPropertyStore* aiCreatePropertyStore(void)
return reinterpret_cast<aiPropertyStore*>( new PropertyMap() ); return reinterpret_cast<aiPropertyStore*>( new PropertyMap() );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API void aiReleasePropertyStore(aiPropertyStore* p) ASSIMP_API void aiReleasePropertyStore(aiPropertyStore* p)
{ {
@ -478,17 +540,17 @@ ASSIMP_API void aiSetImportPropertyInteger(aiPropertyStore* p, const char* szNam
{ {
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
PropertyMap* pp = reinterpret_cast<PropertyMap*>(p); PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
SetGenericProperty<int>(pp->ints,szName,value,NULL); SetGenericProperty<int>(pp->ints,szName,value);
ASSIMP_END_EXCEPTION_REGION(void); ASSIMP_END_EXCEPTION_REGION(void);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Importer::SetPropertyFloat // Importer::SetPropertyFloat
ASSIMP_API void aiSetImportPropertyFloat(aiPropertyStore* p, const char* szName, float value) ASSIMP_API void aiSetImportPropertyFloat(aiPropertyStore* p, const char* szName, ai_real value)
{ {
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
PropertyMap* pp = reinterpret_cast<PropertyMap*>(p); PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
SetGenericProperty<float>(pp->floats,szName,value,NULL); SetGenericProperty<ai_real>(pp->floats,szName,value);
ASSIMP_END_EXCEPTION_REGION(void); ASSIMP_END_EXCEPTION_REGION(void);
} }
@ -502,7 +564,7 @@ ASSIMP_API void aiSetImportPropertyString(aiPropertyStore* p, const char* szName
} }
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
PropertyMap* pp = reinterpret_cast<PropertyMap*>(p); PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
SetGenericProperty<std::string>(pp->strings,szName,std::string(st->C_Str()),NULL); SetGenericProperty<std::string>(pp->strings,szName,std::string(st->C_Str()));
ASSIMP_END_EXCEPTION_REGION(void); ASSIMP_END_EXCEPTION_REGION(void);
} }
@ -516,7 +578,7 @@ ASSIMP_API void aiSetImportPropertyMatrix(aiPropertyStore* p, const char* szName
} }
ASSIMP_BEGIN_EXCEPTION_REGION(); ASSIMP_BEGIN_EXCEPTION_REGION();
PropertyMap* pp = reinterpret_cast<PropertyMap*>(p); PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
SetGenericProperty<aiMatrix4x4>(pp->matrices,szName,*mat,NULL); SetGenericProperty<aiMatrix4x4>(pp->matrices,szName,*mat);
ASSIMP_END_EXCEPTION_REGION(void); ASSIMP_END_EXCEPTION_REGION(void);
} }
@ -524,7 +586,8 @@ ASSIMP_API void aiSetImportPropertyMatrix(aiPropertyStore* p, const char* szName
// Rotation matrix to quaternion // Rotation matrix to quaternion
ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion* quat,const aiMatrix3x3* mat) ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion* quat,const aiMatrix3x3* mat)
{ {
ai_assert(NULL != quat && NULL != mat); ai_assert( NULL != quat );
ai_assert( NULL != mat );
*quat = aiQuaternion(*mat); *quat = aiQuaternion(*mat);
} }
@ -534,7 +597,10 @@ ASSIMP_API void aiDecomposeMatrix(const aiMatrix4x4* mat,aiVector3D* scaling,
aiQuaternion* rotation, aiQuaternion* rotation,
aiVector3D* position) aiVector3D* position)
{ {
ai_assert(NULL != rotation && NULL != position && NULL != scaling && NULL != mat); ai_assert( NULL != rotation );
ai_assert( NULL != position );
ai_assert( NULL != scaling );
ai_assert( NULL != mat );
mat->Decompose(*scaling,*rotation,*position); mat->Decompose(*scaling,*rotation,*position);
} }
@ -558,7 +624,8 @@ ASSIMP_API void aiTransposeMatrix4(aiMatrix4x4* mat)
ASSIMP_API void aiTransformVecByMatrix3(aiVector3D* vec, ASSIMP_API void aiTransformVecByMatrix3(aiVector3D* vec,
const aiMatrix3x3* mat) const aiMatrix3x3* mat)
{ {
ai_assert(NULL != mat && NULL != vec); ai_assert( NULL != mat );
ai_assert( NULL != vec);
*vec *= (*mat); *vec *= (*mat);
} }
@ -566,7 +633,9 @@ ASSIMP_API void aiTransformVecByMatrix3(aiVector3D* vec,
ASSIMP_API void aiTransformVecByMatrix4(aiVector3D* vec, ASSIMP_API void aiTransformVecByMatrix4(aiVector3D* vec,
const aiMatrix4x4* mat) const aiMatrix4x4* mat)
{ {
ai_assert(NULL != mat && NULL != vec); ai_assert( NULL != mat );
ai_assert( NULL != vec );
*vec *= (*mat); *vec *= (*mat);
} }
@ -576,7 +645,8 @@ ASSIMP_API void aiMultiplyMatrix4(
aiMatrix4x4* dst, aiMatrix4x4* dst,
const aiMatrix4x4* src) const aiMatrix4x4* src)
{ {
ai_assert(NULL != dst && NULL != src); ai_assert( NULL != dst );
ai_assert( NULL != src );
*dst = (*dst) * (*src); *dst = (*dst) * (*src);
} }
@ -585,7 +655,8 @@ ASSIMP_API void aiMultiplyMatrix3(
aiMatrix3x3* dst, aiMatrix3x3* dst,
const aiMatrix3x3* src) const aiMatrix3x3* src)
{ {
ai_assert(NULL != dst && NULL != src); ai_assert( NULL != dst );
ai_assert( NULL != src );
*dst = (*dst) * (*src); *dst = (*dst) * (*src);
} }
@ -606,4 +677,24 @@ ASSIMP_API void aiIdentityMatrix4(
*mat = aiMatrix4x4(); *mat = aiMatrix4x4();
} }
// ------------------------------------------------------------------------------------------------
ASSIMP_API C_STRUCT const aiImporterDesc* aiGetImporterDesc( const char *extension ) {
if( NULL == extension ) {
return NULL;
}
const aiImporterDesc *desc( NULL );
std::vector< BaseImporter* > out;
GetImporterInstanceList( out );
for( size_t i = 0; i < out.size(); ++i ) {
if( 0 == strncmp( out[ i ]->GetInfo()->mFileExtensions, extension, strlen( extension ) ) ) {
desc = out[ i ]->GetInfo();
break;
}
}
DeleteImporterInstanceList(out);
return desc;
}
// ------------------------------------------------------------------------------------------------

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
@ -43,11 +43,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Assimp C export interface. See Exporter.cpp for some notes. Assimp C export interface. See Exporter.cpp for some notes.
*/ */
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_EXPORT
#include "CInterfaceIOWrapper.h" #include "CInterfaceIOWrapper.h"
#include "SceneCombiner.h" #include "SceneCombiner.h"
#include "ScenePrivate.h"
#include <assimp/Exporter.hpp>
using namespace Assimp; using namespace Assimp;
@ -59,13 +59,38 @@ ASSIMP_API size_t aiGetExportFormatCount(void)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t pIndex) ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t index)
{ {
// Note: this is valid as the index always pertains to a builtin exporter, // Note: this is valid as the index always pertains to a built-in exporter,
// for which the returned structure is guaranteed to be of static storage duration. // for which the returned structure is guaranteed to be of static storage duration.
return Exporter().GetExportFormatDescription(pIndex); Exporter exporter;
const aiExportFormatDesc* orig( exporter.GetExportFormatDescription( index ) );
if (NULL == orig) {
return NULL;
}
aiExportFormatDesc *desc = new aiExportFormatDesc;
desc->description = new char[ strlen( orig->description ) + 1 ]();
::strncpy( (char*) desc->description, orig->description, strlen( orig->description ) );
desc->fileExtension = new char[ strlen( orig->fileExtension ) + 1 ]();
::strncpy( ( char* ) desc->fileExtension, orig->fileExtension, strlen( orig->fileExtension ) );
desc->id = new char[ strlen( orig->id ) + 1 ]();
::strncpy( ( char* ) desc->id, orig->id, strlen( orig->id ) );
return desc;
} }
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiReleaseExportFormatDescription( const aiExportFormatDesc *desc ) {
if (NULL == desc) {
return;
}
delete [] desc->description;
delete [] desc->fileExtension;
delete [] desc->id;
delete desc;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API void aiCopyScene(const aiScene* pIn, aiScene** pOut) ASSIMP_API void aiCopyScene(const aiScene* pIn, aiScene** pOut)

View File

@ -1,135 +0,0 @@
// Actually just a dummy, used by the compiler to build the precompiled header.
#include "AssimpPCH.h"
#include "./../include/assimp/version.h"
static const unsigned int MajorVersion = 3;
static const unsigned int MinorVersion = 1;
// --------------------------------------------------------------------------------
// Legal information string - dont't remove this.
static const char* LEGAL_INFORMATION =
"Open Asset Import Library (Assimp).\n"
"A free C/C++ library to import various 3D file formats into applications\n\n"
"(c) 2008-2010, assimp team\n"
"License under the terms and conditions of the 3-clause BSD license\n"
"http://assimp.sourceforge.net\n"
;
// ------------------------------------------------------------------------------------------------
// Get legal string
ASSIMP_API const char* aiGetLegalString () {
return LEGAL_INFORMATION;
}
// ------------------------------------------------------------------------------------------------
// Get Assimp minor version
ASSIMP_API unsigned int aiGetVersionMinor () {
return MinorVersion;
}
// ------------------------------------------------------------------------------------------------
// Get Assimp major version
ASSIMP_API unsigned int aiGetVersionMajor () {
return MajorVersion;
}
// ------------------------------------------------------------------------------------------------
// Get flags used for compilation
ASSIMP_API unsigned int aiGetCompileFlags () {
unsigned int flags = 0;
#ifdef ASSIMP_BUILD_BOOST_WORKAROUND
flags |= ASSIMP_CFLAGS_NOBOOST;
#endif
#ifdef ASSIMP_BUILD_SINGLETHREADED
flags |= ASSIMP_CFLAGS_SINGLETHREADED;
#endif
#ifdef ASSIMP_BUILD_DEBUG
flags |= ASSIMP_CFLAGS_DEBUG;
#endif
#ifdef ASSIMP_BUILD_DLL_EXPORT
flags |= ASSIMP_CFLAGS_SHARED;
#endif
#ifdef _STLPORT_VERSION
flags |= ASSIMP_CFLAGS_STLPORT;
#endif
return flags;
}
// include current build revision, which is even updated from time to time -- :-)
#include "revision.h"
// ------------------------------------------------------------------------------------------------
ASSIMP_API unsigned int aiGetVersionRevision ()
{
return GitVersion;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API aiScene::aiScene()
: mFlags(0)
, mRootNode(NULL)
, mNumMeshes(0)
, mMeshes(NULL)
, mNumMaterials(0)
, mMaterials(NULL)
, mNumAnimations(0)
, mAnimations(NULL)
, mNumTextures(0)
, mTextures(NULL)
, mNumLights(0)
, mLights(NULL)
, mNumCameras(0)
, mCameras(NULL)
, mPrivate(new Assimp::ScenePrivateData())
{
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API aiScene::~aiScene()
{
// delete all sub-objects recursively
delete mRootNode;
// To make sure we won't crash if the data is invalid it's
// much better to check whether both mNumXXX and mXXX are
// valid instead of relying on just one of them.
if (mNumMeshes && mMeshes)
for( unsigned int a = 0; a < mNumMeshes; a++)
delete mMeshes[a];
delete [] mMeshes;
if (mNumMaterials && mMaterials)
for( unsigned int a = 0; a < mNumMaterials; a++)
delete mMaterials[a];
delete [] mMaterials;
if (mNumAnimations && mAnimations)
for( unsigned int a = 0; a < mNumAnimations; a++)
delete mAnimations[a];
delete [] mAnimations;
if (mNumTextures && mTextures)
for( unsigned int a = 0; a < mNumTextures; a++)
delete mTextures[a];
delete [] mTextures;
if (mNumLights && mLights)
for( unsigned int a = 0; a < mNumLights; a++)
delete mLights[a];
delete [] mLights;
if (mNumCameras && mCameras)
for( unsigned int a = 0; a < mNumCameras; a++)
delete mCameras[a];
delete [] mCameras;
delete static_cast<Assimp::ScenePrivateData*>( mPrivate );
}

View File

@ -1,162 +0,0 @@
/*
---------------------------------------------------------------------------
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 AssimpPCH.h
* PCH master include. Every unit in Assimp has to include it.
*/
#ifndef ASSIMP_PCH_INCLUDED
#define ASSIMP_PCH_INCLUDED
#define ASSIMP_INTERNAL_BUILD
// ----------------------------------------------------------------------------------------
/* General compile config taken from defs.h. It is important that the user compiles
* using exactly the same settings in defs.h. Settings in AssimpPCH.h may differ,
* they won't affect the public API.
*/
#include "../include/assimp/defs.h"
// Include our stdint.h replacement header for MSVC, take the global header for gcc/mingw
#if defined( _MSC_VER) && (_MSC_VER < 1600)
# include "../include/assimp/Compiler/pstdint.h"
#else
# include <stdint.h>
#endif
/* Undefine the min/max macros defined by some platform headers (namely Windows.h) to
* avoid obvious conflicts with std::min() and std::max().
*/
#undef min
#undef max
/* Concatenate two tokens after evaluating them
*/
#define _AI_CONCAT(a,b) a ## b
#define AI_CONCAT(a,b) _AI_CONCAT(a,b)
/* Helper macro to set a pointer to NULL in debug builds
*/
#if (defined ASSIMP_BUILD_DEBUG)
# define AI_DEBUG_INVALIDATE_PTR(x) x = NULL;
#else
# define AI_DEBUG_INVALIDATE_PTR(x)
#endif
/* Beginning with MSVC8 some C string manipulation functions are mapped to their _safe_
* counterparts (e.g. _itoa_s). This avoids a lot of trouble with deprecation warnings.
*/
#if _MSC_VER >= 1400 && !(defined _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
# define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
#endif
/* size_t to unsigned int, possible loss of data. The compiler is right with his warning
* but this loss of data won't be a problem for us. So shut up, little boy.
*/
#ifdef _MSC_VER
# pragma warning (disable : 4267)
#endif
// ----------------------------------------------------------------------------------------
/* Actually that's not required for MSVC. It is included somewhere in the deeper parts of
* the MSVC STL but it's necessary for proper build with STLport.
*/
#include <ctype.h>
// Runtime/STL headers
#include <vector>
#include <list>
#include <map>
#include <set>
#include <string>
#include <sstream>
#include <iomanip>
#include <cassert>
#include <stack>
#include <queue>
#include <iostream>
#include <algorithm>
#include <numeric>
#include <new>
#include <cstdio>
#include <limits.h>
#include <memory>
// Boost headers
#include <boost/pointer_cast.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#include <boost/make_shared.hpp>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
#include <boost/static_assert.hpp>
#include <boost/lexical_cast.hpp>
// Public ASSIMP headers
#include "../include/assimp/DefaultLogger.hpp"
#include "../include/assimp/IOStream.hpp"
#include "../include/assimp/IOSystem.hpp"
#include "../include/assimp/scene.h"
#include "../include/assimp/importerdesc.h"
#include "../include/assimp/postprocess.h"
#include "../include/assimp/Importer.hpp"
#include "../include/assimp/Exporter.hpp"
// Internal utility headers
#include "BaseImporter.h"
#include "StringComparison.h"
#include "StreamReader.h"
#include "qnan.h"
#include "ScenePrivate.h"
// We need those constants, workaround for any platforms where nobody defined them yet
#if (!defined SIZE_MAX)
# define SIZE_MAX (~((size_t)0))
#endif
#if (!defined UINT_MAX)
# define UINT_MAX (~((unsigned int)0))
#endif
#endif // !! ASSIMP_PCH_INCLUDED

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -41,17 +41,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ASSXML exporter main code * ASSXML exporter main code
*/ */
#include <stdarg.h> #include <stdarg.h>
#include "AssimpPCH.h"
#include "./../include/assimp/version.h" #include "./../include/assimp/version.h"
#include "ProcessHelper.h" #include "ProcessHelper.h"
#include <assimp/IOStream.hpp>
#include <assimp/IOSystem.hpp>
#include <assimp/Exporter.hpp>
#ifdef ASSIMP_BUILD_NO_OWN_ZLIB #ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h> # include <zlib.h>
#else #else
# include "../contrib/zlib/zlib.h" # include <contrib/zlib/zlib.h>
#endif #endif
#include <time.h> #include <time.h>
#include <stdio.h>
#ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_EXPORT
#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER #ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
@ -62,13 +65,20 @@ namespace Assimp {
namespace AssxmlExport { namespace AssxmlExport {
int ioprintf( IOStream * io, const char * format, ... ) // -----------------------------------------------------------------------------------
{ static int ioprintf( IOStream * io, const char *format, ... ) {
char sz[4096]; using namespace std;
if ( nullptr == io ) {
return -1;
}
static const int Size = 4096;
char sz[ Size ];
::memset( sz, '\0', Size );
va_list va; va_list va;
va_start( va, format ); va_start( va, format );
int nSize = vsnprintf( sz, 4096, format, va ); const unsigned int nSize = vsnprintf( sz, Size-1, format, va );
ai_assert( nSize < 4096 ); ai_assert( nSize < Size );
va_end( va ); va_end( va );
io->Write( sz, sizeof(char), nSize ); io->Write( sz, sizeof(char), nSize );
@ -78,8 +88,7 @@ int ioprintf( IOStream * io, const char * format, ... )
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Convert a name to standard XML format // Convert a name to standard XML format
void ConvertName(aiString& out, const aiString& in) static void ConvertName(aiString& out, const aiString& in) {
{
out.length = 0; out.length = 0;
for (unsigned int i = 0; i < in.length; ++i) { for (unsigned int i = 0; i < in.length; ++i) {
switch (in.data[i]) { switch (in.data[i]) {
@ -102,8 +111,7 @@ void ConvertName(aiString& out, const aiString& in)
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Write a single node as text dump // Write a single node as text dump
void WriteNode(const aiNode* node, IOStream * io, unsigned int depth) static void WriteNode(const aiNode* node, IOStream * io, unsigned int depth) {
{
char prefix[512]; char prefix[512];
for (unsigned int i = 0; i < depth;++i) for (unsigned int i = 0; i < depth;++i)
prefix[i] = '\t'; prefix[i] = '\t';
@ -168,32 +176,31 @@ static std::string encodeXML(const std::string& data) {
return buffer; return buffer;
} }
// ----------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------
// Write a text model dump // Write a text model dump
void WriteDump(const aiScene* scene, IOStream* io, bool shortened) static
{ void WriteDump(const aiScene* scene, IOStream* io, bool shortened) {
time_t tt = ::time(NULL); time_t tt = ::time( NULL );
tm* p = ::gmtime(&tt); tm* p = ::gmtime( &tt );
ai_assert( nullptr != p );
aiString name;
// write header // write header
ioprintf(io, std::string header(
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<ASSIMP format_id=\"1\">\n\n" "<ASSIMP format_id=\"1\">\n\n"
"<!-- XML Model dump produced by assimp dump\n" "<!-- XML Model dump produced by assimp dump\n"
" Library version: %i.%i.%i\n" " Library version: %i.%i.%i\n"
" %s\n" " %s\n"
"-->" "-->"
" \n\n" " \n\n"
"<Scene flags=\"%i\" postprocessing=\"%i\">\n", "<Scene flags=\"%d\" postprocessing=\"%i\">\n"
);
aiGetVersionMajor(),aiGetVersionMinor(),aiGetVersionRevision(),asctime(p), const unsigned int majorVersion( aiGetVersionMajor() );
scene->mFlags, const unsigned int minorVersion( aiGetVersionMinor() );
0 /*globalImporter->GetEffectivePostProcessing()*/); const unsigned int rev( aiGetVersionRevision() );
const char *curtime( asctime( p ) );
ioprintf( io, header.c_str(), majorVersion, minorVersion, rev, curtime, scene->mFlags, 0 );
// write the node graph // write the node graph
WriteNode(scene->mRootNode, io, 0); WriteNode(scene->mRootNode, io, 0);
@ -263,6 +270,7 @@ void WriteDump(const aiScene* scene, IOStream* io, bool shortened)
ioprintf(io,"\t</Light>\n"); ioprintf(io,"\t</Light>\n");
} }
#endif #endif
aiString name;
// write textures // write textures
if (scene->mNumTextures) { if (scene->mNumTextures) {
@ -291,16 +299,17 @@ void WriteDump(const aiScene* scene, IOStream* io, bool shortened)
else if (!shortened){ else if (!shortened){
ioprintf(io,"\t\t<Data length=\"%i\"> \n",tex->mWidth*tex->mHeight*4); 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; // const unsigned int width = (unsigned int)std::log10((double)std::max(tex->mHeight,tex->mWidth))+1;
for (unsigned int y = 0; y < tex->mHeight;++y) { for (unsigned int y = 0; y < tex->mHeight;++y) {
for (unsigned int x = 0; x < tex->mWidth;++x) { for (unsigned int x = 0; x < tex->mWidth;++x) {
aiTexel* tx = tex->pcData + y*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; 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); ioprintf(io,"\t\t\t%2x %2x %2x %2x",r,g,b,a);
// group by four for readibility // group by four for readability
if (0 == (x+y*tex->mWidth) % 4) if ( 0 == ( x + y*tex->mWidth ) % 4 ) {
ioprintf(io,"\n"); ioprintf( io, "\n" );
}
} }
} }
} }
@ -448,7 +457,7 @@ void WriteDump(const aiScene* scene, IOStream* io, bool shortened)
ioprintf(io,"<MeshList num=\"%i\">\n",scene->mNumMeshes); ioprintf(io,"<MeshList num=\"%i\">\n",scene->mNumMeshes);
for (unsigned int i = 0; i < scene->mNumMeshes;++i) { for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
aiMesh* mesh = scene->mMeshes[i]; aiMesh* mesh = scene->mMeshes[i];
// const unsigned int width = (unsigned int)log10((double)mesh->mNumVertices)+1; // const unsigned int width = (unsigned int)std::log10((double)mesh->mNumVertices)+1;
// mesh header // mesh header
ioprintf(io,"\t<Mesh types=\"%s %s %s %s\" material_index=\"%i\">\n", ioprintf(io,"\t<Mesh types=\"%s %s %s %s\" material_index=\"%i\">\n",
@ -621,7 +630,7 @@ void WriteDump(const aiScene* scene, IOStream* io, bool shortened)
} // end of namespace AssxmlExport } // end of namespace AssxmlExport
void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene) void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
{ {
IOStream * out = pIOSystem->Open( pFile, "wt" ); IOStream * out = pIOSystem->Open( pFile, "wt" );
if (!out) return; if (!out) return;

View File

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

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
@ -43,13 +43,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the b3d importer class * @brief Implementation of the b3d importer class
*/ */
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_B3D_IMPORTER #ifndef ASSIMP_BUILD_NO_B3D_IMPORTER
// internal headers // internal headers
#include "B3DImporter.h" #include "B3DImporter.h"
#include "TextureTransform.h" #include "TextureTransform.h"
#include "ConvertToLHProcess.h" #include "ConvertToLHProcess.h"
#include "StringUtils.h"
#include <memory>
#include <assimp/IOSystem.hpp>
#include <assimp/anim.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
using namespace Assimp; using namespace Assimp;
using namespace std; using namespace std;
@ -107,7 +114,7 @@ void B3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
cout<<"Hello world from the B3DImporter!"<<endl; cout<<"Hello world from the B3DImporter!"<<endl;
#endif #endif
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile)); std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
// Check whether we can read from the file // Check whether we can read from the file
if( file.get() == NULL) if( file.get() == NULL)
@ -127,12 +134,12 @@ void B3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void B3DImporter::Oops(){ AI_WONT_RETURN void B3DImporter::Oops(){
throw DeadlyImportError( "B3D Importer - INTERNAL ERROR" ); throw DeadlyImportError( "B3D Importer - INTERNAL ERROR" );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void B3DImporter::Fail( string str ){ AI_WONT_RETURN void B3DImporter::Fail( string str ){
#ifdef DEBUG_B3D #ifdef DEBUG_B3D
cout<<"Error in B3D file data: "<<str<<endl; cout<<"Error in B3D file data: "<<str<<endl;
#endif #endif
@ -233,8 +240,10 @@ unsigned B3DImporter::ChunkSize(){
template<class T> template<class T>
T *B3DImporter::to_array( const vector<T> &v ){ T *B3DImporter::to_array( const vector<T> &v ){
if( !v.size() ) return 0; if( v.empty() ) {
T *p=new T[v.size()]; return 0;
}
T *p=new T[ v.size() ];
for( size_t i=0;i<v.size();++i ){ for( size_t i=0;i<v.size();++i ){
p[i]=v[i]; p[i]=v[i];
} }
@ -322,7 +331,7 @@ void B3DImporter::ReadVRTS(){
int sz=12+(_vflags&1?12:0)+(_vflags&2?16:0)+(_tcsets*_tcsize*4); int sz=12+(_vflags&1?12:0)+(_vflags&2?16:0)+(_tcsets*_tcsize*4);
int n_verts=ChunkSize()/sz; int n_verts=ChunkSize()/sz;
int v0=_vertices.size(); int v0=static_cast<int>(_vertices.size());
_vertices.resize( v0+n_verts ); _vertices.resize( v0+n_verts );
for( int i=0;i<n_verts;++i ){ for( int i=0;i<n_verts;++i ){
@ -395,7 +404,7 @@ void B3DImporter::ReadTRIS( int v0 ){
void B3DImporter::ReadMESH(){ void B3DImporter::ReadMESH(){
/*int matid=*/ReadInt(); /*int matid=*/ReadInt();
int v0=_vertices.size(); int v0= static_cast<int>(_vertices.size());
while( ChunkSize() ){ while( ChunkSize() ){
string t=ReadChunk(); string t=ReadChunk();
@ -453,17 +462,17 @@ void B3DImporter::ReadKEYS( aiNodeAnim *nodeAnim ){
} }
if( flags & 1 ){ if( flags & 1 ){
nodeAnim->mNumPositionKeys=trans.size(); nodeAnim->mNumPositionKeys=static_cast<unsigned int>(trans.size());
nodeAnim->mPositionKeys=to_array( trans ); nodeAnim->mPositionKeys=to_array( trans );
} }
if( flags & 2 ){ if( flags & 2 ){
nodeAnim->mNumScalingKeys=scale.size(); nodeAnim->mNumScalingKeys=static_cast<unsigned int>(scale.size());
nodeAnim->mScalingKeys=to_array( scale ); nodeAnim->mScalingKeys=to_array( scale );
} }
if( flags & 4 ){ if( flags & 4 ){
nodeAnim->mNumRotationKeys=rot.size(); nodeAnim->mNumRotationKeys=static_cast<unsigned int>(rot.size());
nodeAnim->mRotationKeys=to_array( rot ); nodeAnim->mRotationKeys=to_array( rot );
} }
} }
@ -497,7 +506,7 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
aiMatrix4x4 tform=trans * rot * scale; aiMatrix4x4 tform=trans * rot * scale;
int nodeid=_nodes.size(); int nodeid=static_cast<int>(_nodes.size());
aiNode *node=new aiNode( name ); aiNode *node=new aiNode( name );
_nodes.push_back( node ); _nodes.push_back( node );
@ -512,9 +521,9 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
while( ChunkSize() ){ while( ChunkSize() ){
string t=ReadChunk(); string t=ReadChunk();
if( t=="MESH" ){ if( t=="MESH" ){
int n=_meshes.size(); unsigned int n= static_cast<unsigned int>(_meshes.size());
ReadMESH(); ReadMESH();
for( int i=n;i<(int)_meshes.size();++i ){ for( unsigned int i=n;i<static_cast<unsigned int>(_meshes.size());++i ){
meshes.push_back( i ); meshes.push_back( i );
} }
}else if( t=="BONE" ){ }else if( t=="BONE" ){
@ -535,10 +544,10 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
ExitChunk(); ExitChunk();
} }
node->mNumMeshes=meshes.size(); node->mNumMeshes= static_cast<unsigned int>(meshes.size());
node->mMeshes=to_array( meshes ); node->mMeshes=to_array( meshes );
node->mNumChildren=children.size(); node->mNumChildren=static_cast<unsigned int>(children.size());
node->mChildren=to_array( children ); node->mChildren=to_array( children );
return node; return node;
@ -548,7 +557,7 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
void B3DImporter::ReadBB3D( aiScene *scene ){ void B3DImporter::ReadBB3D( aiScene *scene ){
_textures.clear(); _textures.clear();
_materials.size(); _materials.clear();
_vertices.clear(); _vertices.clear();
_meshes.clear(); _meshes.clear();
@ -563,7 +572,7 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
if (!DefaultLogger::isNullLogger()) { if (!DefaultLogger::isNullLogger()) {
char dmp[128]; char dmp[128];
sprintf(dmp,"B3D file format version: %i",version); ai_snprintf(dmp, 128, "B3D file format version: %i",version);
DefaultLogger::get()->info(dmp); DefaultLogger::get()->info(dmp);
} }
@ -636,7 +645,7 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
aiNode *bnode=_nodes[i]; aiNode *bnode=_nodes[i];
bone->mName=bnode->mName; bone->mName=bnode->mName;
bone->mNumWeights=weights.size(); bone->mNumWeights= static_cast<unsigned int>(weights.size());
bone->mWeights=to_array( weights ); bone->mWeights=to_array( weights );
aiMatrix4x4 mat=bnode->mTransformation; aiMatrix4x4 mat=bnode->mTransformation;
@ -646,7 +655,7 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
} }
bone->mOffsetMatrix=mat.Inverse(); bone->mOffsetMatrix=mat.Inverse();
} }
mesh->mNumBones=bones.size(); mesh->mNumBones= static_cast<unsigned int>(bones.size());
mesh->mBones=to_array( bones ); mesh->mBones=to_array( bones );
} }
} }
@ -658,21 +667,21 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
if( !_materials.size() ){ if( !_materials.size() ){
_materials.push_back( new aiMaterial ); _materials.push_back( new aiMaterial );
} }
scene->mNumMaterials=_materials.size(); scene->mNumMaterials= static_cast<unsigned int>(_materials.size());
scene->mMaterials=to_array( _materials ); scene->mMaterials=to_array( _materials );
//meshes //meshes
scene->mNumMeshes=_meshes.size(); scene->mNumMeshes= static_cast<unsigned int>(_meshes.size());
scene->mMeshes=to_array( _meshes ); scene->mMeshes=to_array( _meshes );
//animations //animations
if( _animations.size()==1 && _nodeAnims.size() ){ if( _animations.size()==1 && _nodeAnims.size() ){
aiAnimation *anim=_animations.back(); aiAnimation *anim=_animations.back();
anim->mNumChannels=_nodeAnims.size(); anim->mNumChannels=static_cast<unsigned int>(_nodeAnims.size());
anim->mChannels=to_array( _nodeAnims ); anim->mChannels=to_array( _nodeAnims );
scene->mNumAnimations=_animations.size(); scene->mNumAnimations=static_cast<unsigned int>(_animations.size());
scene->mAnimations=to_array( _animations ); scene->mAnimations=to_array( _animations );
} }

View File

@ -1,9 +1,8 @@
/* /*
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -44,13 +43,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_B3DIMPORTER_H_INC #ifndef AI_B3DIMPORTER_H_INC
#define AI_B3DIMPORTER_H_INC #define AI_B3DIMPORTER_H_INC
#include "../include/assimp/types.h" #include <assimp/types.h>
#include "../include/assimp/mesh.h" #include <assimp/mesh.h>
#include "../include/assimp/material.h" #include <assimp/material.h>
#include "BaseImporter.h"
#include <string> #include <string>
#include <vector> #include <vector>
struct aiNodeAnim;
struct aiNode;
struct aiAnimation;
namespace Assimp{ namespace Assimp{
class B3DImporter : public BaseImporter{ class B3DImporter : public BaseImporter{
@ -87,8 +91,8 @@ private:
float weights[4]; float weights[4];
}; };
void Oops(); AI_WONT_RETURN void Oops() AI_WONT_RETURN_SUFFIX;
void Fail( std::string str ); AI_WONT_RETURN void Fail( std::string str ) AI_WONT_RETURN_SUFFIX;
void ReadTEXS(); void ReadTEXS();
void ReadBRUS(); void ReadBRUS();

View File

@ -4,7 +4,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
@ -40,14 +40,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
*/ */
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_BVH_IMPORTER #ifndef ASSIMP_BUILD_NO_BVH_IMPORTER
#include "BVHLoader.h" #include "BVHLoader.h"
#include "fast_atof.h" #include "fast_atof.h"
#include "SkeletonMeshBuilder.h" #include "SkeletonMeshBuilder.h"
#include <assimp/Importer.hpp>
#include <memory>
#include "TinyFormatter.h"
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
using namespace Assimp; using namespace Assimp;
using namespace Assimp::Formatter;
static const aiImporterDesc desc = { static const aiImporterDesc desc = {
"BVH Importer (MoCap)", "BVH Importer (MoCap)",
@ -65,7 +71,10 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
BVHLoader::BVHLoader() BVHLoader::BVHLoader()
: noSkeletonMesh() : mLine(),
mAnimTickDuration(),
mAnimNumFrames(),
noSkeletonMesh()
{} {}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -110,7 +119,7 @@ void BVHLoader::InternReadFile( const std::string& pFile, aiScene* pScene, IOSys
mFileName = pFile; mFileName = pFile;
// read file into memory // read file into memory
boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile)); std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
if( file.get() == NULL) if( file.get() == NULL)
throw DeadlyImportError( "Failed to open file " + pFile + "."); throw DeadlyImportError( "Failed to open file " + pFile + ".");
@ -171,12 +180,12 @@ aiNode* BVHLoader::ReadNode()
// first token is name // first token is name
std::string nodeName = GetNextToken(); std::string nodeName = GetNextToken();
if( nodeName.empty() || nodeName == "{") if( nodeName.empty() || nodeName == "{")
ThrowException( boost::str( boost::format( "Expected node name, but found \"%s\".") % nodeName)); ThrowException( format() << "Expected node name, but found \"" << nodeName << "\"." );
// then an opening brace should follow // then an opening brace should follow
std::string openBrace = GetNextToken(); std::string openBrace = GetNextToken();
if( openBrace != "{") if( openBrace != "{")
ThrowException( boost::str( boost::format( "Expected opening brace \"{\", but found \"%s\".") % openBrace)); ThrowException( format() << "Expected opening brace \"{\", but found \"" << openBrace << "\"." );
// Create a node // Create a node
aiNode* node = new aiNode( nodeName); aiNode* node = new aiNode( nodeName);
@ -208,7 +217,7 @@ aiNode* BVHLoader::ReadNode()
// The real symbol is "End Site". Second part comes in a separate token // The real symbol is "End Site". Second part comes in a separate token
std::string siteToken = GetNextToken(); std::string siteToken = GetNextToken();
if( siteToken != "Site") if( siteToken != "Site")
ThrowException( boost::str( boost::format( "Expected \"End Site\" keyword, but found \"%s %s\".") % token % siteToken)); ThrowException( format() << "Expected \"End Site\" keyword, but found \"" << token << " " << siteToken << "\"." );
aiNode* child = ReadEndSite( nodeName); aiNode* child = ReadEndSite( nodeName);
child->mParent = node; child->mParent = node;
@ -221,14 +230,14 @@ aiNode* BVHLoader::ReadNode()
} else } else
{ {
// everything else is a parse error // everything else is a parse error
ThrowException( boost::str( boost::format( "Unknown keyword \"%s\".") % token)); ThrowException( format() << "Unknown keyword \"" << token << "\"." );
} }
} }
// add the child nodes if there are any // add the child nodes if there are any
if( childNodes.size() > 0) if( childNodes.size() > 0)
{ {
node->mNumChildren = childNodes.size(); node->mNumChildren = static_cast<unsigned int>(childNodes.size());
node->mChildren = new aiNode*[node->mNumChildren]; node->mChildren = new aiNode*[node->mNumChildren];
std::copy( childNodes.begin(), childNodes.end(), node->mChildren); std::copy( childNodes.begin(), childNodes.end(), node->mChildren);
} }
@ -244,7 +253,7 @@ aiNode* BVHLoader::ReadEndSite( const std::string& pParentName)
// check opening brace // check opening brace
std::string openBrace = GetNextToken(); std::string openBrace = GetNextToken();
if( openBrace != "{") if( openBrace != "{")
ThrowException( boost::str( boost::format( "Expected opening brace \"{\", but found \"%s\".") % openBrace)); ThrowException( format() << "Expected opening brace \"{\", but found \"" << openBrace << "\".");
// Create a node // Create a node
aiNode* node = new aiNode( "EndSite_" + pParentName); aiNode* node = new aiNode( "EndSite_" + pParentName);
@ -266,7 +275,7 @@ aiNode* BVHLoader::ReadEndSite( const std::string& pParentName)
} else } else
{ {
// everything else is a parse error // everything else is a parse error
ThrowException( boost::str( boost::format( "Unknown keyword \"%s\".") % token)); ThrowException( format() << "Unknown keyword \"" << token << "\"." );
} }
} }
@ -313,7 +322,7 @@ void BVHLoader::ReadNodeChannels( BVHLoader::Node& pNode)
else if( channelToken == "Zrotation") else if( channelToken == "Zrotation")
pNode.mChannels.push_back( Channel_RotationZ); pNode.mChannels.push_back( Channel_RotationZ);
else else
ThrowException( boost::str( boost::format( "Invalid channel specifier \"%s\".") % channelToken)); ThrowException( format() << "Invalid channel specifier \"" << channelToken << "\"." );
} }
} }
@ -324,7 +333,7 @@ void BVHLoader::ReadMotion( aiScene* /*pScene*/)
// Read number of frames // Read number of frames
std::string tokenFrames = GetNextToken(); std::string tokenFrames = GetNextToken();
if( tokenFrames != "Frames:") if( tokenFrames != "Frames:")
ThrowException( boost::str( boost::format( "Expected frame count \"Frames:\", but found \"%s\".") % tokenFrames)); ThrowException( format() << "Expected frame count \"Frames:\", but found \"" << tokenFrames << "\".");
float numFramesFloat = GetNextTokenAsFloat(); float numFramesFloat = GetNextTokenAsFloat();
mAnimNumFrames = (unsigned int) numFramesFloat; mAnimNumFrames = (unsigned int) numFramesFloat;
@ -333,7 +342,7 @@ void BVHLoader::ReadMotion( aiScene* /*pScene*/)
std::string tokenDuration1 = GetNextToken(); std::string tokenDuration1 = GetNextToken();
std::string tokenDuration2 = GetNextToken(); std::string tokenDuration2 = GetNextToken();
if( tokenDuration1 != "Frame" || tokenDuration2 != "Time:") if( tokenDuration1 != "Frame" || tokenDuration2 != "Time:")
ThrowException( boost::str( boost::format( "Expected frame duration \"Frame Time:\", but found \"%s %s\".") % tokenDuration1 % tokenDuration2)); ThrowException( format() << "Expected frame duration \"Frame Time:\", but found \"" << tokenDuration1 << " " << tokenDuration2 << "\"." );
mAnimTickDuration = GetNextTokenAsFloat(); mAnimTickDuration = GetNextTokenAsFloat();
@ -360,7 +369,7 @@ void BVHLoader::ReadMotion( aiScene* /*pScene*/)
// Retrieves the next token // Retrieves the next token
std::string BVHLoader::GetNextToken() std::string BVHLoader::GetNextToken()
{ {
// skip any preceeding whitespace // skip any preceding whitespace
while( mReader != mBuffer.end()) while( mReader != mBuffer.end())
{ {
if( !isspace( *mReader)) if( !isspace( *mReader))
@ -406,16 +415,16 @@ float BVHLoader::GetNextTokenAsFloat()
ctoken = fast_atoreal_move<float>( ctoken, result); ctoken = fast_atoreal_move<float>( ctoken, result);
if( ctoken != token.c_str() + token.length()) if( ctoken != token.c_str() + token.length())
ThrowException( boost::str( boost::format( "Expected a floating point number, but found \"%s\".") % token)); ThrowException( format() << "Expected a floating point number, but found \"" << token << "\"." );
return result; return result;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Aborts the file reading with an exception // Aborts the file reading with an exception
void BVHLoader::ThrowException( const std::string& pError) AI_WONT_RETURN void BVHLoader::ThrowException( const std::string& pError)
{ {
throw DeadlyImportError( boost::str( boost::format( "%s:%d - %s") % mFileName % mLine % pError)); throw DeadlyImportError( format() << mFileName << ":" << mLine << " - " << pError);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -434,7 +443,7 @@ void BVHLoader::CreateAnimation( aiScene* pScene)
anim->mDuration = double( mAnimNumFrames - 1); anim->mDuration = double( mAnimNumFrames - 1);
// now generate the tracks for all nodes // now generate the tracks for all nodes
anim->mNumChannels = mNodes.size(); anim->mNumChannels = static_cast<unsigned int>(mNodes.size());
anim->mChannels = new aiNodeAnim*[anim->mNumChannels]; anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
// FIX: set the array elements to NULL to ensure proper deletion if an exception is thrown // FIX: set the array elements to NULL to ensure proper deletion if an exception is thrown

View File

@ -4,7 +4,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -49,6 +49,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h" #include "BaseImporter.h"
struct aiNode;
namespace Assimp namespace Assimp
{ {
@ -81,7 +83,7 @@ class BVHLoader : public BaseImporter
std::vector<float> mChannelValues; // motion data values for that node. Of size NumChannels * NumFrames std::vector<float> mChannelValues; // motion data values for that node. Of size NumChannels * NumFrames
Node() { } Node() { }
Node( const aiNode* pNode) : mNode( pNode) { } explicit Node( const aiNode* pNode) : mNode( pNode) { }
}; };
public: public:
@ -134,7 +136,7 @@ protected:
float GetNextTokenAsFloat(); float GetNextTokenAsFloat();
/** Aborts the file reading with an exception */ /** Aborts the file reading with an exception */
void ThrowException( const std::string& pError); AI_WONT_RETURN void ThrowException( const std::string& pError) AI_WONT_RETURN_SUFFIX;
/** Constructs an animation for the motion data and stores it in the given scene */ /** Constructs an animation for the motion data and stores it in the given scene */
void CreateAnimation( aiScene* pScene); void CreateAnimation( aiScene* pScene);

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
@ -43,18 +43,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of BaseImporter * @brief Implementation of BaseImporter
*/ */
#include "AssimpPCH.h"
#include "BaseImporter.h" #include "BaseImporter.h"
#include "FileSystemFilter.h" #include "FileSystemFilter.h"
#include "Importer.h" #include "Importer.h"
#include "ByteSwapper.h"
#include <assimp/scene.h>
#include <assimp/Importer.hpp>
#include <assimp/postprocess.h>
#include <ios>
#include <list>
#include <memory>
#include <sstream>
#include <cctype>
using namespace Assimp; using namespace Assimp;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
BaseImporter::BaseImporter() BaseImporter::BaseImporter()
: progress() : m_progress()
{ {
// nothing to do here // nothing to do here
} }
@ -70,8 +77,8 @@ BaseImporter::~BaseImporter()
// Imports the given file and returns the imported data. // Imports the given file and returns the imported data.
aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, IOSystem* pIOHandler) aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, IOSystem* pIOHandler)
{ {
progress = pImp->GetProgressHandler(); m_progress = pImp->GetProgressHandler();
ai_assert(progress); ai_assert(m_progress);
// Gather configuration properties for this run // Gather configuration properties for this run
SetupProperties( pImp ); SetupProperties( pImp );
@ -89,8 +96,8 @@ aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile,
} catch( const std::exception& err ) { } catch( const std::exception& err ) {
// extract error description // extract error description
mErrorText = err.what(); m_ErrorText = err.what();
DefaultLogger::get()->error(mErrorText); DefaultLogger::get()->error(m_ErrorText);
return NULL; return NULL;
} }
@ -129,47 +136,55 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
/*static*/ bool BaseImporter::SearchFileHeaderForToken(IOSystem* pIOHandler, /*static*/ bool BaseImporter::SearchFileHeaderForToken( IOSystem* pIOHandler,
const std::string& pFile, const std::string& pFile,
const char** tokens, const char** tokens,
unsigned int numTokens, unsigned int numTokens,
unsigned int searchBytes /* = 200 */, unsigned int searchBytes /* = 200 */,
bool tokensSol /* false */) bool tokensSol /* false */)
{ {
ai_assert(NULL != tokens && 0 != numTokens && 0 != searchBytes); ai_assert( NULL != tokens );
ai_assert( 0 != numTokens );
ai_assert( 0 != searchBytes);
if (!pIOHandler) if (!pIOHandler)
return false; return false;
boost::scoped_ptr<IOStream> pStream (pIOHandler->Open(pFile)); std::unique_ptr<IOStream> pStream (pIOHandler->Open(pFile));
if (pStream.get() ) { if (pStream.get() ) {
// read 200 characters from the file // read 200 characters from the file
boost::scoped_array<char> _buffer (new char[searchBytes+1 /* for the '\0' */]); std::unique_ptr<char[]> _buffer (new char[searchBytes+1 /* for the '\0' */]);
char* buffer = _buffer.get(); char* buffer = _buffer.get();
if( NULL == buffer ) {
const unsigned int read = pStream->Read(buffer,1,searchBytes);
if (!read)
return false; return false;
}
for (unsigned int i = 0; i < read;++i) const size_t read = pStream->Read(buffer,1,searchBytes);
buffer[i] = ::tolower(buffer[i]); if( !read ) {
return false;
}
for( size_t i = 0; i < read; ++i ) {
buffer[ i ] = ::tolower( buffer[ i ] );
}
// It is not a proper handling of unicode files here ... // It is not a proper handling of unicode files here ...
// ehm ... but it works in most cases. // ehm ... but it works in most cases.
char* cur = buffer,*cur2 = buffer,*end = &buffer[read]; char* cur = buffer,*cur2 = buffer,*end = &buffer[read];
while (cur != end) { while (cur != end) {
if (*cur) if( *cur ) {
*cur2++ = *cur; *cur2++ = *cur;
}
++cur; ++cur;
} }
*cur2 = '\0'; *cur2 = '\0';
for (unsigned int i = 0; i < numTokens;++i) { for (unsigned int i = 0; i < numTokens;++i) {
ai_assert(NULL != tokens[i]); ai_assert(NULL != tokens[i]);
const char* r = strstr(buffer,tokens[i]); const char* r = strstr(buffer,tokens[i]);
if (!r) if( !r ) {
continue; continue;
}
// We got a match, either we don't care where it is, or it happens to // We got a match, either we don't care where it is, or it happens to
// be in the beginning of the file / line // be in the beginning of the file / line
if (!tokensSol || r == buffer || r[-1] == '\r' || r[-1] == '\n') { if (!tokensSol || r == buffer || r[-1] == '\r' || r[-1] == '\n') {
@ -178,6 +193,7 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
} }
} }
} }
return false; return false;
} }
@ -239,7 +255,7 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
const uint32_t* magic_u32; const uint32_t* magic_u32;
}; };
magic = reinterpret_cast<const char*>(_magic); magic = reinterpret_cast<const char*>(_magic);
boost::scoped_ptr<IOStream> pStream (pIOHandler->Open(pFile)); std::unique_ptr<IOStream> pStream (pIOHandler->Open(pFile));
if (pStream.get() ) { if (pStream.get() ) {
// skip to offset // skip to offset
@ -257,7 +273,7 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
for (unsigned int i = 0; i < num; ++i) { for (unsigned int i = 0; i < num; ++i) {
// also check against big endian versions of tokens with size 2,4 // also check against big endian versions of tokens with size 2,4
// that's just for convinience, the chance that we cause conflicts // that's just for convenience, the chance that we cause conflicts
// is quite low and it can save some lines and prevent nasty bugs // is quite low and it can save some lines and prevent nasty bugs
if (2 == size) { if (2 == size) {
uint16_t rev = *magic_u16; uint16_t rev = *magic_u16;
@ -319,7 +335,7 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
// UTF 32 BE with BOM // UTF 32 BE with BOM
if(*((uint32_t*)&data.front()) == 0xFFFE0000) { if(*((uint32_t*)&data.front()) == 0xFFFE0000) {
// swap the endianess .. // swap the endianness ..
for(uint32_t* p = (uint32_t*)&data.front(), *end = (uint32_t*)&data.back(); p <= end; ++p) { for(uint32_t* p = (uint32_t*)&data.front(), *end = (uint32_t*)&data.back(); p <= end; ++p) {
AI_SWAP4P(p); AI_SWAP4P(p);
} }
@ -350,7 +366,7 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
// UTF 16 BE with BOM // UTF 16 BE with BOM
if(*((uint16_t*)&data.front()) == 0xFFFE) { if(*((uint16_t*)&data.front()) == 0xFFFE) {
// swap the endianess .. // swap the endianness ..
for(uint16_t* p = (uint16_t*)&data.front(), *end = (uint16_t*)&data.back(); p <= end; ++p) { for(uint16_t* p = (uint16_t*)&data.front(), *end = (uint16_t*)&data.back(); p <= end; ++p) {
ByteSwap::Swap2(p); ByteSwap::Swap2(p);
} }
@ -383,11 +399,11 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
// Convert to UTF8 data to ISO-8859-1 // Convert to UTF8 data to ISO-8859-1
void BaseImporter::ConvertUTF8toISO8859_1(std::string& data) void BaseImporter::ConvertUTF8toISO8859_1(std::string& data)
{ {
unsigned int size = data.size(); size_t size = data.size();
unsigned int i = 0, j = 0; size_t i = 0, j = 0;
while(i < size) { while(i < size) {
if((unsigned char) data[i] < 0x80) { if ((unsigned char) data[i] < (size_t) 0x80) {
data[j] = data[i]; data[j] = data[i];
} else if(i < size - 1) { } else if(i < size - 1) {
if((unsigned char) data[i] == 0xC2) { if((unsigned char) data[i] == 0xC2) {
@ -418,61 +434,80 @@ void BaseImporter::ConvertUTF8toISO8859_1(std::string& data)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BaseImporter::TextFileToBuffer(IOStream* stream, void BaseImporter::TextFileToBuffer(IOStream* stream,
std::vector<char>& data) std::vector<char>& data,
TextFileMode mode)
{ {
ai_assert(NULL != stream); ai_assert(NULL != stream);
const size_t fileSize = stream->FileSize(); const size_t fileSize = stream->FileSize();
if (mode == FORBID_EMPTY) {
if(!fileSize) { if(!fileSize) {
throw DeadlyImportError("File is empty"); throw DeadlyImportError("File is empty");
} }
}
data.reserve(fileSize+1); data.reserve(fileSize+1);
data.resize(fileSize); data.resize(fileSize);
if(fileSize > 0) {
if(fileSize != stream->Read( &data[0], 1, fileSize)) { if(fileSize != stream->Read( &data[0], 1, fileSize)) {
throw DeadlyImportError("File read error"); throw DeadlyImportError("File read error");
} }
ConvertToUTF8(data); ConvertToUTF8(data);
}
// append a binary zero to simplify string parsing // append a binary zero to simplify string parsing
data.push_back(0); data.push_back(0);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
namespace Assimp namespace Assimp {
{
// Represents an import request // Represents an import request
struct LoadRequest struct LoadRequest {
{
LoadRequest(const std::string& _file, unsigned int _flags,const BatchLoader::PropertyMap* _map, unsigned int _id) LoadRequest(const std::string& _file, unsigned int _flags,const BatchLoader::PropertyMap* _map, unsigned int _id)
: file(_file), flags(_flags), refCnt(1),scene(NULL), loaded(false), id(_id) : file(_file)
{ , flags(_flags)
if (_map) , refCnt(1)
, scene(NULL)
, loaded(false)
, id(_id) {
if ( _map ) {
map = *_map; map = *_map;
} }
}
bool operator== ( const std::string& f ) const {
return file == f;
}
const std::string file; const std::string file;
unsigned int flags; unsigned int flags;
unsigned int refCnt; unsigned int refCnt;
aiScene* scene; aiScene *scene;
bool loaded; bool loaded;
BatchLoader::PropertyMap map; BatchLoader::PropertyMap map;
unsigned int id; unsigned int id;
bool operator== (const std::string& f) {
return file == f;
}
}; };
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// BatchLoader::pimpl data structure // BatchLoader::pimpl data structure
struct Assimp::BatchData struct Assimp::BatchData {
{ BatchData( IOSystem* pIO, bool validate )
BatchData() : pIOSystem( pIO )
: next_id(0xffff) , pImporter( nullptr )
{} , next_id(0xffff)
, validate( validate ) {
ai_assert( NULL != pIO );
pImporter = new Importer();
pImporter->SetIOHandler( pIO );
}
~BatchData() {
pImporter->SetIOHandler( NULL ); /* get pointer back into our possession */
delete pImporter;
}
// IO system to be used for all imports // IO system to be used for all imports
IOSystem* pIOSystem; IOSystem* pIOSystem;
@ -488,53 +523,59 @@ struct Assimp::BatchData
// Id for next item // Id for next item
unsigned int next_id; unsigned int next_id;
// Validation enabled state
bool validate;
}; };
typedef std::list<LoadRequest>::iterator LoadReqIt;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
BatchLoader::BatchLoader(IOSystem* pIO) BatchLoader::BatchLoader(IOSystem* pIO, bool validate )
{ {
ai_assert(NULL != pIO); ai_assert(NULL != pIO);
data = new BatchData(); m_data = new BatchData( pIO, validate );
data->pIOSystem = pIO;
data->pImporter = new Importer();
data->pImporter->SetIOHandler(data->pIOSystem);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
BatchLoader::~BatchLoader() BatchLoader::~BatchLoader()
{ {
// delete all scenes wthat have not been polled by the user // delete all scenes what have not been polled by the user
for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) { for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) {
delete (*it).scene; delete (*it).scene;
} }
data->pImporter->SetIOHandler(NULL); /* get pointer back into our posession */ delete m_data;
delete data->pImporter;
delete data;
} }
// ------------------------------------------------------------------------------------------------
void BatchLoader::setValidation( bool enabled ) {
m_data->validate = enabled;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
unsigned int BatchLoader::AddLoadRequest (const std::string& file, bool BatchLoader::getValidation() const {
return m_data->validate;
}
// ------------------------------------------------------------------------------------------------
unsigned int BatchLoader::AddLoadRequest(const std::string& file,
unsigned int steps /*= 0*/, const PropertyMap* map /*= NULL*/) unsigned int steps /*= 0*/, const PropertyMap* map /*= NULL*/)
{ {
ai_assert(!file.empty()); ai_assert(!file.empty());
// check whether we have this loading request already // check whether we have this loading request already
std::list<LoadRequest>::iterator it; for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) {
for (it = data->requests.begin();it != data->requests.end(); ++it) {
// Call IOSystem's path comparison function here // Call IOSystem's path comparison function here
if (data->pIOSystem->ComparePaths((*it).file,file)) { if ( m_data->pIOSystem->ComparePaths((*it).file,file)) {
if (map) { if (map) {
if (!((*it).map == *map)) if ( !( ( *it ).map == *map ) ) {
continue; continue;
} }
else if (!(*it).map.empty()) }
else if ( !( *it ).map.empty() ) {
continue; continue;
}
(*it).refCnt++; (*it).refCnt++;
return (*it).id; return (*it).id;
@ -542,20 +583,18 @@ unsigned int BatchLoader::AddLoadRequest (const std::string& file,
} }
// no, we don't have it. So add it to the queue ... // no, we don't have it. So add it to the queue ...
data->requests.push_back(LoadRequest(file,steps,map,data->next_id)); m_data->requests.push_back(LoadRequest(file,steps,map, m_data->next_id));
return data->next_id++; return m_data->next_id++;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiScene* BatchLoader::GetImport (unsigned int which) aiScene* BatchLoader::GetImport( unsigned int which )
{ {
for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) { for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) {
if ((*it).id == which && (*it).loaded) { if ((*it).id == which && (*it).loaded) {
aiScene* sc = (*it).scene; aiScene* sc = (*it).scene;
if (!(--(*it).refCnt)) { if (!(--(*it).refCnt)) {
data->requests.erase(it); m_data->requests.erase(it);
} }
return sc; return sc;
} }
@ -567,14 +606,15 @@ aiScene* BatchLoader::GetImport (unsigned int which)
void BatchLoader::LoadAll() void BatchLoader::LoadAll()
{ {
// no threaded implementation for the moment // no threaded implementation for the moment
for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) { for ( LoadReqIt it = m_data->requests.begin();it != m_data->requests.end(); ++it) {
// force validation in debug builds // force validation in debug builds
unsigned int pp = (*it).flags; unsigned int pp = (*it).flags;
#ifdef ASSIMP_BUILD_DEBUG if ( m_data->validate ) {
pp |= aiProcess_ValidateDataStructure; pp |= aiProcess_ValidateDataStructure;
#endif }
// setup config properties if necessary // setup config properties if necessary
ImporterPimpl* pimpl = data->pImporter->Pimpl(); ImporterPimpl* pimpl = m_data->pImporter->Pimpl();
pimpl->mFloatProperties = (*it).map.floats; pimpl->mFloatProperties = (*it).map.floats;
pimpl->mIntProperties = (*it).map.ints; pimpl->mIntProperties = (*it).map.ints;
pimpl->mStringProperties = (*it).map.strings; pimpl->mStringProperties = (*it).map.strings;
@ -585,14 +625,10 @@ void BatchLoader::LoadAll()
DefaultLogger::get()->info("%%% BEGIN EXTERNAL FILE %%%"); DefaultLogger::get()->info("%%% BEGIN EXTERNAL FILE %%%");
DefaultLogger::get()->info("File: " + (*it).file); DefaultLogger::get()->info("File: " + (*it).file);
} }
data->pImporter->ReadFile((*it).file,pp); m_data->pImporter->ReadFile((*it).file,pp);
(*it).scene = data->pImporter->GetOrphanedScene(); (*it).scene = m_data->pImporter->GetOrphanedScene();
(*it).loaded = true; (*it).loaded = true;
DefaultLogger::get()->info("%%% END EXTERNAL FILE %%%"); DefaultLogger::get()->info("%%% END EXTERNAL FILE %%%");
} }
} }

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -47,19 +47,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string> #include <string>
#include <map> #include <map>
#include <vector> #include <vector>
#include "./../include/assimp/types.h" #include <set>
#include <assimp/types.h>
#include <assimp/ProgressHandler.hpp>
struct aiScene; struct aiScene;
namespace Assimp { namespace Assimp {
class IOSystem;
class Importer; class Importer;
class BaseImporter; class IOSystem;
class BaseProcess; class BaseProcess;
class SharedPostProcessInfo; class SharedPostProcessInfo;
class IOStream; class IOStream;
// utility to do char4 to uint32 in a portable manner // utility to do char4 to uint32 in a portable manner
#define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \ #define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \
(string[1] << 16) + (string[2] << 8) + string[3])) (string[1] << 16) + (string[2] << 8) + string[3]))
@ -68,7 +70,7 @@ class IOStream;
template <typename T> template <typename T>
struct ScopeGuard struct ScopeGuard
{ {
ScopeGuard(T* obj) : obj(obj), mdismiss() {} explicit ScopeGuard(T* obj) : obj(obj), mdismiss() {}
~ScopeGuard () throw() { ~ScopeGuard () throw() {
if (!mdismiss) { if (!mdismiss) {
delete obj; delete obj;
@ -90,6 +92,11 @@ struct ScopeGuard
} }
private: private:
// no copying allowed.
ScopeGuard();
ScopeGuard( const ScopeGuard & );
ScopeGuard &operator = ( const ScopeGuard & );
T* obj; T* obj;
bool mdismiss; bool mdismiss;
}; };
@ -169,12 +176,12 @@ public:
); );
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns the error description of the last error that occured. /** Returns the error description of the last error that occurred.
* @return A description of the last error that occured. An empty * @return A description of the last error that occurred. An empty
* string if there was no error. * string if there was no error.
*/ */
const std::string& GetErrorText() const { const std::string& GetErrorText() const {
return mErrorText; return m_ErrorText;
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
@ -340,6 +347,13 @@ public: // static utilities
static void ConvertUTF8toISO8859_1( static void ConvertUTF8toISO8859_1(
std::string& data); std::string& data);
// -------------------------------------------------------------------
/// @brief Enum to define, if empty files are ok or not.
enum TextFileMode {
ALLOW_EMPTY,
FORBID_EMPTY
};
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Utility for text file loaders which copies the contents of the /** Utility for text file loaders which copies the contents of the
* file into a memory buffer and converts it to our UTF8 * file into a memory buffer and converts it to our UTF8
@ -347,18 +361,37 @@ public: // static utilities
* @param stream Stream to read from. * @param stream Stream to read from.
* @param data Output buffer to be resized and filled with the * @param data Output buffer to be resized and filled with the
* converted text file data. The buffer is terminated with * converted text file data. The buffer is terminated with
* a binary 0. */ * a binary 0.
* @param mode Whether it is OK to load empty text files. */
static void TextFileToBuffer( static void TextFileToBuffer(
IOStream* stream, IOStream* stream,
std::vector<char>& data); std::vector<char>& data,
TextFileMode mode = FORBID_EMPTY);
// -------------------------------------------------------------------
/** Utility function to move a std::vector into a aiScene array
* @param vec The vector to be moved
* @param out The output pointer to the allocated array.
* @param numOut The output count of elements copied. */
template<typename T>
AI_FORCE_INLINE
static void CopyVector(
std::vector<T>& vec,
T*& out,
unsigned int& outLength)
{
outLength = unsigned(vec.size());
if (outLength) {
out = new T[outLength];
std::swap_ranges(vec.begin(), vec.end(), out);
}
}
protected: protected:
/// Error description in case there was one.
/** Error description in case there was one. */ std::string m_ErrorText;
std::string mErrorText; /// Currently set progress handler.
ProgressHandler* m_progress;
/** Currently set progress handler */
ProgressHandler* progress;
}; };

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
@ -41,10 +41,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of BaseProcess */ /** @file Implementation of BaseProcess */
#include "AssimpPCH.h"
#include "BaseImporter.h" #include "BaseImporter.h"
#include "BaseProcess.h" #include "BaseProcess.h"
#include <assimp/DefaultLogger.hpp>
#include <assimp/scene.h>
#include "Importer.h" #include "Importer.h"
using namespace Assimp; using namespace Assimp;

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -44,7 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <map> #include <map>
#include "../include/assimp/types.h" #include <assimp/types.h>
#include "GenericProperty.h" #include "GenericProperty.h"
struct aiScene; struct aiScene;
@ -74,7 +74,7 @@ public:
template <typename T> template <typename T>
struct THeapData : public Base struct THeapData : public Base
{ {
THeapData(T* in) explicit THeapData(T* in)
: data (in) : data (in)
{} {}
@ -89,7 +89,7 @@ public:
template <typename T> template <typename T>
struct TStaticData : public Base struct TStaticData : public Base
{ {
TStaticData(T in) explicit TStaticData(T in)
: data (in) : data (in)
{} {}

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
@ -45,9 +45,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Used for file formats which embed their textures into the model file. * Used for file formats which embed their textures into the model file.
*/ */
#include "AssimpPCH.h"
#include "Bitmap.h" #include "Bitmap.h"
#include <assimp/texture.h>
#include <assimp/IOStream.hpp>
#include "ByteSwapper.h"
namespace Assimp { namespace Assimp {
@ -82,7 +84,12 @@ namespace Assimp {
template<typename T> template<typename T>
inline std::size_t Copy(uint8_t* data, T& field) { inline std::size_t Copy(uint8_t* data, T& field) {
#ifdef AI_BUILD_BIG_ENDIAN
T field_swapped=AI_BE(field);
std::memcpy(data, &field_swapped, sizeof(field)); return sizeof(field);
#else
std::memcpy(data, &AI_BE(field), sizeof(field)); return sizeof(field); std::memcpy(data, &AI_BE(field), sizeof(field)); return sizeof(field);
#endif
} }
void Bitmap::WriteHeader(Header& header, IOStream* file) { void Bitmap::WriteHeader(Header& header, IOStream* file) {

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
@ -48,8 +48,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_BITMAP_H_INC #ifndef AI_BITMAP_H_INC
#define AI_BITMAP_H_INC #define AI_BITMAP_H_INC
#include <stdint.h>
#include <cstddef>
struct aiTexture;
namespace Assimp { namespace Assimp {
class IOStream;
class Bitmap { class Bitmap {
protected: protected:

View File

@ -42,7 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Conversion of Blender's new BMesh stuff * @brief Conversion of Blender's new BMesh stuff
*/ */
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
@ -150,7 +149,7 @@ void BlenderBMeshConverter::ConvertPolyToFaces( const MPoly& poly )
// UVs are optional, so only convert when present. // UVs are optional, so only convert when present.
if ( BMesh->mloopuv.size() ) if ( BMesh->mloopuv.size() )
{ {
if ( (poly.loopstart + poly.totloop ) >= static_cast<int>( BMesh->mloopuv.size() ) ) if ( (poly.loopstart + poly.totloop ) > static_cast<int>( BMesh->mloopuv.size() ) )
{ {
ThrowException( "BMesh uv loop array has incorrect size" ); ThrowException( "BMesh uv loop array has incorrect size" );
} }
@ -181,7 +180,7 @@ void BlenderBMeshConverter::AddFace( int v1, int v2, int v3, int v4 )
// TODO - Work out how materials work // TODO - Work out how materials work
face.mat_nr = 0; face.mat_nr = 0;
triMesh->mface.push_back( face ); triMesh->mface.push_back( face );
triMesh->totface = triMesh->mface.size( ); triMesh->totface = static_cast<int>(triMesh->mface.size( ));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -42,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the Blender `DNA`, that is its own * @brief Implementation of the Blender `DNA`, that is its own
* serialized set of data structures. * serialized set of data structures.
*/ */
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
#include "BlenderDNA.h" #include "BlenderDNA.h"
@ -53,13 +53,13 @@ using namespace Assimp;
using namespace Assimp::Blender; using namespace Assimp::Blender;
using namespace Assimp::Formatter; using namespace Assimp::Formatter;
#define for_each BOOST_FOREACH static bool match4(StreamReaderAny& stream, const char* string) {
bool match4(StreamReaderAny& stream, const char* string) { ai_assert( nullptr != string );
char tmp[] = { char tmp[] = {
(stream).GetI1(), (const char)(stream).GetI1(),
(stream).GetI1(), (const char)(stream).GetI1(),
(stream).GetI1(), (const char)(stream).GetI1(),
(stream).GetI1() (const char)(stream).GetI1()
}; };
return (tmp[0]==string[0] && tmp[1]==string[1] && tmp[2]==string[2] && tmp[3]==string[3]); return (tmp[0]==string[0] && tmp[1]==string[1] && tmp[2]==string[2] && tmp[3]==string[3]);
} }
@ -70,7 +70,7 @@ struct Type {
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void DNAParser :: Parse () void DNAParser::Parse ()
{ {
StreamReaderAny& stream = *db.reader.get(); StreamReaderAny& stream = *db.reader.get();
DNA& dna = db.dna; DNA& dna = db.dna;
@ -85,7 +85,7 @@ void DNAParser :: Parse ()
} }
std::vector<std::string> names (stream.GetI4()); std::vector<std::string> names (stream.GetI4());
for_each(std::string& s, names) { for(std::string& s : names) {
while (char c = stream.GetI1()) { while (char c = stream.GetI1()) {
s += c; s += c;
} }
@ -98,7 +98,7 @@ void DNAParser :: Parse ()
} }
std::vector<Type> types (stream.GetI4()); std::vector<Type> types (stream.GetI4());
for_each(Type& s, types) { for(Type& s : types) {
while (char c = stream.GetI1()) { while (char c = stream.GetI1()) {
s.name += c; s.name += c;
} }
@ -110,7 +110,7 @@ void DNAParser :: Parse ()
throw DeadlyImportError("BlenderDNA: Expected TLEN field"); throw DeadlyImportError("BlenderDNA: Expected TLEN field");
} }
for_each(Type& s, types) { for(Type& s : types) {
s.size = stream.GetI2(); s.size = stream.GetI2();
} }
@ -237,13 +237,15 @@ void DNA :: DumpToFile()
f << "Field format: type name offset size" << "\n"; f << "Field format: type name offset size" << "\n";
f << "Structure format: name size" << "\n"; f << "Structure format: name size" << "\n";
for_each(const Structure& s, structures) { for(const Structure& s : structures) {
f << s.name << " " << s.size << "\n\n"; f << s.name << " " << s.size << "\n\n";
for_each(const Field& ff, s.fields) { for(const Field& ff : s.fields) {
f << "\t" << ff.type << " " << ff.name << " " << ff.offset << " " << ff.size << std::endl; f << "\t" << ff.type << " " << ff.name << " " << ff.offset << " " << ff.size << "\n";
} }
f << std::endl; f << "\n";
} }
f << std::flush;
DefaultLogger::get()->info("BlenderDNA: Dumped dna to dna.txt"); DefaultLogger::get()->info("BlenderDNA: Dumped dna to dna.txt");
} }
#endif #endif
@ -269,17 +271,17 @@ void DNA :: DumpToFile()
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
boost::shared_ptr< ElemBase > DNA :: ConvertBlobToStructure( std::shared_ptr< ElemBase > DNA :: ConvertBlobToStructure(
const Structure& structure, const Structure& structure,
const FileDatabase& db const FileDatabase& db
) const ) const
{ {
std::map<std::string, FactoryPair >::const_iterator it = converters.find(structure.name); std::map<std::string, FactoryPair >::const_iterator it = converters.find(structure.name);
if (it == converters.end()) { if (it == converters.end()) {
return boost::shared_ptr< ElemBase >(); return std::shared_ptr< ElemBase >();
} }
boost::shared_ptr< ElemBase > ret = (structure.*((*it).second.first))(); std::shared_ptr< ElemBase > ret = (structure.*((*it).second.first))();
(structure.*((*it).second.second))(ret,db); (structure.*((*it).second.second))(ret,db);
return ret; return ret;
@ -344,10 +346,10 @@ void SectionParser :: Next()
stream.SetCurrentPos(current.start + current.size); stream.SetCurrentPos(current.start + current.size);
const char tmp[] = { const char tmp[] = {
stream.GetI1(), (const char)stream.GetI1(),
stream.GetI1(), (const char)stream.GetI1(),
stream.GetI1(), (const char)stream.GetI1(),
stream.GetI1() (const char)stream.GetI1()
}; };
current.id = std::string(tmp,tmp[3]?4:tmp[2]?3:tmp[1]?2:1); current.id = std::string(tmp,tmp[3]?4:tmp[2]?3:tmp[1]?2:1);

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -47,6 +47,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h" #include "BaseImporter.h"
#include "TinyFormatter.h" #include "TinyFormatter.h"
#include "StreamReader.h"
#include <assimp/DefaultLogger.hpp>
#include <stdint.h>
#include <memory>
// enable verbose log output. really verbose, so be careful. // enable verbose log output. really verbose, so be careful.
#ifdef ASSIMP_BUILD_DEBUG #ifdef ASSIMP_BUILD_DEBUG
@ -56,15 +61,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// #define ASSIMP_BUILD_BLENDER_NO_STATS // #define ASSIMP_BUILD_BLENDER_NO_STATS
namespace Assimp { namespace Assimp {
template <bool,bool> class StreamReader;
typedef StreamReader<true,true> StreamReaderAny;
namespace Blender { template <bool,bool> class StreamReader;
class FileDatabase; typedef StreamReader<true,true> StreamReaderAny;
struct FileBlockHead;
template <template <typename> class TOUT> namespace Blender {
class ObjectCache;
class FileDatabase;
struct FileBlockHead;
template <template <typename> class TOUT>
class ObjectCache;
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** Exception class used by the blender loader to selectively catch exceptions /** Exception class used by the blender loader to selectively catch exceptions
@ -73,62 +80,65 @@ namespace Assimp {
* the loader itself, it will still be caught by Assimp due to its * the loader itself, it will still be caught by Assimp due to its
* ancestry. */ * ancestry. */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Error : DeadlyImportError struct Error : DeadlyImportError {
{
Error (const std::string& s) Error (const std::string& s)
: DeadlyImportError(s) : DeadlyImportError(s) {
{} // empty
}
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** The only purpose of this structure is to feed a virtual dtor into its /** The only purpose of this structure is to feed a virtual dtor into its
* descendents. It serves as base class for all data structure fields. */ * descendents. It serves as base class for all data structure fields. */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct ElemBase struct ElemBase {
{ virtual ~ElemBase() {
virtual ~ElemBase() {} // empty
}
/** Type name of the element. The type /** Type name of the element. The type
* string points is the `c_str` of the `name` attribute of the * string points is the `c_str` of the `name` attribute of the
* corresponding `Structure`, that is, it is only valid as long * corresponding `Structure`, that is, it is only valid as long
* as the DNA is not modified. The dna_type is only set if the * as the DNA is not modified. The dna_type is only set if the
* data type is not static, i.e. a boost::shared_ptr<ElemBase> * data type is not static, i.e. a std::shared_ptr<ElemBase>
* in the scene description would have its type resolved * in the scene description would have its type resolved
* at runtime, so this member is always set. */ * at runtime, so this member is always set. */
const char* dna_type; const char* dna_type;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** Represents a generic pointer to a memory location, which can be either 32 /** Represents a generic pointer to a memory location, which can be either 32
* or 64 bits. These pointers are loaded from the BLEND file and finally * or 64 bits. These pointers are loaded from the BLEND file and finally
* fixed to point to the real, converted representation of the objects * fixed to point to the real, converted representation of the objects
* they used to point to.*/ * they used to point to.*/
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Pointer struct Pointer {
{ Pointer()
Pointer() : val() {} : val() {
// empty
}
uint64_t val; uint64_t val;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** Represents a generic offset within a BLEND file */ /** Represents a generic offset within a BLEND file */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct FileOffset struct FileOffset {
{ FileOffset()
FileOffset() : val() {} : val() {
// empty
}
uint64_t val; uint64_t val;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** Dummy derivate of std::vector to be able to use it in templates simultaenously /** Dummy derivate of std::vector to be able to use it in templates simultaenously
* with boost::shared_ptr, which takes only one template argument * with std::shared_ptr, which takes only one template argument
* while std::vector takes three. Also we need to provide some special member * while std::vector takes three. Also we need to provide some special member
* functions of shared_ptr */ * functions of shared_ptr */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
template <typename T> template <typename T>
class vector : public std::vector<T> class vector : public std::vector<T> {
{
public: public:
using std::vector<T>::resize; using std::vector<T>::resize;
using std::vector<T>::empty; using std::vector<T>::empty;
@ -145,8 +155,7 @@ public:
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** Mixed flags for use in #Field */ /** Mixed flags for use in #Field */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
enum FieldFlags enum FieldFlags {
{
FieldFlag_Pointer = 0x1, FieldFlag_Pointer = 0x1,
FieldFlag_Array = 0x2 FieldFlag_Array = 0x2
}; };
@ -154,8 +163,7 @@ enum FieldFlags
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** Represents a single member of a data structure in a BLEND file */ /** Represents a single member of a data structure in a BLEND file */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Field struct Field {
{
std::string name; std::string name;
std::string type; std::string type;
@ -175,8 +183,7 @@ struct Field
* mission critical so we need them, while others can silently be default * mission critical so we need them, while others can silently be default
* initialized and no animations are harmed. */ * initialized and no animations are harmed. */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
enum ErrorPolicy enum ErrorPolicy {
{
/** Substitute default value and ignore */ /** Substitute default value and ignore */
ErrorPolicy_Igno, ErrorPolicy_Igno,
/** Substitute default value and write to log */ /** Substitute default value and write to log */
@ -197,15 +204,14 @@ enum ErrorPolicy
* binary `blob` read from the file to such a structure instance with * binary `blob` read from the file to such a structure instance with
* meaningful contents. */ * meaningful contents. */
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
class Structure class Structure {
{
template <template <typename> class> friend class ObjectCache; template <template <typename> class> friend class ObjectCache;
public: public:
Structure() Structure()
: cache_idx(-1) : cache_idx(static_cast<size_t>(-1) ){
{} // empty
}
public: public:
@ -255,11 +261,11 @@ public:
// -------------------------------------------------------- // --------------------------------------------------------
// generic converter // generic converter
template <typename T> template <typename T>
void Convert(boost::shared_ptr<ElemBase> in,const FileDatabase& db) const; void Convert(std::shared_ptr<ElemBase> in,const FileDatabase& db) const;
// -------------------------------------------------------- // --------------------------------------------------------
// generic allocator // generic allocator
template <typename T> boost::shared_ptr<ElemBase> Allocate() const; template <typename T> std::shared_ptr<ElemBase> Allocate() const;
@ -277,7 +283,7 @@ public:
// -------------------------------------------------------- // --------------------------------------------------------
// field parsing for pointer or dynamic array types // field parsing for pointer or dynamic array types
// (boost::shared_ptr or boost::shared_array) // (std::shared_ptr)
// The return value indicates whether the data was already cached. // The return value indicates whether the data was already cached.
template <int error_policy, template <typename> class TOUT, typename T> template <int error_policy, template <typename> class TOUT, typename T>
bool ReadFieldPtr(TOUT<T>& out, const char* name, bool ReadFieldPtr(TOUT<T>& out, const char* name,
@ -286,7 +292,7 @@ public:
// -------------------------------------------------------- // --------------------------------------------------------
// field parsing for static arrays of pointer or dynamic // field parsing for static arrays of pointer or dynamic
// array types (boost::shared_ptr[] or boost::shared_array[]) // array types (std::shared_ptr[])
// The return value indicates whether the data was already cached. // The return value indicates whether the data was already cached.
template <int error_policy, template <typename> class TOUT, typename T, size_t N> template <int error_policy, template <typename> class TOUT, typename T, size_t N>
bool ReadFieldPtr(TOUT<T> (&out)[N], const char* name, bool ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
@ -313,7 +319,7 @@ private:
const FileDatabase& db, const Field& f, bool) const; const FileDatabase& db, const Field& f, bool) const;
// -------------------------------------------------------- // --------------------------------------------------------
bool ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval, bool ResolvePointer( std::shared_ptr< FileOffset >& out, const Pointer & ptrval,
const FileDatabase& db, const Field& f, bool) const; const FileDatabase& db, const Field& f, bool) const;
// -------------------------------------------------------- // --------------------------------------------------------
@ -324,8 +330,8 @@ private:
private: private:
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
template <typename T> T* _allocate(boost::shared_ptr<T>& out, size_t& s) const { template <typename T> T* _allocate(std::shared_ptr<T>& out, size_t& s) const {
out = boost::shared_ptr<T>(new T()); out = std::shared_ptr<T>(new T());
s = 1; s = 1;
return out.get(); return out.get();
} }
@ -389,7 +395,7 @@ template <> struct Structure :: _defaultInitializer<ErrorPolicy_Fail> {
}; };
// ------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------
template <> inline bool Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out, template <> inline bool Structure :: ResolvePointer<std::shared_ptr,ElemBase>(std::shared_ptr<ElemBase>& out,
const Pointer & ptrval, const Pointer & ptrval,
const FileDatabase& db, const FileDatabase& db,
const Field& f, const Field& f,
@ -408,11 +414,11 @@ class DNA
public: public:
typedef void (Structure::*ConvertProcPtr) ( typedef void (Structure::*ConvertProcPtr) (
boost::shared_ptr<ElemBase> in, std::shared_ptr<ElemBase> in,
const FileDatabase& const FileDatabase&
) const; ) const;
typedef boost::shared_ptr<ElemBase> ( typedef std::shared_ptr<ElemBase> (
Structure::*AllocProcPtr) () const; Structure::*AllocProcPtr) () const;
typedef std::pair< AllocProcPtr, ConvertProcPtr > FactoryPair; typedef std::pair< AllocProcPtr, ConvertProcPtr > FactoryPair;
@ -459,7 +465,7 @@ public:
* @param structure Destination structure definition * @param structure Destination structure definition
* @param db File database. * @param db File database.
* @return A null pointer if no appropriate converter is available.*/ * @return A null pointer if no appropriate converter is available.*/
boost::shared_ptr< ElemBase > ConvertBlobToStructure( std::shared_ptr< ElemBase > ConvertBlobToStructure(
const Structure& structure, const Structure& structure,
const FileDatabase& db const FileDatabase& db
) const; ) const;
@ -704,8 +710,6 @@ class FileDatabase
template <template <typename> class TOUT> friend class ObjectCache; template <template <typename> class TOUT> friend class ObjectCache;
public: public:
FileDatabase() FileDatabase()
: _cacheArrays(*this) : _cacheArrays(*this)
, _cache(*this) , _cache(*this)
@ -713,13 +717,12 @@ public:
{} {}
public: public:
// publicly accessible fields // publicly accessible fields
bool i64bit; bool i64bit;
bool little; bool little;
DNA dna; DNA dna;
boost::shared_ptr< StreamReaderAny > reader; std::shared_ptr< StreamReaderAny > reader;
vector< FileBlockHead > entries; vector< FileBlockHead > entries;
public: public:
@ -733,7 +736,7 @@ public:
// arrays of objects are never cached because we can't easily // arrays of objects are never cached because we can't easily
// ensure their proper destruction. // ensure their proper destruction.
template <typename T> template <typename T>
ObjectCache<boost::shared_ptr>& cache(boost::shared_ptr<T>& /*in*/) const { ObjectCache<std::shared_ptr>& cache(std::shared_ptr<T>& /*in*/) const {
return _cache; return _cache;
} }
@ -750,7 +753,7 @@ private:
#endif #endif
mutable ObjectCache<vector> _cacheArrays; mutable ObjectCache<vector> _cacheArrays;
mutable ObjectCache<boost::shared_ptr> _cache; mutable ObjectCache<std::shared_ptr> _cache;
mutable size_t next_cache_idx; mutable size_t next_cache_idx;
}; };

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -45,6 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_BLEND_DNA_INL #ifndef INCLUDED_AI_BLEND_DNA_INL
#define INCLUDED_AI_BLEND_DNA_INL #define INCLUDED_AI_BLEND_DNA_INL
#include <memory>
namespace Assimp { namespace Assimp {
namespace Blender { namespace Blender {
@ -81,14 +83,14 @@ const Field& Structure :: operator [] (const size_t i) const
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
template <typename T> boost::shared_ptr<ElemBase> Structure :: Allocate() const template <typename T> std::shared_ptr<ElemBase> Structure :: Allocate() const
{ {
return boost::shared_ptr<T>(new T()); return std::shared_ptr<T>(new T());
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
template <typename T> void Structure :: Convert( template <typename T> void Structure :: Convert(
boost::shared_ptr<ElemBase> in, std::shared_ptr<ElemBase> in,
const FileDatabase& db) const const FileDatabase& db) const
{ {
Convert<T> (*static_cast<T*> ( in.get() ),db); Convert<T> (*static_cast<T*> ( in.get() ),db);
@ -364,7 +366,7 @@ bool Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const Fil
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
inline bool Structure :: ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval, inline bool Structure :: ResolvePointer( std::shared_ptr< FileOffset >& out, const Pointer & ptrval,
const FileDatabase& db, const FileDatabase& db,
const Field&, const Field&,
bool) const bool) const
@ -379,7 +381,7 @@ inline bool Structure :: ResolvePointer( boost::shared_ptr< FileOffset >& out, c
// find the file block the pointer is pointing to // find the file block the pointer is pointing to
const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db); const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
out = boost::shared_ptr< FileOffset > (new FileOffset()); out = std::shared_ptr< FileOffset > (new FileOffset());
out->val = block->start+ static_cast<size_t>((ptrval.val - block->address.val) ); out->val = block->start+ static_cast<size_t>((ptrval.val - block->address.val) );
return false; return false;
} }
@ -424,7 +426,7 @@ bool Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
template <> bool Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out, template <> bool Structure :: ResolvePointer<std::shared_ptr,ElemBase>(std::shared_ptr<ElemBase>& out,
const Pointer & ptrval, const Pointer & ptrval,
const FileDatabase& db, const FileDatabase& db,
const Field&, const Field&,
@ -530,7 +532,7 @@ template <typename T> struct signless;
template <> struct signless<char> {typedef unsigned char type;}; template <> struct signless<char> {typedef unsigned char type;};
template <> struct signless<short> {typedef unsigned short type;}; template <> struct signless<short> {typedef unsigned short type;};
template <> struct signless<int> {typedef unsigned int type;}; template <> struct signless<int> {typedef unsigned int type;};
template <> struct signless<unsigned char> { typedef unsigned char type; };
template <typename T> template <typename T>
struct static_cast_silent { struct static_cast_silent {
template <typename V> template <typename V>
@ -612,6 +614,22 @@ template <> inline void Structure :: Convert<char> (char& dest,const FileDatab
ConvertDispatcher(dest,*this,db); ConvertDispatcher(dest,*this,db);
} }
// ------------------------------------------------------------------------------------------------
template <> inline void Structure::Convert<unsigned char>(unsigned char& dest, const FileDatabase& db) const
{
// automatic rescaling from char to float and vice versa (seems useful for RGB colors)
if (name == "float") {
dest = static_cast<unsigned char>(db.reader->GetF4() * 255.f);
return;
}
else if (name == "double") {
dest = static_cast<unsigned char>(db.reader->GetF8() * 255.f);
return;
}
ConvertDispatcher(dest, *this, db);
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
template <> inline void Structure :: Convert<float> (float& dest,const FileDatabase& db) const template <> inline void Structure :: Convert<float> (float& dest,const FileDatabase& db) const
{ {
@ -701,7 +719,7 @@ template <template <typename> class TOUT> template <typename T> void ObjectCache
typename StructureCache::const_iterator it = caches[s.cache_idx].find(ptr); typename StructureCache::const_iterator it = caches[s.cache_idx].find(ptr);
if (it != caches[s.cache_idx].end()) { if (it != caches[s.cache_idx].end()) {
out = boost::static_pointer_cast<T>( (*it).second ); out = std::static_pointer_cast<T>( (*it).second );
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
++db.stats().cache_hits; ++db.stats().cache_hits;
@ -721,7 +739,7 @@ template <template <typename> class TOUT> template <typename T> void ObjectCache
s.cache_idx = db.next_cache_idx++; s.cache_idx = db.next_cache_idx++;
caches.resize(db.next_cache_idx); caches.resize(db.next_cache_idx);
} }
caches[s.cache_idx][ptr] = boost::static_pointer_cast<ElemBase>( out ); caches[s.cache_idx][ptr] = std::static_pointer_cast<ElemBase>( out );
#ifndef ASSIMP_BUILD_BLENDER_NO_STATS #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
++db.stats().cached_objects; ++db.stats().cached_objects;

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -49,8 +49,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderDNA.h" #include "BlenderDNA.h"
#include "BlenderScene.h" #include "BlenderScene.h"
#include "BlenderSceneGen.h" #include "BlenderSceneGen.h"
#include <deque>
#include "./../include/assimp/material.h"
#define for_each(x,y) BOOST_FOREACH(x,y) struct aiTexture;
namespace Assimp { namespace Assimp {
namespace Blender { namespace Blender {
@ -66,7 +68,7 @@ namespace Blender {
} }
~TempArray () { ~TempArray () {
for_each(T* elem, arr) { for(T* elem : arr) {
delete elem; delete elem;
} }
} }
@ -118,6 +120,16 @@ namespace Blender {
#ifdef _MSC_VER #ifdef _MSC_VER
# pragma warning(disable:4351) # pragma warning(disable:4351)
#endif #endif
struct ObjectCompare {
bool operator() (const Object* left, const Object* right) const {
return ::strncmp(left->id.name, right->id.name, strlen( left->id.name ) ) == 0;
}
};
// When keeping objects in sets, sort them by their name.
typedef std::set<const Object*, ObjectCompare> ObjectSet;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
/** ConversionData acts as intermediate storage location for /** ConversionData acts as intermediate storage location for
* the various ConvertXXX routines in BlenderImporter.*/ * the various ConvertXXX routines in BlenderImporter.*/
@ -130,7 +142,13 @@ namespace Blender {
, db(db) , db(db)
{} {}
std::set<const Object*> objects; struct ObjectCompare {
bool operator() (const Object* left, const Object* right) const {
return ::strncmp( left->id.name, right->id.name, strlen( left->id.name ) ) == 0;
}
};
ObjectSet objects;
TempArray <std::vector, aiMesh> meshes; TempArray <std::vector, aiMesh> meshes;
TempArray <std::vector, aiCamera> cameras; TempArray <std::vector, aiCamera> cameras;
@ -139,7 +157,7 @@ namespace Blender {
TempArray <std::vector, aiTexture> textures; TempArray <std::vector, aiTexture> textures;
// set of all materials referenced by at least one mesh in the scene // set of all materials referenced by at least one mesh in the scene
std::deque< boost::shared_ptr< Material > > materials_raw; std::deque< std::shared_ptr< Material > > materials_raw;
// counter to name sentinel textures inserted as substitutes for procedural textures. // counter to name sentinel textures inserted as substitutes for procedural textures.
unsigned int sentinel_cnt; unsigned int sentinel_cnt;

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -42,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file BlenderLoader.cpp /** @file BlenderLoader.cpp
* @brief Implementation of the Blender3D importer class. * @brief Implementation of the Blender3D importer class.
*/ */
#include "AssimpPCH.h"
//#define ASSIMP_BUILD_NO_COMPRESSED_BLEND //#define ASSIMP_BUILD_NO_COMPRESSED_BLEND
// Uncomment this to disable support for (gzip)compressed .BLEND files // Uncomment this to disable support for (gzip)compressed .BLEND files
@ -52,9 +52,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderIntermediate.h" #include "BlenderIntermediate.h"
#include "BlenderModifier.h" #include "BlenderModifier.h"
#include "BlenderBMesh.h" #include "BlenderBMesh.h"
#include "StringUtils.h"
#include <assimp/scene.h>
#include "StringComparison.h"
#include "StreamReader.h" #include "StreamReader.h"
#include "MemoryIOWrapper.h" #include "MemoryIOWrapper.h"
#include <cctype>
#include <cstdint>
// zlib is needed for compressed blend files // zlib is needed for compressed blend files
#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND #ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
@ -100,6 +106,8 @@ BlenderImporter::~BlenderImporter()
delete modifier_cache; delete modifier_cache;
} }
static const char* Tokens[] = { "BLENDER" };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool BlenderImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const bool BlenderImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
@ -111,8 +119,7 @@ bool BlenderImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, b
else if ((!extension.length() || checkSig) && pIOHandler) { else if ((!extension.length() || checkSig) && pIOHandler) {
// note: this won't catch compressed files // note: this won't catch compressed files
const char* tokens[] = {"BLENDER"}; return SearchFileHeaderForToken(pIOHandler,pFile, Tokens,1);
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
} }
return false; return false;
} }
@ -159,14 +166,14 @@ void BlenderImporter::InternReadFile( const std::string& pFile,
#endif #endif
FileDatabase file; FileDatabase file;
boost::shared_ptr<IOStream> stream(pIOHandler->Open(pFile,"rb")); std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile,"rb"));
if (!stream) { if (!stream) {
ThrowException("Could not open file for reading"); ThrowException("Could not open file for reading");
} }
char magic[8] = {0}; char magic[8] = {0};
stream->Read(magic,7,1); stream->Read(magic,7,1);
if (strcmp(magic,"BLENDER")) { if (strcmp(magic, Tokens[0] )) {
// Check for presence of the gzip header. If yes, assume it is a // Check for presence of the gzip header. If yes, assume it is a
// compressed blend file and try uncompressing it, else fail. This is to // compressed blend file and try uncompressing it, else fail. This is to
// avoid uncompressing random files which our loader might end up with. // avoid uncompressing random files which our loader might end up with.
@ -185,7 +192,7 @@ void BlenderImporter::InternReadFile( const std::string& pFile,
// http://www.gzip.org/zlib/rfc-gzip.html#header-trailer // http://www.gzip.org/zlib/rfc-gzip.html#header-trailer
stream->Seek(0L,aiOrigin_SET); stream->Seek(0L,aiOrigin_SET);
boost::shared_ptr<StreamReaderLE> reader = boost::shared_ptr<StreamReaderLE>(new StreamReaderLE(stream)); std::shared_ptr<StreamReaderLE> reader = std::shared_ptr<StreamReaderLE>(new StreamReaderLE(stream));
// build a zlib stream // build a zlib stream
z_stream zstream; z_stream zstream;
@ -255,9 +262,9 @@ void BlenderImporter::InternReadFile( const std::string& pFile,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderImporter::ParseBlendFile(FileDatabase& out, boost::shared_ptr<IOStream> stream) void BlenderImporter::ParseBlendFile(FileDatabase& out, std::shared_ptr<IOStream> stream)
{ {
out.reader = boost::shared_ptr<StreamReaderAny>(new StreamReaderAny(stream,out.little)); out.reader = std::shared_ptr<StreamReaderAny>(new StreamReaderAny(stream,out.little));
DNAParser dna_reader(out); DNAParser dna_reader(out);
const DNA* dna = NULL; const DNA* dna = NULL;
@ -300,7 +307,7 @@ void BlenderImporter::ExtractScene(Scene& out, const FileDatabase& file)
const Structure& ss = file.dna.structures[(*it).second]; const Structure& ss = file.dna.structures[(*it).second];
// we need a scene somewhere to start with. // we need a scene somewhere to start with.
for_each(const FileBlockHead& bl,file.entries) { for(const FileBlockHead& bl :file.entries) {
// Fix: using the DNA index is more reliable to locate scenes // Fix: using the DNA index is more reliable to locate scenes
//if (bl.id == "SC") { //if (bl.id == "SC") {
@ -337,15 +344,16 @@ void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in,const FileD
// the file. This is terrible. Here, we're first looking for // the file. This is terrible. Here, we're first looking for
// all objects which don't have parent objects at all - // all objects which don't have parent objects at all -
std::deque<const Object*> no_parents; std::deque<const Object*> no_parents;
for (boost::shared_ptr<Base> cur = boost::static_pointer_cast<Base> ( in.base.first ); cur; cur = cur->next) { for (std::shared_ptr<Base> cur = std::static_pointer_cast<Base> ( in.base.first ); cur; cur = cur->next) {
if (cur->object) { if (cur->object) {
if(!cur->object->parent) { if(!cur->object->parent) {
no_parents.push_back(cur->object.get()); no_parents.push_back(cur->object.get());
} } else {
else conv.objects.insert(cur->object.get()); conv.objects.insert( cur->object.get() );
} }
} }
for (boost::shared_ptr<Base> cur = in.basact; cur; cur = cur->next) { }
for (std::shared_ptr<Base> cur = in.basact; cur; cur = cur->next) {
if (cur->object) { if (cur->object) {
if(cur->object->parent) { if(cur->object->parent) {
conv.objects.insert(cur->object.get()); conv.objects.insert(cur->object.get());
@ -399,7 +407,7 @@ void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in,const FileD
} }
// acknowledge that the scene might come out incomplete // acknowledge that the scene might come out incomplete
// by Assimps definition of `complete`: blender scenes // by Assimp's definition of `complete`: blender scenes
// can consist of thousands of cameras or lights with // can consist of thousands of cameras or lights with
// not a single mesh between them. // not a single mesh between them.
if (!out->mNumMeshes) { if (!out->mNumMeshes) {
@ -416,7 +424,7 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
// check if the file contents are bundled with the BLEND file // check if the file contents are bundled with the BLEND file
if (img->packedfile) { if (img->packedfile) {
name.data[0] = '*'; name.data[0] = '*';
name.length = 1+ ASSIMP_itoa10(name.data+1,MAXLEN-1,conv_data.textures->size()); name.length = 1+ ASSIMP_itoa10(name.data+1,static_cast<unsigned int>(MAXLEN-1), static_cast<int32_t>(conv_data.textures->size()));
conv_data.textures->push_back(new aiTexture()); conv_data.textures->push_back(new aiTexture());
aiTexture* tex = conv_data.textures->back(); aiTexture* tex = conv_data.textures->back();
@ -425,8 +433,9 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
// so we can extract the file extension from it. // so we can extract the file extension from it.
const size_t nlen = strlen( img->name ); const size_t nlen = strlen( img->name );
const char* s = img->name+nlen, *e = s; const char* s = img->name+nlen, *e = s;
while ( s >= img->name && *s != '.' ) {
while (s >= img->name && *s != '.')--s; --s;
}
tex->achFormatHint[0] = s+1>e ? '\0' : ::tolower( s[1] ); tex->achFormatHint[0] = s+1>e ? '\0' : ::tolower( s[1] );
tex->achFormatHint[1] = s+2>e ? '\0' : ::tolower( s[2] ); tex->achFormatHint[1] = s+2>e ? '\0' : ::tolower( s[2] );
@ -443,8 +452,7 @@ void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const M
tex->pcData = reinterpret_cast<aiTexel*>(ch); tex->pcData = reinterpret_cast<aiTexel*>(ch);
LogInfo("Reading embedded texture, original file was "+std::string(img->name)); LogInfo("Reading embedded texture, original file was "+std::string(img->name));
} } else {
else {
name = aiString( img->name ); name = aiString( img->name );
} }
@ -492,7 +500,7 @@ void BlenderImporter::AddSentinelTexture(aiMaterial* out, const Material* mat, c
(void)mat; (void)tex; (void)conv_data; (void)mat; (void)tex; (void)conv_data;
aiString name; aiString name;
name.length = sprintf(name.data, "Procedural,num=%i,type=%s",conv_data.sentinel_cnt++, name.length = ai_snprintf(name.data, MAXLEN, "Procedural,num=%i,type=%s",conv_data.sentinel_cnt++,
GetTextureTypeDisplayString(tex->tex->type) GetTextureTypeDisplayString(tex->tex->type)
); );
out->AddProperty(&name,AI_MATKEY_TEXTURE_DIFFUSE( out->AddProperty(&name,AI_MATKEY_TEXTURE_DIFFUSE(
@ -549,40 +557,158 @@ void BlenderImporter::ResolveTexture(aiMaterial* out, const Material* mat, const
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderImporter::BuildMaterials(ConversionData& conv_data) void BlenderImporter::BuildDefaultMaterial(Blender::ConversionData& conv_data)
{ {
conv_data.materials->reserve(conv_data.materials_raw.size());
// add a default material if necessary // add a default material if necessary
unsigned int index = static_cast<unsigned int>( -1 ); unsigned int index = static_cast<unsigned int>( -1 );
for_each( aiMesh* mesh, conv_data.meshes.get() ) { for( aiMesh* mesh : conv_data.meshes.get() ) {
if (mesh->mMaterialIndex == static_cast<unsigned int>( -1 )) { if (mesh->mMaterialIndex == static_cast<unsigned int>( -1 )) {
if (index == static_cast<unsigned int>( -1 )) { if (index == static_cast<unsigned int>( -1 )) {
// Setup a default material.
// ok, we need to add a dedicated default material for some poor material-less meshes std::shared_ptr<Material> p(new Material());
boost::shared_ptr<Material> p(new Material()); ai_assert(::strlen(AI_DEFAULT_MATERIAL_NAME) < sizeof(p->id.name)-2);
strcpy( p->id.name+2, AI_DEFAULT_MATERIAL_NAME ); strcpy( p->id.name+2, AI_DEFAULT_MATERIAL_NAME );
// Note: MSVC11 does not zero-initialize Material here, although it should.
// Thus all relevant fields should be explicitly initialized. We cannot add
// a default constructor to Material since the DNA codegen does not support
// parsing it.
p->r = p->g = p->b = 0.6f; p->r = p->g = p->b = 0.6f;
p->specr = p->specg = p->specb = 0.6f; p->specr = p->specg = p->specb = 0.6f;
p->ambr = p->ambg = p->ambb = 0.0f; p->ambr = p->ambg = p->ambb = 0.0f;
p->mirr = p->mirg = p->mirb = 0.0f; p->mirr = p->mirg = p->mirb = 0.0f;
p->emit = 0.f; p->emit = 0.f;
p->alpha = 0.f; p->alpha = 0.f;
p->har = 0;
// XXX add more / or add default c'tor to Material
index = static_cast<unsigned int>( conv_data.materials_raw.size() ); index = static_cast<unsigned int>( conv_data.materials_raw.size() );
conv_data.materials_raw.push_back(p); conv_data.materials_raw.push_back(p);
LogInfo("Adding default material");
LogInfo("Adding default material ...");
} }
mesh->mMaterialIndex = index; mesh->mMaterialIndex = index;
} }
} }
}
for_each(boost::shared_ptr<Material> mat, conv_data.materials_raw) { void BlenderImporter::AddBlendParams(aiMaterial* result, const Material* source)
{
aiColor3D diffuseColor(source->r, source->g, source->b);
result->AddProperty(&diffuseColor, 1, "$mat.blend.diffuse.color", 0, 0);
float diffuseIntensity = source->ref;
result->AddProperty(&diffuseIntensity, 1, "$mat.blend.diffuse.intensity", 0, 0);
int diffuseShader = source->diff_shader;
result->AddProperty(&diffuseShader, 1, "$mat.blend.diffuse.shader", 0, 0);
int diffuseRamp = 0;
result->AddProperty(&diffuseRamp, 1, "$mat.blend.diffuse.ramp", 0, 0);
aiColor3D specularColor(source->specr, source->specg, source->specb);
result->AddProperty(&specularColor, 1, "$mat.blend.specular.color", 0, 0);
float specularIntensity = source->spec;
result->AddProperty(&specularIntensity, 1, "$mat.blend.specular.intensity", 0, 0);
int specularShader = source->spec_shader;
result->AddProperty(&specularShader, 1, "$mat.blend.specular.shader", 0, 0);
int specularRamp = 0;
result->AddProperty(&specularRamp, 1, "$mat.blend.specular.ramp", 0, 0);
int specularHardness = source->har;
result->AddProperty(&specularHardness, 1, "$mat.blend.specular.hardness", 0, 0);
int transparencyUse = source->mode & MA_TRANSPARENCY ? 1 : 0;
result->AddProperty(&transparencyUse, 1, "$mat.blend.transparency.use", 0, 0);
int transparencyMethod = source->mode & MA_RAYTRANSP ? 2 : (source->mode & MA_ZTRANSP ? 1 : 0);
result->AddProperty(&transparencyMethod, 1, "$mat.blend.transparency.method", 0, 0);
float transparencyAlpha = source->alpha;
result->AddProperty(&transparencyAlpha, 1, "$mat.blend.transparency.alpha", 0, 0);
float transparencySpecular = source->spectra;
result->AddProperty(&transparencySpecular, 1, "$mat.blend.transparency.specular", 0, 0);
float transparencyFresnel = source->fresnel_tra;
result->AddProperty(&transparencyFresnel, 1, "$mat.blend.transparency.fresnel", 0, 0);
float transparencyBlend = source->fresnel_tra_i;
result->AddProperty(&transparencyBlend, 1, "$mat.blend.transparency.blend", 0, 0);
float transparencyIor = source->ang;
result->AddProperty(&transparencyIor, 1, "$mat.blend.transparency.ior", 0, 0);
float transparencyFilter = source->filter;
result->AddProperty(&transparencyFilter, 1, "$mat.blend.transparency.filter", 0, 0);
float transparencyFalloff = source->tx_falloff;
result->AddProperty(&transparencyFalloff, 1, "$mat.blend.transparency.falloff", 0, 0);
float transparencyLimit = source->tx_limit;
result->AddProperty(&transparencyLimit, 1, "$mat.blend.transparency.limit", 0, 0);
int transparencyDepth = source->ray_depth_tra;
result->AddProperty(&transparencyDepth, 1, "$mat.blend.transparency.depth", 0, 0);
float transparencyGlossAmount = source->gloss_tra;
result->AddProperty(&transparencyGlossAmount, 1, "$mat.blend.transparency.glossAmount", 0, 0);
float transparencyGlossThreshold = source->adapt_thresh_tra;
result->AddProperty(&transparencyGlossThreshold, 1, "$mat.blend.transparency.glossThreshold", 0, 0);
int transparencyGlossSamples = source->samp_gloss_tra;
result->AddProperty(&transparencyGlossSamples, 1, "$mat.blend.transparency.glossSamples", 0, 0);
int mirrorUse = source->mode & MA_RAYMIRROR ? 1 : 0;
result->AddProperty(&mirrorUse, 1, "$mat.blend.mirror.use", 0, 0);
float mirrorReflectivity = source->ray_mirror;
result->AddProperty(&mirrorReflectivity, 1, "$mat.blend.mirror.reflectivity", 0, 0);
aiColor3D mirrorColor(source->mirr, source->mirg, source->mirb);
result->AddProperty(&mirrorColor, 1, "$mat.blend.mirror.color", 0, 0);
float mirrorFresnel = source->fresnel_mir;
result->AddProperty(&mirrorFresnel, 1, "$mat.blend.mirror.fresnel", 0, 0);
float mirrorBlend = source->fresnel_mir_i;
result->AddProperty(&mirrorBlend, 1, "$mat.blend.mirror.blend", 0, 0);
int mirrorDepth = source->ray_depth;
result->AddProperty(&mirrorDepth, 1, "$mat.blend.mirror.depth", 0, 0);
float mirrorMaxDist = source->dist_mir;
result->AddProperty(&mirrorMaxDist, 1, "$mat.blend.mirror.maxDist", 0, 0);
int mirrorFadeTo = source->fadeto_mir;
result->AddProperty(&mirrorFadeTo, 1, "$mat.blend.mirror.fadeTo", 0, 0);
float mirrorGlossAmount = source->gloss_mir;
result->AddProperty(&mirrorGlossAmount, 1, "$mat.blend.mirror.glossAmount", 0, 0);
float mirrorGlossThreshold = source->adapt_thresh_mir;
result->AddProperty(&mirrorGlossThreshold, 1, "$mat.blend.mirror.glossThreshold", 0, 0);
int mirrorGlossSamples = source->samp_gloss_mir;
result->AddProperty(&mirrorGlossSamples, 1, "$mat.blend.mirror.glossSamples", 0, 0);
float mirrorGlossAnisotropic = source->aniso_gloss_mir;
result->AddProperty(&mirrorGlossAnisotropic, 1, "$mat.blend.mirror.glossAnisotropic", 0, 0);
}
void BlenderImporter::BuildMaterials(ConversionData& conv_data)
{
conv_data.materials->reserve(conv_data.materials_raw.size());
BuildDefaultMaterial(conv_data);
for(std::shared_ptr<Material> mat : conv_data.materials_raw) {
// reset per material global counters // reset per material global counters
for (size_t i = 0; i < sizeof(conv_data.next_texture)/sizeof(conv_data.next_texture[0]);++i) { for (size_t i = 0; i < sizeof(conv_data.next_texture)/sizeof(conv_data.next_texture[0]);++i) {
@ -591,12 +717,12 @@ void BlenderImporter::BuildMaterials(ConversionData& conv_data)
aiMaterial* mout = new aiMaterial(); aiMaterial* mout = new aiMaterial();
conv_data.materials->push_back(mout); conv_data.materials->push_back(mout);
// For any new material field handled here, the default material above must be updated with an appropriate default value.
// set material name // set material name
aiString name = aiString(mat->id.name+2); // skip over the name prefix 'MA' aiString name = aiString(mat->id.name+2); // skip over the name prefix 'MA'
mout->AddProperty(&name,AI_MATKEY_NAME); mout->AddProperty(&name,AI_MATKEY_NAME);
// basic material colors // basic material colors
aiColor3D col(mat->r,mat->g,mat->b); aiColor3D col(mat->r,mat->g,mat->b);
if (mat->r || mat->g || mat->b ) { if (mat->r || mat->g || mat->b ) {
@ -623,6 +749,12 @@ void BlenderImporter::BuildMaterials(ConversionData& conv_data)
col = aiColor3D(mat->ambr,mat->ambg,mat->ambb); col = aiColor3D(mat->ambr,mat->ambg,mat->ambb);
mout->AddProperty(&col,1,AI_MATKEY_COLOR_AMBIENT); mout->AddProperty(&col,1,AI_MATKEY_COLOR_AMBIENT);
// is mirror enabled?
if( mat->mode & MA_RAYMIRROR ) {
const float ray_mirror = mat->ray_mirror;
mout->AddProperty(&ray_mirror,1,AI_MATKEY_REFLECTIVITY);
}
col = aiColor3D(mat->mirr,mat->mirg,mat->mirb); col = aiColor3D(mat->mirr,mat->mirg,mat->mirb);
mout->AddProperty(&col,1,AI_MATKEY_COLOR_REFLECTIVE); mout->AddProperty(&col,1,AI_MATKEY_COLOR_REFLECTIVE);
@ -633,6 +765,8 @@ void BlenderImporter::BuildMaterials(ConversionData& conv_data)
ResolveTexture(mout,mat.get(),mat->mtex[i].get(),conv_data); ResolveTexture(mout,mat.get(),mat->mtex[i].get(),conv_data);
} }
AddBlendParams(mout, mat.get());
} }
} }
@ -659,11 +793,15 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
ConversionData& conv_data, TempArray<std::vector,aiMesh>& temp ConversionData& conv_data, TempArray<std::vector,aiMesh>& temp
) )
{ {
// TODO: Resolve various problems with BMesh triangulation before re-enabling.
// See issues #400, #373, #318 #315 and #132.
#if defined(TODO_FIX_BMESH_CONVERSION)
BlenderBMeshConverter BMeshConverter( mesh ); BlenderBMeshConverter BMeshConverter( mesh );
if ( BMeshConverter.ContainsBMesh( ) ) if ( BMeshConverter.ContainsBMesh( ) )
{ {
mesh = BMeshConverter.TriangulateBMesh( ); mesh = BMeshConverter.TriangulateBMesh( );
} }
#endif
typedef std::pair<const int,size_t> MyPair; typedef std::pair<const int,size_t> MyPair;
if ((!mesh->totface && !mesh->totloop) || !mesh->totvert) { if ((!mesh->totface && !mesh->totloop) || !mesh->totvert) {
@ -704,7 +842,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
temp->reserve(temp->size() + per_mat.size()); temp->reserve(temp->size() + per_mat.size());
std::map<size_t,size_t> mat_num_to_mesh_idx; std::map<size_t,size_t> mat_num_to_mesh_idx;
for_each(MyPair& it, per_mat) { for(MyPair& it : per_mat) {
mat_num_to_mesh_idx[it.first] = temp->size(); mat_num_to_mesh_idx[it.first] = temp->size();
temp->push_back(new aiMesh()); temp->push_back(new aiMesh());
@ -717,7 +855,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
//out->mNumVertices = 0 //out->mNumVertices = 0
out->mFaces = new aiFace[it.second](); out->mFaces = new aiFace[it.second]();
// all submeshes created from this mesh are named equally. this allows // all sub-meshes created from this mesh are named equally. this allows
// curious users to recover the original adjacency. // curious users to recover the original adjacency.
out->mName = aiString(mesh->id.name+2); out->mName = aiString(mesh->id.name+2);
// skip over the name prefix 'ME' // skip over the name prefix 'ME'
@ -731,8 +869,8 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
ThrowException("Material index is out of range"); ThrowException("Material index is out of range");
} }
boost::shared_ptr<Material> mat = mesh->mat[it.first]; std::shared_ptr<Material> mat = mesh->mat[it.first];
const std::deque< boost::shared_ptr<Material> >::iterator has = std::find( const std::deque< std::shared_ptr<Material> >::iterator has = std::find(
conv_data.materials_raw.begin(), conv_data.materials_raw.begin(),
conv_data.materials_raw.end(),mat conv_data.materials_raw.end(),mat
); );
@ -983,12 +1121,13 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
const aiFace& f = out->mFaces[out->mNumFaces++]; const aiFace& f = out->mFaces[out->mNumFaces++];
aiColor4D* vo = &out->mColors[0][out->mNumVertices]; aiColor4D* vo = &out->mColors[0][out->mNumVertices];
const ai_real scaleZeroToOne = 1.f/255.f;
for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) { for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
const MLoopCol& col = mesh->mloopcol[v.loopstart + j]; const MLoopCol& col = mesh->mloopcol[v.loopstart + j];
vo->r = col.r; vo->r = ai_real(col.r) * scaleZeroToOne;
vo->g = col.g; vo->g = ai_real(col.g) * scaleZeroToOne;
vo->b = col.b; vo->b = ai_real(col.b) * scaleZeroToOne;
vo->a = col.a; vo->a = ai_real(col.a) * scaleZeroToOne;
} }
} }
@ -999,13 +1138,19 @@ 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* cam, ConversionData& /*conv_data*/)
{ {
ScopeGuard<aiCamera> out(new aiCamera()); ScopeGuard<aiCamera> out(new aiCamera());
out->mName = obj->id.name+2; out->mName = obj->id.name+2;
out->mPosition = aiVector3D(0.f, 0.f, 0.f); out->mPosition = aiVector3D(0.f, 0.f, 0.f);
out->mUp = aiVector3D(0.f, 1.f, 0.f); out->mUp = aiVector3D(0.f, 1.f, 0.f);
out->mLookAt = aiVector3D(0.f, 0.f, -1.f); out->mLookAt = aiVector3D(0.f, 0.f, -1.f);
if (cam->sensor_x && cam->lens) {
out->mHorizontalFOV = std::atan2(cam->sensor_x, 2.f * cam->lens);
}
out->mClipPlaneNear = cam->clipsta;
out->mClipPlaneFar = cam->clipend;
return out.dismiss(); return out.dismiss();
} }
@ -1025,7 +1170,24 @@ aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, c
// blender orients directional lights as facing toward -z // blender orients directional lights as facing toward -z
out->mDirection = aiVector3D(0.f, 0.f, -1.f); out->mDirection = aiVector3D(0.f, 0.f, -1.f);
out->mUp = aiVector3D(0.f, 1.f, 0.f);
break; break;
case Lamp::Type_Area:
out->mType = aiLightSource_AREA;
if (lamp->area_shape == 0) {
out->mSize = aiVector2D(lamp->area_size, lamp->area_size);
}
else {
out->mSize = aiVector2D(lamp->area_size, lamp->area_sizey);
}
// blender orients directional lights as facing toward -z
out->mDirection = aiVector3D(0.f, 0.f, -1.f);
out->mUp = aiVector3D(0.f, 1.f, 0.f);
break;
default: default:
break; break;
} }
@ -1040,7 +1202,7 @@ aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, c
aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, ConversionData& conv_data, const aiMatrix4x4& parentTransform) aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, ConversionData& conv_data, const aiMatrix4x4& parentTransform)
{ {
std::deque<const Object*> children; std::deque<const Object*> children;
for(std::set<const Object*>::iterator it = conv_data.objects.begin(); it != conv_data.objects.end() ;) { for(ObjectSet::iterator it = conv_data.objects.begin(); it != conv_data.objects.end() ;) {
const Object* object = *it; const Object* object = *it;
if (object->parent == obj) { if (object->parent == obj) {
children.push_back(object); children.push_back(object);
@ -1069,7 +1231,7 @@ aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, Convers
if (conv_data.meshes->size() > old) { if (conv_data.meshes->size() > old) {
node->mMeshes = new unsigned int[node->mNumMeshes = static_cast<unsigned int>(conv_data.meshes->size()-old)]; node->mMeshes = new unsigned int[node->mNumMeshes = static_cast<unsigned int>(conv_data.meshes->size()-old)];
for (unsigned int i = 0; i < node->mNumMeshes; ++i) { for (unsigned int i = 0; i < node->mNumMeshes; ++i) {
node->mMeshes[i] = i + old; node->mMeshes[i] = static_cast<unsigned int>(i + old);
} }
}} }}
break; break;
@ -1133,7 +1295,7 @@ aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, Convers
if (children.size()) { if (children.size()) {
node->mNumChildren = static_cast<unsigned int>(children.size()); node->mNumChildren = static_cast<unsigned int>(children.size());
aiNode** nd = node->mChildren = new aiNode*[node->mNumChildren](); aiNode** nd = node->mChildren = new aiNode*[node->mNumChildren]();
for_each (const Object* nobj,children) { for (const Object* nobj :children) {
*nd = ConvertNode(in,nobj,conv_data,node->mTransformation * parentTransform); *nd = ConvertNode(in,nobj,conv_data,node->mTransformation * parentTransform);
(*nd++)->mParent = node; (*nd++)->mParent = node;
} }
@ -1145,5 +1307,4 @@ aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, Convers
return node.dismiss(); return node.dismiss();
} }
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
#endif

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -46,6 +46,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BaseImporter.h" #include "BaseImporter.h"
#include "LogAux.h" #include "LogAux.h"
#include <memory>
struct aiNode;
struct aiMesh;
struct aiLight;
struct aiCamera;
struct aiMaterial;
namespace Assimp { namespace Assimp {
@ -98,7 +105,6 @@ public:
BlenderImporter(); BlenderImporter();
~BlenderImporter(); ~BlenderImporter();
public: public:
// -------------------- // --------------------
@ -126,7 +132,7 @@ protected:
// -------------------- // --------------------
void ParseBlendFile(Blender::FileDatabase& out, void ParseBlendFile(Blender::FileDatabase& out,
boost::shared_ptr<IOStream> stream std::shared_ptr<IOStream> stream
); );
// -------------------- // --------------------
@ -172,9 +178,18 @@ private:
); );
// -------------------- // --------------------
void BuildDefaultMaterial(
Blender::ConversionData& conv_data
);
void AddBlendParams(
aiMaterial* result,
const Blender::Material* source
);
void BuildMaterials( void BuildMaterials(
Blender::ConversionData& conv_data Blender::ConversionData& conv_data
) ; );
// -------------------- // --------------------
void ResolveTexture( void ResolveTexture(

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -41,12 +41,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file BlenderModifier.cpp /** @file BlenderModifier.cpp
* @brief Implementation of some blender modifiers (i.e subdivision, mirror). * @brief Implementation of some blender modifiers (i.e subdivision, mirror).
*/ */
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
#include "BlenderModifier.h" #include "BlenderModifier.h"
#include "SceneCombiner.h" #include "SceneCombiner.h"
#include "Subdivision.h" #include "Subdivision.h"
#include <assimp/scene.h>
#include <memory>
#include <functional> #include <functional>
@ -109,8 +111,8 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_d
// we're allowed to dereference the pointers without risking to crash. We might still be // we're allowed to dereference the pointers without risking to crash. We might still be
// invoking UB btw - we're assuming that the ModifierData member of the respective modifier // invoking UB btw - we're assuming that the ModifierData member of the respective modifier
// structures is at offset sizeof(vftable) with no padding. // structures is at offset sizeof(vftable) with no padding.
const SharedModifierData* cur = boost::static_pointer_cast<const SharedModifierData> ( orig_object.modifiers.first.get() ); const SharedModifierData* cur = static_cast<const SharedModifierData *> ( orig_object.modifiers.first.get() );
for (; cur; cur = boost::static_pointer_cast<const SharedModifierData> ( cur->modifier.next.get() ), ++ful) { for (; cur; cur = static_cast<const SharedModifierData *> ( cur->modifier.next.get() ), ++ful) {
ai_assert(cur->dna_type); ai_assert(cur->dna_type);
const Structure* s = conv_data.db.dna.Get( cur->dna_type ); const Structure* s = conv_data.db.dna.Get( cur->dna_type );
@ -149,7 +151,7 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_d
BlenderModifier* const modifier = *curmod; BlenderModifier* const modifier = *curmod;
if(modifier->IsActive(dat)) { if(modifier->IsActive(dat)) {
modifier->DoIt(out,conv_data,*boost::static_pointer_cast<const ElemBase>(cur),in,orig_object); modifier->DoIt(out,conv_data,*static_cast<const ElemBase *>(cur),in,orig_object);
cnt++; cnt++;
curgod = NULL; curgod = NULL;
@ -273,9 +275,6 @@ void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, co
orig_object.id.name,"`"); orig_object.id.name,"`");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool BlenderModifier_Subdivision :: IsActive (const ModifierData& modin) bool BlenderModifier_Subdivision :: IsActive (const ModifierData& modin)
{ {
@ -308,11 +307,11 @@ void BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data
return; return;
}; };
boost::scoped_ptr<Subdivider> subd(Subdivider::Create(algo)); std::unique_ptr<Subdivider> subd(Subdivider::Create(algo));
ai_assert(subd); ai_assert(subd);
aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes]; aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes];
boost::scoped_array<aiMesh*> tempmeshes(new aiMesh*[out.mNumMeshes]()); std::unique_ptr<aiMesh*[]> tempmeshes(new aiMesh*[out.mNumMeshes]());
subd->Subdivide(meshes,out.mNumMeshes,tempmeshes.get(),std::max( mir.renderLevels, mir.levels ),true); subd->Subdivide(meshes,out.mNumMeshes,tempmeshes.get(),std::max( mir.renderLevels, mir.levels ),true);
std::copy(tempmeshes.get(),tempmeshes.get()+out.mNumMeshes,meshes); std::copy(tempmeshes.get(),tempmeshes.get()+out.mNumMeshes,meshes);
@ -321,4 +320,4 @@ void BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data
orig_object.id.name,"`"); orig_object.id.name,"`");
} }
#endif #endif // ASSIMP_BUILD_NO_BLEND_IMPORTER

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -46,8 +46,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderIntermediate.h" #include "BlenderIntermediate.h"
#include "TinyFormatter.h" #include "TinyFormatter.h"
namespace Assimp { namespace Assimp {
namespace Blender { namespace Blender {
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
/** Dummy base class for all blender modifiers. Modifiers are reused between imports, so /** Dummy base class for all blender modifiers. Modifiers are reused between imports, so
@ -56,8 +57,8 @@ namespace Assimp {
class BlenderModifier class BlenderModifier
{ {
public: public:
virtual ~BlenderModifier() { virtual ~BlenderModifier() {
// empty
} }
public: public:

View File

@ -2,7 +2,7 @@
Open Asset Import Library (ASSIMP) Open Asset Import Library (ASSIMP)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2010, ASSIMP Development Team Copyright (c) 2006-2016, ASSIMP Development Team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -41,7 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file BlenderScene.cpp /** @file BlenderScene.cpp
* @brief MACHINE GENERATED BY ./scripts/BlenderImporter/genblenddna.py * @brief MACHINE GENERATED BY ./scripts/BlenderImporter/genblenddna.py
*/ */
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
#include "BlenderDNA.h" #include "BlenderDNA.h"
@ -64,7 +64,7 @@ template <> void Structure :: Convert<Object> (
ReadFieldArray2<ErrorPolicy_Warn>(dest.parentinv,"parentinv",db); ReadFieldArray2<ErrorPolicy_Warn>(dest.parentinv,"parentinv",db);
ReadFieldArray<ErrorPolicy_Warn>(dest.parsubstr,"parsubstr",db); ReadFieldArray<ErrorPolicy_Warn>(dest.parsubstr,"parsubstr",db);
{ {
boost::shared_ptr<Object> parent; std::shared_ptr<Object> parent;
ReadFieldPtr<ErrorPolicy_Warn>(parent,"*parent",db); ReadFieldPtr<ErrorPolicy_Warn>(parent,"*parent",db);
dest.parent = parent.get(); dest.parent = parent.get();
} }
@ -206,6 +206,10 @@ template <> void Structure :: Convert<Lamp> (
ReadField<ErrorPolicy_Igno>(dest.att2,"att2",db); ReadField<ErrorPolicy_Igno>(dest.att2,"att2",db);
ReadField<ErrorPolicy_Igno>((int&)dest.falloff_type,"falloff_type",db); ReadField<ErrorPolicy_Igno>((int&)dest.falloff_type,"falloff_type",db);
ReadField<ErrorPolicy_Igno>(dest.sun_brightness,"sun_brightness",db); ReadField<ErrorPolicy_Igno>(dest.sun_brightness,"sun_brightness",db);
ReadField<ErrorPolicy_Igno>(dest.area_size,"area_size",db);
ReadField<ErrorPolicy_Igno>(dest.area_sizey,"area_sizey",db);
ReadField<ErrorPolicy_Igno>(dest.area_sizez,"area_sizez",db);
ReadField<ErrorPolicy_Igno>(dest.area_shape,"area_shape",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
@ -297,7 +301,6 @@ template <> void Structure :: Convert<Material> (
const FileDatabase& db const FileDatabase& db
) const ) const
{ {
ReadField<ErrorPolicy_Fail>(dest.id,"id",db); ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
ReadField<ErrorPolicy_Warn>(dest.r,"r",db); ReadField<ErrorPolicy_Warn>(dest.r,"r",db);
ReadField<ErrorPolicy_Warn>(dest.g,"g",db); ReadField<ErrorPolicy_Warn>(dest.g,"g",db);
@ -313,9 +316,11 @@ template <> void Structure :: Convert<Material> (
ReadField<ErrorPolicy_Igno>(dest.mirg,"mirg",db); ReadField<ErrorPolicy_Igno>(dest.mirg,"mirg",db);
ReadField<ErrorPolicy_Igno>(dest.mirb,"mirb",db); ReadField<ErrorPolicy_Igno>(dest.mirb,"mirb",db);
ReadField<ErrorPolicy_Warn>(dest.emit,"emit",db); ReadField<ErrorPolicy_Warn>(dest.emit,"emit",db);
ReadField<ErrorPolicy_Igno>(dest.ray_mirror,"ray_mirror",db);
ReadField<ErrorPolicy_Warn>(dest.alpha,"alpha",db); ReadField<ErrorPolicy_Warn>(dest.alpha,"alpha",db);
ReadField<ErrorPolicy_Igno>(dest.ref,"ref",db); ReadField<ErrorPolicy_Igno>(dest.ref,"ref",db);
ReadField<ErrorPolicy_Igno>(dest.translucency,"translucency",db); ReadField<ErrorPolicy_Igno>(dest.translucency,"translucency",db);
ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db);
ReadField<ErrorPolicy_Igno>(dest.roughness,"roughness",db); ReadField<ErrorPolicy_Igno>(dest.roughness,"roughness",db);
ReadField<ErrorPolicy_Igno>(dest.darkness,"darkness",db); ReadField<ErrorPolicy_Igno>(dest.darkness,"darkness",db);
ReadField<ErrorPolicy_Igno>(dest.refrac,"refrac",db); ReadField<ErrorPolicy_Igno>(dest.refrac,"refrac",db);
@ -324,6 +329,91 @@ template <> void Structure :: Convert<Material> (
ReadField<ErrorPolicy_Warn>(dest.spec_shader,"spec_shader",db); ReadField<ErrorPolicy_Warn>(dest.spec_shader,"spec_shader",db);
ReadFieldPtr<ErrorPolicy_Igno>(dest.mtex,"*mtex",db); ReadFieldPtr<ErrorPolicy_Igno>(dest.mtex,"*mtex",db);
ReadField<ErrorPolicy_Igno>(dest.amb, "amb", db);
ReadField<ErrorPolicy_Igno>(dest.ang, "ang", db);
ReadField<ErrorPolicy_Igno>(dest.spectra, "spectra", db);
ReadField<ErrorPolicy_Igno>(dest.spec, "spec", db);
ReadField<ErrorPolicy_Igno>(dest.zoffs, "zoffs", db);
ReadField<ErrorPolicy_Igno>(dest.add, "add", db);
ReadField<ErrorPolicy_Igno>(dest.fresnel_mir, "fresnel_mir", db);
ReadField<ErrorPolicy_Igno>(dest.fresnel_mir_i, "fresnel_mir_i", db);
ReadField<ErrorPolicy_Igno>(dest.fresnel_tra, "fresnel_tra", db);
ReadField<ErrorPolicy_Igno>(dest.fresnel_tra_i, "fresnel_tra_i", db);
ReadField<ErrorPolicy_Igno>(dest.filter, "filter", db);
ReadField<ErrorPolicy_Igno>(dest.tx_limit, "tx_limit", db);
ReadField<ErrorPolicy_Igno>(dest.tx_falloff, "tx_falloff", db);
ReadField<ErrorPolicy_Igno>(dest.gloss_mir, "gloss_mir", db);
ReadField<ErrorPolicy_Igno>(dest.gloss_tra, "gloss_tra", db);
ReadField<ErrorPolicy_Igno>(dest.adapt_thresh_mir, "adapt_thresh_mir", db);
ReadField<ErrorPolicy_Igno>(dest.adapt_thresh_tra, "adapt_thresh_tra", db);
ReadField<ErrorPolicy_Igno>(dest.aniso_gloss_mir, "aniso_gloss_mir", db);
ReadField<ErrorPolicy_Igno>(dest.dist_mir, "dist_mir", db);
ReadField<ErrorPolicy_Igno>(dest.hasize, "hasize", db);
ReadField<ErrorPolicy_Igno>(dest.flaresize, "flaresize", db);
ReadField<ErrorPolicy_Igno>(dest.subsize, "subsize", db);
ReadField<ErrorPolicy_Igno>(dest.flareboost, "flareboost", db);
ReadField<ErrorPolicy_Igno>(dest.strand_sta, "strand_sta", db);
ReadField<ErrorPolicy_Igno>(dest.strand_end, "strand_end", db);
ReadField<ErrorPolicy_Igno>(dest.strand_ease, "strand_ease", db);
ReadField<ErrorPolicy_Igno>(dest.strand_surfnor, "strand_surfnor", db);
ReadField<ErrorPolicy_Igno>(dest.strand_min, "strand_min", db);
ReadField<ErrorPolicy_Igno>(dest.strand_widthfade, "strand_widthfade", db);
ReadField<ErrorPolicy_Igno>(dest.sbias, "sbias", db);
ReadField<ErrorPolicy_Igno>(dest.lbias, "lbias", db);
ReadField<ErrorPolicy_Igno>(dest.shad_alpha, "shad_alpha", db);
ReadField<ErrorPolicy_Igno>(dest.param, "param", db);
ReadField<ErrorPolicy_Igno>(dest.rms, "rms", db);
ReadField<ErrorPolicy_Igno>(dest.rampfac_col, "rampfac_col", db);
ReadField<ErrorPolicy_Igno>(dest.rampfac_spec, "rampfac_spec", db);
ReadField<ErrorPolicy_Igno>(dest.friction, "friction", db);
ReadField<ErrorPolicy_Igno>(dest.fh, "fh", db);
ReadField<ErrorPolicy_Igno>(dest.reflect, "reflect", db);
ReadField<ErrorPolicy_Igno>(dest.fhdist, "fhdist", db);
ReadField<ErrorPolicy_Igno>(dest.xyfrict, "xyfrict", db);
ReadField<ErrorPolicy_Igno>(dest.sss_radius, "sss_radius", db);
ReadField<ErrorPolicy_Igno>(dest.sss_col, "sss_col", db);
ReadField<ErrorPolicy_Igno>(dest.sss_error, "sss_error", db);
ReadField<ErrorPolicy_Igno>(dest.sss_scale, "sss_scale", db);
ReadField<ErrorPolicy_Igno>(dest.sss_ior, "sss_ior", db);
ReadField<ErrorPolicy_Igno>(dest.sss_colfac, "sss_colfac", db);
ReadField<ErrorPolicy_Igno>(dest.sss_texfac, "sss_texfac", db);
ReadField<ErrorPolicy_Igno>(dest.sss_front, "sss_front", db);
ReadField<ErrorPolicy_Igno>(dest.sss_back, "sss_back", db);
ReadField<ErrorPolicy_Igno>(dest.material_type, "material_type", db);
ReadField<ErrorPolicy_Igno>(dest.flag, "flag", db);
ReadField<ErrorPolicy_Igno>(dest.ray_depth, "ray_depth", db);
ReadField<ErrorPolicy_Igno>(dest.ray_depth_tra, "ray_depth_tra", db);
ReadField<ErrorPolicy_Igno>(dest.samp_gloss_mir, "samp_gloss_mir", db);
ReadField<ErrorPolicy_Igno>(dest.samp_gloss_tra, "samp_gloss_tra", db);
ReadField<ErrorPolicy_Igno>(dest.fadeto_mir, "fadeto_mir", db);
ReadField<ErrorPolicy_Igno>(dest.shade_flag, "shade_flag", db);
ReadField<ErrorPolicy_Igno>(dest.flarec, "flarec", db);
ReadField<ErrorPolicy_Igno>(dest.starc, "starc", db);
ReadField<ErrorPolicy_Igno>(dest.linec, "linec", db);
ReadField<ErrorPolicy_Igno>(dest.ringc, "ringc", db);
ReadField<ErrorPolicy_Igno>(dest.pr_lamp, "pr_lamp", db);
ReadField<ErrorPolicy_Igno>(dest.pr_texture, "pr_texture", db);
ReadField<ErrorPolicy_Igno>(dest.ml_flag, "ml_flag", db);
ReadField<ErrorPolicy_Igno>(dest.diff_shader, "diff_shader", db);
ReadField<ErrorPolicy_Igno>(dest.spec_shader, "spec_shader", db);
ReadField<ErrorPolicy_Igno>(dest.texco, "texco", db);
ReadField<ErrorPolicy_Igno>(dest.mapto, "mapto", db);
ReadField<ErrorPolicy_Igno>(dest.ramp_show, "ramp_show", db);
ReadField<ErrorPolicy_Igno>(dest.pad3, "pad3", db);
ReadField<ErrorPolicy_Igno>(dest.dynamode, "dynamode", db);
ReadField<ErrorPolicy_Igno>(dest.pad2, "pad2", db);
ReadField<ErrorPolicy_Igno>(dest.sss_flag, "sss_flag", db);
ReadField<ErrorPolicy_Igno>(dest.sss_preset, "sss_preset", db);
ReadField<ErrorPolicy_Igno>(dest.shadowonly_flag, "shadowonly_flag", db);
ReadField<ErrorPolicy_Igno>(dest.index, "index", db);
ReadField<ErrorPolicy_Igno>(dest.vcol_alpha, "vcol_alpha", db);
ReadField<ErrorPolicy_Igno>(dest.pad4, "pad4", db);
ReadField<ErrorPolicy_Igno>(dest.seed1, "seed1", db);
ReadField<ErrorPolicy_Igno>(dest.seed2, "seed2", db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
@ -335,7 +425,7 @@ template <> void Structure :: Convert<MTexPoly> (
{ {
{ {
boost::shared_ptr<Image> tpage; std::shared_ptr<Image> tpage;
ReadFieldPtr<ErrorPolicy_Igno>(tpage,"*tpage",db); ReadFieldPtr<ErrorPolicy_Igno>(tpage,"*tpage",db);
dest.tpage = tpage.get(); dest.tpage = tpage.get();
} }
@ -620,7 +710,10 @@ template <> void Structure :: Convert<Camera> (
ReadField<ErrorPolicy_Fail>(dest.id,"id",db); ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
ReadField<ErrorPolicy_Warn>((int&)dest.type,"type",db); ReadField<ErrorPolicy_Warn>((int&)dest.type,"type",db);
ReadField<ErrorPolicy_Warn>((int&)dest.flag,"flag",db); ReadField<ErrorPolicy_Warn>((int&)dest.flag,"flag",db);
ReadField<ErrorPolicy_Warn>(dest.angle,"angle",db); ReadField<ErrorPolicy_Warn>(dest.lens,"lens",db);
ReadField<ErrorPolicy_Warn>(dest.sensor_x,"sensor_x",db);
ReadField<ErrorPolicy_Igno>(dest.clipsta,"clipsta",db);
ReadField<ErrorPolicy_Igno>(dest.clipend,"clipend",db);
db.reader->IncPtr(size); db.reader->IncPtr(size);
} }
@ -712,5 +805,5 @@ void DNA::RegisterConverters() {
converters["Image"] = DNA::FactoryPair( &Structure::Allocate<Image>, &Structure::Convert<Image> ); converters["Image"] = DNA::FactoryPair( &Structure::Allocate<Image>, &Structure::Convert<Image> );
} }
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
#endif

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -44,8 +44,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_BLEND_SCENE_H #ifndef INCLUDED_AI_BLEND_SCENE_H
#define INCLUDED_AI_BLEND_SCENE_H #define INCLUDED_AI_BLEND_SCENE_H
#include "BlenderDNA.h"
namespace Assimp { namespace Assimp {
namespace Blender { namespace Blender {
// Minor parts of this file are extracts from blender data structures, // Minor parts of this file are extracts from blender data structures,
// declared in the ./source/blender/makesdna directory. // declared in the ./source/blender/makesdna directory.
@ -62,7 +64,7 @@ namespace Assimp {
// * C++ style comments only // * C++ style comments only
// //
// * Structures may include the primitive types char, int, short, // * Structures may include the primitive types char, int, short,
// float, double. Signedness specifiers are not allowed on // float, double. Signed specifiers are not allowed on
// integers. Enum types are allowed, but they must have been // integers. Enum types are allowed, but they must have been
// defined in this header. // defined in this header.
// //
@ -71,7 +73,7 @@ namespace Assimp {
// //
// * Pointers to other structures or primitive types are allowed. // * Pointers to other structures or primitive types are allowed.
// No references or double pointers or arrays of pointers. // No references or double pointers or arrays of pointers.
// A pointer to a T is normally written as boost::shared_ptr, while a // A pointer to a T is normally written as std::shared_ptr, while a
// pointer to an array of elements is written as boost:: // pointer to an array of elements is written as boost::
// shared_array. To avoid cyclic pointers, use raw pointers in // shared_array. To avoid cyclic pointers, use raw pointers in
// one direction. // one direction.
@ -83,33 +85,44 @@ namespace Assimp {
// provided they are neither pointers nor arrays. // provided they are neither pointers nor arrays.
// //
// * One of WARN, FAIL can be appended to the declaration ( // * One of WARN, FAIL can be appended to the declaration (
// prior to the semiolon to specifiy the error handling policy if // prior to the semicolon to specify the error handling policy if
// this field is missing in the input DNA). If none of those // this field is missing in the input DNA). If none of those
// is specified the default policy is to subtitute a default // is specified the default policy is to substitute a default
// value for the field. // value for the field.
// //
#define WARN // warn if field is missing, substitute default value // warn if field is missing, substitute default value
#define FAIL // fail the import if the field does not exist #ifdef WARN
# undef WARN
#endif
#define WARN
// fail the import if the field does not exist
#ifdef FAIL
# undef FAIL
#endif
#define FAIL
struct Object; struct Object;
struct MTex; struct MTex;
struct Image; struct Image;
#include <memory>
#define AI_BLEND_MESH_MAX_VERTS 2000000000L #define AI_BLEND_MESH_MAX_VERTS 2000000000L
static const size_t MaxNameLen = 1024;
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct ID : ElemBase { struct ID : ElemBase {
char name[ MaxNameLen ] WARN;
char name[24] WARN;
short flag; short flag;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct ListBase : ElemBase { struct ListBase : ElemBase {
std::shared_ptr<ElemBase> first;
boost::shared_ptr<ElemBase> first; std::shared_ptr<ElemBase> last;
boost::shared_ptr<ElemBase> last;
}; };
@ -117,14 +130,13 @@ struct ListBase : ElemBase {
struct PackedFile : ElemBase { struct PackedFile : ElemBase {
int size WARN; int size WARN;
int seek WARN; int seek WARN;
boost::shared_ptr< FileOffset > data WARN; std::shared_ptr< FileOffset > data WARN;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct GroupObject : ElemBase { struct GroupObject : ElemBase {
std::shared_ptr<GroupObject> prev,next FAIL;
boost::shared_ptr<GroupObject> prev,next FAIL; std::shared_ptr<Object> ob;
boost::shared_ptr<Object> ob;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@ -132,13 +144,12 @@ struct Group : ElemBase {
ID id FAIL; ID id FAIL;
int layer; int layer;
boost::shared_ptr<GroupObject> gobject; std::shared_ptr<GroupObject> gobject;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct World : ElemBase { struct World : ElemBase {
ID id FAIL; ID id FAIL;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@ -171,7 +182,7 @@ struct MLoopUV : ElemBase {
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
// Note that red and blue are not swapped, as with MCol // Note that red and blue are not swapped, as with MCol
struct MLoopCol : ElemBase { struct MLoopCol : ElemBase {
char r, g, b, a; unsigned char r, g, b, a;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@ -213,14 +224,13 @@ struct TFace : ElemBase {
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MTFace : ElemBase { struct MTFace : ElemBase {
float uv[4][2] FAIL; float uv[4][2] FAIL;
char flag; char flag;
short mode; short mode;
short tile; short tile;
short unwrap; short unwrap;
// boost::shared_ptr<Image> tpage; // std::shared_ptr<Image> tpage;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@ -231,12 +241,16 @@ struct MDeformWeight : ElemBase {
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct MDeformVert : ElemBase { struct MDeformVert : ElemBase {
vector<MDeformWeight> dw WARN; vector<MDeformWeight> dw WARN;
int totweight; int totweight;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
#define MA_RAYMIRROR 0x40000
#define MA_TRANSPARENCY 0x10000
#define MA_RAYTRANSP 0x20000
#define MA_ZTRANSP 0x00040
struct Material : ElemBase { struct Material : ElemBase {
ID id FAIL; ID id FAIL;
@ -246,19 +260,103 @@ struct Material : ElemBase {
float ambr,ambg,ambb WARN; float ambr,ambg,ambb WARN;
float mirr,mirg,mirb; float mirr,mirg,mirb;
float emit WARN; float emit WARN;
float ray_mirror;
float alpha WARN; float alpha WARN;
float ref; float ref;
float translucency; float translucency;
int mode;
float roughness; float roughness;
float darkness; float darkness;
float refrac; float refrac;
boost::shared_ptr<Group> group; float amb;
float ang;
float spectra;
float spec;
float zoffs;
float add;
float fresnel_mir;
float fresnel_mir_i;
float fresnel_tra;
float fresnel_tra_i;
float filter;
float tx_limit;
float tx_falloff;
float gloss_mir;
float gloss_tra;
float adapt_thresh_mir;
float adapt_thresh_tra;
float aniso_gloss_mir;
float dist_mir;
float hasize;
float flaresize;
float subsize;
float flareboost;
float strand_sta;
float strand_end;
float strand_ease;
float strand_surfnor;
float strand_min;
float strand_widthfade;
float sbias;
float lbias;
float shad_alpha;
float param;
float rms;
float rampfac_col;
float rampfac_spec;
float friction;
float fh;
float reflect;
float fhdist;
float xyfrict;
float sss_radius;
float sss_col;
float sss_error;
float sss_scale;
float sss_ior;
float sss_colfac;
float sss_texfac;
float sss_front;
float sss_back;
short material_type;
short flag;
short ray_depth;
short ray_depth_tra;
short samp_gloss_mir;
short samp_gloss_tra;
short fadeto_mir;
short shade_flag;
short flarec;
short starc;
short linec;
short ringc;
short pr_lamp;
short pr_texture;
short ml_flag;
short texco;
short mapto;
short ramp_show;
short pad3;
short dynamode;
short pad2;
short sss_flag;
short sss_preset;
short shadowonly_flag;
short index;
short vcol_alpha;
short pad4;
char seed1;
char seed2;
std::shared_ptr<Group> group;
short diff_shader WARN; short diff_shader WARN;
short spec_shader WARN; short spec_shader WARN;
boost::shared_ptr<MTex> mtex[18]; std::shared_ptr<MTex> mtex[18];
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@ -289,7 +387,7 @@ struct Mesh : ElemBase {
vector<MDeformVert> dvert; vector<MDeformVert> dvert;
vector<MCol> mcol; vector<MCol> mcol;
vector< boost::shared_ptr<Material> > mat FAIL; vector< std::shared_ptr<Material> > mat FAIL;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@ -298,7 +396,7 @@ struct Library : ElemBase {
char name[240] WARN; char name[240] WARN;
char filename[240] FAIL; char filename[240] FAIL;
boost::shared_ptr<Library> parent WARN; std::shared_ptr<Library> parent WARN;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@ -310,18 +408,10 @@ struct Camera : ElemBase {
ID id FAIL; ID id FAIL;
// struct AnimData *adt;
Type type,flag WARN; Type type,flag WARN;
float angle WARN; float lens WARN;
//float passepartalpha, angle; float sensor_x WARN;
//float clipsta, clipend; float clipsta, clipend;
//float lens, ortho_scale, drawsize;
//float shiftx, shifty;
//float YF_dofdist, YF_aperture;
//short YF_bkhtype, YF_bkhbias;
//float YF_bkhrot;
}; };
@ -371,8 +461,8 @@ struct Lamp : ElemBase {
//short ray_samp, ray_sampy, ray_sampz; //short ray_samp, ray_sampy, ray_sampz;
//short ray_samp_type; //short ray_samp_type;
//short area_shape; short area_shape;
//float area_size, area_sizey, area_sizez; float area_size, area_sizey, area_sizez;
//float adapt_thresh; //float adapt_thresh;
//short ray_samp_method; //short ray_samp_method;
@ -446,8 +536,8 @@ struct ModifierData : ElemBase {
eModifierType_ShapeKey eModifierType_ShapeKey
}; };
boost::shared_ptr<ElemBase> next WARN; std::shared_ptr<ElemBase> next WARN;
boost::shared_ptr<ElemBase> prev WARN; std::shared_ptr<ElemBase> prev WARN;
int type, mode; int type, mode;
char name[32]; char name[32];
@ -491,7 +581,7 @@ struct MirrorModifierData : ElemBase {
short axis, flag; short axis, flag;
float tolerance; float tolerance;
boost::shared_ptr<Object> mirror_ob; std::shared_ptr<Object> mirror_ob;
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@ -519,34 +609,60 @@ struct Object : ElemBase {
char parsubstr[32] WARN; char parsubstr[32] WARN;
Object* parent WARN; Object* parent WARN;
boost::shared_ptr<Object> track WARN; std::shared_ptr<Object> track WARN;
boost::shared_ptr<Object> proxy,proxy_from,proxy_group WARN; std::shared_ptr<Object> proxy,proxy_from,proxy_group WARN;
boost::shared_ptr<Group> dup_group WARN; std::shared_ptr<Group> dup_group WARN;
boost::shared_ptr<ElemBase> data FAIL; std::shared_ptr<ElemBase> data FAIL;
ListBase modifiers; ListBase modifiers;
Object()
: ElemBase()
, type( Type_EMPTY )
, parent( nullptr )
, track()
, proxy()
, proxy_from()
, data() {
// empty
}
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Base : ElemBase { struct Base : ElemBase {
Base* prev WARN; Base* prev WARN;
boost::shared_ptr<Base> next WARN; std::shared_ptr<Base> next WARN;
boost::shared_ptr<Object> object WARN; std::shared_ptr<Object> object WARN;
Base()
: ElemBase()
, next()
, object() {
// empty
// empty
}
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Scene : ElemBase { struct Scene : ElemBase {
ID id FAIL; ID id FAIL;
boost::shared_ptr<Object> camera WARN; std::shared_ptr<Object> camera WARN;
boost::shared_ptr<World> world WARN; std::shared_ptr<World> world WARN;
boost::shared_ptr<Base> basact WARN; std::shared_ptr<Base> basact WARN;
ListBase base; ListBase base;
};
Scene()
: ElemBase()
, camera()
, world()
, basact() {
// empty
}
};
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct Image : ElemBase { struct Image : ElemBase {
@ -566,7 +682,7 @@ struct Image : ElemBase {
//unsigned int bindcode; //unsigned int bindcode;
//unsigned int *repbind; //unsigned int *repbind;
boost::shared_ptr<PackedFile> packedfile; std::shared_ptr<PackedFile> packedfile;
//struct PreviewImage * preview; //struct PreviewImage * preview;
float lastupdate; float lastupdate;
@ -574,6 +690,11 @@ struct Image : ElemBase {
short animspeed; short animspeed;
short gen_x, gen_y, gen_type; short gen_x, gen_y, gen_type;
Image()
: ElemBase() {
// empty
}
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@ -652,7 +773,7 @@ struct Tex : ElemBase {
//bNodeTree *nodetree; //bNodeTree *nodetree;
//Ipo *ipo; //Ipo *ipo;
boost::shared_ptr<Image> ima WARN; std::shared_ptr<Image> ima WARN;
//PluginTex *plugin; //PluginTex *plugin;
//ColorBand *coba; //ColorBand *coba;
//EnvMap *env; //EnvMap *env;
@ -661,6 +782,12 @@ struct Tex : ElemBase {
//VoxelData *vd; //VoxelData *vd;
//char use_nodes; //char use_nodes;
Tex()
: ElemBase() {
// empty
}
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@ -719,8 +846,8 @@ struct MTex : ElemBase {
MapType mapto; MapType mapto;
BlendType blendtype; BlendType blendtype;
boost::shared_ptr<Object> object; std::shared_ptr<Object> object;
boost::shared_ptr<Tex> tex; std::shared_ptr<Tex> tex;
char uvname[32]; char uvname[32];
Projection projx,projy,projz; Projection projx,projy,projz;
@ -749,9 +876,13 @@ struct MTex : ElemBase {
//float lifefac, sizefac, ivelfac, pvelfac; //float lifefac, sizefac, ivelfac, pvelfac;
//float shadowfac; //float shadowfac;
//float zenupfac, zendownfac, blendfac; //float zenupfac, zendownfac, blendfac;
MTex()
: ElemBase() {
// empty
}
}; };
}
}
} }
#endif #endif

View File

@ -2,7 +2,7 @@
Open Asset Import Library (ASSIMP) Open Asset Import Library (ASSIMP)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2010, ASSIMP Development Team Copyright (c) 2006-2016, ASSIMP Development Team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -44,9 +44,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef INCLUDED_AI_BLEND_SCENEGEN_H #ifndef INCLUDED_AI_BLEND_SCENEGEN_H
#define INCLUDED_AI_BLEND_SCENEGEN_H #define INCLUDED_AI_BLEND_SCENEGEN_H
namespace Assimp { #include "BlenderDNA.h"
namespace Blender { #include "BlenderScene.h"
namespace Assimp {
namespace Blender {
template <> void Structure :: Convert<Object> ( template <> void Structure :: Convert<Object> (
Object& dest, Object& dest,

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2013, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -42,7 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief A simple tessellation wrapper * @brief A simple tessellation wrapper
*/ */
#include "AssimpPCH.h"
#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
@ -51,6 +50,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "BlenderBMesh.h" #include "BlenderBMesh.h"
#include "BlenderTessellator.h" #include "BlenderTessellator.h"
#include <stddef.h>
static const unsigned int BLEND_TESS_MAGIC = 0x83ed9ac3; static const unsigned int BLEND_TESS_MAGIC = 0x83ed9ac3;
#if ASSIMP_BLEND_WITH_GLU_TESSELLATE #if ASSIMP_BLEND_WITH_GLU_TESSELLATE
@ -141,7 +142,7 @@ void BlenderTessellatorGL::TriangulateDrawCalls( const TessDataGL& tessData )
{ {
// NOTE - Because we are supplying a callback to GLU_TESS_EDGE_FLAG_DATA we don't technically // NOTE - Because we are supplying a callback to GLU_TESS_EDGE_FLAG_DATA we don't technically
// need support for GL_TRIANGLE_STRIP and GL_TRIANGLE_FAN but we'll keep it here in case // need support for GL_TRIANGLE_STRIP and GL_TRIANGLE_FAN but we'll keep it here in case
// GLU tessellate changes or tristrips and fans are wanted. // GLU tessellate changes or tri-strips and fans are wanted.
// See: http://www.opengl.org/sdk/docs/man2/xhtml/gluTessCallback.xml // See: http://www.opengl.org/sdk/docs/man2/xhtml/gluTessCallback.xml
for ( unsigned int i = 0; i < tessData.drawCalls.size( ); ++i ) for ( unsigned int i = 0; i < tessData.drawCalls.size( ); ++i )
{ {
@ -165,7 +166,7 @@ void BlenderTessellatorGL::TriangulateDrawCalls( const TessDataGL& tessData )
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::MakeFacesFromTris( const VertexGL* vertices, int vertexCount ) void BlenderTessellatorGL::MakeFacesFromTris( const VertexGL* vertices, int vertexCount )
{ {
int triangleCount = vertexCount / 3; const int triangleCount = vertexCount / 3;
for ( int i = 0; i < triangleCount; ++i ) for ( int i = 0; i < triangleCount; ++i )
{ {
int vertexBase = i * 3; int vertexBase = i * 3;
@ -176,7 +177,7 @@ void BlenderTessellatorGL::MakeFacesFromTris( const VertexGL* vertices, int vert
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::MakeFacesFromTriStrip( const VertexGL* vertices, int vertexCount ) void BlenderTessellatorGL::MakeFacesFromTriStrip( const VertexGL* vertices, int vertexCount )
{ {
int triangleCount = vertexCount - 2; const int triangleCount = vertexCount - 2;
for ( int i = 0; i < triangleCount; ++i ) for ( int i = 0; i < triangleCount; ++i )
{ {
int vertexBase = i; int vertexBase = i;
@ -187,7 +188,7 @@ void BlenderTessellatorGL::MakeFacesFromTriStrip( const VertexGL* vertices, int
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::MakeFacesFromTriFan( const VertexGL* vertices, int vertexCount ) void BlenderTessellatorGL::MakeFacesFromTriFan( const VertexGL* vertices, int vertexCount )
{ {
int triangleCount = vertexCount - 2; const int triangleCount = vertexCount - 2;
for ( int i = 0; i < triangleCount; ++i ) for ( int i = 0; i < triangleCount; ++i )
{ {
int vertexBase = i; int vertexBase = i;
@ -324,7 +325,7 @@ void BlenderTessellatorP2T::Copy3DVertices( const MLoop* polyLoop, int vertexCou
aiMatrix4x4 BlenderTessellatorP2T::GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const aiMatrix4x4 BlenderTessellatorP2T::GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const
{ {
aiVector3D sideA( 1.0f, 0.0f, 0.0f ); aiVector3D sideA( 1.0f, 0.0f, 0.0f );
if ( fabs( plane.normal * sideA ) > 0.999f ) if ( std::fabs( plane.normal * sideA ) > 0.999f )
{ {
sideA = aiVector3D( 0.0f, 1.0f, 0.0f ); sideA = aiVector3D( 0.0f, 1.0f, 0.0f );
} }
@ -354,7 +355,7 @@ aiMatrix4x4 BlenderTessellatorP2T::GeneratePointTransformMatrix( const Blender::
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const void BlenderTessellatorP2T::TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const
{ {
for ( unsigned int i = 0; i < vertices.size( ); ++i ) for ( size_t i = 0; i < vertices.size( ); ++i )
{ {
PointP2T& point = vertices[ i ]; PointP2T& point = vertices[ i ];
point.point3D = transform * point.point3D; point.point3D = transform * point.point3D;
@ -366,21 +367,16 @@ void BlenderTessellatorP2T::TransformAndFlattenVectices( const aiMatrix4x4& tran
void BlenderTessellatorP2T::ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const void BlenderTessellatorP2T::ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const
{ {
pointRefs.resize( points.size( ) ); pointRefs.resize( points.size( ) );
for ( unsigned int i = 0; i < points.size( ); ++i ) for ( size_t i = 0; i < points.size( ); ++i )
{ {
pointRefs[ i ] = &points[ i ].point2D; pointRefs[ i ] = &points[ i ].point2D;
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Yes this is filthy... but we have no choice
#define OffsetOf( Class, Member ) ( static_cast< unsigned int >( \
reinterpret_cast<uint8_t*>(&( reinterpret_cast< Class* >( NULL )->*( &Class::Member ) )) - \
static_cast<uint8_t*>(NULL) ) )
inline PointP2T& BlenderTessellatorP2T::GetActualPointStructure( p2t::Point& point ) const inline PointP2T& BlenderTessellatorP2T::GetActualPointStructure( p2t::Point& point ) const
{ {
unsigned int pointOffset = OffsetOf( PointP2T, point2D ); unsigned int pointOffset = offsetof( PointP2T, point2D );
PointP2T& pointStruct = *reinterpret_cast< PointP2T* >( reinterpret_cast< char* >( &point ) - pointOffset ); PointP2T& pointStruct = *reinterpret_cast< PointP2T* >( reinterpret_cast< char* >( &point ) - pointOffset );
if ( pointStruct.magic != static_cast<int>( BLEND_TESS_MAGIC ) ) if ( pointStruct.magic != static_cast<int>( BLEND_TESS_MAGIC ) )
{ {
@ -392,7 +388,7 @@ inline PointP2T& BlenderTessellatorP2T::GetActualPointStructure( p2t::Point& poi
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const void BlenderTessellatorP2T::MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const
{ {
for ( unsigned int i = 0; i < triangles.size( ); ++i ) for ( size_t i = 0; i < triangles.size( ); ++i )
{ {
p2t::Triangle& Triangle = *triangles[ i ]; p2t::Triangle& Triangle = *triangles[ i ];
@ -416,11 +412,11 @@ float BlenderTessellatorP2T::FindLargestMatrixElem( const aiMatrix3x3& mtx ) con
{ {
float result = 0.0f; float result = 0.0f;
for ( int x = 0; x < 3; ++x ) for ( unsigned int x = 0; x < 3; ++x )
{ {
for ( int y = 0; y < 3; ++y ) for ( unsigned int y = 0; y < 3; ++y )
{ {
result = p2tMax( fabs( mtx[ x ][ y ] ), result ); result = p2tMax( std::fabs( mtx[ x ][ y ] ), result );
} }
} }
@ -428,14 +424,14 @@ float BlenderTessellatorP2T::FindLargestMatrixElem( const aiMatrix3x3& mtx ) con
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Aparently Assimp doesn't have matrix scaling // Apparently Assimp doesn't have matrix scaling
aiMatrix3x3 BlenderTessellatorP2T::ScaleMatrix( const aiMatrix3x3& mtx, float scale ) const aiMatrix3x3 BlenderTessellatorP2T::ScaleMatrix( const aiMatrix3x3& mtx, float scale ) const
{ {
aiMatrix3x3 result; aiMatrix3x3 result;
for ( int x = 0; x < 3; ++x ) for ( unsigned int x = 0; x < 3; ++x )
{ {
for ( int y = 0; y < 3; ++y ) for ( unsigned int y = 0; y < 3; ++y )
{ {
result[ x ][ y ] = mtx[ x ][ y ] * scale; result[ x ][ y ] = mtx[ x ][ y ] * scale;
} }
@ -449,7 +445,7 @@ aiMatrix3x3 BlenderTessellatorP2T::ScaleMatrix( const aiMatrix3x3& mtx, float sc
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html // Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
aiVector3D BlenderTessellatorP2T::GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const aiVector3D BlenderTessellatorP2T::GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const
{ {
float scale = FindLargestMatrixElem( mtx ); const float scale = FindLargestMatrixElem( mtx );
aiMatrix3x3 mc = ScaleMatrix( mtx, 1.0f / scale ); aiMatrix3x3 mc = ScaleMatrix( mtx, 1.0f / scale );
mc = mc * mc * mc; mc = mc * mc * mc;
@ -474,20 +470,20 @@ PlaneP2T BlenderTessellatorP2T::FindLLSQPlane( const std::vector< PointP2T >& po
{ {
PlaneP2T result; PlaneP2T result;
aiVector3D sum( 0.0f ); aiVector3D sum( 0.0 );
for ( unsigned int i = 0; i < points.size( ); ++i ) for ( size_t i = 0; i < points.size( ); ++i )
{ {
sum += points[ i ].point3D; sum += points[ i ].point3D;
} }
result.centre = sum * ( 1.0f / points.size( ) ); result.centre = sum * (ai_real)( 1.0 / points.size( ) );
float sumXX = 0.0f; ai_real sumXX = 0.0;
float sumXY = 0.0f; ai_real sumXY = 0.0;
float sumXZ = 0.0f; ai_real sumXZ = 0.0;
float sumYY = 0.0f; ai_real sumYY = 0.0;
float sumYZ = 0.0f; ai_real sumYZ = 0.0;
float sumZZ = 0.0f; ai_real sumZZ = 0.0;
for ( unsigned int i = 0; i < points.size( ); ++i ) for ( size_t i = 0; i < points.size( ); ++i )
{ {
aiVector3D offset = points[ i ].point3D - result.centre; aiVector3D offset = points[ i ].point3D - result.centre;
sumXX += offset.x * offset.x; sumXX += offset.x * offset.x;
@ -500,7 +496,7 @@ PlaneP2T BlenderTessellatorP2T::FindLLSQPlane( const std::vector< PointP2T >& po
aiMatrix3x3 mtx( sumXX, sumXY, sumXZ, sumXY, sumYY, sumYZ, sumXZ, sumYZ, sumZZ ); aiMatrix3x3 mtx( sumXX, sumXY, sumXZ, sumXY, sumYY, sumYZ, sumXZ, sumYZ, sumZZ );
float det = mtx.Determinant( ); const ai_real det = mtx.Determinant( );
if ( det == 0.0f ) if ( det == 0.0f )
{ {
result.normal = aiVector3D( 0.0f ); result.normal = aiVector3D( 0.0f );

View File

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

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2012, assimp team Copyright (c) 2006-2016, assimp team
All rights reserved. All rights reserved.
@ -45,6 +45,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_BLOBIOSYSTEM_H_INCLUDED #ifndef AI_BLOBIOSYSTEM_H_INCLUDED
#define AI_BLOBIOSYSTEM_H_INCLUDED #define AI_BLOBIOSYSTEM_H_INCLUDED
#include "./../include/assimp/IOStream.hpp"
#include "./../include/assimp/cexport.h"
#include "./../include/assimp/IOSystem.hpp"
#include "./../include/assimp/DefaultLogger.hpp"
#include <stdint.h>
#include <set>
#include <vector>
namespace Assimp { namespace Assimp {
class BlobIOSystem; class BlobIOSystem;
@ -120,9 +128,11 @@ public:
{ {
case aiOrigin_CUR: case aiOrigin_CUR:
cursor += pOffset; cursor += pOffset;
break;
case aiOrigin_END: case aiOrigin_END:
cursor = file_size - pOffset; cursor = file_size - pOffset;
break;
case aiOrigin_SET: case aiOrigin_SET:
cursor = pOffset; cursor = pOffset;
@ -213,7 +223,7 @@ public:
virtual ~BlobIOSystem() virtual ~BlobIOSystem()
{ {
BOOST_FOREACH(BlobEntry& blobby, blobs) { for(BlobEntry& blobby : blobs) {
delete blobby.second; delete blobby.second;
} }
} }
@ -232,7 +242,7 @@ public:
{ {
// one must be the master // one must be the master
aiExportDataBlob* master = NULL, *cur; aiExportDataBlob* master = NULL, *cur;
BOOST_FOREACH(const BlobEntry& blobby, blobs) { for(const BlobEntry& blobby : blobs) {
if (blobby.first == AI_BLOBIO_MAGIC) { if (blobby.first == AI_BLOBIO_MAGIC) {
master = blobby.second; master = blobby.second;
break; break;
@ -246,7 +256,7 @@ public:
master->name.Set(""); master->name.Set("");
cur = master; cur = master;
BOOST_FOREACH(const BlobEntry& blobby, blobs) { for(const BlobEntry& blobby : blobs) {
if (blobby.second == master) { if (blobby.second == master) {
continue; continue;
} }

View File

@ -1,23 +0,0 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View File

@ -1,99 +0,0 @@
#ifndef BOOST_FOREACH
///////////////////////////////////////////////////////////////////////////////
// A stripped down version of FOREACH for
// illustration purposes. NOT FOR GENERAL USE.
// For a complete implementation, see BOOST_FOREACH at
// http://boost-sandbox.sourceforge.net/vault/index.php?directory=eric_niebler
//
// Copyright 2004 Eric Niebler.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Adapted to Assimp November 29th, 2008 (Alexander Gessler).
// Added code to handle both const and non-const iterators, simplified some
// parts.
///////////////////////////////////////////////////////////////////////////////
namespace boost {
namespace foreach_detail {
///////////////////////////////////////////////////////////////////////////////
// auto_any
struct auto_any_base
{
operator bool() const { return false; }
};
template<typename T>
struct auto_any : auto_any_base
{
auto_any(T const& t) : item(t) {}
mutable T item;
};
template<typename T>
T& auto_any_cast(auto_any_base const& any)
{
return static_cast<auto_any<T> const&>(any).item;
}
///////////////////////////////////////////////////////////////////////////////
// FOREACH helper function
template<typename T>
auto_any<typename T::const_iterator> begin(T const& t)
{
return t.begin();
}
template<typename T>
auto_any<typename T::const_iterator> end(T const& t)
{
return t.end();
}
// iterator
template<typename T>
bool done(auto_any_base const& cur, auto_any_base const& end, T&)
{
typedef typename T::iterator iter_type;
return auto_any_cast<iter_type>(cur) == auto_any_cast<iter_type>(end);
}
template<typename T>
void next(auto_any_base const& cur, T&)
{
++auto_any_cast<typename T::iterator>(cur);
}
template<typename T>
typename T::reference deref(auto_any_base const& cur, T&)
{
return *auto_any_cast<typename T::iterator>(cur);
}
template<typename T>
typename T::const_reference deref(auto_any_base const& cur, const T&)
{
return *auto_any_cast<typename T::iterator>(cur);
}
} // end foreach_detail
///////////////////////////////////////////////////////////////////////////////
// FOREACH
#define BOOST_FOREACH(item, container) \
if(boost::foreach_detail::auto_any_base const& foreach_magic_b = boost::foreach_detail::begin(container)) {} else \
if(boost::foreach_detail::auto_any_base const& foreach_magic_e = boost::foreach_detail::end(container)) {} else \
for(;!boost::foreach_detail::done(foreach_magic_b,foreach_magic_e,container); boost::foreach_detail::next(foreach_magic_b,container)) \
if (bool ugly_and_unique_break = false) {} else \
for(item = boost::foreach_detail::deref(foreach_magic_b,container); !ugly_and_unique_break; ugly_and_unique_break = true)
} // end boost
#endif

View File

@ -1,81 +0,0 @@
/* DEPRECATED! - use code/TinyFormatter.h instead.
*
*
* */
#ifndef AI_BOOST_FORMAT_DUMMY_INCLUDED
#define AI_BOOST_FORMAT_DUMMY_INCLUDED
#if (!defined BOOST_FORMAT_HPP) || (defined ASSIMP_FORCE_NOBOOST)
#include <string>
#include <vector>
namespace boost
{
class format
{
public:
format (const std::string& _d)
: d(_d)
{
}
template <typename T>
format& operator % (T in)
{
// XXX add replacement for boost::lexical_cast?
std::ostringstream ss;
ss << in; // note: ss cannot be an rvalue, or the global operator << (const char*) is not called for T == const char*.
chunks.push_back( ss.str());
return *this;
}
operator std::string () const {
std::string res; // pray for NRVO to kick in
size_t start = 0, last = 0;
std::vector<std::string>::const_iterator chunkin = chunks.begin();
for ( start = d.find('%');start != std::string::npos; start = d.find('%',last)) {
res += d.substr(last,start-last);
last = start+2;
if (d[start+1] == '%') {
res += "%";
continue;
}
if (chunkin == chunks.end()) {
break;
}
res += *chunkin++;
}
res += d.substr(last);
return res;
}
private:
std::string d;
std::vector<std::string> chunks;
};
inline std::string str(const std::string& s) {
return s;
}
}
#else
# error "format.h was already included"
#endif //
#endif // !! AI_BOOST_FORMAT_DUMMY_INCLUDED

View File

@ -1,26 +0,0 @@
/// A quick replacement for boost::lexical_cast for all the Boost haters out there
#ifndef __AI_BOOST_WORKAROUND_LEXICAL_CAST
#define __AI_BOOST_WORKAROUND_LEXICAL_CAST
#include <sstream>
namespace boost
{
/// A quick replacement for boost::lexical_cast - should work for all types a stringstream can handle
template <typename TargetType, typename SourceType>
TargetType lexical_cast( const SourceType& source)
{
std::stringstream stream;
TargetType result;
stream << source;
stream >> result;
return result;
}
} // namespace boost
#endif // __AI_BOOST_WORKAROUND_LEXICAL_CAST

View File

@ -1,57 +0,0 @@
// please note that this replacement implementation does not
// provide the performance benefit of the original, which
// makes only one allocation as opposed to two allocations
// (smart pointer counter and payload) which are usually
// required if object and smart pointer are constructed
// independently.
#ifndef INCLUDED_AI_BOOST_MAKE_SHARED
#define INCLUDED_AI_BOOST_MAKE_SHARED
namespace boost {
template <typename T>
shared_ptr<T> make_shared() {
return shared_ptr<T>(new T());
}
template <typename T, typename T0>
shared_ptr<T> make_shared(const T0& t0) {
return shared_ptr<T>(new T(t0));
}
template <typename T, typename T0,typename T1>
shared_ptr<T> make_shared(const T0& t0, const T1& t1) {
return shared_ptr<T>(new T(t0,t1));
}
template <typename T, typename T0,typename T1,typename T2>
shared_ptr<T> make_shared(const T0& t0, const T1& t1, const T2& t2) {
return shared_ptr<T>(new T(t0,t1,t2));
}
template <typename T, typename T0,typename T1,typename T2,typename T3>
shared_ptr<T> make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3) {
return shared_ptr<T>(new T(t0,t1,t2,t3));
}
template <typename T, typename T0,typename T1,typename T2,typename T3, typename T4>
shared_ptr<T> make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4) {
return shared_ptr<T>(new T(t0,t1,t2,t3,t4));
}
template <typename T, typename T0,typename T1,typename T2,typename T3, typename T4, typename T5>
shared_ptr<T> make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5) {
return shared_ptr<T>(new T(t0,t1,t2,t3,t4,t5));
}
template <typename T, typename T0,typename T1,typename T2,typename T3, typename T4, typename T5, typename T6>
shared_ptr<T> make_shared(const T0& t0, const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5, const T6& t6) {
return shared_ptr<T>(new T(t0,t1,t2,t3,t4,t5,t6));
}
}
#endif

View File

@ -1,37 +0,0 @@
#ifndef BOOST_MATH_COMMON_FACTOR_RT_HPP
#define BOOST_MATH_COMMON_FACTOR_RT_HPP
namespace boost {
namespace math {
// TODO: use binary GCD for unsigned integers ....
template < typename IntegerType >
IntegerType gcd( IntegerType a, IntegerType b )
{
const IntegerType zero = (IntegerType)0;
while ( true )
{
if ( a == zero )
return b;
b %= a;
if ( b == zero )
return a;
a %= b;
}
}
template < typename IntegerType >
IntegerType lcm( IntegerType a, IntegerType b )
{
const IntegerType t = gcd (a,b);
if (!t)return t;
return a / t * b;
}
}}
#endif

View File

@ -1,36 +0,0 @@
// Boost noncopyable.hpp header file --------------------------------------//
// (C) Copyright Beman Dawes 1999-2003. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/utility for documentation.
#ifndef BOOST_NONCOPYABLE_HPP_INCLUDED
#define BOOST_NONCOPYABLE_HPP_INCLUDED
namespace boost {
// Private copy constructor and copy assignment ensure classes derived from
// class noncopyable cannot be copied.
// Contributed by Dave Abrahams
namespace noncopyable_ // protection from unintended ADL
{
class noncopyable
{
protected:
noncopyable() {}
~noncopyable() {}
private: // emphasize the following members are private
noncopyable( const noncopyable& );
const noncopyable& operator=( const noncopyable& );
};
}
typedef noncopyable_::noncopyable noncopyable;
} // namespace boost
#endif // BOOST_NONCOPYABLE_HPP_INCLUDED

View File

@ -1,45 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_POINTER_CAST_HPP
#define BOOST_POINTER_CAST_HPP
namespace boost {
//static_pointer_cast overload for raw pointers
template<class T, class U>
inline T* static_pointer_cast(U *ptr)
{
return static_cast<T*>(ptr);
}
//dynamic_pointer_cast overload for raw pointers
template<class T, class U>
inline T* dynamic_pointer_cast(U *ptr)
{
return dynamic_cast<T*>(ptr);
}
//const_pointer_cast overload for raw pointers
template<class T, class U>
inline T* const_pointer_cast(U *ptr)
{
return const_cast<T*>(ptr);
}
//reinterpret_pointer_cast overload for raw pointers
template<class T, class U>
inline T* reinterpret_pointer_cast(U *ptr)
{
return reinterpret_cast<T*>(ptr);
}
} // namespace boost
#endif //BOOST_POINTER_CAST_HPP

View File

@ -1,79 +0,0 @@
#ifndef __AI_BOOST_SCOPED_ARRAY_INCLUDED
#define __AI_BOOST_SCOPED_ARRAY_INCLUDED
#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED
namespace boost {
// small replacement for boost::scoped_array
template <class T>
class scoped_array
{
public:
// provide a default construtctor
scoped_array()
: ptr(0)
{
}
// construction from an existing heap object of type T
scoped_array(T* _ptr)
: ptr(_ptr)
{
}
// automatic destruction of the wrapped object at the
// end of our lifetime
~scoped_array()
{
delete[] ptr;
}
inline T* get()
{
return ptr;
}
inline T* operator-> ()
{
return ptr;
}
inline void reset (T* t = 0)
{
delete[] ptr;
ptr = t;
}
T & operator[](std::ptrdiff_t i) const
{
return ptr[i];
}
void swap(scoped_array & b)
{
std::swap(ptr, b.ptr);
}
private:
// encapsulated object pointer
T* ptr;
};
template<class T>
inline void swap(scoped_array<T> & a, scoped_array<T> & b)
{
a.swap(b);
}
} // end of namespace boost
#else
# error "scoped_array.h was already included"
#endif
#endif // __AI_BOOST_SCOPED_ARRAY_INCLUDED

View File

@ -1,79 +0,0 @@
#ifndef __AI_BOOST_SCOPED_PTR_INCLUDED
#define __AI_BOOST_SCOPED_PTR_INCLUDED
#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED
namespace boost {
// small replacement for boost::scoped_ptr
template <class T>
class scoped_ptr
{
public:
// provide a default construtctor
scoped_ptr()
: ptr(0)
{
}
// construction from an existing heap object of type T
scoped_ptr(T* _ptr)
: ptr(_ptr)
{
}
// automatic destruction of the wrapped object at the
// end of our lifetime
~scoped_ptr()
{
delete ptr;
}
inline T* get() const
{
return ptr;
}
inline operator T*()
{
return ptr;
}
inline T* operator-> ()
{
return ptr;
}
inline void reset (T* t = 0)
{
delete ptr;
ptr = t;
}
void swap(scoped_ptr & b)
{
std::swap(ptr, b.ptr);
}
private:
// encapsulated object pointer
T* ptr;
};
template<class T>
inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b)
{
a.swap(b);
}
} // end of namespace boost
#else
# error "scoped_ptr.h was already included"
#endif
#endif // __AI_BOOST_SCOPED_PTR_INCLUDED

View File

@ -1,228 +0,0 @@
#ifndef INCLUDED_AI_BOOST_SHARED_ARRAY
#define INCLUDED_AI_BOOST_SHARED_ARRAY
#ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED
// ------------------------------
// Internal stub
namespace boost {
namespace array_detail {
class controller {
public:
controller()
: cnt(1)
{}
public:
template <typename T>
controller* decref(T* pt) {
if (--cnt <= 0) {
delete this;
delete[] pt;
}
return NULL;
}
controller* incref() {
++cnt;
return this;
}
long get() const {
return cnt;
}
private:
long cnt;
};
struct empty {};
template <typename DEST, typename SRC>
struct is_convertible_stub {
struct yes {char s[1];};
struct no {char s[2];};
static yes foo(DEST*);
static no foo(...);
enum {result = (sizeof(foo((SRC*)0)) == sizeof(yes) ? 1 : 0)};
};
template <bool> struct enable_if {};
template <> struct enable_if<true> {
typedef empty result;
};
template <typename DEST, typename SRC>
struct is_convertible : public enable_if<is_convertible_stub<DEST,SRC>::result > {
};
}
// ------------------------------
// Small replacement for boost::shared_array, not threadsafe because no
// atomic reference counter is in use.
// ------------------------------
template <class T>
class shared_array
{
template <typename TT> friend class shared_array;
template<class TT> friend bool operator== (const shared_array<TT>& a, const shared_array<TT>& b);
template<class TT> friend bool operator!= (const shared_array<TT>& a, const shared_array<TT>& b);
template<class TT> friend bool operator< (const shared_array<TT>& a, const shared_array<TT>& b);
public:
typedef T element_type;
public:
// provide a default constructor
shared_array()
: ptr()
, ctr(NULL)
{
}
// construction from an existing object of type T
explicit shared_array(T* ptr)
: ptr(ptr)
, ctr(ptr ? new array_detail::controller() : NULL)
{
}
shared_array(const shared_array& r)
: ptr(r.ptr)
, ctr(r.ctr ? r.ctr->incref() : NULL)
{
}
template <typename Y>
shared_array(const shared_array<Y>& r,typename detail::is_convertible<T,Y>::result = detail::empty())
: ptr(r.ptr)
, ctr(r.ctr ? r.ctr->incref() : NULL)
{
}
// automatic destruction of the wrapped object when all
// references are freed.
~shared_array() {
if (ctr) {
ctr = ctr->decref(ptr);
}
}
shared_array& operator=(const shared_array& r) {
if (this == &r) {
return *this;
}
if (ctr) {
ctr->decref(ptr);
}
ptr = r.ptr;
ctr = ptr?r.ctr->incref():NULL;
return *this;
}
template <typename Y>
shared_array& operator=(const shared_array<Y>& r) {
if (this == &r) {
return *this;
}
if (ctr) {
ctr->decref(ptr);
}
ptr = r.ptr;
ctr = ptr?r.ctr->incref():NULL;
return *this;
}
// pointer access
inline operator T*() {
return ptr;
}
inline T* operator-> () const {
return ptr;
}
// standard semantics
inline T* get() {
return ptr;
}
T& operator[] (std::ptrdiff_t index) const {
return ptr[index];
}
inline const T* get() const {
return ptr;
}
inline operator bool () const {
return ptr != NULL;
}
inline bool unique() const {
return use_count() == 1;
}
inline long use_count() const {
return ctr->get();
}
inline void reset (T* t = 0) {
if (ctr) {
ctr->decref(ptr);
}
ptr = t;
ctr = ptr?new array_detail::controller():NULL;
}
void swap(shared_array & b) {
std::swap(ptr, b.ptr);
std::swap(ctr, b.ctr);
}
private:
// encapsulated object pointer
T* ptr;
// control block
array_detail::controller* ctr;
};
template<class T>
inline void swap(shared_array<T> & a, shared_array<T> & b)
{
a.swap(b);
}
template<class T>
bool operator== (const shared_array<T>& a, const shared_array<T>& b) {
return a.ptr == b.ptr;
}
template<class T>
bool operator!= (const shared_array<T>& a, const shared_array<T>& b) {
return a.ptr != b.ptr;
}
template<class T>
bool operator< (const shared_array<T>& a, const shared_array<T>& b) {
return a.ptr < b.ptr;
}
} // end of namespace boost
#else
# error "shared_array.h was already included"
#endif
#endif // INCLUDED_AI_BOOST_SHARED_ARRAY

View File

@ -1,257 +0,0 @@
#ifndef INCLUDED_AI_BOOST_SHARED_PTR
#define INCLUDED_AI_BOOST_SHARED_PTR
#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
// ------------------------------
// Internal stub
namespace boost {
namespace detail {
class controller {
public:
controller()
: cnt(1)
{}
public:
template <typename T>
controller* decref(T* pt) {
if (--cnt <= 0) {
delete this;
delete pt;
}
return NULL;
}
controller* incref() {
++cnt;
return this;
}
long get() const {
return cnt;
}
private:
long cnt;
};
struct empty {};
template <typename DEST, typename SRC>
struct is_convertible_stub {
struct yes {char s[1];};
struct no {char s[2];};
static yes foo(DEST*);
static no foo(...);
enum {result = (sizeof(foo((SRC*)0)) == sizeof(yes) ? 1 : 0)};
};
template <bool> struct enable_if {};
template <> struct enable_if<true> {
typedef empty result;
};
template <typename DEST, typename SRC>
struct is_convertible : public enable_if<is_convertible_stub<DEST,SRC>::result > {
};
}
// ------------------------------
// Small replacement for boost::shared_ptr, not threadsafe because no
// atomic reference counter is in use.
// ------------------------------
template <class T>
class shared_ptr
{
template <typename TT> friend class shared_ptr;
template<class TT, class U> friend shared_ptr<TT> static_pointer_cast (shared_ptr<U> ptr);
template<class TT, class U> friend shared_ptr<TT> dynamic_pointer_cast (shared_ptr<U> ptr);
template<class TT, class U> friend shared_ptr<TT> const_pointer_cast (shared_ptr<U> ptr);
template<class TT> friend bool operator== (const shared_ptr<TT>& a, const shared_ptr<TT>& b);
template<class TT> friend bool operator!= (const shared_ptr<TT>& a, const shared_ptr<TT>& b);
template<class TT> friend bool operator< (const shared_ptr<TT>& a, const shared_ptr<TT>& b);
public:
typedef T element_type;
public:
// provide a default constructor
shared_ptr()
: ptr()
, ctr(NULL)
{
}
// construction from an existing object of type T
explicit shared_ptr(T* ptr)
: ptr(ptr)
, ctr(ptr ? new detail::controller() : NULL)
{
}
shared_ptr(const shared_ptr& r)
: ptr(r.ptr)
, ctr(r.ctr ? r.ctr->incref() : NULL)
{
}
template <typename Y>
shared_ptr(const shared_ptr<Y>& r,typename detail::is_convertible<T,Y>::result = detail::empty())
: ptr(r.ptr)
, ctr(r.ctr ? r.ctr->incref() : NULL)
{
}
// automatic destruction of the wrapped object when all
// references are freed.
~shared_ptr() {
if (ctr) {
ctr = ctr->decref(ptr);
}
}
shared_ptr& operator=(const shared_ptr& r) {
if (this == &r) {
return *this;
}
if (ctr) {
ctr->decref(ptr);
}
ptr = r.ptr;
ctr = ptr?r.ctr->incref():NULL;
return *this;
}
template <typename Y>
shared_ptr& operator=(const shared_ptr<Y>& r) {
if (this == &r) {
return *this;
}
if (ctr) {
ctr->decref(ptr);
}
ptr = r.ptr;
ctr = ptr?r.ctr->incref():NULL;
return *this;
}
// pointer access
inline operator T*() const {
return ptr;
}
inline T* operator-> () const {
return ptr;
}
// standard semantics
inline T* get() {
return ptr;
}
inline const T* get() const {
return ptr;
}
inline operator bool () const {
return ptr != NULL;
}
inline bool unique() const {
return use_count() == 1;
}
inline long use_count() const {
return ctr->get();
}
inline void reset (T* t = 0) {
if (ctr) {
ctr->decref(ptr);
}
ptr = t;
ctr = ptr?new detail::controller():NULL;
}
void swap(shared_ptr & b) {
std::swap(ptr, b.ptr);
std::swap(ctr, b.ctr);
}
private:
// for use by the various xxx_pointer_cast helper templates
explicit shared_ptr(T* ptr, detail::controller* ctr)
: ptr(ptr)
, ctr(ctr->incref())
{
}
private:
// encapsulated object pointer
T* ptr;
// control block
detail::controller* ctr;
};
template<class T>
inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
{
a.swap(b);
}
template<class T>
bool operator== (const shared_ptr<T>& a, const shared_ptr<T>& b) {
return a.ptr == b.ptr;
}
template<class T>
bool operator!= (const shared_ptr<T>& a, const shared_ptr<T>& b) {
return a.ptr != b.ptr;
}
template<class T>
bool operator< (const shared_ptr<T>& a, const shared_ptr<T>& b) {
return a.ptr < b.ptr;
}
template<class T, class U>
inline shared_ptr<T> static_pointer_cast( shared_ptr<U> ptr)
{
return shared_ptr<T>(static_cast<T*>(ptr.ptr),ptr.ctr);
}
template<class T, class U>
inline shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> ptr)
{
return shared_ptr<T>(dynamic_cast<T*>(ptr.ptr),ptr.ctr);
}
template<class T, class U>
inline shared_ptr<T> const_pointer_cast( shared_ptr<U> ptr)
{
return shared_ptr<T>(const_cast<T*>(ptr.ptr),ptr.ctr);
}
} // end of namespace boost
#else
# error "shared_ptr.h was already included"
#endif
#endif // INCLUDED_AI_BOOST_SHARED_PTR

View File

@ -1,20 +0,0 @@
#ifndef AI_BOOST_STATIC_ASSERT_INCLUDED
#define AI_BOOST_STATIC_ASSERT_INCLUDED
#ifndef BOOST_STATIC_ASSERT
namespace boost {
namespace detail {
template <bool b> class static_assertion_failure;
template <> class static_assertion_failure<true> {};
}
}
#define BOOST_STATIC_ASSERT(eval) \
{boost::detail::static_assertion_failure<(eval)> assert_dummy;(void)assert_dummy;}
#endif
#endif // !! AI_BOOST_STATIC_ASSERT_INCLUDED

View File

@ -1,72 +0,0 @@
// boost timer.hpp header file ---------------------------------------------//
// Copyright Beman Dawes 1994-99. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/timer for documentation.
// Revision History
// 01 Apr 01 Modified to use new <boost/limits.hpp> header. (JMaddock)
// 12 Jan 01 Change to inline implementation to allow use without library
// builds. See docs for more rationale. (Beman Dawes)
// 25 Sep 99 elapsed_max() and elapsed_min() added (John Maddock)
// 16 Jul 99 Second beta
// 6 Jul 99 Initial boost version
#ifndef BOOST_TIMER_HPP
#define BOOST_TIMER_HPP
//#include <boost/config.hpp>
#include <ctime>
//#include <boost/limits.hpp>
# ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::clock_t; using ::clock; }
# endif
namespace boost {
// timer -------------------------------------------------------------------//
// A timer object measures elapsed time.
// It is recommended that implementations measure wall clock rather than CPU
// time since the intended use is performance measurement on systems where
// total elapsed time is more important than just process or CPU time.
// Warnings: The maximum measurable elapsed time may well be only 596.5+ hours
// due to implementation limitations. The accuracy of timings depends on the
// accuracy of timing information provided by the underlying platform, and
// this varies a great deal from platform to platform.
class timer
{
public:
timer() { _start_time = std::clock(); } // postcondition: elapsed()==0
// timer( const timer& src ); // post: elapsed()==src.elapsed()
// ~timer(){}
// timer& operator=( const timer& src ); // post: elapsed()==src.elapsed()
void restart() { _start_time = std::clock(); } // post: elapsed()==0
double elapsed() const // return elapsed time in seconds
{ return double(std::clock() - _start_time) / CLOCKS_PER_SEC; }
double elapsed_max() const // return estimated maximum value for elapsed()
// Portability warning: elapsed_max() may return too high a value on systems
// where std::clock_t overflows or resets at surprising values.
{
return (double((std::numeric_limits<std::clock_t>::max)())
- double(_start_time)) / double(CLOCKS_PER_SEC);
}
double elapsed_min() const // return minimum value for elapsed()
{ return double(1)/double(CLOCKS_PER_SEC); }
private:
std::clock_t _start_time;
}; // timer
} // namespace boost
#endif // BOOST_TIMER_HPP

View File

@ -1,283 +0,0 @@
// A very small replacement for boost::tuple
// (c) Alexander Gessler, 2008 [alexander.gessler@gmx.net]
#ifndef BOOST_TUPLE_INCLUDED
#define BOOST_TUPLE_INCLUDED
namespace boost {
namespace detail {
// Represents an empty tuple slot (up to 5 supported)
struct nulltype {};
// For readable error messages
struct tuple_component_idx_out_of_bounds;
// To share some code for the const/nonconst versions of the getters
template <bool b, typename T>
struct ConstIf {
typedef T t;
};
template <typename T>
struct ConstIf<true,T> {
typedef const T t;
};
// Predeclare some stuff
template <typename, unsigned, typename, bool, unsigned> struct value_getter;
// Helper to obtain the type of a tuple element
template <typename T, unsigned NIDX, typename TNEXT, unsigned N /*= 0*/>
struct type_getter {
typedef type_getter<typename TNEXT::type,NIDX+1,typename TNEXT::next_type,N> next_elem_getter;
typedef typename next_elem_getter::type type;
};
template <typename T, unsigned NIDX, typename TNEXT >
struct type_getter <T,NIDX,TNEXT,NIDX> {
typedef T type;
};
// Base class for all explicit specializations of list_elem
template <typename T, unsigned NIDX, typename TNEXT >
struct list_elem_base {
// Store template parameters
typedef TNEXT next_type;
typedef T type;
static const unsigned nidx = NIDX;
};
// Represents an element in the tuple component list
template <typename T, unsigned NIDX, typename TNEXT >
struct list_elem : list_elem_base<T,NIDX,TNEXT>{
// Real members
T me;
TNEXT next;
// Get the value of a specific tuple element
template <unsigned N>
typename type_getter<T,NIDX,TNEXT,N>::type& get () {
value_getter <T,NIDX,TNEXT,false,N> s;
return s(*this);
}
// Get the value of a specific tuple element
template <unsigned N>
const typename type_getter<T,NIDX,TNEXT,N>::type& get () const {
value_getter <T,NIDX,TNEXT,true,N> s;
return s(*this);
}
// Explicit cast
template <typename T2, typename TNEXT2 >
operator list_elem<T2,NIDX,TNEXT2> () const {
list_elem<T2,NIDX,TNEXT2> ret;
ret.me = (T2)me;
ret.next = next;
return ret;
}
// Recursively compare two elements (last element returns always true)
bool operator == (const list_elem& s) const {
return (me == s.me && next == s.next);
}
};
// Represents a non-used tuple element - the very last element processed
template <typename TNEXT, unsigned NIDX >
struct list_elem<nulltype,NIDX,TNEXT> : list_elem_base<nulltype,NIDX,TNEXT> {
template <unsigned N, bool IS_CONST = true> struct value_getter {
/* just dummy members to produce readable error messages */
tuple_component_idx_out_of_bounds operator () (typename ConstIf<IS_CONST,list_elem>::t& me);
};
template <unsigned N> struct type_getter {
/* just dummy members to produce readable error messages */
typedef tuple_component_idx_out_of_bounds type;
};
// dummy
list_elem& operator = (const list_elem& /*other*/) {
return *this;
}
// dummy
bool operator == (const list_elem& other) {
return true;
}
};
// Represents the absolute end of the list
typedef list_elem<nulltype,0,int> list_end;
// Helper obtain to query the value of a tuple element
// NOTE: This can't be a nested class as the compiler won't accept a full or
// partial specialization of a nested class of a non-specialized template
template <typename T, unsigned NIDX, typename TNEXT, bool IS_CONST, unsigned N>
struct value_getter {
// calling list_elem
typedef list_elem<T,NIDX,TNEXT> outer_elem;
// typedef for the getter for next element
typedef value_getter<typename TNEXT::type,NIDX+1,typename TNEXT::next_type,
IS_CONST, N> next_value_getter;
typename ConstIf<IS_CONST,typename type_getter<T,NIDX,TNEXT,N>::type>::t&
operator () (typename ConstIf<IS_CONST,outer_elem >::t& me) {
next_value_getter s;
return s(me.next);
}
};
template <typename T, unsigned NIDX, typename TNEXT, bool IS_CONST>
struct value_getter <T,NIDX,TNEXT,IS_CONST,NIDX> {
typedef list_elem<T,NIDX,TNEXT> outer_elem;
typename ConstIf<IS_CONST,T>::t& operator () (typename ConstIf<IS_CONST,outer_elem >::t& me) {
return me.me;
}
};
}
// A very minimal implementation for up to 5 elements
template <typename T0 = detail::nulltype,
typename T1 = detail::nulltype,
typename T2 = detail::nulltype,
typename T3 = detail::nulltype,
typename T4 = detail::nulltype>
class tuple {
template <typename T0b,
typename T1b,
typename T2b,
typename T3b,
typename T4b >
friend class tuple;
private:
typedef detail::list_elem<T0,0,
detail::list_elem<T1,1,
detail::list_elem<T2,2,
detail::list_elem<T3,3,
detail::list_elem<T4,4,
detail::list_end > > > > > very_long;
very_long m;
public:
// Get a specific tuple element
template <unsigned N>
typename detail::type_getter<T0,0,typename very_long::next_type, N>::type& get () {
return m.template get<N>();
}
// ... and the const version
template <unsigned N>
const typename detail::type_getter<T0,0,typename very_long::next_type, N>::type& get () const {
return m.template get<N>();
}
// comparison operators
bool operator== (const tuple& other) const {
return m == other.m;
}
// ... and the other way round
bool operator!= (const tuple& other) const {
return !(m == other.m);
}
// cast to another tuple - all single elements must be convertible
template <typename T0b, typename T1b,typename T2b,typename T3b, typename T4b>
operator tuple <T0b,T1b,T2b,T3b,T4b> () const {
tuple <T0b,T1b,T2b,T3b,T4b> s;
s.m = (typename tuple <T0b,T1b,T2b,T3b,T4b>::very_long)m;
return s;
}
};
// Another way to access an element ...
template <unsigned N,typename T0,typename T1,typename T2,typename T3,typename T4>
inline typename tuple<T0,T1,T2,T3,T4>::very_long::template type_getter<N>::type& get (
tuple<T0,T1,T2,T3,T4>& m) {
return m.template get<N>();
}
// ... and the const version
template <unsigned N,typename T0,typename T1,typename T2,typename T3,typename T4>
inline const typename tuple<T0,T1,T2,T3,T4>::very_long::template type_getter<N>::type& get (
const tuple<T0,T1,T2,T3,T4>& m) {
return m.template get<N>();
}
// Constructs a tuple with 5 elements
template <typename T0,typename T1,typename T2,typename T3,typename T4>
inline tuple <T0,T1,T2,T3,T4> make_tuple (const T0& t0,
const T1& t1,const T2& t2,const T3& t3,const T4& t4) {
tuple <T0,T1,T2,T3,T4> t;
t.template get<0>() = t0;
t.template get<1>() = t1;
t.template get<2>() = t2;
t.template get<3>() = t3;
t.template get<4>() = t4;
return t;
}
// Constructs a tuple with 4 elements
template <typename T0,typename T1,typename T2,typename T3>
inline tuple <T0,T1,T2,T3> make_tuple (const T0& t0,
const T1& t1,const T2& t2,const T3& t3) {
tuple <T0,T1,T2,T3> t;
t.template get<0>() = t0;
t.template get<1>() = t1;
t.template get<2>() = t2;
t.template get<3>() = t3;
return t;
}
// Constructs a tuple with 3 elements
template <typename T0,typename T1,typename T2>
inline tuple <T0,T1,T2> make_tuple (const T0& t0,
const T1& t1,const T2& t2) {
tuple <T0,T1,T2> t;
t.template get<0>() = t0;
t.template get<1>() = t1;
t.template get<2>() = t2;
return t;
}
// Constructs a tuple with 2 elements
template <typename T0,typename T1>
inline tuple <T0,T1> make_tuple (const T0& t0,
const T1& t1) {
tuple <T0,T1> t;
t.template get<0>() = t0;
t.template get<1>() = t1;
return t;
}
// Constructs a tuple with 1 elements (well ...)
template <typename T0>
inline tuple <T0> make_tuple (const T0& t0) {
tuple <T0> t;
t.template get<0>() = t0;
return t;
}
// Constructs a tuple with 0 elements (well ...)
inline tuple <> make_tuple () {
tuple <> t;
return t;
}
}
#endif // !! BOOST_TUPLE_INCLUDED

View File

@ -1,285 +0,0 @@
/*
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 Helper class tp perform various byte oder swappings
(e.g. little to big endian) */
#ifndef AI_BYTESWAP_H_INC
#define AI_BYTESWAP_H_INC
#include "../include/assimp/ai_assert.h"
#include "../include/assimp/types.h"
#if _MSC_VER >= 1400
#include <stdlib.h>
#endif
namespace Assimp {
// --------------------------------------------------------------------------------------
/** Defines some useful byte order swap routines.
*
* This is required to read big-endian model formats on little-endian machines,
* and vice versa. Direct use of this class is DEPRECATED. Use #StreamReader instead. */
// --------------------------------------------------------------------------------------
class ByteSwap
{
ByteSwap() {}
public:
// ----------------------------------------------------------------------
/** Swap two bytes of data
* @param[inout] _szOut A void* to save the reintcasts for the caller. */
static inline void Swap2(void* _szOut)
{
ai_assert(_szOut);
#if _MSC_VER >= 1400
uint16_t* const szOut = reinterpret_cast<uint16_t*>(_szOut);
*szOut = _byteswap_ushort(*szOut);
#else
uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
std::swap(szOut[0],szOut[1]);
#endif
}
// ----------------------------------------------------------------------
/** Swap four bytes of data
* @param[inout] _szOut A void* to save the reintcasts for the caller. */
static inline void Swap4(void* _szOut)
{
ai_assert(_szOut);
#if _MSC_VER >= 1400
uint32_t* const szOut = reinterpret_cast<uint32_t*>(_szOut);
*szOut = _byteswap_ulong(*szOut);
#else
uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
std::swap(szOut[0],szOut[3]);
std::swap(szOut[1],szOut[2]);
#endif
}
// ----------------------------------------------------------------------
/** Swap eight bytes of data
* @param[inout] _szOut A void* to save the reintcasts for the caller. */
static inline void Swap8(void* _szOut)
{
ai_assert(_szOut);
#if _MSC_VER >= 1400
uint64_t* const szOut = reinterpret_cast<uint64_t*>(_szOut);
*szOut = _byteswap_uint64(*szOut);
#else
uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
std::swap(szOut[0],szOut[7]);
std::swap(szOut[1],szOut[6]);
std::swap(szOut[2],szOut[5]);
std::swap(szOut[3],szOut[4]);
#endif
}
// ----------------------------------------------------------------------
/** ByteSwap a float. Not a joke.
* @param[inout] fOut ehm. .. */
static inline void Swap(float* fOut) {
Swap4(fOut);
}
// ----------------------------------------------------------------------
/** ByteSwap a double. Not a joke.
* @param[inout] fOut ehm. .. */
static inline void Swap(double* fOut) {
Swap8(fOut);
}
// ----------------------------------------------------------------------
/** ByteSwap an int16t. Not a joke.
* @param[inout] fOut ehm. .. */
static inline void Swap(int16_t* fOut) {
Swap2(fOut);
}
static inline void Swap(uint16_t* fOut) {
Swap2(fOut);
}
// ----------------------------------------------------------------------
/** ByteSwap an int32t. Not a joke.
* @param[inout] fOut ehm. .. */
static inline void Swap(int32_t* fOut){
Swap4(fOut);
}
static inline void Swap(uint32_t* fOut){
Swap4(fOut);
}
// ----------------------------------------------------------------------
/** ByteSwap an int64t. Not a joke.
* @param[inout] fOut ehm. .. */
static inline void Swap(int64_t* fOut) {
Swap8(fOut);
}
static inline void Swap(uint64_t* fOut) {
Swap8(fOut);
}
// ----------------------------------------------------------------------
//! Templatized ByteSwap
//! \returns param tOut as swapped
template<typename Type>
static inline Type Swapped(Type tOut)
{
return _swapper<Type,sizeof(Type)>()(tOut);
}
private:
template <typename T, size_t size> struct _swapper;
};
template <typename T> struct ByteSwap::_swapper<T,2> {
T operator() (T tOut) {
Swap2(&tOut);
return tOut;
}
};
template <typename T> struct ByteSwap::_swapper<T,4> {
T operator() (T tOut) {
Swap4(&tOut);
return tOut;
}
};
template <typename T> struct ByteSwap::_swapper<T,8> {
T operator() (T tOut) {
Swap8(&tOut);
return tOut;
}
};
// --------------------------------------------------------------------------------------
// ByteSwap macros for BigEndian/LittleEndian support
// --------------------------------------------------------------------------------------
#if (defined AI_BUILD_BIG_ENDIAN)
# define AI_LE(t) (t)
# define AI_BE(t) ByteSwap::Swapped(t)
# define AI_LSWAP2(p)
# define AI_LSWAP4(p)
# define AI_LSWAP8(p)
# define AI_LSWAP2P(p)
# define AI_LSWAP4P(p)
# define AI_LSWAP8P(p)
# define LE_NCONST const
# define AI_SWAP2(p) ByteSwap::Swap2(&(p))
# define AI_SWAP4(p) ByteSwap::Swap4(&(p))
# define AI_SWAP8(p) ByteSwap::Swap8(&(p))
# define AI_SWAP2P(p) ByteSwap::Swap2((p))
# define AI_SWAP4P(p) ByteSwap::Swap4((p))
# define AI_SWAP8P(p) ByteSwap::Swap8((p))
# define BE_NCONST
#else
# define AI_BE(t) (t)
# define AI_LE(t) ByteSwap::Swapped(t)
# define AI_SWAP2(p)
# define AI_SWAP4(p)
# define AI_SWAP8(p)
# define AI_SWAP2P(p)
# define AI_SWAP4P(p)
# define AI_SWAP8P(p)
# define BE_NCONST const
# define AI_LSWAP2(p) ByteSwap::Swap2(&(p))
# define AI_LSWAP4(p) ByteSwap::Swap4(&(p))
# define AI_LSWAP8(p) ByteSwap::Swap8(&(p))
# define AI_LSWAP2P(p) ByteSwap::Swap2((p))
# define AI_LSWAP4P(p) ByteSwap::Swap4((p))
# define AI_LSWAP8P(p) ByteSwap::Swap8((p))
# define LE_NCONST
#endif
namespace Intern {
// --------------------------------------------------------------------------------------------
template <typename T, bool doit>
struct ByteSwapper {
void operator() (T* inout) {
ByteSwap::Swap(inout);
}
};
template <typename T>
struct ByteSwapper<T,false> {
void operator() (T*) {
}
};
// --------------------------------------------------------------------------------------------
template <bool SwapEndianess, typename T, bool RuntimeSwitch>
struct Getter {
void operator() (T* inout, bool le) {
#ifdef AI_BUILD_BIG_ENDIAN
le = le;
#else
le = !le;
#endif
if (le) {
ByteSwapper<T,(sizeof(T)>1?true:false)> () (inout);
}
else ByteSwapper<T,false> () (inout);
}
};
template <bool SwapEndianess, typename T>
struct Getter<SwapEndianess,T,false> {
void operator() (T* inout, bool /*le*/) {
// static branch
ByteSwapper<T,(SwapEndianess && sizeof(T)>1)> () (inout);
}
};
} // end Intern
} // end Assimp
#endif //!! AI_BYTESWAP_H_INC

286
code/ByteSwapper.h 100644
View File

@ -0,0 +1,286 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2016, 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 Helper class tp perform various byte oder swappings
(e.g. little to big endian) */
#ifndef AI_BYTESWAPPER_H_INC
#define AI_BYTESWAPPER_H_INC
#include <assimp/ai_assert.h>
#include <assimp/types.h>
#include <stdint.h>
#if _MSC_VER >= 1400
#include <stdlib.h>
#endif
namespace Assimp {
// --------------------------------------------------------------------------------------
/** Defines some useful byte order swap routines.
*
* This is required to read big-endian model formats on little-endian machines,
* and vice versa. Direct use of this class is DEPRECATED. Use #StreamReader instead. */
// --------------------------------------------------------------------------------------
class ByteSwap
{
ByteSwap() {}
public:
// ----------------------------------------------------------------------
/** Swap two bytes of data
* @param[inout] _szOut A void* to save the reintcasts for the caller. */
static inline void Swap2(void* _szOut)
{
ai_assert(_szOut);
#if _MSC_VER >= 1400
uint16_t* const szOut = reinterpret_cast<uint16_t*>(_szOut);
*szOut = _byteswap_ushort(*szOut);
#else
uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
std::swap(szOut[0],szOut[1]);
#endif
}
// ----------------------------------------------------------------------
/** Swap four bytes of data
* @param[inout] _szOut A void* to save the reintcasts for the caller. */
static inline void Swap4(void* _szOut)
{
ai_assert(_szOut);
#if _MSC_VER >= 1400
uint32_t* const szOut = reinterpret_cast<uint32_t*>(_szOut);
*szOut = _byteswap_ulong(*szOut);
#else
uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
std::swap(szOut[0],szOut[3]);
std::swap(szOut[1],szOut[2]);
#endif
}
// ----------------------------------------------------------------------
/** Swap eight bytes of data
* @param[inout] _szOut A void* to save the reintcasts for the caller. */
static inline void Swap8(void* _szOut)
{
ai_assert(_szOut);
#if _MSC_VER >= 1400
uint64_t* const szOut = reinterpret_cast<uint64_t*>(_szOut);
*szOut = _byteswap_uint64(*szOut);
#else
uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
std::swap(szOut[0],szOut[7]);
std::swap(szOut[1],szOut[6]);
std::swap(szOut[2],szOut[5]);
std::swap(szOut[3],szOut[4]);
#endif
}
// ----------------------------------------------------------------------
/** ByteSwap a float. Not a joke.
* @param[inout] fOut ehm. .. */
static inline void Swap(float* fOut) {
Swap4(fOut);
}
// ----------------------------------------------------------------------
/** ByteSwap a double. Not a joke.
* @param[inout] fOut ehm. .. */
static inline void Swap(double* fOut) {
Swap8(fOut);
}
// ----------------------------------------------------------------------
/** ByteSwap an int16t. Not a joke.
* @param[inout] fOut ehm. .. */
static inline void Swap(int16_t* fOut) {
Swap2(fOut);
}
static inline void Swap(uint16_t* fOut) {
Swap2(fOut);
}
// ----------------------------------------------------------------------
/** ByteSwap an int32t. Not a joke.
* @param[inout] fOut ehm. .. */
static inline void Swap(int32_t* fOut){
Swap4(fOut);
}
static inline void Swap(uint32_t* fOut){
Swap4(fOut);
}
// ----------------------------------------------------------------------
/** ByteSwap an int64t. Not a joke.
* @param[inout] fOut ehm. .. */
static inline void Swap(int64_t* fOut) {
Swap8(fOut);
}
static inline void Swap(uint64_t* fOut) {
Swap8(fOut);
}
// ----------------------------------------------------------------------
//! Templatized ByteSwap
//! \returns param tOut as swapped
template<typename Type>
static inline Type Swapped(Type tOut)
{
return _swapper<Type,sizeof(Type)>()(tOut);
}
private:
template <typename T, size_t size> struct _swapper;
};
template <typename T> struct ByteSwap::_swapper<T,2> {
T operator() (T tOut) {
Swap2(&tOut);
return tOut;
}
};
template <typename T> struct ByteSwap::_swapper<T,4> {
T operator() (T tOut) {
Swap4(&tOut);
return tOut;
}
};
template <typename T> struct ByteSwap::_swapper<T,8> {
T operator() (T tOut) {
Swap8(&tOut);
return tOut;
}
};
// --------------------------------------------------------------------------------------
// ByteSwap macros for BigEndian/LittleEndian support
// --------------------------------------------------------------------------------------
#if (defined AI_BUILD_BIG_ENDIAN)
# define AI_LE(t) (t)
# define AI_BE(t) ByteSwap::Swapped(t)
# define AI_LSWAP2(p)
# define AI_LSWAP4(p)
# define AI_LSWAP8(p)
# define AI_LSWAP2P(p)
# define AI_LSWAP4P(p)
# define AI_LSWAP8P(p)
# define LE_NCONST const
# define AI_SWAP2(p) ByteSwap::Swap2(&(p))
# define AI_SWAP4(p) ByteSwap::Swap4(&(p))
# define AI_SWAP8(p) ByteSwap::Swap8(&(p))
# define AI_SWAP2P(p) ByteSwap::Swap2((p))
# define AI_SWAP4P(p) ByteSwap::Swap4((p))
# define AI_SWAP8P(p) ByteSwap::Swap8((p))
# define BE_NCONST
#else
# define AI_BE(t) (t)
# define AI_LE(t) ByteSwap::Swapped(t)
# define AI_SWAP2(p)
# define AI_SWAP4(p)
# define AI_SWAP8(p)
# define AI_SWAP2P(p)
# define AI_SWAP4P(p)
# define AI_SWAP8P(p)
# define BE_NCONST const
# define AI_LSWAP2(p) ByteSwap::Swap2(&(p))
# define AI_LSWAP4(p) ByteSwap::Swap4(&(p))
# define AI_LSWAP8(p) ByteSwap::Swap8(&(p))
# define AI_LSWAP2P(p) ByteSwap::Swap2((p))
# define AI_LSWAP4P(p) ByteSwap::Swap4((p))
# define AI_LSWAP8P(p) ByteSwap::Swap8((p))
# define LE_NCONST
#endif
namespace Intern {
// --------------------------------------------------------------------------------------------
template <typename T, bool doit>
struct ByteSwapper {
void operator() (T* inout) {
ByteSwap::Swap(inout);
}
};
template <typename T>
struct ByteSwapper<T,false> {
void operator() (T*) {
}
};
// --------------------------------------------------------------------------------------------
template <bool SwapEndianess, typename T, bool RuntimeSwitch>
struct Getter {
void operator() (T* inout, bool le) {
#ifdef AI_BUILD_BIG_ENDIAN
le = le;
#else
le = !le;
#endif
if (le) {
ByteSwapper<T,(sizeof(T)>1?true:false)> () (inout);
}
else ByteSwapper<T,false> () (inout);
}
};
template <bool SwapEndianess, typename T>
struct Getter<SwapEndianess,T,false> {
void operator() (T* inout, bool /*le*/) {
// static branch
ByteSwapper<T,(SwapEndianess && sizeof(T)>1)> () (inout);
}
};
} // end Intern
} // end Assimp
#endif //!! AI_BYTESWAPPER_H_INC

View File

@ -0,0 +1,650 @@
/*
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 C4DImporter.cpp
* @brief Implementation of the Cinema4D importer class.
*/
#ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
// no #ifdefing here, Cinema4D support is carried out in a branch of assimp
// where it is turned on in the CMake settings.
#ifndef _MSC_VER
# error C4D support is currently MSVC only
#endif
#include "C4DImporter.h"
#include "TinyFormatter.h"
#include <memory>
#include <assimp/IOSystem.hpp>
#include <assimp/scene.h>
#include <assimp/ai_assert.h>
#if defined(_M_X64) || defined(__amd64__)
# define __C4D_64BIT
#endif
#define __PC
#include "c4d_file.h"
#include "default_alien_overloads.h"
using namespace melange;
// overload this function and fill in your own unique data
void GetWriterInfo(int &id, String &appname)
{
id = 2424226;
appname = "Open Asset Import Library";
}
using namespace Assimp;
using namespace Assimp::Formatter;
namespace Assimp {
template<> const std::string LogFunctions<C4DImporter>::log_prefix = "C4D: ";
}
static const aiImporterDesc desc = {
"Cinema4D Importer",
"",
"",
"",
aiImporterFlags_SupportBinaryFlavour,
0,
0,
0,
0,
"c4d"
};
// ------------------------------------------------------------------------------------------------
C4DImporter::C4DImporter()
{}
// ------------------------------------------------------------------------------------------------
C4DImporter::~C4DImporter()
{}
// ------------------------------------------------------------------------------------------------
bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
const std::string& extension = GetExtension(pFile);
if (extension == "c4d") {
return true;
}
else if ((!extension.length() || checkSig) && pIOHandler) {
// TODO
}
return false;
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc* C4DImporter::GetInfo () const
{
return &desc;
}
// ------------------------------------------------------------------------------------------------
void C4DImporter::SetupProperties(const Importer* /*pImp*/)
{
// nothing to be done for the moment
}
// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void C4DImporter::InternReadFile( const std::string& pFile,
aiScene* pScene, IOSystem* pIOHandler)
{
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
if( file.get() == NULL) {
ThrowException("failed to open file " + pFile);
}
const size_t file_size = file->FileSize();
std::vector<uint8_t> mBuffer(file_size);
file->Read(&mBuffer[0], 1, file_size);
Filename f;
f.SetMemoryReadMode(&mBuffer[0], file_size);
// open document first
BaseDocument* doc = LoadDocument(f, SCENEFILTER_OBJECTS | SCENEFILTER_MATERIALS);
if(doc == NULL) {
ThrowException("failed to read document " + pFile);
}
pScene->mRootNode = new aiNode("<C4DRoot>");
// first convert all materials
ReadMaterials(doc->GetFirstMaterial());
// process C4D scenegraph recursively
try {
RecurseHierarchy(doc->GetFirstObject(), pScene->mRootNode);
}
catch(...) {
for(aiMesh* mesh : meshes) {
delete mesh;
}
BaseDocument::Free(doc);
throw;
}
BaseDocument::Free(doc);
// copy meshes over
pScene->mNumMeshes = static_cast<unsigned int>(meshes.size());
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]();
std::copy(meshes.begin(), meshes.end(), pScene->mMeshes);
// copy materials over, adding a default material if necessary
unsigned int mat_count = static_cast<unsigned int>(materials.size());
for(aiMesh* mesh : meshes) {
ai_assert(mesh->mMaterialIndex <= mat_count);
if(mesh->mMaterialIndex >= mat_count) {
++mat_count;
ScopeGuard<aiMaterial> def_material(new aiMaterial());
const aiString name(AI_DEFAULT_MATERIAL_NAME);
def_material->AddProperty(&name, AI_MATKEY_NAME);
materials.push_back(def_material.dismiss());
break;
}
}
pScene->mNumMaterials = static_cast<unsigned int>(materials.size());
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]();
std::copy(materials.begin(), materials.end(), pScene->mMaterials);
}
// ------------------------------------------------------------------------------------------------
bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader)
{
// based on Melange sample code (C4DImportExport.cpp)
while(shader) {
if(shader->GetType() == Xlayer) {
BaseContainer* container = shader->GetDataInstance();
GeData blend = container->GetData(SLA_LAYER_BLEND);
iBlendDataType* blend_list = reinterpret_cast<iBlendDataType*>(blend.GetCustomDataType(CUSTOMDATA_BLEND_LIST));
if (!blend_list)
{
LogWarn("ignoring XLayer shader: no blend list given");
continue;
}
LayerShaderLayer *lsl = dynamic_cast<LayerShaderLayer*>(blend_list->m_BlendLayers.GetObject(0));
// Ignore the actual layer blending - models for real-time rendering should not
// use them in a non-trivial way. Just try to find textures that we can apply
// to the model.
while (lsl)
{
if (lsl->GetType() == TypeFolder)
{
BlendFolder* const folder = dynamic_cast<BlendFolder*>(lsl);
LayerShaderLayer *subLsl = dynamic_cast<LayerShaderLayer*>(folder->m_Children.GetObject(0));
while (subLsl)
{
if (subLsl->GetType() == TypeShader) {
BlendShader* const shader = dynamic_cast<BlendShader*>(subLsl);
if(ReadShader(out, static_cast<BaseShader*>(shader->m_pLink->GetLink()))) {
return true;
}
}
subLsl = subLsl->GetNext();
}
}
else if (lsl->GetType() == TypeShader) {
BlendShader* const shader = dynamic_cast<BlendShader*>(lsl);
if(ReadShader(out, static_cast<BaseShader*>(shader->m_pLink->GetLink()))) {
return true;
}
}
lsl = lsl->GetNext();
}
}
else if ( shader->GetType() == Xbitmap )
{
aiString path;
shader->GetFileName().GetString().GetCString(path.data, MAXLEN-1);
path.length = ::strlen(path.data);
out->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0));
return true;
}
else {
LogWarn("ignoring shader type: " + std::string(GetObjectTypeName(shader->GetType())));
}
shader = shader->GetNext();
}
return false;
}
// ------------------------------------------------------------------------------------------------
void C4DImporter::ReadMaterials(melange::BaseMaterial* mat)
{
// based on Melange sample code
while (mat)
{
const String& name = mat->GetName();
if (mat->GetType() == Mmaterial)
{
aiMaterial* out = new aiMaterial();
material_mapping[mat] = static_cast<unsigned int>(materials.size());
materials.push_back(out);
aiString ai_name;
name.GetCString(ai_name.data, MAXLEN-1);
ai_name.length = ::strlen(ai_name.data);
out->AddProperty(&ai_name, AI_MATKEY_NAME);
Material& m = dynamic_cast<Material&>(*mat);
if (m.GetChannelState(CHANNEL_COLOR))
{
GeData data;
mat->GetParameter(MATERIAL_COLOR_COLOR, data);
Vector color = data.GetVector();
mat->GetParameter(MATERIAL_COLOR_BRIGHTNESS, data);
const Float brightness = data.GetFloat();
color *= brightness;
aiVector3D v;
v.x = color.x;
v.y = color.y;
v.z = color.z;
out->AddProperty(&v, 1, AI_MATKEY_COLOR_DIFFUSE);
}
BaseShader* const shader = m.GetShader(MATERIAL_COLOR_SHADER);
if(shader) {
ReadShader(out, shader);
}
}
else
{
LogWarn("ignoring plugin material: " + std::string(GetObjectTypeName(mat->GetType())));
}
mat = mat->GetNext();
}
}
// ------------------------------------------------------------------------------------------------
void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent)
{
ai_assert(parent != NULL);
std::vector<aiNode*> nodes;
// based on Melange sample code
while (object)
{
const String& name = object->GetName();
const LONG type = object->GetType();
const Matrix& ml = object->GetMl();
aiString string;
name.GetCString(string.data, MAXLEN-1);
string.length = ::strlen(string.data);
aiNode* const nd = new aiNode();
nd->mParent = parent;
nd->mName = string;
nd->mTransformation.a1 = ml.v1.x;
nd->mTransformation.b1 = ml.v1.y;
nd->mTransformation.c1 = ml.v1.z;
nd->mTransformation.a2 = ml.v2.x;
nd->mTransformation.b2 = ml.v2.y;
nd->mTransformation.c2 = ml.v2.z;
nd->mTransformation.a3 = ml.v3.x;
nd->mTransformation.b3 = ml.v3.y;
nd->mTransformation.c3 = ml.v3.z;
nd->mTransformation.a4 = ml.off.x;
nd->mTransformation.b4 = ml.off.y;
nd->mTransformation.c4 = ml.off.z;
nodes.push_back(nd);
GeData data;
if (type == Ocamera)
{
object->GetParameter(CAMERAOBJECT_FOV, data);
// TODO: read camera
}
else if (type == Olight)
{
// TODO: read light
}
else if (type == Opolygon)
{
aiMesh* const mesh = ReadMesh(object);
if(mesh != NULL) {
nd->mNumMeshes = 1;
nd->mMeshes = new unsigned int[1];
nd->mMeshes[0] = static_cast<unsigned int>(meshes.size());
meshes.push_back(mesh);
}
}
else {
LogWarn("ignoring object: " + std::string(GetObjectTypeName(type)));
}
RecurseHierarchy(object->GetDown(), nd);
object = object->GetNext();
}
// copy nodes over to parent
parent->mNumChildren = static_cast<unsigned int>(nodes.size());
parent->mChildren = new aiNode*[parent->mNumChildren]();
std::copy(nodes.begin(), nodes.end(), parent->mChildren);
}
// ------------------------------------------------------------------------------------------------
aiMesh* C4DImporter::ReadMesh(BaseObject* object)
{
assert(object != NULL && object->GetType() == Opolygon);
// based on Melange sample code
PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object);
ai_assert(polyObject != NULL);
const LONG pointCount = polyObject->GetPointCount();
const LONG polyCount = polyObject->GetPolygonCount();
if(!polyObject || !pointCount) {
LogWarn("ignoring mesh with zero vertices or faces");
return NULL;
}
const Vector* points = polyObject->GetPointR();
ai_assert(points != NULL);
const CPolygon* polys = polyObject->GetPolygonR();
ai_assert(polys != NULL);
ScopeGuard<aiMesh> mesh(new aiMesh());
mesh->mNumFaces = static_cast<unsigned int>(polyCount);
aiFace* face = mesh->mFaces = new aiFace[mesh->mNumFaces]();
mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
mesh->mMaterialIndex = 0;
unsigned int vcount = 0;
// first count vertices
for (LONG i = 0; i < polyCount; i++)
{
vcount += 3;
// TODO: do we also need to handle lines or points with similar checks?
if (polys[i].c != polys[i].d)
{
mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
++vcount;
}
}
ai_assert(vcount > 0);
mesh->mNumVertices = vcount;
aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
aiVector3D* normals, *uvs, *tangents, *bitangents;
unsigned int n = 0;
// check if there are normals, tangents or UVW coordinates
BaseTag* tag = object->GetTag(Tnormal);
NormalTag* normals_src = NULL;
if(tag) {
normals_src = dynamic_cast<NormalTag*>(tag);
normals = mesh->mNormals = new aiVector3D[mesh->mNumVertices]();
}
tag = object->GetTag(Ttangent);
TangentTag* tangents_src = NULL;
if(tag) {
tangents_src = dynamic_cast<TangentTag*>(tag);
tangents = mesh->mTangents = new aiVector3D[mesh->mNumVertices]();
bitangents = mesh->mBitangents = new aiVector3D[mesh->mNumVertices]();
}
tag = object->GetTag(Tuvw);
UVWTag* uvs_src = NULL;
if(tag) {
uvs_src = dynamic_cast<UVWTag*>(tag);
uvs = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]();
}
// copy vertices and extra channels over and populate faces
for (LONG i = 0; i < polyCount; ++i, ++face)
{
ai_assert(polys[i].a < pointCount && polys[i].a >= 0);
const Vector& pointA = points[polys[i].a];
verts->x = pointA.x;
verts->y = pointA.y;
verts->z = pointA.z;
++verts;
ai_assert(polys[i].b < pointCount && polys[i].b >= 0);
const Vector& pointB = points[polys[i].b];
verts->x = pointB.x;
verts->y = pointB.y;
verts->z = pointB.z;
++verts;
ai_assert(polys[i].c < pointCount && polys[i].c >= 0);
const Vector& pointC = points[polys[i].c];
verts->x = pointC.x;
verts->y = pointC.y;
verts->z = pointC.z;
++verts;
// TODO: do we also need to handle lines or points with similar checks?
if (polys[i].c != polys[i].d)
{
ai_assert(polys[i].d < pointCount && polys[i].d >= 0);
face->mNumIndices = 4;
mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
const Vector& pointD = points[polys[i].d];
verts->x = pointD.x;
verts->y = pointD.y;
verts->z = pointD.z;
++verts;
}
else {
face->mNumIndices = 3;
}
face->mIndices = new unsigned int[face->mNumIndices];
for(unsigned int j = 0; j < face->mNumIndices; ++j) {
face->mIndices[j] = n++;
}
// copy normals
if (normals_src) {
if(i >= normals_src->GetDataCount()) {
LogError("unexpected number of normals, ignoring");
}
else {
ConstNormalHandle normal_handle = normals_src->GetDataAddressR();
NormalStruct nor;
NormalTag::Get(normal_handle, i, nor);
normals->x = nor.a.x;
normals->y = nor.a.y;
normals->z = nor.a.z;
++normals;
normals->x = nor.b.x;
normals->y = nor.b.y;
normals->z = nor.b.z;
++normals;
normals->x = nor.c.x;
normals->y = nor.c.y;
normals->z = nor.c.z;
++normals;
if(face->mNumIndices == 4) {
normals->x = nor.d.x;
normals->y = nor.d.y;
normals->z = nor.d.z;
++normals;
}
}
}
// copy tangents and bitangents
if (tangents_src) {
for(unsigned int k = 0; k < face->mNumIndices; ++k) {
LONG l;
switch(k) {
case 0:
l = polys[i].a;
break;
case 1:
l = polys[i].b;
break;
case 2:
l = polys[i].c;
break;
case 3:
l = polys[i].d;
break;
default:
ai_assert(false);
}
if(l >= tangents_src->GetDataCount()) {
LogError("unexpected number of tangents, ignoring");
break;
}
Tangent tan = tangents_src->GetDataR()[l];
tangents->x = tan.vl.x;
tangents->y = tan.vl.y;
tangents->z = tan.vl.z;
++tangents;
bitangents->x = tan.vr.x;
bitangents->y = tan.vr.y;
bitangents->z = tan.vr.z;
++bitangents;
}
}
// copy UVs
if (uvs_src) {
if(i >= uvs_src->GetDataCount()) {
LogError("unexpected number of UV coordinates, ignoring");
}
else {
UVWStruct uvw;
uvs_src->Get(uvs_src->GetDataAddressR(),i,uvw);
uvs->x = uvw.a.x;
uvs->y = 1.0f-uvw.a.y;
uvs->z = uvw.a.z;
++uvs;
uvs->x = uvw.b.x;
uvs->y = 1.0f-uvw.b.y;
uvs->z = uvw.b.z;
++uvs;
uvs->x = uvw.c.x;
uvs->y = 1.0f-uvw.c.y;
uvs->z = uvw.c.z;
++uvs;
if(face->mNumIndices == 4) {
uvs->x = uvw.d.x;
uvs->y = 1.0f-uvw.d.y;
uvs->z = uvw.d.z;
++uvs;
}
}
}
}
mesh->mMaterialIndex = ResolveMaterial(polyObject);
return mesh.dismiss();
}
// ------------------------------------------------------------------------------------------------
unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj)
{
ai_assert(obj != NULL);
const unsigned int mat_count = static_cast<unsigned int>(materials.size());
BaseTag* tag = obj->GetTag(Ttexture);
if(tag == NULL) {
return mat_count;
}
TextureTag& ttag = dynamic_cast<TextureTag&>(*tag);
BaseMaterial* const mat = ttag.GetMaterial();
assert(mat != NULL);
const MaterialMap::const_iterator it = material_mapping.find(mat);
if(it == material_mapping.end()) {
return mat_count;
}
ai_assert((*it).second < mat_count);
return (*it).second;
}
#endif // ASSIMP_BUILD_NO_C4D_IMPORTER

123
code/C4DImporter.h 100644
View File

@ -0,0 +1,123 @@
/*
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 C4DImporter.h
* @brief Declaration of the Cinema4D (*.c4d) importer class.
*/
#ifndef INCLUDED_AI_CINEMA_4D_LOADER_H
#define INCLUDED_AI_CINEMA_4D_LOADER_H
#include "BaseImporter.h"
#include "LogAux.h"
#include <set>
struct aiNode;
struct aiMesh;
struct aiMaterial;
struct aiImporterDesc;
namespace melange {
class BaseObject; // c4d_file.h
class PolygonObject;
class BaseMaterial;
class BaseShader;
}
namespace Assimp {
// TinyFormatter.h
namespace Formatter {
template <typename T,typename TR, typename A> class basic_formatter;
typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
}
// -------------------------------------------------------------------------------------------
/** Importer class to load Cinema4D files using the Melange library to be obtained from
* www.plugincafe.com
*
* Note that Melange is not free software. */
// -------------------------------------------------------------------------------------------
class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter>
{
public:
C4DImporter();
~C4DImporter();
public:
// --------------------
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const;
protected:
// --------------------
const aiImporterDesc* GetInfo () const;
// --------------------
void SetupProperties(const Importer* pImp);
// --------------------
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler);
private:
void ReadMaterials(melange::BaseMaterial* mat);
void RecurseHierarchy(melange::BaseObject* object, aiNode* parent);
aiMesh* ReadMesh(melange::BaseObject* object);
unsigned int ResolveMaterial(melange::PolygonObject* obj);
bool ReadShader(aiMaterial* out, melange::BaseShader* shader);
std::vector<aiMesh*> meshes;
std::vector<aiMaterial*> materials;
typedef std::map<melange::BaseMaterial*, unsigned int> MaterialMap;
MaterialMap material_mapping;
}; // !class C4DImporter
} // end of namespace Assimp
#endif // INCLUDED_AI_CINEMA_4D_LOADER_H

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