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,29 +1,64 @@
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
compiler: 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

View File

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

58
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:
@ -18,18 +52,18 @@ FEATURES:
FIXES/HOUSEKEEPING: FIXES/HOUSEKEEPING:
- Hundreds of bugfixes in all parts of the library - Hundreds of bugfixes in all parts of the library
- CMake is now the primary build system - CMake is now the primary build system
API COMPATIBILITY: API COMPATIBILITY:
- 3.1.1 is not binary compatible to 3.0 due to aiNode::mMetaData - 3.1.1 is not binary compatible to 3.0 due to aiNode::mMetaData
and aiMesh::mName and aiMesh::mName
- Export interface has been cleaned up and unified - Export interface has been cleaned up and unified
- Other than that no relevant changes - Other than that no relevant changes
3.0 (2012-07-07) 3.0 (2012-07-07)
FEATURES: FEATURES:
- new export interface similar to the import API. - new export interface similar to the import API.
- Supported export formats: Collada, OBJ, PLY and STL - Supported export formats: Collada, OBJ, PLY and STL
- added new import formats: XGL/ZGL, M3 (experimental) - added new import formats: XGL/ZGL, M3 (experimental)
- new postprocessing steps: Debone - new postprocessing steps: Debone
@ -46,11 +80,11 @@ FIXES/HOUSEKEEPING:
- improved CMake build system - improved CMake build system
- templatized math library - templatized math library
- reduce dependency on boost.thread, only remaining spot - reduce dependency on boost.thread, only remaining spot
is synchronization for the C logging API is synchronization for the C logging API
API COMPATIBILITY: API COMPATIBILITY:
- renamed headers, export interface, C API properties and meta data - renamed headers, export interface, C API properties and meta data
prevent compatibility with code written for 2.0, but in prevent compatibility with code written for 2.0, but in
most cases these can be easily resolved most cases these can be easily resolved
- Note: 3.0 is not binary compatible with 2.0 - Note: 3.0 is not binary compatible with 2.0
@ -68,9 +102,9 @@ FEATURES:
spatial structure) in some expensive postprocessing steps spatial structure) in some expensive postprocessing steps
- AssimpView now uses a reworked layout which leaves more space - AssimpView now uses a reworked layout which leaves more space
to the scene hierarchy window to the scene hierarchy window
- Add C# bindings ('Assimp.NET') - Add C# bindings ('Assimp.NET')
- Keep BSD-licensed and otherwise free test files in separate - Keep BSD-licensed and otherwise free test files in separate
folders (./test/models and ./test/models-nonbsd). folders (./test/models and ./test/models-nonbsd).
FIXES: FIXES:
@ -80,20 +114,20 @@ FIXES:
- OpenGL-sample now works with MinGW - OpenGL-sample now works with MinGW
- Fix Importer::FindLoader failing on uppercase file extensions - Fix Importer::FindLoader failing on uppercase file extensions
- Fix flawed path handling when locating external files - Fix flawed path handling when locating external files
- Limit the maximum number of vertices, faces, face indices and - Limit the maximum number of vertices, faces, face indices and
weights that Assimp is able to handle. This is to avoid weights that Assimp is able to handle. This is to avoid
crashes due to overflowing counters. crashes due to overflowing counters.
- Updated XCode project files - Updated XCode project files
- Further CMAKE build improvements - Further CMAKE build improvements
API CHANGES: API CHANGES:
- Add data structures for vertex-based animations (These are not - Add data structures for vertex-based animations (These are not
currently used, however ...) currently used, however ...)
- Some Assimp::Importer methods are const now. - Some Assimp::Importer methods are const now.

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)
@ -64,214 +195,265 @@ INCLUDE (PrecompiledHeader)
# source tree. During an out-of-source build, however, do not litter this # source tree. During an out-of-source build, however, do not litter this
# directory, since that is probably what the user wanted to avoid. # directory, since that is probably what the user wanted to avoid.
IF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR ) IF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib" ) SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib" )
SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib" ) SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib" )
SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/bin" ) SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/bin" )
ENDIF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR ) ENDIF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
# Cache these to allow the user to override them manually. # Cache these to allow the user to override them manually.
SET( ASSIMP_LIB_INSTALL_DIR "lib" CACHE PATH SET( ASSIMP_LIB_INSTALL_DIR "lib" CACHE 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)
# add make uninstall capability # add make uninstall capability
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
ENDIF() ENDIF()
# Globally enable Boost resp. the Boost workaround – it is also needed by the
# 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 "" CACHE STRING
# set(ASSIMP_BUILD_ARCHITECTURE "amd64") "describe the current architecture."
# else(CMAKE_CL_64)
# set(ASSIMP_BUILD_ARCHITECTURE "x86")
# endif(CMAKE_CL_64)
SET ( ASSIMP_BUILD_ARCHITECTURE "" CACHE STRING
"describe the current architecture."
) )
IF ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "") IF ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "")
ELSE ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "") ELSE ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "")
ADD_DEFINITIONS ( -D'ASSIMP_BUILD_ARCHITECTURE="${ASSIMP_BUILD_ARCHITECTURE}"' ) ADD_DEFINITIONS ( -D'ASSIMP_BUILD_ARCHITECTURE="${ASSIMP_BUILD_ARCHITECTURE}"' )
ENDIF ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "") ENDIF ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "")
# ${CMAKE_GENERATOR} # ${CMAKE_GENERATOR}
SET ( ASSIMP_BUILD_COMPILER "" CACHE STRING SET ( ASSIMP_BUILD_COMPILER "" CACHE STRING
"describe the current compiler." "describe the current compiler."
) )
IF ( ASSIMP_BUILD_COMPILER STREQUAL "") IF ( ASSIMP_BUILD_COMPILER STREQUAL "")
ELSE ( ASSIMP_BUILD_COMPILER STREQUAL "") ELSE ( ASSIMP_BUILD_COMPILER STREQUAL "")
ADD_DEFINITIONS ( -D'ASSIMP_BUILD_COMPILER="${ASSIMP_BUILD_COMPILER}"' ) ADD_DEFINITIONS ( -D'ASSIMP_BUILD_COMPILER="${ASSIMP_BUILD_COMPILER}"' )
ENDIF ( ASSIMP_BUILD_COMPILER STREQUAL "") ENDIF ( ASSIMP_BUILD_COMPILER STREQUAL "")
MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER ) MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER )
ADD_SUBDIRECTORY( code/ ) 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_NONFREE_C4D_IMPORTER)
IF ( MSVC )
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 ( ASSIMP_BUILD_ASSIMP_TOOLS )
IF ( WIN32 ) IF ( WIN32 AND DirectX_D3DX9_LIBRARY )
ADD_SUBDIRECTORY( tools/assimp_view/ ) option ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} )
ENDIF ( WIN32 ) IF ( ASSIMP_BUILD_ASSIMP_VIEW )
ADD_SUBDIRECTORY( tools/assimp_cmd/ ) 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 ) ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
option ( ASSIMP_BUILD_SAMPLES
"If the official samples are built as well (needs Glut)."
OFF
)
IF ( ASSIMP_BUILD_SAMPLES) IF ( ASSIMP_BUILD_SAMPLES)
IF ( WIN32 ) IF ( WIN32 )
ADD_SUBDIRECTORY( samples/SimpleTexturedOpenGL/ ) ADD_SUBDIRECTORY( samples/SimpleTexturedOpenGL/ )
ENDIF ( WIN32 ) ENDIF ( WIN32 )
ADD_SUBDIRECTORY( samples/SimpleOpenGL/ ) ADD_SUBDIRECTORY( samples/SimpleOpenGL/ )
ENDIF ( ASSIMP_BUILD_SAMPLES ) ENDIF ( ASSIMP_BUILD_SAMPLES )
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

30
LICENSE
View File

@ -1,10 +1,10 @@
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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
@ -21,16 +21,16 @@ following 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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@ -41,9 +41,9 @@ AN EXCEPTION applies to all files in the ./test/models-nonbsd folder.
These are 3d models for testing purposes, from various free sources These are 3d models for testing purposes, from various free sources
on the internet. They are - unless otherwise stated - copyright of on the internet. They are - unless otherwise stated - copyright of
their respective creators, which may impose additional requirements their respective creators, which may impose additional requirements
on the use of their work. For any of these models, see on the use of their work. For any of these models, see
<model-name>.source.txt for more legal information. Contact us if you <model-name>.source.txt for more legal information. Contact us if you
are a copyright holder and believe that we credited you inproperly or are a copyright holder and believe that we credited you inproperly or
if you don't want your files to appear in the repository. if you don't want your files to appear in the repository.
@ -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.

121
Readme.md
View File

@ -1,41 +1,58 @@
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
- ASE - ASE
- DXF - DXF
- HMP - HMP
- MD2 - MD2
- MD3 - MD3
- MD5 - MD5
- MDC - MDC
- MDL - MDL
- NFF - NFF
- PLY - PLY
- STL - STL
- X - X
- OBJ - OBJ
- OpenGEX
- SMD - SMD
- LWO - LWO
- LXO - LXO
- LWS - LWS
- TER - TER
- AC3D - AC3D
- MS3D - MS3D
- COB - COB
- Q3BSP - Q3BSP
- XGL - XGL
@ -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)
Additionally, the following formats are also supported, but not part of the core library as they depend on proprietary libraries. - 3MF
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
See [the full list here](http://assimp.sourceforge.net/main_features_formats.html). - glTF (partial)
### 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)
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 ### ### 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

@ -1,347 +1,347 @@
## Debian Source Package Generator ## Debian Source Package Generator
# #
# Copyright (c) 2010 Daniel Pfeifer <daniel@pfeifer-mail.de> # Copyright (c) 2010 Daniel Pfeifer <daniel@pfeifer-mail.de>
# Many modifications by Rosen Diankov <rosen.diankov@gmail.com> # Many modifications by Rosen Diankov <rosen.diankov@gmail.com>
# #
# Creates source debian files and manages library dependencies # Creates source debian files and manages library dependencies
# #
# Features: # Features:
# #
# - Automatically generates symbols and run-time dependencies from the build dependencies # - Automatically generates symbols and run-time dependencies from the build dependencies
# - Custom copy of source directory via CPACK_DEBIAN_PACKAGE_SOURCE_COPY # - Custom copy of source directory via CPACK_DEBIAN_PACKAGE_SOURCE_COPY
# - Simultaneous output of multiple debian source packages for each distribution # - Simultaneous output of multiple debian source packages for each distribution
# - Can specificy distribution-specific dependencies by suffixing DEPENDS with _${DISTRO_NAME}, for example: CPACK_DEBIAN_PACKAGE_DEPENDS_LUCID, CPACK_COMPONENT_MYCOMP0_DEPENDS_LUCID # - Can specificy distribution-specific dependencies by suffixing DEPENDS with _${DISTRO_NAME}, for example: CPACK_DEBIAN_PACKAGE_DEPENDS_LUCID, CPACK_COMPONENT_MYCOMP0_DEPENDS_LUCID
# #
# Usage: # Usage:
# #
# set(CPACK_DEBIAN_BUILD_DEPENDS debhelper cmake) # set(CPACK_DEBIAN_BUILD_DEPENDS debhelper cmake)
# set(CPACK_DEBIAN_PACKAGE_PRIORITY optional) # set(CPACK_DEBIAN_PACKAGE_PRIORITY optional)
# set(CPACK_DEBIAN_PACKAGE_SECTION devel) # set(CPACK_DEBIAN_PACKAGE_SECTION devel)
# set(CPACK_DEBIAN_CMAKE_OPTIONS "-DMYOPTION=myvalue") # set(CPACK_DEBIAN_CMAKE_OPTIONS "-DMYOPTION=myvalue")
# set(CPACK_DEBIAN_PACKAGE_DEPENDS mycomp0 mycomp1 some_ubuntu_package) # set(CPACK_DEBIAN_PACKAGE_DEPENDS mycomp0 mycomp1 some_ubuntu_package)
# set(CPACK_DEBIAN_PACKAGE_DEPENDS_UBUNTU_LUCID mycomp0 mycomp1 lucid_specific_package) # set(CPACK_DEBIAN_PACKAGE_DEPENDS_UBUNTU_LUCID mycomp0 mycomp1 lucid_specific_package)
# set(CPACK_DEBIAN_PACKAGE_NAME mypackage) # set(CPACK_DEBIAN_PACKAGE_NAME mypackage)
# set(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES unnecessary_file unnecessary_dir/file0) # set(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES unnecessary_file unnecessary_dir/file0)
# set(CPACK_DEBIAN_PACKAGE_SOURCE_COPY svn export --force) # if using subversion # set(CPACK_DEBIAN_PACKAGE_SOURCE_COPY svn export --force) # if using subversion
# set(CPACK_DEBIAN_DISTRIBUTION_NAME ubuntu) # set(CPACK_DEBIAN_DISTRIBUTION_NAME ubuntu)
# set(CPACK_DEBIAN_DISTRIBUTION_RELEASES karmic lucid maverick natty) # set(CPACK_DEBIAN_DISTRIBUTION_RELEASES karmic lucid maverick natty)
# set(CPACK_DEBIAN_CHANGELOG " * Extra change log lines") # set(CPACK_DEBIAN_CHANGELOG " * Extra change log lines")
# set(CPACK_DEBIAN_PACKAGE_SUGGESTS "ipython") # set(CPACK_DEBIAN_PACKAGE_SUGGESTS "ipython")
# set(CPACK_COMPONENT_X_RECOMMENDS "recommended-package") # set(CPACK_COMPONENT_X_RECOMMENDS "recommended-package")
## ##
find_program(DEBUILD_EXECUTABLE debuild) find_program(DEBUILD_EXECUTABLE debuild)
find_program(DPUT_EXECUTABLE dput) find_program(DPUT_EXECUTABLE dput)
if(NOT DEBUILD_EXECUTABLE OR NOT DPUT_EXECUTABLE) if(NOT DEBUILD_EXECUTABLE OR NOT DPUT_EXECUTABLE)
return() return()
endif(NOT DEBUILD_EXECUTABLE OR NOT DPUT_EXECUTABLE) endif(NOT DEBUILD_EXECUTABLE OR NOT DPUT_EXECUTABLE)
# DEBIAN/control # DEBIAN/control
# debian policy enforce lower case for package name # debian policy enforce lower case for package name
# Package: (mandatory) # Package: (mandatory)
IF(NOT CPACK_DEBIAN_PACKAGE_NAME) IF(NOT CPACK_DEBIAN_PACKAGE_NAME)
STRING(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_DEBIAN_PACKAGE_NAME) STRING(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_DEBIAN_PACKAGE_NAME)
ENDIF(NOT CPACK_DEBIAN_PACKAGE_NAME) ENDIF(NOT CPACK_DEBIAN_PACKAGE_NAME)
# Section: (recommended) # Section: (recommended)
IF(NOT CPACK_DEBIAN_PACKAGE_SECTION) IF(NOT CPACK_DEBIAN_PACKAGE_SECTION)
SET(CPACK_DEBIAN_PACKAGE_SECTION "devel") SET(CPACK_DEBIAN_PACKAGE_SECTION "devel")
ENDIF(NOT CPACK_DEBIAN_PACKAGE_SECTION) ENDIF(NOT CPACK_DEBIAN_PACKAGE_SECTION)
# Priority: (recommended) # Priority: (recommended)
IF(NOT CPACK_DEBIAN_PACKAGE_PRIORITY) IF(NOT CPACK_DEBIAN_PACKAGE_PRIORITY)
SET(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") SET(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
ENDIF(NOT CPACK_DEBIAN_PACKAGE_PRIORITY) ENDIF(NOT CPACK_DEBIAN_PACKAGE_PRIORITY)
file(STRINGS ${CPACK_PACKAGE_DESCRIPTION_FILE} DESC_LINES) file(STRINGS ${CPACK_PACKAGE_DESCRIPTION_FILE} DESC_LINES)
foreach(LINE ${DESC_LINES}) foreach(LINE ${DESC_LINES})
set(DEB_LONG_DESCRIPTION "${DEB_LONG_DESCRIPTION} ${LINE}\n") set(DEB_LONG_DESCRIPTION "${DEB_LONG_DESCRIPTION} ${LINE}\n")
endforeach(LINE ${DESC_LINES}) endforeach(LINE ${DESC_LINES})
file(REMOVE_RECURSE "${CMAKE_BINARY_DIR}/Debian") file(REMOVE_RECURSE "${CMAKE_BINARY_DIR}/Debian")
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/Debian") file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/Debian")
set(DEBIAN_SOURCE_ORIG_DIR "${CMAKE_BINARY_DIR}/Debian/${CPACK_DEBIAN_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") set(DEBIAN_SOURCE_ORIG_DIR "${CMAKE_BINARY_DIR}/Debian/${CPACK_DEBIAN_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
if( CPACK_DEBIAN_PACKAGE_SOURCE_COPY ) if( CPACK_DEBIAN_PACKAGE_SOURCE_COPY )
execute_process(COMMAND ${CPACK_DEBIAN_PACKAGE_SOURCE_COPY} "${CMAKE_SOURCE_DIR}" "${DEBIAN_SOURCE_ORIG_DIR}.orig") execute_process(COMMAND ${CPACK_DEBIAN_PACKAGE_SOURCE_COPY} "${CMAKE_SOURCE_DIR}" "${DEBIAN_SOURCE_ORIG_DIR}.orig")
else() else()
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR} "${DEBIAN_SOURCE_ORIG_DIR}.orig") execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR} "${DEBIAN_SOURCE_ORIG_DIR}.orig")
execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory "${DEBIAN_SOURCE_ORIG_DIR}.orig/.git") execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory "${DEBIAN_SOURCE_ORIG_DIR}.orig/.git")
execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory "${DEBIAN_SOURCE_ORIG_DIR}.orig/.svn") execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory "${DEBIAN_SOURCE_ORIG_DIR}.orig/.svn")
endif() endif()
# remove unnecessary folders # remove unnecessary folders
foreach(REMOVE_DIR ${CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES}) foreach(REMOVE_DIR ${CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES})
file(REMOVE_RECURSE ${DEBIAN_SOURCE_ORIG_DIR}.orig/${REMOVE_DIR}) file(REMOVE_RECURSE ${DEBIAN_SOURCE_ORIG_DIR}.orig/${REMOVE_DIR})
endforeach() endforeach()
# create the original source tar # create the original source tar
execute_process(COMMAND ${CMAKE_COMMAND} -E tar czf "${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}.orig.tar.gz" "${CPACK_DEBIAN_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.orig" WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/Debian) execute_process(COMMAND ${CMAKE_COMMAND} -E tar czf "${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_PACKAGE_VERSION}.orig.tar.gz" "${CPACK_DEBIAN_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.orig" WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/Debian)
set(DEB_SOURCE_CHANGES) set(DEB_SOURCE_CHANGES)
foreach(RELEASE ${CPACK_DEBIAN_DISTRIBUTION_RELEASES}) foreach(RELEASE ${CPACK_DEBIAN_DISTRIBUTION_RELEASES})
set(DEBIAN_SOURCE_DIR "${DEBIAN_SOURCE_ORIG_DIR}-${CPACK_DEBIAN_DISTRIBUTION_NAME}1~${RELEASE}1") set(DEBIAN_SOURCE_DIR "${DEBIAN_SOURCE_ORIG_DIR}-${CPACK_DEBIAN_DISTRIBUTION_NAME}1~${RELEASE}1")
set(RELEASE_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}-${CPACK_DEBIAN_DISTRIBUTION_NAME}1~${RELEASE}1") set(RELEASE_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}-${CPACK_DEBIAN_DISTRIBUTION_NAME}1~${RELEASE}1")
string(TOUPPER ${RELEASE} RELEASE_UPPER) string(TOUPPER ${RELEASE} RELEASE_UPPER)
string(TOUPPER ${CPACK_DEBIAN_DISTRIBUTION_NAME} DISTRIBUTION_NAME_UPPER) string(TOUPPER ${CPACK_DEBIAN_DISTRIBUTION_NAME} DISTRIBUTION_NAME_UPPER)
file(MAKE_DIRECTORY ${DEBIAN_SOURCE_DIR}/debian) file(MAKE_DIRECTORY ${DEBIAN_SOURCE_DIR}/debian)
############################################################################## ##############################################################################
# debian/control # debian/control
set(DEBIAN_CONTROL ${DEBIAN_SOURCE_DIR}/debian/control) set(DEBIAN_CONTROL ${DEBIAN_SOURCE_DIR}/debian/control)
file(WRITE ${DEBIAN_CONTROL} file(WRITE ${DEBIAN_CONTROL}
"Source: ${CPACK_DEBIAN_PACKAGE_NAME}\n" "Source: ${CPACK_DEBIAN_PACKAGE_NAME}\n"
"Section: ${CPACK_DEBIAN_PACKAGE_SECTION}\n" "Section: ${CPACK_DEBIAN_PACKAGE_SECTION}\n"
"Priority: ${CPACK_DEBIAN_PACKAGE_PRIORITY}\n" "Priority: ${CPACK_DEBIAN_PACKAGE_PRIORITY}\n"
"DM-Upload-Allowed: yes\n" "DM-Upload-Allowed: yes\n"
"Maintainer: ${CPACK_PACKAGE_CONTACT}\n" "Maintainer: ${CPACK_PACKAGE_CONTACT}\n"
"Build-Depends: " "Build-Depends: "
) )
if( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) if( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
foreach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) foreach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) endforeach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
else( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) else( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
if( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER} ) if( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}}) foreach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}}) endforeach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}})
else( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER} ) else( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS}) foreach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS}) endforeach(DEP ${CPACK_DEBIAN_BUILD_DEPENDS})
endif( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER} ) endif( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
endif( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) endif( CPACK_DEBIAN_BUILD_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
file(APPEND ${DEBIAN_CONTROL} "\n" file(APPEND ${DEBIAN_CONTROL} "\n"
"Standards-Version: 3.8.4\n" "Standards-Version: 3.8.4\n"
"Homepage: ${CPACK_PACKAGE_VENDOR}\n" "Homepage: ${CPACK_PACKAGE_VENDOR}\n"
"\n" "\n"
"Package: ${CPACK_DEBIAN_PACKAGE_NAME}\n" "Package: ${CPACK_DEBIAN_PACKAGE_NAME}\n"
"Architecture: any\n" "Architecture: any\n"
"Depends: " "Depends: "
) )
if( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) if( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
foreach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) foreach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) endforeach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
else( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) else( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
if( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER} ) if( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}}) foreach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}}) endforeach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}})
else( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER} ) else( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS}) foreach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS}) endforeach(DEP ${CPACK_DEBIAN_PACKAGE_DEPENDS})
endif( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER} ) endif( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
endif( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) endif( CPACK_DEBIAN_PACKAGE_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
file(APPEND ${DEBIAN_CONTROL} "\nRecommends: ") file(APPEND ${DEBIAN_CONTROL} "\nRecommends: ")
if( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) if( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
foreach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) foreach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) endforeach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
else( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) else( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
if( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} ) if( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}}) foreach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}}) endforeach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}})
else( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} ) else( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS}) foreach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS}) endforeach(DEP ${CPACK_DEBIAN_PACKAGE_RECOMMENDS})
endif( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} ) endif( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} )
endif( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) endif( CPACK_DEBIAN_PACKAGE_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
file(APPEND ${DEBIAN_CONTROL} "\nSuggests: ") file(APPEND ${DEBIAN_CONTROL} "\nSuggests: ")
if( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) if( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
foreach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) foreach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) endforeach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
else( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) else( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
if( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER} ) if( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}}) foreach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}}) endforeach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}})
else( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER} ) else( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS}) foreach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS})
file(APPEND ${DEBIAN_CONTROL} "${DEP}, ") file(APPEND ${DEBIAN_CONTROL} "${DEP}, ")
endforeach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS}) endforeach(DEP ${CPACK_DEBIAN_PACKAGE_SUGGESTS})
endif( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER} ) endif( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER} )
endif( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) endif( CPACK_DEBIAN_PACKAGE_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
file(APPEND ${DEBIAN_CONTROL} "\n" file(APPEND ${DEBIAN_CONTROL} "\n"
"Description: ${CPACK_PACKAGE_DISPLAY_NAME} ${CPACK_PACKAGE_DESCRIPTION_SUMMARY}\n" "Description: ${CPACK_PACKAGE_DISPLAY_NAME} ${CPACK_PACKAGE_DESCRIPTION_SUMMARY}\n"
"${DEB_LONG_DESCRIPTION}" "${DEB_LONG_DESCRIPTION}"
) )
foreach(COMPONENT ${CPACK_COMPONENTS_ALL}) foreach(COMPONENT ${CPACK_COMPONENTS_ALL})
string(TOUPPER ${COMPONENT} UPPER_COMPONENT) string(TOUPPER ${COMPONENT} UPPER_COMPONENT)
set(DEPENDS "\${shlibs:Depends}") set(DEPENDS "\${shlibs:Depends}")
if( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) if( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
set(DEPENDS "${DEPENDS}, ${DEP}") set(DEPENDS "${DEPENDS}, ${DEP}")
endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
else( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) else( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
if( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER} ) if( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}}) foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}})
set(DEPENDS "${DEPENDS}, ${DEP}") set(DEPENDS "${DEPENDS}, ${DEP}")
endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}}) endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}})
else( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER} ) else( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS}) foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS})
set(DEPENDS "${DEPENDS}, ${DEP}") set(DEPENDS "${DEPENDS}, ${DEP}")
endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS}) endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS})
endif( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER} ) endif( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER} )
endif( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) endif( CPACK_COMPONENT_${UPPER_COMPONENT}_DEPENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
set(RECOMMENDS) set(RECOMMENDS)
if( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) if( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
set(RECOMMENDS "${RECOMMENDS} ${DEP}, ") set(RECOMMENDS "${RECOMMENDS} ${DEP}, ")
endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
else( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) else( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
if( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} ) if( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}}) foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}})
set(RECOMMENDS "${RECOMMENDS} ${DEP}, ") set(RECOMMENDS "${RECOMMENDS} ${DEP}, ")
endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}}) endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}})
else( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} ) else( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS}) foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS})
set(RECOMMENDS "${RECOMMENDS} ${DEP}, ") set(RECOMMENDS "${RECOMMENDS} ${DEP}, ")
endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS}) endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS})
endif( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} ) endif( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER} )
endif( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) endif( CPACK_COMPONENT_${UPPER_COMPONENT}_RECOMMENDS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
set(SUGGESTS) set(SUGGESTS)
if( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) if( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
set(SUGGESTS "${SUGGESTS} ${DEP}, ") set(SUGGESTS "${SUGGESTS} ${DEP}, ")
endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}}) endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER}})
else( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) else( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
if( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER} ) if( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}}) foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}})
set(SUGGESTS "${SUGGESTS} ${DEP}, ") set(SUGGESTS "${SUGGESTS} ${DEP}, ")
endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}}) endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}})
else( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER} ) else( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER} )
foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS}) foreach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS})
set(SUGGESTS "${SUGGESTS} ${DEP}, ") set(SUGGESTS "${SUGGESTS} ${DEP}, ")
endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS}) endforeach(DEP ${CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS})
endif( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER} ) endif( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER} )
endif( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} ) endif( CPACK_COMPONENT_${UPPER_COMPONENT}_SUGGESTS_${DISTRIBUTION_NAME_UPPER}_${RELEASE_UPPER} )
file(APPEND ${DEBIAN_CONTROL} "\n" file(APPEND ${DEBIAN_CONTROL} "\n"
"Package: ${COMPONENT}\n" "Package: ${COMPONENT}\n"
"Architecture: any\n" "Architecture: any\n"
"Depends: ${DEPENDS}\n" "Depends: ${DEPENDS}\n"
"Recommends: ${RECOMMENDS}\n" "Recommends: ${RECOMMENDS}\n"
"Suggests: ${SUGGESTS}\n" "Suggests: ${SUGGESTS}\n"
"Description: ${CPACK_PACKAGE_DISPLAY_NAME} ${CPACK_COMPONENT_${UPPER_COMPONENT}_DISPLAY_NAME}\n" "Description: ${CPACK_PACKAGE_DISPLAY_NAME} ${CPACK_COMPONENT_${UPPER_COMPONENT}_DISPLAY_NAME}\n"
"${DEB_LONG_DESCRIPTION}" "${DEB_LONG_DESCRIPTION}"
" .\n" " .\n"
" ${CPACK_COMPONENT_${UPPER_COMPONENT}_DESCRIPTION}\n" " ${CPACK_COMPONENT_${UPPER_COMPONENT}_DESCRIPTION}\n"
) )
endforeach(COMPONENT ${CPACK_COMPONENTS_ALL}) endforeach(COMPONENT ${CPACK_COMPONENTS_ALL})
############################################################################## ##############################################################################
# debian/copyright # debian/copyright
set(DEBIAN_COPYRIGHT ${DEBIAN_SOURCE_DIR}/debian/copyright) set(DEBIAN_COPYRIGHT ${DEBIAN_SOURCE_DIR}/debian/copyright)
execute_process(COMMAND ${CMAKE_COMMAND} -E execute_process(COMMAND ${CMAKE_COMMAND} -E
copy ${CPACK_RESOURCE_FILE_LICENSE} ${DEBIAN_COPYRIGHT} copy ${CPACK_RESOURCE_FILE_LICENSE} ${DEBIAN_COPYRIGHT}
) )
############################################################################## ##############################################################################
# debian/rules # debian/rules
set(DEBIAN_RULES ${DEBIAN_SOURCE_DIR}/debian/rules) set(DEBIAN_RULES ${DEBIAN_SOURCE_DIR}/debian/rules)
file(WRITE ${DEBIAN_RULES} file(WRITE ${DEBIAN_RULES}
"#!/usr/bin/make -f\n" "#!/usr/bin/make -f\n"
"\n" "\n"
"BUILDDIR = build_dir\n" "BUILDDIR = build_dir\n"
"\n" "\n"
"build:\n" "build:\n"
" mkdir $(BUILDDIR)\n" " mkdir $(BUILDDIR)\n"
" cd $(BUILDDIR); cmake -DCMAKE_BUILD_TYPE=Release ${CPACK_DEBIAN_CMAKE_OPTIONS} -DCMAKE_INSTALL_PREFIX=/usr ..\n" " cd $(BUILDDIR); cmake -DCMAKE_BUILD_TYPE=Release ${CPACK_DEBIAN_CMAKE_OPTIONS} -DCMAKE_INSTALL_PREFIX=/usr ..\n"
" $(MAKE) -C $(BUILDDIR) preinstall\n" " $(MAKE) -C $(BUILDDIR) preinstall\n"
" touch build\n" " touch build\n"
"\n" "\n"
"binary: binary-indep binary-arch\n" "binary: binary-indep binary-arch\n"
"\n" "\n"
"binary-indep: build\n" "binary-indep: build\n"
"\n" "\n"
"binary-arch: build\n" "binary-arch: build\n"
" cd $(BUILDDIR); cmake -DCOMPONENT=Unspecified -DCMAKE_INSTALL_PREFIX=../debian/tmp/usr -P cmake_install.cmake\n" " cd $(BUILDDIR); cmake -DCOMPONENT=Unspecified -DCMAKE_INSTALL_PREFIX=../debian/tmp/usr -P cmake_install.cmake\n"
" mkdir -p debian/tmp/DEBIAN\n" " mkdir -p debian/tmp/DEBIAN\n"
" dpkg-gensymbols -p${CPACK_DEBIAN_PACKAGE_NAME}\n" " dpkg-gensymbols -p${CPACK_DEBIAN_PACKAGE_NAME}\n"
) )
foreach(COMPONENT ${CPACK_COMPONENTS_ALL}) foreach(COMPONENT ${CPACK_COMPONENTS_ALL})
set(PATH debian/${COMPONENT}) set(PATH debian/${COMPONENT})
file(APPEND ${DEBIAN_RULES} file(APPEND ${DEBIAN_RULES}
" cd $(BUILDDIR); cmake -DCOMPONENT=${COMPONENT} -DCMAKE_INSTALL_PREFIX=../${PATH}/usr -P cmake_install.cmake\n" " cd $(BUILDDIR); cmake -DCOMPONENT=${COMPONENT} -DCMAKE_INSTALL_PREFIX=../${PATH}/usr -P cmake_install.cmake\n"
" mkdir -p ${PATH}/DEBIAN\n" " mkdir -p ${PATH}/DEBIAN\n"
" dpkg-gensymbols -p${COMPONENT} -P${PATH}\n" " dpkg-gensymbols -p${COMPONENT} -P${PATH}\n"
) )
endforeach(COMPONENT ${CPACK_COMPONENTS_ALL}) endforeach(COMPONENT ${CPACK_COMPONENTS_ALL})
file(APPEND ${DEBIAN_RULES} file(APPEND ${DEBIAN_RULES}
" dh_shlibdeps\n" " dh_shlibdeps\n"
" dh_strip\n" # for reducing size " dh_strip\n" # for reducing size
" dpkg-gencontrol -p${CPACK_DEBIAN_PACKAGE_NAME}\n" " dpkg-gencontrol -p${CPACK_DEBIAN_PACKAGE_NAME}\n"
" dpkg --build debian/tmp ..\n" " dpkg --build debian/tmp ..\n"
) )
foreach(COMPONENT ${CPACK_COMPONENTS_ALL}) foreach(COMPONENT ${CPACK_COMPONENTS_ALL})
set(PATH debian/${COMPONENT}) set(PATH debian/${COMPONENT})
file(APPEND ${DEBIAN_RULES} file(APPEND ${DEBIAN_RULES}
" dpkg-gencontrol -p${COMPONENT} -P${PATH} -Tdebian/${COMPONENT}.substvars\n" " dpkg-gencontrol -p${COMPONENT} -P${PATH} -Tdebian/${COMPONENT}.substvars\n"
" dpkg --build ${PATH} ..\n" " dpkg --build ${PATH} ..\n"
) )
endforeach(COMPONENT ${CPACK_COMPONENTS_ALL}) endforeach(COMPONENT ${CPACK_COMPONENTS_ALL})
file(APPEND ${DEBIAN_RULES} file(APPEND ${DEBIAN_RULES}
"\n" "\n"
"clean:\n" "clean:\n"
" rm -f build\n" " rm -f build\n"
" rm -rf $(BUILDDIR)\n" " rm -rf $(BUILDDIR)\n"
"\n" "\n"
".PHONY: binary binary-arch binary-indep clean\n" ".PHONY: binary binary-arch binary-indep clean\n"
) )
execute_process(COMMAND chmod +x ${DEBIAN_RULES}) execute_process(COMMAND chmod +x ${DEBIAN_RULES})
############################################################################## ##############################################################################
# debian/compat # debian/compat
file(WRITE ${DEBIAN_SOURCE_DIR}/debian/compat "7") file(WRITE ${DEBIAN_SOURCE_DIR}/debian/compat "7")
############################################################################## ##############################################################################
# debian/source/format # debian/source/format
file(WRITE ${DEBIAN_SOURCE_DIR}/debian/source/format "3.0 (quilt)") file(WRITE ${DEBIAN_SOURCE_DIR}/debian/source/format "3.0 (quilt)")
############################################################################## ##############################################################################
# debian/changelog # debian/changelog
set(DEBIAN_CHANGELOG ${DEBIAN_SOURCE_DIR}/debian/changelog) set(DEBIAN_CHANGELOG ${DEBIAN_SOURCE_DIR}/debian/changelog)
execute_process(COMMAND date -R OUTPUT_VARIABLE DATE_TIME) execute_process(COMMAND date -R OUTPUT_VARIABLE DATE_TIME)
file(WRITE ${DEBIAN_CHANGELOG} file(WRITE ${DEBIAN_CHANGELOG}
"${CPACK_DEBIAN_PACKAGE_NAME} (${RELEASE_PACKAGE_VERSION}) ${RELEASE}; urgency=medium\n\n" "${CPACK_DEBIAN_PACKAGE_NAME} (${RELEASE_PACKAGE_VERSION}) ${RELEASE}; urgency=medium\n\n"
" * Package built with CMake\n\n" " * Package built with CMake\n\n"
"${CPACK_DEBIAN_CHANGELOG}" "${CPACK_DEBIAN_CHANGELOG}"
" -- ${CPACK_PACKAGE_CONTACT} ${DATE_TIME}" " -- ${CPACK_PACKAGE_CONTACT} ${DATE_TIME}"
) )
############################################################################## ##############################################################################
# debuild -S # debuild -S
if( DEB_SOURCE_CHANGES ) if( DEB_SOURCE_CHANGES )
set(DEBUILD_OPTIONS "-sd") set(DEBUILD_OPTIONS "-sd")
else() else()
set(DEBUILD_OPTIONS "-sa") set(DEBUILD_OPTIONS "-sa")
endif() endif()
set(SOURCE_CHANGES_FILE "${CPACK_DEBIAN_PACKAGE_NAME}_${RELEASE_PACKAGE_VERSION}_source.changes") set(SOURCE_CHANGES_FILE "${CPACK_DEBIAN_PACKAGE_NAME}_${RELEASE_PACKAGE_VERSION}_source.changes")
set(DEB_SOURCE_CHANGES ${DEB_SOURCE_CHANGES} "${SOURCE_CHANGES_FILE}") set(DEB_SOURCE_CHANGES ${DEB_SOURCE_CHANGES} "${SOURCE_CHANGES_FILE}")
add_custom_command(OUTPUT "${SOURCE_CHANGES_FILE}" COMMAND ${DEBUILD_EXECUTABLE} -S ${DEBUILD_OPTIONS} WORKING_DIRECTORY ${DEBIAN_SOURCE_DIR}) add_custom_command(OUTPUT "${SOURCE_CHANGES_FILE}" COMMAND ${DEBUILD_EXECUTABLE} -S ${DEBUILD_OPTIONS} WORKING_DIRECTORY ${DEBIAN_SOURCE_DIR})
endforeach(RELEASE ${CPACK_DEBIAN_DISTRIBUTION_RELEASES}) endforeach(RELEASE ${CPACK_DEBIAN_DISTRIBUTION_RELEASES})
############################################################################## ##############################################################################
# dput ppa:your-lp-id/ppa <source.changes> # dput ppa:your-lp-id/ppa <source.changes>
add_custom_target(dput ${DPUT_EXECUTABLE} ${DPUT_HOST} ${DEB_SOURCE_CHANGES} DEPENDS ${DEB_SOURCE_CHANGES} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/Debian) add_custom_target(dput ${DPUT_EXECUTABLE} ${DPUT_HOST} ${DEB_SOURCE_CHANGES} DEPENDS ${DEB_SOURCE_CHANGES} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/Debian)

View File

@ -1,100 +1,101 @@
#------------------------------------------------------------------- #-------------------------------------------------------------------
# This file is part of the CMake build system for OGRE # This file is part of the CMake build system for OGRE
# (Object-oriented Graphics Rendering Engine) # (Object-oriented Graphics Rendering Engine)
# For the latest info, see http://www.ogre3d.org/ # For the latest info, see http://www.ogre3d.org/
# #
# The contents of this file are placed in the public domain. Feel # The contents of this file are placed in the public domain. Feel
# free to make use of it in any way you like. # free to make use of it in any way you like.
#------------------------------------------------------------------- #-------------------------------------------------------------------
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Find DirectX SDK # Find DirectX SDK
# Define: # Define:
# DirectX_FOUND # DirectX_FOUND
# DirectX_INCLUDE_DIR # DirectX_INCLUDE_DIR
# DirectX_LIBRARY # DirectX_LIBRARY
# DirectX_ROOT_DIR # DirectX_ROOT_DIR
if(WIN32) # The only platform it makes sense to check for DirectX SDK if(WIN32) # The only platform it makes sense to check for DirectX SDK
include(FindPkgMacros) include(FindPkgMacros)
findpkg_begin(DirectX) findpkg_begin(DirectX)
# Get path, convert backslashes as ${ENV_DXSDK_DIR} # Get path, convert backslashes as ${ENV_DXSDK_DIR}
getenv_path(DXSDK_DIR) getenv_path(DXSDK_DIR)
getenv_path(DIRECTX_HOME) getenv_path(DIRECTX_HOME)
getenv_path(DIRECTX_ROOT) getenv_path(DIRECTX_ROOT)
getenv_path(DIRECTX_BASE) getenv_path(DIRECTX_BASE)
# construct search paths # construct search paths
set(DirectX_PREFIX_PATH set(DirectX_PREFIX_PATH
"${DXSDK_DIR}" "${ENV_DXSDK_DIR}" "${DXSDK_DIR}" "${ENV_DXSDK_DIR}"
"${DIRECTX_HOME}" "${ENV_DIRECTX_HOME}" "${DIRECTX_HOME}" "${ENV_DIRECTX_HOME}"
"${DIRECTX_ROOT}" "${ENV_DIRECTX_ROOT}" "${DIRECTX_ROOT}" "${ENV_DIRECTX_ROOT}"
"${DIRECTX_BASE}" "${ENV_DIRECTX_BASE}" "${DIRECTX_BASE}" "${ENV_DIRECTX_BASE}"
"C:/apps_x86/Microsoft DirectX SDK*" "C:/apps_x86/Microsoft DirectX SDK*"
"C:/Program Files (x86)/Microsoft DirectX SDK*" "C:/Program Files (x86)/Microsoft DirectX SDK*"
"C:/apps/Microsoft DirectX SDK*" "C:/apps/Microsoft DirectX SDK*"
"C:/Program Files/Microsoft DirectX SDK*" "C:/Program Files/Microsoft DirectX SDK*"
"$ENV{ProgramFiles}/Microsoft DirectX SDK*" "C:/Program Files (x86)/Windows Kits/8.1"
) "$ENV{ProgramFiles}/Microsoft DirectX SDK*"
create_search_paths(DirectX) )
# redo search if prefix path changed create_search_paths(DirectX)
clear_if_changed(DirectX_PREFIX_PATH # redo search if prefix path changed
DirectX_LIBRARY clear_if_changed(DirectX_PREFIX_PATH
DirectX_INCLUDE_DIR DirectX_LIBRARY
) DirectX_INCLUDE_DIR
)
find_path(DirectX_INCLUDE_DIR NAMES d3d9.h HINTS ${DirectX_INC_SEARCH_PATH})
# dlls are in DirectX_ROOT_DIR/Developer Runtime/x64|x86 find_path(DirectX_INCLUDE_DIR NAMES d3d9.h HINTS ${DirectX_INC_SEARCH_PATH})
# lib files are in DirectX_ROOT_DIR/Lib/x64|x86 # dlls are in DirectX_ROOT_DIR/Developer Runtime/x64|x86
if(CMAKE_CL_64) # lib files are in DirectX_ROOT_DIR/Lib/x64|x86
set(DirectX_LIBPATH_SUFFIX "x64") if(CMAKE_CL_64)
else(CMAKE_CL_64) set(DirectX_LIBPATH_SUFFIX "x64")
set(DirectX_LIBPATH_SUFFIX "x86") else(CMAKE_CL_64)
endif(CMAKE_CL_64) set(DirectX_LIBPATH_SUFFIX "x86")
find_library(DirectX_LIBRARY NAMES d3d9 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) endif(CMAKE_CL_64)
find_library(DirectX_D3DX9_LIBRARY NAMES d3dx9 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) find_library(DirectX_LIBRARY NAMES d3d9 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
find_library(DirectX_DXERR_LIBRARY NAMES DxErr HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) find_library(DirectX_D3DX9_LIBRARY NAMES d3dx9 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
find_library(DirectX_DXGUID_LIBRARY NAMES dxguid HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) find_library(DirectX_DXERR_LIBRARY NAMES DxErr HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
find_library(DirectX_DXGUID_LIBRARY NAMES dxguid HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
# look for dxgi (needed by both 10 and 11)
find_library(DirectX_DXGI_LIBRARY NAMES dxgi HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) # look for dxgi (needed by both 10 and 11)
find_library(DirectX_DXGI_LIBRARY NAMES dxgi HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
# look for d3dcompiler (needed by 11)
find_library(DirectX_D3DCOMPILER_LIBRARY NAMES d3dcompiler HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) # look for d3dcompiler (needed by 11)
find_library(DirectX_D3DCOMPILER_LIBRARY NAMES d3dcompiler HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
findpkg_finish(DirectX)
set(DirectX_LIBRARIES ${DirectX_LIBRARIES} findpkg_finish(DirectX)
${DirectX_D3DX9_LIBRARY} set(DirectX_LIBRARIES ${DirectX_LIBRARIES}
${DirectX_DXERR_LIBRARY} ${DirectX_D3DX9_LIBRARY}
${DirectX_DXGUID_LIBRARY} ${DirectX_DXERR_LIBRARY}
) ${DirectX_DXGUID_LIBRARY}
)
mark_as_advanced(DirectX_D3DX9_LIBRARY DirectX_DXERR_LIBRARY DirectX_DXGUID_LIBRARY
DirectX_DXGI_LIBRARY DirectX_D3DCOMPILER_LIBRARY) mark_as_advanced(DirectX_D3DX9_LIBRARY DirectX_DXERR_LIBRARY DirectX_DXGUID_LIBRARY
DirectX_DXGI_LIBRARY DirectX_D3DCOMPILER_LIBRARY)
# look for D3D11 components
if (DirectX_FOUND) # look for D3D11 components
find_path(DirectX_D3D11_INCLUDE_DIR NAMES D3D11Shader.h HINTS ${DirectX_INC_SEARCH_PATH}) if (DirectX_FOUND)
get_filename_component(DirectX_LIBRARY_DIR "${DirectX_LIBRARY}" PATH) find_path(DirectX_D3D11_INCLUDE_DIR NAMES D3D11Shader.h HINTS ${DirectX_INC_SEARCH_PATH})
message(STATUS "DX lib dir: ${DirectX_LIBRARY_DIR}") get_filename_component(DirectX_LIBRARY_DIR "${DirectX_LIBRARY}" PATH)
find_library(DirectX_D3D11_LIBRARY NAMES d3d11 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) message(STATUS "DX lib dir: ${DirectX_LIBRARY_DIR}")
find_library(DirectX_D3DX11_LIBRARY NAMES d3dx11 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX}) find_library(DirectX_D3D11_LIBRARY NAMES d3d11 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
if (DirectX_D3D11_INCLUDE_DIR AND DirectX_D3D11_LIBRARY) find_library(DirectX_D3DX11_LIBRARY NAMES d3dx11 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
set(DirectX_D3D11_FOUND TRUE) if (DirectX_D3D11_INCLUDE_DIR AND DirectX_D3D11_LIBRARY)
set(DirectX_D3D11_INCLUDE_DIR ${DirectX_D3D11_INCLUDE_DIR}) set(DirectX_D3D11_FOUND TRUE)
set(DirectX_D3D11_LIBRARIES ${DirectX_D3D11_LIBRARIES} set(DirectX_D3D11_INCLUDE_DIR ${DirectX_D3D11_INCLUDE_DIR})
${DirectX_D3D11_LIBRARY} set(DirectX_D3D11_LIBRARIES ${DirectX_D3D11_LIBRARIES}
${DirectX_D3DX11_LIBRARY} ${DirectX_D3D11_LIBRARY}
${DirectX_DXGI_LIBRARY} ${DirectX_D3DX11_LIBRARY}
${DirectX_DXERR_LIBRARY} ${DirectX_DXGI_LIBRARY}
${DirectX_DXGUID_LIBRARY} ${DirectX_DXERR_LIBRARY}
${DirectX_D3DCOMPILER_LIBRARY} ${DirectX_DXGUID_LIBRARY}
) ${DirectX_D3DCOMPILER_LIBRARY}
endif () )
mark_as_advanced(DirectX_D3D11_INCLUDE_DIR DirectX_D3D11_LIBRARY DirectX_D3DX11_LIBRARY) endif ()
endif () mark_as_advanced(DirectX_D3D11_INCLUDE_DIR DirectX_D3D11_LIBRARY DirectX_D3DX11_LIBRARY)
endif ()
endif(WIN32)
endif(WIN32)

View File

@ -1,142 +1,143 @@
#------------------------------------------------------------------- #-------------------------------------------------------------------
# This file is part of the CMake build system for OGRE # This file is part of the CMake build system for OGRE
# (Object-oriented Graphics Rendering Engine) # (Object-oriented Graphics Rendering Engine)
# For the latest info, see http://www.ogre3d.org/ # For the latest info, see http://www.ogre3d.org/
# #
# The contents of this file are placed in the public domain. Feel # The contents of this file are placed in the public domain. Feel
# free to make use of it in any way you like. # free to make use of it in any way you like.
#------------------------------------------------------------------- #-------------------------------------------------------------------
################################################################## ##################################################################
# Provides some common functionality for the FindPackage modules # Provides some common functionality for the FindPackage modules
################################################################## ##################################################################
# Begin processing of package # Begin processing of package
macro(findpkg_begin PREFIX) macro(findpkg_begin PREFIX)
if (NOT ${PREFIX}_FIND_QUIETLY) if (NOT ${PREFIX}_FIND_QUIETLY)
message(STATUS "Looking for ${PREFIX}...") message(STATUS "Looking for ${PREFIX}...")
endif () endif ()
endmacro(findpkg_begin) endmacro(findpkg_begin)
# Display a status message unless FIND_QUIETLY is set # Display a status message unless FIND_QUIETLY is set
macro(pkg_message PREFIX) macro(pkg_message PREFIX)
if (NOT ${PREFIX}_FIND_QUIETLY) if (NOT ${PREFIX}_FIND_QUIETLY)
message(STATUS ${ARGN}) message(STATUS ${ARGN})
endif () endif ()
endmacro(pkg_message) endmacro(pkg_message)
# Get environment variable, define it as ENV_$var and make sure backslashes are converted to forward slashes # Get environment variable, define it as ENV_$var and make sure backslashes are converted to forward slashes
macro(getenv_path VAR) macro(getenv_path VAR)
set(ENV_${VAR} $ENV{${VAR}}) set(ENV_${VAR} $ENV{${VAR}})
# replace won't work if var is blank # replace won't work if var is blank
if (ENV_${VAR}) if (ENV_${VAR})
string( REGEX REPLACE "\\\\" "/" ENV_${VAR} ${ENV_${VAR}} ) string( REGEX REPLACE "\\\\" "/" ENV_${VAR} ${ENV_${VAR}} )
endif () endif ()
endmacro(getenv_path) endmacro(getenv_path)
# Construct search paths for includes and libraries from a PREFIX_PATH # Construct search paths for includes and libraries from a PREFIX_PATH
macro(create_search_paths PREFIX) macro(create_search_paths PREFIX)
foreach(dir ${${PREFIX}_PREFIX_PATH}) foreach(dir ${${PREFIX}_PREFIX_PATH})
set(${PREFIX}_INC_SEARCH_PATH ${${PREFIX}_INC_SEARCH_PATH} set(${PREFIX}_INC_SEARCH_PATH ${${PREFIX}_INC_SEARCH_PATH}
${dir}/include ${dir}/include/${PREFIX} ${dir}/Headers) ${dir}/include ${dir}/include/${PREFIX} ${dir}/Headers)
set(${PREFIX}_LIB_SEARCH_PATH ${${PREFIX}_LIB_SEARCH_PATH} set(${PREFIX}_LIB_SEARCH_PATH ${${PREFIX}_LIB_SEARCH_PATH}
${dir}/lib ${dir}/lib/${PREFIX} ${dir}/Libs) ${dir}/lib ${dir}/lib/${PREFIX} ${dir}/Libs)
endforeach(dir) endforeach(dir)
set(${PREFIX}_FRAMEWORK_SEARCH_PATH ${${PREFIX}_PREFIX_PATH}) set(${PREFIX}_FRAMEWORK_SEARCH_PATH ${${PREFIX}_PREFIX_PATH})
endmacro(create_search_paths) endmacro(create_search_paths)
# clear cache variables if a certain variable changed # clear cache variables if a certain variable changed
macro(clear_if_changed TESTVAR) macro(clear_if_changed TESTVAR)
# test against internal check variable # test against internal check variable
if (NOT "${${TESTVAR}}" STREQUAL "${${TESTVAR}_INT_CHECK}") if (NOT "${${TESTVAR}}" STREQUAL "${${TESTVAR}_INT_CHECK}")
message(STATUS "${TESTVAR} changed.") message(STATUS "${TESTVAR} changed.")
foreach(var ${ARGN}) foreach(var ${ARGN})
set(${var} "NOTFOUND" CACHE STRING "x" FORCE) set(${var} "NOTFOUND" CACHE STRING "x" FORCE)
endforeach(var) endforeach(var)
endif () endif ()
set(${TESTVAR}_INT_CHECK ${${TESTVAR}} CACHE INTERNAL "x" FORCE) set(${TESTVAR}_INT_CHECK ${${TESTVAR}} CACHE INTERNAL "x" FORCE)
endmacro(clear_if_changed) endmacro(clear_if_changed)
# Try to get some hints from pkg-config, if available # Try to get some hints from pkg-config, if available
macro(use_pkgconfig PREFIX PKGNAME) macro(use_pkgconfig PREFIX PKGNAME)
find_package(PkgConfig) find_package(PkgConfig)
if (PKG_CONFIG_FOUND) if (PKG_CONFIG_FOUND)
pkg_check_modules(${PREFIX} ${PKGNAME}) pkg_check_modules(${PREFIX} ${PKGNAME})
endif () endif ()
endmacro (use_pkgconfig) endmacro (use_pkgconfig)
# Couple a set of release AND debug libraries (or frameworks) # Couple a set of release AND debug libraries (or frameworks)
macro(make_library_set PREFIX) macro(make_library_set PREFIX)
if (${PREFIX}_FWK) if (${PREFIX}_FWK)
set(${PREFIX} ${${PREFIX}_FWK}) set(${PREFIX} ${${PREFIX}_FWK})
elseif (${PREFIX}_REL AND ${PREFIX}_DBG) elseif (${PREFIX}_REL AND ${PREFIX}_DBG)
set(${PREFIX} optimized ${${PREFIX}_REL} debug ${${PREFIX}_DBG}) set(${PREFIX} optimized ${${PREFIX}_REL} debug ${${PREFIX}_DBG})
elseif (${PREFIX}_REL) elseif (${PREFIX}_REL)
set(${PREFIX} ${${PREFIX}_REL}) set(${PREFIX} ${${PREFIX}_REL})
elseif (${PREFIX}_DBG) elseif (${PREFIX}_DBG)
set(${PREFIX} ${${PREFIX}_DBG}) set(${PREFIX} ${${PREFIX}_DBG})
endif () endif ()
endmacro(make_library_set) endmacro(make_library_set)
# Generate debug names from given release names # Generate debug names from given release names
macro(get_debug_names PREFIX) macro(get_debug_names PREFIX)
foreach(i ${${PREFIX}}) foreach(i ${${PREFIX}})
set(${PREFIX}_DBG ${${PREFIX}_DBG} ${i}d ${i}D ${i}_d ${i}_D ${i}_debug ${i}) set(${PREFIX}_DBG ${${PREFIX}_DBG} ${i}d ${i}D ${i}_d ${i}_D ${i}_debug ${i})
endforeach(i) endforeach(i)
endmacro(get_debug_names) endmacro(get_debug_names)
# Add the parent dir from DIR to VAR # Add the parent dir from DIR to VAR
macro(add_parent_dir VAR DIR) macro(add_parent_dir VAR DIR)
get_filename_component(${DIR}_TEMP "${${DIR}}/.." ABSOLUTE) get_filename_component(${DIR}_TEMP "${${DIR}}/.." ABSOLUTE)
set(${VAR} ${${VAR}} ${${DIR}_TEMP}) set(${VAR} ${${VAR}} ${${DIR}_TEMP})
endmacro(add_parent_dir) endmacro(add_parent_dir)
# Do the final processing for the package find. # Do the final processing for the package find.
macro(findpkg_finish PREFIX) macro(findpkg_finish PREFIX)
# skip if already processed during this run # skip if already processed during this run
if (NOT ${PREFIX}_FOUND) if (NOT ${PREFIX}_FOUND)
if (${PREFIX}_INCLUDE_DIR AND ${PREFIX}_LIBRARY) if (${PREFIX}_INCLUDE_DIR AND ${PREFIX}_LIBRARY)
set(${PREFIX}_FOUND TRUE) set(${PREFIX}_FOUND TRUE)
set(${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIR}) set(${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIR})
set(${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARY}) set(${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARY})
if (NOT ${PREFIX}_FIND_QUIETLY) if (NOT ${PREFIX}_FIND_QUIETLY)
message(STATUS "Found ${PREFIX}: ${${PREFIX}_LIBRARIES}") message(STATUS "Found ${PREFIX}: ${${PREFIX}_LIBRARIES}")
endif () endif ()
else () else ()
if (NOT ${PREFIX}_FIND_QUIETLY) if (NOT ${PREFIX}_FIND_QUIETLY)
message(STATUS "Could not locate ${PREFIX}") message(STATUS "Could not locate ${PREFIX}")
endif () endif ()
if (${PREFIX}_FIND_REQUIRED) if (${PREFIX}_FIND_REQUIRED)
message(FATAL_ERROR "Required library ${PREFIX} not found! Install the library (including dev packages) and try again. If the library is already installed, set the missing variables manually in cmake.") message(FATAL_ERROR "Required library ${PREFIX} not found! Install the library (including dev packages) and try again. If the library is already installed, set the missing variables manually in cmake.")
endif () endif ()
endif () endif ()
mark_as_advanced(${PREFIX}_INCLUDE_DIR ${PREFIX}_LIBRARY ${PREFIX}_LIBRARY_REL ${PREFIX}_LIBRARY_DBG ${PREFIX}_LIBRARY_FWK) mark_as_advanced(${PREFIX}_INCLUDE_DIR ${PREFIX}_LIBRARY ${PREFIX}_LIBRARY_REL ${PREFIX}_LIBRARY_DBG ${PREFIX}_LIBRARY_FWK)
endif () endif ()
endmacro(findpkg_finish) endmacro(findpkg_finish)
# Slightly customised framework finder # Slightly customised framework finder
MACRO(findpkg_framework fwk) MACRO(findpkg_framework fwk)
IF(APPLE) IF(APPLE)
SET(${fwk}_FRAMEWORK_PATH SET(${fwk}_FRAMEWORK_PATH
${${fwk}_FRAMEWORK_SEARCH_PATH} ${${fwk}_FRAMEWORK_SEARCH_PATH}
${CMAKE_FRAMEWORK_PATH} ${CMAKE_FRAMEWORK_PATH}
~/Library/Frameworks ~/Library/Frameworks
/Library/Frameworks /Library/Frameworks
/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}) )
SET(fwkpath ${dir}/${fwk}.framework) FOREACH(dir ${${fwk}_FRAMEWORK_PATH})
IF(EXISTS ${fwkpath}) SET(fwkpath ${dir}/${fwk}.framework)
SET(${fwk}_FRAMEWORK_INCLUDES ${${fwk}_FRAMEWORK_INCLUDES} IF(EXISTS ${fwkpath})
${fwkpath}/Headers ${fwkpath}/PrivateHeaders) SET(${fwk}_FRAMEWORK_INCLUDES ${${fwk}_FRAMEWORK_INCLUDES}
if (NOT ${fwk}_LIBRARY_FWK) ${fwkpath}/Headers ${fwkpath}/PrivateHeaders)
SET(${fwk}_LIBRARY_FWK "-framework ${fwk}") if (NOT ${fwk}_LIBRARY_FWK)
endif () SET(${fwk}_LIBRARY_FWK "-framework ${fwk}")
ENDIF(EXISTS ${fwkpath}) endif ()
ENDFOREACH(dir) ENDIF(EXISTS ${fwkpath})
ENDIF(APPLE) ENDFOREACH(dir)
ENDMACRO(findpkg_framework) ENDIF(APPLE)
ENDMACRO(findpkg_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,48 +1,48 @@
#------------------------------------------------------------------- #-------------------------------------------------------------------
# This file is part of the CMake build system for OGRE # This file is part of the CMake build system for OGRE
# (Object-oriented Graphics Rendering Engine) # (Object-oriented Graphics Rendering Engine)
# For the latest info, see http://www.ogre3d.org/ # For the latest info, see http://www.ogre3d.org/
# #
# The contents of this file are placed in the public domain. Feel # The contents of this file are placed in the public domain. Feel
# free to make use of it in any way you like. # free to make use of it in any way you like.
#------------------------------------------------------------------- #-------------------------------------------------------------------
# - Try to find ZLIB # - Try to find ZLIB
# Once done, this will define # Once done, this will define
# #
# ZLIB_FOUND - system has ZLIB # ZLIB_FOUND - system has ZLIB
# ZLIB_INCLUDE_DIRS - the ZLIB include directories # ZLIB_INCLUDE_DIRS - the ZLIB include directories
# ZLIB_LIBRARIES - link these to use ZLIB # ZLIB_LIBRARIES - link these to use ZLIB
include(FindPkgMacros) include(FindPkgMacros)
findpkg_begin(ZLIB) findpkg_begin(ZLIB)
# Get path, convert backslashes as ${ENV_${var}} # Get path, convert backslashes as ${ENV_${var}}
getenv_path(ZLIB_HOME) getenv_path(ZLIB_HOME)
# construct search paths # construct search paths
set(ZLIB_PREFIX_PATH ${ZLIB_HOME} ${ENV_ZLIB_HOME}) set(ZLIB_PREFIX_PATH ${ZLIB_HOME} ${ENV_ZLIB_HOME})
create_search_paths(ZLIB) create_search_paths(ZLIB)
# redo search if prefix path changed # redo search if prefix path changed
clear_if_changed(ZLIB_PREFIX_PATH clear_if_changed(ZLIB_PREFIX_PATH
ZLIB_LIBRARY_FWK ZLIB_LIBRARY_FWK
ZLIB_LIBRARY_REL ZLIB_LIBRARY_REL
ZLIB_LIBRARY_DBG ZLIB_LIBRARY_DBG
ZLIB_INCLUDE_DIR ZLIB_INCLUDE_DIR
) )
set(ZLIB_LIBRARY_NAMES z zlib zdll) set(ZLIB_LIBRARY_NAMES z zlib zdll)
get_debug_names(ZLIB_LIBRARY_NAMES) get_debug_names(ZLIB_LIBRARY_NAMES)
use_pkgconfig(ZLIB_PKGC zzip-zlib-config) use_pkgconfig(ZLIB_PKGC zzip-zlib-config)
findpkg_framework(ZLIB) findpkg_framework(ZLIB)
find_path(ZLIB_INCLUDE_DIR NAMES zlib.h HINTS ${ZLIB_INC_SEARCH_PATH} ${ZLIB_PKGC_INCLUDE_DIRS}) find_path(ZLIB_INCLUDE_DIR NAMES zlib.h HINTS ${ZLIB_INC_SEARCH_PATH} ${ZLIB_PKGC_INCLUDE_DIRS})
find_library(ZLIB_LIBRARY_REL NAMES ${ZLIB_LIBRARY_NAMES} HINTS ${ZLIB_LIB_SEARCH_PATH} ${ZLIB_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" release relwithdebinfo minsizerel) find_library(ZLIB_LIBRARY_REL NAMES ${ZLIB_LIBRARY_NAMES} HINTS ${ZLIB_LIB_SEARCH_PATH} ${ZLIB_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" release relwithdebinfo minsizerel)
find_library(ZLIB_LIBRARY_DBG NAMES ${ZLIB_LIBRARY_NAMES_DBG} HINTS ${ZLIB_LIB_SEARCH_PATH} ${ZLIB_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" debug) find_library(ZLIB_LIBRARY_DBG NAMES ${ZLIB_LIBRARY_NAMES_DBG} HINTS ${ZLIB_LIB_SEARCH_PATH} ${ZLIB_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" debug)
make_library_set(ZLIB_LIBRARY) make_library_set(ZLIB_LIBRARY)
findpkg_finish(ZLIB) findpkg_finish(ZLIB)

View File

@ -1,25 +1,81 @@
FIND_PATH( if(CMAKE_SIZEOF_VOID_P EQUAL 8)
assimp_INCLUDE_DIRS set(ASSIMP_ARCHITECTURE "64")
NAMES postprocess.h scene.h version.h config.h cimport.h elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
PATHS /usr/local/include/ set(ASSIMP_ARCHITECTURE "32")
) endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
if(WIN32)
set(ASSIMP_ROOT_DIR CACHE PATH "ASSIMP root directory")
FIND_LIBRARY( # Find path of each library
assimp_LIBRARIES find_path(ASSIMP_INCLUDE_DIR
NAMES assimp NAMES
PATHS /usr/local/lib/ assimp/anim.h
) HINTS
${ASSIMP_ROOT_DIR}/include
)
IF (assimp_INCLUDE_DIRS AND assimp_LIBRARIES) if(MSVC12)
SET(assimp_FOUND TRUE) set(ASSIMP_MSVC_VERSION "vc120")
ENDIF (assimp_INCLUDE_DIRS AND assimp_LIBRARIES) 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)
IF (assimp_FOUND) find_path(
IF (NOT assimp_FIND_QUIETLY) assimp_INCLUDE_DIRS
MESSAGE(STATUS "Found asset importer library: ${assimp_LIBRARIES}") NAMES postprocess.h scene.h version.h config.h cimport.h
ENDIF (NOT assimp_FIND_QUIETLY) PATHS /usr/local/include/
ELSE (assimp_FOUND) )
IF (assimp_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find asset importer library") find_library(
ENDIF (assimp_FIND_REQUIRED) assimp_LIBRARIES
ENDIF (assimp_FOUND) NAMES assimp
PATHS /usr/local/lib/
)
if (assimp_INCLUDE_DIRS AND assimp_LIBRARIES)
SET(assimp_FOUND TRUE)
ENDIF (assimp_INCLUDE_DIRS AND assimp_LIBRARIES)
if (assimp_FOUND)
if (NOT assimp_FIND_QUIETLY)
message(STATUS "Found asset importer library: ${assimp_LIBRARIES}")
endif (NOT assimp_FIND_QUIETLY)
else (assimp_FOUND)
if (assimp_FIND_REQUIRED)
message(FATAL_ERROR "Could not find asset importer library")
endif (assimp_FIND_REQUIRED)
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

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -2,11 +2,11 @@
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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
@ -23,16 +23,16 @@ following 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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
@ -45,13 +45,17 @@ 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,32 +64,33 @@ 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:
void WriteMeshes(); void WriteMeshes();
void WriteMaterials(); void WriteMaterials();
void WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags); void WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags);
void WriteFaceMaterialChunk(const aiMesh& mesh); void WriteFaceMaterialChunk(const aiMesh& mesh);
int WriteHierarchy(const aiNode& node, int level, int sibling_level); int WriteHierarchy(const aiNode& node, int level, int sibling_level);
void WriteString(const std::string& s); void WriteString(const std::string& s);
void WriteString(const aiString& s); void WriteString(const aiString& s);
void WriteColor(const aiColor3D& color); void WriteColor(const aiColor3D& color);
void WritePercentChunk(float f); void WritePercentChunk(float f);
void WritePercentChunk(double f);
private: private:
const aiScene* const scene; const aiScene* const scene;
StreamWriterLE writer; StreamWriterLE writer;
std::map<const aiNode*, aiMatrix4x4> trafos; std::map<const aiNode*, aiMatrix4x4> trafos;
typedef std::multimap<const aiNode*, unsigned int> MeshesByNodeMap; typedef std::multimap<const aiNode*, unsigned int> MeshesByNodeMap;
MeshesByNodeMap meshes; MeshesByNodeMap meshes;
}; };

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,280 +1,282 @@
/* /*
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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer. following disclaimer.
* Redistributions in binary form must reproduce the above * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other following disclaimer in the documentation and/or other
materials provided with the distribution. materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its * Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products contributors may be used to endorse or promote products
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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file 3DSLoader.h /** @file 3DSLoader.h
* @brief 3DS File format loader * @brief 3DS File format loader
*/ */
#ifndef AI_3DSIMPORTER_H_INC #ifndef AI_3DSIMPORTER_H_INC
#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"
namespace Assimp { struct aiNode;
namespace Assimp {
using namespace D3DS;
// --------------------------------------------------------------------------------- using namespace D3DS;
/** Importer class for 3D Studio r3 and r4 3DS files
*/ // ---------------------------------------------------------------------------------
class Discreet3DSImporter : public BaseImporter /** Importer class for 3D Studio r3 and r4 3DS files
{ */
public: class Discreet3DSImporter : public BaseImporter
{
Discreet3DSImporter(); public:
~Discreet3DSImporter();
Discreet3DSImporter();
public: ~Discreet3DSImporter();
// ------------------------------------------------------------------- public:
/** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. // -------------------------------------------------------------------
*/ /** Returns whether the class can handle the format of the given file.
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, * See BaseImporter::CanRead() for details.
bool checkSig) const; */
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
// ------------------------------------------------------------------- bool checkSig) const;
/** Called prior to ReadFile().
* The function is a request to the importer to update its configuration // -------------------------------------------------------------------
* basing on the Importer's configuration property list. /** Called prior to ReadFile().
*/ * The function is a request to the importer to update its configuration
void SetupProperties(const Importer* pImp); * basing on the Importer's configuration property list.
*/
protected: void SetupProperties(const Importer* pImp);
// ------------------------------------------------------------------- protected:
/** Return importer meta information.
* See #BaseImporter::GetInfo for the details // -------------------------------------------------------------------
*/ /** Return importer meta information.
const aiImporterDesc* GetInfo () const; * See #BaseImporter::GetInfo for the details
*/
// ------------------------------------------------------------------- const aiImporterDesc* GetInfo () const;
/** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details // -------------------------------------------------------------------
*/ /** Imports the given file into the given scene structure.
void InternReadFile( const std::string& pFile, aiScene* pScene, * See BaseImporter::InternReadFile() for details
IOSystem* pIOHandler); */
void InternReadFile( const std::string& pFile, aiScene* pScene,
// ------------------------------------------------------------------- IOSystem* pIOHandler);
/** Converts a temporary material to the outer representation
*/ // -------------------------------------------------------------------
void ConvertMaterial(D3DS::Material& p_cMat, /** Converts a temporary material to the outer representation
aiMaterial& p_pcOut); */
void ConvertMaterial(D3DS::Material& p_cMat,
// ------------------------------------------------------------------- aiMaterial& p_pcOut);
/** Read a chunk
* // -------------------------------------------------------------------
* @param pcOut Receives the current chunk /** Read a chunk
*/ *
void ReadChunk(Discreet3DS::Chunk* pcOut); * @param pcOut Receives the current chunk
*/
// ------------------------------------------------------------------- void ReadChunk(Discreet3DS::Chunk* pcOut);
/** Parse a percentage chunk. mCurrent will point to the next
* chunk behind afterwards. If no percentage chunk is found // -------------------------------------------------------------------
* QNAN is returned. /** Parse a percentage chunk. mCurrent will point to the next
*/ * chunk behind afterwards. If no percentage chunk is found
float ParsePercentageChunk(); * QNAN is returned.
*/
// ------------------------------------------------------------------- ai_real ParsePercentageChunk();
/** Parse a color chunk. mCurrent will point to the next
* chunk behind afterwards. If no color chunk is found // -------------------------------------------------------------------
* QNAN is returned in all members. /** Parse a color chunk. mCurrent will point to the next
*/ * chunk behind afterwards. If no color chunk is found
void ParseColorChunk(aiColor3D* p_pcOut, * QNAN is returned in all members.
bool p_bAcceptPercent = true); */
void ParseColorChunk(aiColor3D* p_pcOut,
bool p_bAcceptPercent = true);
// -------------------------------------------------------------------
/** Skip a chunk in the file
*/ // -------------------------------------------------------------------
void SkipChunk(); /** Skip a chunk in the file
*/
// ------------------------------------------------------------------- void SkipChunk();
/** Generate the nodegraph
*/ // -------------------------------------------------------------------
void GenerateNodeGraph(aiScene* pcOut); /** Generate the nodegraph
*/
// ------------------------------------------------------------------- void GenerateNodeGraph(aiScene* pcOut);
/** Parse a main top-level chunk in the file
*/ // -------------------------------------------------------------------
void ParseMainChunk(); /** Parse a main top-level chunk in the file
*/
// ------------------------------------------------------------------- void ParseMainChunk();
/** Parse a top-level chunk in the file
*/ // -------------------------------------------------------------------
void ParseChunk(const char* name, unsigned int num); /** Parse a top-level chunk in the file
*/
// ------------------------------------------------------------------- void ParseChunk(const char* name, unsigned int num);
/** Parse a top-level editor chunk in the file
*/ // -------------------------------------------------------------------
void ParseEditorChunk(); /** Parse a top-level editor chunk in the file
*/
// ------------------------------------------------------------------- void ParseEditorChunk();
/** Parse a top-level object chunk in the file
*/ // -------------------------------------------------------------------
void ParseObjectChunk(); /** Parse a top-level object chunk in the file
*/
// ------------------------------------------------------------------- void ParseObjectChunk();
/** Parse a material chunk in the file
*/ // -------------------------------------------------------------------
void ParseMaterialChunk(); /** Parse a material chunk in the file
*/
// ------------------------------------------------------------------- void ParseMaterialChunk();
/** Parse a mesh chunk in the file
*/ // -------------------------------------------------------------------
void ParseMeshChunk(); /** Parse a mesh chunk in the file
*/
// ------------------------------------------------------------------- void ParseMeshChunk();
/** Parse a light chunk in the file
*/ // -------------------------------------------------------------------
void ParseLightChunk(); /** Parse a light chunk in the file
*/
// ------------------------------------------------------------------- void ParseLightChunk();
/** Parse a camera chunk in the file
*/ // -------------------------------------------------------------------
void ParseCameraChunk(); /** Parse a camera chunk in the file
*/
// ------------------------------------------------------------------- void ParseCameraChunk();
/** Parse a face list chunk in the file
*/ // -------------------------------------------------------------------
void ParseFaceChunk(); /** Parse a face list chunk in the file
*/
// ------------------------------------------------------------------- void ParseFaceChunk();
/** Parse a keyframe chunk in the file
*/ // -------------------------------------------------------------------
void ParseKeyframeChunk(); /** Parse a keyframe chunk in the file
*/
// ------------------------------------------------------------------- void ParseKeyframeChunk();
/** Parse a hierarchy chunk in the file
*/ // -------------------------------------------------------------------
void ParseHierarchyChunk(uint16_t parent); /** Parse a hierarchy chunk in the file
*/
// ------------------------------------------------------------------- void ParseHierarchyChunk(uint16_t parent);
/** Parse a texture chunk in the file
*/ // -------------------------------------------------------------------
void ParseTextureChunk(D3DS::Texture* pcOut); /** Parse a texture chunk in the file
*/
// ------------------------------------------------------------------- void ParseTextureChunk(D3DS::Texture* pcOut);
/** Convert the meshes in the file
*/ // -------------------------------------------------------------------
void ConvertMeshes(aiScene* pcOut); /** Convert the meshes in the file
*/
// ------------------------------------------------------------------- void ConvertMeshes(aiScene* pcOut);
/** Replace the default material in the scene
*/ // -------------------------------------------------------------------
void ReplaceDefaultMaterial(); /** Replace the default material in the scene
*/
// ------------------------------------------------------------------- void ReplaceDefaultMaterial();
/** Convert the whole scene
*/ // -------------------------------------------------------------------
void ConvertScene(aiScene* pcOut); /** Convert the whole scene
*/
// ------------------------------------------------------------------- void ConvertScene(aiScene* pcOut);
/** generate unique vertices for a mesh
*/ // -------------------------------------------------------------------
void MakeUnique(D3DS::Mesh& sMesh); /** generate unique vertices for a mesh
*/
// ------------------------------------------------------------------- void MakeUnique(D3DS::Mesh& sMesh);
/** Add a node to the node graph
*/ // -------------------------------------------------------------------
void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn, /** Add a node to the node graph
aiMatrix4x4& absTrafo); */
void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn,
// ------------------------------------------------------------------- aiMatrix4x4& absTrafo);
/** Search for a node in the graph.
* Called recursively // -------------------------------------------------------------------
*/ /** Search for a node in the graph.
void InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCurrent); * Called recursively
*/
// ------------------------------------------------------------------- void InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCurrent);
/** Apply the master scaling factor to the mesh
*/ // -------------------------------------------------------------------
void ApplyMasterScale(aiScene* pScene); /** Apply the master scaling factor to the mesh
*/
// ------------------------------------------------------------------- void ApplyMasterScale(aiScene* pScene);
/** Clamp all indices in the file to a valid range
*/ // -------------------------------------------------------------------
void CheckIndices(D3DS::Mesh& sMesh); /** Clamp all indices in the file to a valid range
*/
// ------------------------------------------------------------------- void CheckIndices(D3DS::Mesh& sMesh);
/** Skip the TCB info in a track key
*/ // -------------------------------------------------------------------
void SkipTCBInfo(); /** Skip the TCB info in a track key
*/
protected: void SkipTCBInfo();
/** Stream to read from */ protected:
StreamReaderLE* stream;
/** Stream to read from */
/** Last touched node index */ StreamReaderLE* stream;
short mLastNodeIndex;
/** Last touched node index */
/** Current node, root node */ short mLastNodeIndex;
D3DS::Node* mCurrentNode, *mRootNode;
/** Current node, root node */
/** Scene under construction */ D3DS::Node* mCurrentNode, *mRootNode;
D3DS::Scene* mScene;
/** Scene under construction */
/** Ambient base color of the scene */ D3DS::Scene* mScene;
aiColor3D mClrAmbient;
/** Ambient base color of the scene */
/** Master scaling factor of the scene */ aiColor3D mClrAmbient;
float mMasterScale;
/** Master scaling factor of the scene */
/** Path to the background image of the scene */ ai_real mMasterScale;
std::string mBackgroundImage;
bool bHasBG; /** Path to the background image of the scene */
std::string mBackgroundImage;
/** true if PRJ file */ bool bHasBG;
bool bIsPrj;
}; /** true if PRJ file */
bool bIsPrj;
} // end of namespace Assimp };
#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER } // end of namespace Assimp
#endif // AI_3DSIMPORTER_H_INC #endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER
#endif // AI_3DSIMPORTER_H_INC

File diff suppressed because it is too large Load Diff

View File

@ -1,267 +1,274 @@
/* /*
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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer. following disclaimer.
* Redistributions in binary form must reproduce the above * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other following disclaimer in the documentation and/or other
materials provided with the distribution. materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its * Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products contributors may be used to endorse or promote products
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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file ACLoader.h /** @file ACLoader.h
* @brief Declaration of the .ac importer class. * @brief Declaration of the .ac importer class.
*/ */
#ifndef AI_AC3DLOADER_H_INCLUDED #ifndef AI_AC3DLOADER_H_INCLUDED
#define AI_AC3DLOADER_H_INCLUDED #define AI_AC3DLOADER_H_INCLUDED
#include <vector> #include <vector>
#include "BaseImporter.h" #include "BaseImporter.h"
#include "../include/assimp/types.h" #include <assimp/types.h>
namespace Assimp { struct aiNode;
struct aiMesh;
// --------------------------------------------------------------------------- struct aiMaterial;
/** AC3D (*.ac) importer class struct aiLight;
*/
class AC3DImporter : public BaseImporter
{ namespace Assimp {
public:
AC3DImporter(); // ---------------------------------------------------------------------------
~AC3DImporter(); /** AC3D (*.ac) importer class
*/
class AC3DImporter : public BaseImporter
{
// Represents an AC3D material public:
struct Material AC3DImporter();
{ ~AC3DImporter();
Material()
: rgb (0.6f,0.6f,0.6f)
, spec (1.f,1.f,1.f)
, shin (0.f) // Represents an AC3D material
, trans (0.f) struct Material
{} {
Material()
// base color of the material : rgb (0.6f,0.6f,0.6f)
aiColor3D rgb; , spec (1.f,1.f,1.f)
, shin (0.f)
// ambient color of the material , trans (0.f)
aiColor3D amb; {}
// emissive color of the material // base color of the material
aiColor3D emis; aiColor3D rgb;
// specular color of the material // ambient color of the material
aiColor3D spec; aiColor3D amb;
// shininess exponent // emissive color of the material
float shin; aiColor3D emis;
// transparency. 0 == opaque // specular color of the material
float trans; aiColor3D spec;
// name of the material. optional. // shininess exponent
std::string name; float shin;
};
// transparency. 0 == opaque
// Represents an AC3D surface float trans;
struct Surface
{ // name of the material. optional.
Surface() std::string name;
: mat (0) };
, flags (0)
{} // Represents an AC3D surface
struct Surface
unsigned int mat,flags; {
Surface()
typedef std::pair<unsigned int, aiVector2D > SurfaceEntry; : mat (0)
std::vector< SurfaceEntry > entries; , flags (0)
}; {}
// Represents an AC3D object unsigned int mat,flags;
struct Object
{ typedef std::pair<unsigned int, aiVector2D > SurfaceEntry;
Object() std::vector< SurfaceEntry > entries;
: type (World) };
, name( "" )
, children() // Represents an AC3D object
, texture( "" ) struct Object
, texRepeat( 1.f, 1.f ) {
, texOffset( 0.0f, 0.0f ) Object()
, rotation() : type (World)
, translation() , name( "" )
, vertices() , children()
, surfaces() , texture( "" )
, numRefs (0) , texRepeat( 1.f, 1.f )
, subDiv (0) , texOffset( 0.0f, 0.0f )
{} , rotation()
, translation()
// Type description , vertices()
enum Type , surfaces()
{ , numRefs (0)
World = 0x0, , subDiv (0)
Poly = 0x1, , crease()
Group = 0x2, {}
Light = 0x4
} type; // Type description
enum Type
// name of the object {
std::string name; World = 0x0,
Poly = 0x1,
// object children Group = 0x2,
std::vector<Object> children; Light = 0x4
} type;
// texture to be assigned to all surfaces of the object
std::string texture; // name of the object
std::string name;
// texture repat factors (scaling for all coordinates)
aiVector2D texRepeat, texOffset; // object children
std::vector<Object> children;
// rotation matrix
aiMatrix3x3 rotation; // texture to be assigned to all surfaces of the object
std::string texture;
// translation vector
aiVector3D translation; // texture repat factors (scaling for all coordinates)
aiVector2D texRepeat, texOffset;
// vertices
std::vector<aiVector3D> vertices; // rotation matrix
aiMatrix3x3 rotation;
// surfaces
std::vector<Surface> surfaces; // translation vector
aiVector3D translation;
// number of indices (= num verts in verbose format)
unsigned int numRefs; // vertices
std::vector<aiVector3D> vertices;
// number of subdivisions to be performed on the
// imported data // surfaces
unsigned int subDiv; std::vector<Surface> surfaces;
// max angle limit for smoothing // number of indices (= num verts in verbose format)
float crease; unsigned int numRefs;
};
// number of subdivisions to be performed on the
// imported data
public: unsigned int subDiv;
// ------------------------------------------------------------------- // max angle limit for smoothing
/** Returns whether the class can handle the format of the given file. float crease;
* See BaseImporter::CanRead() for details. };
*/
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const; public:
protected: // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.
// ------------------------------------------------------------------- * See BaseImporter::CanRead() for details.
/** Return importer meta information. */
* See #BaseImporter::GetInfo for the details */ bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
const aiImporterDesc* GetInfo () const; bool checkSig) const;
// ------------------------------------------------------------------- protected:
/** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details*/ // -------------------------------------------------------------------
void InternReadFile( const std::string& pFile, aiScene* pScene, /** Return importer meta information.
IOSystem* pIOHandler); * See #BaseImporter::GetInfo for the details */
const aiImporterDesc* GetInfo () const;
// -------------------------------------------------------------------
/** Called prior to ReadFile(). // -------------------------------------------------------------------
* The function is a request to the importer to update its configuration /** Imports the given file into the given scene structure.
* basing on the Importer's configuration property list.*/ * See BaseImporter::InternReadFile() for details*/
void SetupProperties(const Importer* pImp); void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler);
private:
// -------------------------------------------------------------------
// ------------------------------------------------------------------- /** Called prior to ReadFile().
/** Get the next line from the file. * The function is a request to the importer to update its configuration
* @return false if the end of the file was reached*/ * basing on the Importer's configuration property list.*/
bool GetNextLine(); void SetupProperties(const Importer* pImp);
// ------------------------------------------------------------------- private:
/** Load the object section. This method is called recursively to
* load subobjects, the method returns after a 'kids 0' was // -------------------------------------------------------------------
* encountered. /** Get the next line from the file.
* @objects List of output objects*/ * @return false if the end of the file was reached*/
void LoadObjectSection(std::vector<Object>& objects); bool GetNextLine();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Convert all objects into meshes and nodes. /** Load the object section. This method is called recursively to
* @param object Current object to work on * load subobjects, the method returns after a 'kids 0' was
* @param meshes Pointer to the list of output meshes * encountered.
* @param outMaterials List of output materials * @objects List of output objects*/
* @param materials Material list void LoadObjectSection(std::vector<Object>& objects);
* @param Scenegraph node for the object */
aiNode* ConvertObjectSection(Object& object, // -------------------------------------------------------------------
std::vector<aiMesh*>& meshes, /** Convert all objects into meshes and nodes.
std::vector<aiMaterial*>& outMaterials, * @param object Current object to work on
const std::vector<Material>& materials, * @param meshes Pointer to the list of output meshes
aiNode* parent = NULL); * @param outMaterials List of output materials
* @param materials Material list
// ------------------------------------------------------------------- * @param Scenegraph node for the object */
/** Convert a material aiNode* ConvertObjectSection(Object& object,
* @param object Current object std::vector<aiMesh*>& meshes,
* @param matSrc Source material description std::vector<aiMaterial*>& outMaterials,
* @param matDest Destination material to be filled */ const std::vector<Material>& materials,
void ConvertMaterial(const Object& object, aiNode* parent = NULL);
const Material& matSrc,
aiMaterial& matDest); // -------------------------------------------------------------------
/** Convert a material
private: * @param object Current object
* @param matSrc Source material description
* @param matDest Destination material to be filled */
// points to the next data line void ConvertMaterial(const Object& object,
const char* buffer; const Material& matSrc,
aiMaterial& matDest);
// Configuration option: if enabled, up to two meshes
// are generated per material: those faces who have private:
// their bf cull flags set are separated.
bool configSplitBFCull;
// points to the next data line
// Configuration switch: subdivision surfaces are only const char* buffer;
// evaluated if the value is true.
bool configEvalSubdivision; // Configuration option: if enabled, up to two meshes
// are generated per material: those faces who have
// counts how many objects we have in the tree. // their bf cull flags set are separated.
// basing on this information we can find a bool configSplitBFCull;
// good estimate how many meshes we'll have in the final scene.
unsigned int mNumMeshes; // Configuration switch: subdivision surfaces are only
// evaluated if the value is true.
// current list of light sources bool configEvalSubdivision;
std::vector<aiLight*>* mLights;
// counts how many objects we have in the tree.
// name counters // basing on this information we can find a
unsigned int lights, groups, polys, worlds; // good estimate how many meshes we'll have in the final scene.
}; unsigned int mNumMeshes;
} // end of namespace Assimp // current list of light sources
std::vector<aiLight*>* mLights;
#endif // AI_AC3DIMPORTER_H_INC
// name counters
unsigned int lights, groups, polys, worlds;
};
} // end of namespace Assimp
#endif // AI_AC3DIMPORTER_H_INC

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

File diff suppressed because it is too large Load Diff

View File

@ -1,205 +1,205 @@
/* /*
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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer. following disclaimer.
* Redistributions in binary form must reproduce the above * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other following disclaimer in the documentation and/or other
materials provided with the distribution. materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its * Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products contributors may be used to endorse or promote products
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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file ASELoader.h /** @file ASELoader.h
* @brief Definition of the .ASE importer class. * @brief Definition of the .ASE importer class.
*/ */
#ifndef AI_ASELOADER_H_INCLUDED #ifndef AI_ASELOADER_H_INCLUDED
#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"
namespace Assimp { namespace Assimp {
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------
/** Importer class for the 3DS ASE ASCII format. /** Importer class for the 3DS ASE ASCII format.
* *
*/ */
class ASEImporter : public BaseImporter { class ASEImporter : public BaseImporter {
public: public:
ASEImporter(); ASEImporter();
~ASEImporter(); ~ASEImporter();
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. * See BaseImporter::CanRead() for details.
*/ */
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const; bool checkSig) const;
protected: protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Return importer meta information. /** Return importer meta information.
* See #BaseImporter::GetInfo for the details * See #BaseImporter::GetInfo for the details
*/ */
const aiImporterDesc* GetInfo () const; const aiImporterDesc* GetInfo () const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Imports the given file into the given scene structure. /** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details * See BaseImporter::InternReadFile() for details
*/ */
void InternReadFile( const std::string& pFile, aiScene* pScene, void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler); IOSystem* pIOHandler);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Called prior to ReadFile(). /** Called prior to ReadFile().
* The function is a request to the importer to update its configuration * The function is a request to the importer to update its configuration
* basing on the Importer's configuration property list. * basing on the Importer's configuration property list.
*/ */
void SetupProperties(const Importer* pImp); void SetupProperties(const Importer* pImp);
private: private:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Generate normal vectors basing on smoothing groups /** Generate normal vectors basing on smoothing groups
* (in some cases the normal are already contained in the file) * (in some cases the normal are already contained in the file)
* \param mesh Mesh to work on * \param mesh Mesh to work on
* \return false if the normals have been recomputed * \return false if the normals have been recomputed
*/ */
bool GenerateNormals(ASE::Mesh& mesh); bool GenerateNormals(ASE::Mesh& mesh);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Create valid vertex/normal/UV/color/face lists. /** Create valid vertex/normal/UV/color/face lists.
* All elements are unique, faces have only one set of indices * All elements are unique, faces have only one set of indices
* after this step occurs. * after this step occurs.
* \param mesh Mesh to work on * \param mesh Mesh to work on
*/ */
void BuildUniqueRepresentation(ASE::Mesh& mesh); void BuildUniqueRepresentation(ASE::Mesh& mesh);
/** Create one-material-per-mesh meshes ;-) /** Create one-material-per-mesh meshes ;-)
* \param mesh Mesh to work with * \param mesh Mesh to work with
* \param Receives the list of all created meshes * \param Receives the list of all created meshes
*/ */
void ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOut); void ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOut);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Convert a material to a aiMaterial object /** Convert a material to a aiMaterial object
* \param mat Input material * \param mat Input material
*/ */
void ConvertMaterial(ASE::Material& mat); void ConvertMaterial(ASE::Material& mat);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Setup the final material indices for each mesh /** Setup the final material indices for each mesh
*/ */
void BuildMaterialIndices(); void BuildMaterialIndices();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Build the node graph /** Build the node graph
*/ */
void BuildNodes(std::vector<ASE::BaseNode*>& nodes); void BuildNodes(std::vector<ASE::BaseNode*>& nodes);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Build output cameras /** Build output cameras
*/ */
void BuildCameras(); void BuildCameras();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Build output lights /** Build output lights
*/ */
void BuildLights(); void BuildLights();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Build output animations /** Build output animations
*/ */
void BuildAnimations(const std::vector<ASE::BaseNode*>& nodes); void BuildAnimations(const std::vector<ASE::BaseNode*>& nodes);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Add sub nodes to a node /** Add sub nodes to a node
* \param pcParent parent node to be filled * \param pcParent parent node to be filled
* \param szName Name of the parent node * \param szName Name of the parent node
* \param matrix Current transform * \param matrix Current transform
*/ */
void AddNodes(const std::vector<ASE::BaseNode*>& nodes, void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
aiNode* pcParent,const char* szName); aiNode* pcParent,const char* szName);
void AddNodes(const std::vector<ASE::BaseNode*>& nodes, void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
aiNode* pcParent,const char* szName, aiNode* pcParent,const char* szName,
const aiMatrix4x4& matrix); const aiMatrix4x4& matrix);
void AddMeshes(const ASE::BaseNode* snode,aiNode* node); void AddMeshes(const ASE::BaseNode* snode,aiNode* node);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Generate a default material and add it to the parser's list /** Generate a default material and add it to the parser's list
* Called if no material has been found in the file (rare for ASE, * Called if no material has been found in the file (rare for ASE,
* but not impossible) * but not impossible)
*/ */
void GenerateDefaultMaterial(); void GenerateDefaultMaterial();
protected: protected:
/** Parser instance */ /** Parser instance */
ASE::Parser* mParser; ASE::Parser* mParser;
/** Buffer to hold the loaded file */ /** Buffer to hold the loaded file */
char* mBuffer; char* mBuffer;
/** Scene to be filled */ /** Scene to be filled */
aiScene* pcScene; aiScene* pcScene;
/** Config options: Recompute the normals in every case - WA /** Config options: Recompute the normals in every case - WA
for 3DS Max broken ASE normal export */ for 3DS Max broken ASE normal export */
bool configRecomputeNormals; bool configRecomputeNormals;
bool noSkeletonMesh; bool noSkeletonMesh;
}; };
} // end of namespace Assimp } // end of namespace Assimp
#endif // AI_3DSIMPORTER_H_INC #endif // AI_3DSIMPORTER_H_INC

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,11 +2,11 @@
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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
@ -23,16 +23,16 @@ following 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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -3,11 +3,11 @@
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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
@ -24,16 +24,16 @@ following 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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
@ -46,11 +46,22 @@ 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
namespace Assimp { namespace Assimp {
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
/** Importer class for 3D Studio r3 and r4 3DS files /** Importer class for 3D Studio r3 and r4 3DS files
@ -63,15 +74,15 @@ private:
protected: protected:
public: public:
virtual bool CanRead( virtual bool CanRead(
const std::string& pFile, const std::string& pFile,
IOSystem* pIOHandler, IOSystem* pIOHandler,
bool checkSig bool checkSig
) const; ) const;
virtual const aiImporterDesc* GetInfo() const; virtual const aiImporterDesc* GetInfo() const;
virtual void InternReadFile( virtual void InternReadFile(
const std::string& pFile, const std::string& pFile,
aiScene* pScene, aiScene* pScene,
IOSystem* pIOHandler IOSystem* pIOHandler
); );
void ReadBinaryScene( IOStream * stream, aiScene* pScene ); void ReadBinaryScene( IOStream * stream, aiScene* pScene );

File diff suppressed because it is too large Load Diff

View File

@ -1,129 +1,154 @@
/* /*
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
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,
with or without modification, are permitted provided that the following with or without modification, are permitted provided that the following
conditions are met: conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer. following disclaimer.
* Redistributions in binary form must reproduce the above * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other following disclaimer in the documentation and/or other
materials provided with the distribution. materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its * Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products contributors may be used to endorse or promote products
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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
*/ */
/** @file AssimpCExport.cpp /** @file AssimpCExport.cpp
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
#include "CInterfaceIOWrapper.h"
#ifndef ASSIMP_BUILD_NO_EXPORT #include "SceneCombiner.h"
#include "CInterfaceIOWrapper.h" #include "ScenePrivate.h"
#include "SceneCombiner.h" #include <assimp/Exporter.hpp>
using namespace Assimp; using namespace Assimp;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API size_t aiGetExportFormatCount(void) ASSIMP_API size_t aiGetExportFormatCount(void)
{ {
return Exporter().GetExportFormatCount(); return Exporter().GetExportFormatCount();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t pIndex) ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t 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;
// ------------------------------------------------------------------------------------------------ }
ASSIMP_API void aiCopyScene(const aiScene* pIn, aiScene** pOut)
{ aiExportFormatDesc *desc = new aiExportFormatDesc;
if (!pOut || !pIn) { desc->description = new char[ strlen( orig->description ) + 1 ]();
return; ::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 ) );
SceneCombiner::CopyScene(pOut,pIn,true); desc->id = new char[ strlen( orig->id ) + 1 ]();
ScenePriv(*pOut)->mIsCopy = true; ::strncpy( ( char* ) desc->id, orig->id, strlen( orig->id ) );
}
return desc;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API void aiFreeScene(const C_STRUCT aiScene* pIn) // ------------------------------------------------------------------------------------------------
{ ASSIMP_API void aiReleaseExportFormatDescription( const aiExportFormatDesc *desc ) {
// note: aiReleaseImport() is also able to delete scene copies, but in addition if (NULL == desc) {
// it also handles scenes with import metadata. return;
delete pIn; }
}
delete [] desc->description;
delete [] desc->fileExtension;
// ------------------------------------------------------------------------------------------------ delete [] desc->id;
ASSIMP_API aiReturn aiExportScene( const aiScene* pScene, const char* pFormatId, const char* pFileName, unsigned int pPreprocessing ) delete desc;
{ }
return ::aiExportSceneEx(pScene,pFormatId,pFileName,NULL,pPreprocessing);
} // ------------------------------------------------------------------------------------------------
ASSIMP_API void aiCopyScene(const aiScene* pIn, aiScene** pOut)
{
// ------------------------------------------------------------------------------------------------ if (!pOut || !pIn) {
ASSIMP_API aiReturn aiExportSceneEx( const aiScene* pScene, const char* pFormatId, const char* pFileName, aiFileIO* pIO, unsigned int pPreprocessing ) return;
{ }
Exporter exp;
SceneCombiner::CopyScene(pOut,pIn,true);
if (pIO) { ScenePriv(*pOut)->mIsCopy = true;
exp.SetIOHandler(new CIOSystemWrapper(pIO)); }
}
return exp.Export(pScene,pFormatId,pFileName,pPreprocessing);
} // ------------------------------------------------------------------------------------------------
ASSIMP_API void aiFreeScene(const C_STRUCT aiScene* pIn)
{
// ------------------------------------------------------------------------------------------------ // note: aiReleaseImport() is also able to delete scene copies, but in addition
ASSIMP_API const C_STRUCT aiExportDataBlob* aiExportSceneToBlob( const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing ) // it also handles scenes with import metadata.
{ delete pIn;
Exporter exp; }
if (!exp.ExportToBlob(pScene,pFormatId,pPreprocessing)) {
return NULL;
} // ------------------------------------------------------------------------------------------------
const aiExportDataBlob* blob = exp.GetOrphanedBlob(); ASSIMP_API aiReturn aiExportScene( const aiScene* pScene, const char* pFormatId, const char* pFileName, unsigned int pPreprocessing )
ai_assert(blob); {
return ::aiExportSceneEx(pScene,pFormatId,pFileName,NULL,pPreprocessing);
return blob; }
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
ASSIMP_API C_STRUCT void aiReleaseExportBlob( const aiExportDataBlob* pData ) ASSIMP_API aiReturn aiExportSceneEx( const aiScene* pScene, const char* pFormatId, const char* pFileName, aiFileIO* pIO, unsigned int pPreprocessing )
{ {
delete pData; Exporter exp;
}
if (pIO) {
#endif // !ASSIMP_BUILD_NO_EXPORT exp.SetIOHandler(new CIOSystemWrapper(pIO));
}
return exp.Export(pScene,pFormatId,pFileName,pPreprocessing);
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API const C_STRUCT aiExportDataBlob* aiExportSceneToBlob( const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing )
{
Exporter exp;
if (!exp.ExportToBlob(pScene,pFormatId,pPreprocessing)) {
return NULL;
}
const aiExportDataBlob* blob = exp.GetOrphanedBlob();
ai_assert(blob);
return blob;
}
// ------------------------------------------------------------------------------------------------
ASSIMP_API C_STRUCT void aiReleaseExportBlob( const aiExportDataBlob* pData )
{
delete pData;
}
#endif // !ASSIMP_BUILD_NO_EXPORT

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

File diff suppressed because it is too large Load Diff

View File

@ -2,11 +2,11 @@
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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
@ -23,16 +23,16 @@ following 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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -1,126 +1,130 @@
/*
/* Open Asset Import Library (assimp)
Open Asset Import Library (assimp) ----------------------------------------------------------------------
----------------------------------------------------------------------
Copyright (c) 2006-2016, assimp team
Copyright (c) 2006-2012, 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, with or without modification, are permitted provided that the
with or without modification, are permitted provided that the following conditions are met:
following conditions are met:
* Redistributions of source code must retain the above
* Redistributions of source code must retain the above copyright notice, this list of conditions and the
copyright notice, this list of conditions and the following disclaimer.
following disclaimer.
* Redistributions in binary form must reproduce the above
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
copyright notice, this list of conditions and the following disclaimer in the documentation and/or other
following disclaimer in the documentation and/or other materials provided with the distribution.
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
* Neither the name of the assimp team, nor the names of its contributors may be used to endorse or promote products
contributors may be used to endorse or promote products 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, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
---------------------------------------------------------------------- */
*/
/** @file Definition of the .b3d importer class. */
/** @file Definition of the .b3d importer class. */
#ifndef AI_B3DIMPORTER_H_INC
#ifndef AI_B3DIMPORTER_H_INC #define AI_B3DIMPORTER_H_INC
#define AI_B3DIMPORTER_H_INC
#include <assimp/types.h>
#include "../include/assimp/types.h" #include <assimp/mesh.h>
#include "../include/assimp/mesh.h" #include <assimp/material.h>
#include "../include/assimp/material.h" #include "BaseImporter.h"
#include <string> #include <string>
#include <vector> #include <vector>
namespace Assimp{ struct aiNodeAnim;
struct aiNode;
class B3DImporter : public BaseImporter{ struct aiAnimation;
public:
namespace Assimp{
virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
class B3DImporter : public BaseImporter{
protected: public:
virtual const aiImporterDesc* GetInfo () const; virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
protected:
private:
virtual const aiImporterDesc* GetInfo () const;
int ReadByte(); virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
int ReadInt();
float ReadFloat(); private:
aiVector2D ReadVec2();
aiVector3D ReadVec3(); int ReadByte();
aiQuaternion ReadQuat(); int ReadInt();
std::string ReadString(); float ReadFloat();
std::string ReadChunk(); aiVector2D ReadVec2();
void ExitChunk(); aiVector3D ReadVec3();
unsigned ChunkSize(); aiQuaternion ReadQuat();
std::string ReadString();
template<class T> std::string ReadChunk();
T *to_array( const std::vector<T> &v ); void ExitChunk();
unsigned ChunkSize();
struct Vertex{
aiVector3D vertex; template<class T>
aiVector3D normal; T *to_array( const std::vector<T> &v );
aiVector3D texcoords;
unsigned char bones[4]; struct Vertex{
float weights[4]; aiVector3D vertex;
}; aiVector3D normal;
aiVector3D texcoords;
void Oops(); unsigned char bones[4];
void Fail( std::string str ); float weights[4];
};
void ReadTEXS();
void ReadBRUS(); AI_WONT_RETURN void Oops() AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Fail( std::string str ) AI_WONT_RETURN_SUFFIX;
void ReadVRTS();
void ReadTRIS( int v0 ); void ReadTEXS();
void ReadMESH(); void ReadBRUS();
void ReadBONE( int id );
void ReadKEYS( aiNodeAnim *nodeAnim ); void ReadVRTS();
void ReadANIM(); void ReadTRIS( int v0 );
void ReadMESH();
aiNode *ReadNODE( aiNode *parent ); void ReadBONE( int id );
void ReadKEYS( aiNodeAnim *nodeAnim );
void ReadBB3D( aiScene *scene ); void ReadANIM();
unsigned _pos; aiNode *ReadNODE( aiNode *parent );
// unsigned _size;
std::vector<unsigned char> _buf; void ReadBB3D( aiScene *scene );
std::vector<unsigned> _stack;
unsigned _pos;
std::vector<std::string> _textures; // unsigned _size;
std::vector<aiMaterial*> _materials; std::vector<unsigned char> _buf;
std::vector<unsigned> _stack;
int _vflags,_tcsets,_tcsize;
std::vector<Vertex> _vertices; std::vector<std::string> _textures;
std::vector<aiMaterial*> _materials;
std::vector<aiNode*> _nodes;
std::vector<aiMesh*> _meshes; int _vflags,_tcsets,_tcsize;
std::vector<aiNodeAnim*> _nodeAnims; std::vector<Vertex> _vertices;
std::vector<aiAnimation*> _animations;
}; std::vector<aiNode*> _nodes;
std::vector<aiMesh*> _meshes;
} std::vector<aiNodeAnim*> _nodeAnims;
std::vector<aiAnimation*> _animations;
#endif };
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,169 +1,171 @@
/** Defines the BHV motion capturing loader class */ /** Defines the BHV motion capturing loader class */
/* /*
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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer. following disclaimer.
* Redistributions in binary form must reproduce the above * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other following disclaimer in the documentation and/or other
materials provided with the distribution. materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its * Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products contributors may be used to endorse or promote products
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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file BVHLoader.h /** @file BVHLoader.h
* @brief Biovision BVH import * @brief Biovision BVH import
*/ */
#ifndef AI_BVHLOADER_H_INC #ifndef AI_BVHLOADER_H_INC
#define AI_BVHLOADER_H_INC #define AI_BVHLOADER_H_INC
#include "BaseImporter.h" #include "BaseImporter.h"
namespace Assimp struct aiNode;
{
namespace Assimp
// -------------------------------------------------------------------------------- {
/** Loader class to read Motion Capturing data from a .bvh file.
* // --------------------------------------------------------------------------------
* This format only contains a hierarchy of joints and a series of keyframes for /** Loader class to read Motion Capturing data from a .bvh file.
* the hierarchy. It contains no actual mesh data, but we generate a dummy mesh *
* inside the loader just to be able to see something. * This format only contains a hierarchy of joints and a series of keyframes for
*/ * the hierarchy. It contains no actual mesh data, but we generate a dummy mesh
class BVHLoader : public BaseImporter * inside the loader just to be able to see something.
{ */
class BVHLoader : public BaseImporter
/** Possible animation channels for which the motion data holds the values */ {
enum ChannelType
{ /** Possible animation channels for which the motion data holds the values */
Channel_PositionX, enum ChannelType
Channel_PositionY, {
Channel_PositionZ, Channel_PositionX,
Channel_RotationX, Channel_PositionY,
Channel_RotationY, Channel_PositionZ,
Channel_RotationZ Channel_RotationX,
}; Channel_RotationY,
Channel_RotationZ
/** Collected list of node. Will be bones of the dummy mesh some day, addressed by their array index */ };
struct Node
{ /** Collected list of node. Will be bones of the dummy mesh some day, addressed by their array index */
const aiNode* mNode; struct Node
std::vector<ChannelType> mChannels; {
std::vector<float> mChannelValues; // motion data values for that node. Of size NumChannels * NumFrames const aiNode* mNode;
std::vector<ChannelType> mChannels;
Node() { } std::vector<float> mChannelValues; // motion data values for that node. Of size NumChannels * NumFrames
Node( const aiNode* pNode) : mNode( pNode) { }
}; Node() { }
explicit Node( const aiNode* pNode) : mNode( pNode) { }
public: };
BVHLoader(); public:
~BVHLoader();
BVHLoader();
public: ~BVHLoader();
/** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. */ public:
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const; /** Returns whether the class can handle the format of the given file.
* See BaseImporter::CanRead() for details. */
void SetupProperties(const Importer* pImp); bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const;
const aiImporterDesc* GetInfo () const;
void SetupProperties(const Importer* pImp);
protected: const aiImporterDesc* GetInfo () const;
protected:
/** Imports the given file into the given scene structure.
* See BaseImporter::InternReadFile() for details
*/ /** Imports the given file into the given scene structure.
void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); * See BaseImporter::InternReadFile() for details
*/
protected: void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
/** Reads the file */
void ReadStructure( aiScene* pScene); protected:
/** Reads the file */
/** Reads the hierarchy */ void ReadStructure( aiScene* pScene);
void ReadHierarchy( aiScene* pScene);
/** Reads the hierarchy */
/** Reads a node and recursively its childs and returns the created node. */ void ReadHierarchy( aiScene* pScene);
aiNode* ReadNode();
/** Reads a node and recursively its childs and returns the created node. */
/** Reads an end node and returns the created node. */ aiNode* ReadNode();
aiNode* ReadEndSite( const std::string& pParentName);
/** Reads an end node and returns the created node. */
/** Reads a node offset for the given node */ aiNode* ReadEndSite( const std::string& pParentName);
void ReadNodeOffset( aiNode* pNode);
/** Reads a node offset for the given node */
/** Reads the animation channels into the given node */ void ReadNodeOffset( aiNode* pNode);
void ReadNodeChannels( BVHLoader::Node& pNode);
/** Reads the animation channels into the given node */
/** Reads the motion data */ void ReadNodeChannels( BVHLoader::Node& pNode);
void ReadMotion( aiScene* pScene);
/** Reads the motion data */
/** Retrieves the next token */ void ReadMotion( aiScene* pScene);
std::string GetNextToken();
/** Retrieves the next token */
/** Reads the next token as a float */ std::string GetNextToken();
float GetNextTokenAsFloat();
/** Reads the next token as a float */
/** Aborts the file reading with an exception */ float GetNextTokenAsFloat();
void ThrowException( const std::string& pError);
/** Aborts the file reading with an exception */
/** Constructs an animation for the motion data and stores it in the given scene */ AI_WONT_RETURN void ThrowException( const std::string& pError) AI_WONT_RETURN_SUFFIX;
void CreateAnimation( aiScene* pScene);
/** Constructs an animation for the motion data and stores it in the given scene */
protected: void CreateAnimation( aiScene* pScene);
/** Filename, for a verbose error message */
std::string mFileName; protected:
/** Filename, for a verbose error message */
/** Buffer to hold the loaded file */ std::string mFileName;
std::vector<char> mBuffer;
/** Buffer to hold the loaded file */
/** Next char to read from the buffer */ std::vector<char> mBuffer;
std::vector<char>::const_iterator mReader;
/** Next char to read from the buffer */
/** Current line, for error messages */ std::vector<char>::const_iterator mReader;
unsigned int mLine;
/** Current line, for error messages */
/** Collected list of nodes. Will be bones of the dummy mesh some day, addressed by their array index. unsigned int mLine;
* Also contain the motion data for the node's channels
*/ /** Collected list of nodes. Will be bones of the dummy mesh some day, addressed by their array index.
std::vector<Node> mNodes; * Also contain the motion data for the node's channels
*/
/** basic Animation parameters */ std::vector<Node> mNodes;
float mAnimTickDuration;
unsigned int mAnimNumFrames; /** basic Animation parameters */
float mAnimTickDuration;
bool noSkeletonMesh; unsigned int mAnimNumFrames;
};
bool noSkeletonMesh;
} // end of namespace Assimp };
#endif // AI_BVHLOADER_H_INC } // end of namespace Assimp
#endif // AI_BVHLOADER_H_INC

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -1,105 +1,105 @@
/* /*
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
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,
with or without modification, are permitted provided that the following with or without modification, are permitted provided that the following
conditions are met: conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer. following disclaimer.
* Redistributions in binary form must reproduce the above * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other following disclaimer in the documentation and/or other
materials provided with the distribution. materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its * Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products contributors may be used to endorse or promote products
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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 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;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
BaseProcess::BaseProcess() BaseProcess::BaseProcess()
: shared() : shared()
, progress() , progress()
{ {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
BaseProcess::~BaseProcess() BaseProcess::~BaseProcess()
{ {
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BaseProcess::ExecuteOnScene( Importer* pImp) void BaseProcess::ExecuteOnScene( Importer* pImp)
{ {
ai_assert(NULL != pImp && NULL != pImp->Pimpl()->mScene); ai_assert(NULL != pImp && NULL != pImp->Pimpl()->mScene);
progress = pImp->GetProgressHandler(); progress = pImp->GetProgressHandler();
ai_assert(progress); ai_assert(progress);
SetupProperties( pImp ); SetupProperties( pImp );
// catch exceptions thrown inside the PostProcess-Step // catch exceptions thrown inside the PostProcess-Step
try try
{ {
Execute(pImp->Pimpl()->mScene); Execute(pImp->Pimpl()->mScene);
} catch( const std::exception& err ) { } catch( const std::exception& err ) {
// extract error description // extract error description
pImp->Pimpl()->mErrorString = err.what(); pImp->Pimpl()->mErrorString = err.what();
DefaultLogger::get()->error(pImp->Pimpl()->mErrorString); DefaultLogger::get()->error(pImp->Pimpl()->mErrorString);
// and kill the partially imported data // and kill the partially imported data
delete pImp->Pimpl()->mScene; delete pImp->Pimpl()->mScene;
pImp->Pimpl()->mScene = NULL; pImp->Pimpl()->mScene = NULL;
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BaseProcess::SetupProperties(const Importer* /*pImp*/) void BaseProcess::SetupProperties(const Importer* /*pImp*/)
{ {
// the default implementation does nothing // the default implementation does nothing
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool BaseProcess::RequireVerboseFormat() const bool BaseProcess::RequireVerboseFormat() const
{ {
return true; return true;
} }

View File

@ -1,294 +1,294 @@
/* /*
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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer. following disclaimer.
* Redistributions in binary form must reproduce the above * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other following disclaimer in the documentation and/or other
materials provided with the distribution. materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its * Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products contributors may be used to endorse or promote products
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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file Base class of all import post processing steps */ /** @file Base class of all import post processing steps */
#ifndef INCLUDED_AI_BASEPROCESS_H #ifndef INCLUDED_AI_BASEPROCESS_H
#define INCLUDED_AI_BASEPROCESS_H #define INCLUDED_AI_BASEPROCESS_H
#include <map> #include <map>
#include "../include/assimp/types.h" #include <assimp/types.h>
#include "GenericProperty.h" #include "GenericProperty.h"
struct aiScene; struct aiScene;
namespace Assimp { namespace Assimp {
class Importer; class Importer;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper class to allow post-processing steps to interact with each other. /** Helper class to allow post-processing steps to interact with each other.
* *
* The class maintains a simple property list that can be used by pp-steps * The class maintains a simple property list that can be used by pp-steps
* to provide additional information to other steps. This is primarily * to provide additional information to other steps. This is primarily
* intended for cross-step optimizations. * intended for cross-step optimizations.
*/ */
class SharedPostProcessInfo class SharedPostProcessInfo
{ {
public: public:
struct Base struct Base
{ {
virtual ~Base() virtual ~Base()
{} {}
}; };
//! Represents data that is allocated on the heap, thus needs to be deleted //! Represents data that is allocated on the heap, thus needs to be deleted
template <typename T> template <typename T>
struct THeapData : public Base struct THeapData : public Base
{ {
THeapData(T* in) explicit THeapData(T* in)
: data (in) : data (in)
{} {}
~THeapData() ~THeapData()
{ {
delete data; delete data;
} }
T* data; T* data;
}; };
//! Represents static, by-value data not allocated on the heap //! Represents static, by-value data not allocated on the heap
template <typename T> template <typename T>
struct TStaticData : public Base struct TStaticData : public Base
{ {
TStaticData(T in) explicit TStaticData(T in)
: data (in) : data (in)
{} {}
~TStaticData() ~TStaticData()
{} {}
T data; T data;
}; };
// some typedefs for cleaner code // some typedefs for cleaner code
typedef unsigned int KeyType; typedef unsigned int KeyType;
typedef std::map<KeyType, Base*> PropertyMap; typedef std::map<KeyType, Base*> PropertyMap;
public: public:
//! Destructor //! Destructor
~SharedPostProcessInfo() ~SharedPostProcessInfo()
{ {
Clean(); Clean();
} }
//! Remove all stored properties from the table //! Remove all stored properties from the table
void Clean() void Clean()
{ {
// invoke the virtual destructor for all stored properties // invoke the virtual destructor for all stored properties
for (PropertyMap::iterator it = pmap.begin(), end = pmap.end(); for (PropertyMap::iterator it = pmap.begin(), end = pmap.end();
it != end; ++it) it != end; ++it)
{ {
delete (*it).second; delete (*it).second;
} }
pmap.clear(); pmap.clear();
} }
//! Add a heap property to the list //! Add a heap property to the list
template <typename T> template <typename T>
void AddProperty( const char* name, T* in ){ void AddProperty( const char* name, T* in ){
AddProperty(name,(Base*)new THeapData<T>(in)); AddProperty(name,(Base*)new THeapData<T>(in));
} }
//! Add a static by-value property to the list //! Add a static by-value property to the list
template <typename T> template <typename T>
void AddProperty( const char* name, T in ){ void AddProperty( const char* name, T in ){
AddProperty(name,(Base*)new TStaticData<T>(in)); AddProperty(name,(Base*)new TStaticData<T>(in));
} }
//! Get a heap property //! Get a heap property
template <typename T> template <typename T>
bool GetProperty( const char* name, T*& out ) const bool GetProperty( const char* name, T*& out ) const
{ {
THeapData<T>* t = (THeapData<T>*)GetPropertyInternal(name); THeapData<T>* t = (THeapData<T>*)GetPropertyInternal(name);
if(!t) if(!t)
{ {
out = NULL; out = NULL;
return false; return false;
} }
out = t->data; out = t->data;
return true; return true;
} }
//! Get a static, by-value property //! Get a static, by-value property
template <typename T> template <typename T>
bool GetProperty( const char* name, T& out ) const bool GetProperty( const char* name, T& out ) const
{ {
TStaticData<T>* t = (TStaticData<T>*)GetPropertyInternal(name); TStaticData<T>* t = (TStaticData<T>*)GetPropertyInternal(name);
if(!t)return false; if(!t)return false;
out = t->data; out = t->data;
return true; return true;
} }
//! Remove a property of a specific type //! Remove a property of a specific type
void RemoveProperty( const char* name) { void RemoveProperty( const char* name) {
SetGenericPropertyPtr<Base>(pmap,name,NULL); SetGenericPropertyPtr<Base>(pmap,name,NULL);
} }
private: private:
void AddProperty( const char* name, Base* data) { void AddProperty( const char* name, Base* data) {
SetGenericPropertyPtr<Base>(pmap,name,data); SetGenericPropertyPtr<Base>(pmap,name,data);
} }
Base* GetPropertyInternal( const char* name) const { Base* GetPropertyInternal( const char* name) const {
return GetGenericProperty<Base*>(pmap,name,NULL); return GetGenericProperty<Base*>(pmap,name,NULL);
} }
private: private:
//! Map of all stored properties //! Map of all stored properties
PropertyMap pmap; PropertyMap pmap;
}; };
#if 0 #if 0
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** @brief Represents a dependency table for a postprocessing steps. /** @brief Represents a dependency table for a postprocessing steps.
* *
* For future use. * For future use.
*/ */
struct PPDependencyTable struct PPDependencyTable
{ {
unsigned int execute_me_before_these; unsigned int execute_me_before_these;
unsigned int execute_me_after_these; unsigned int execute_me_after_these;
unsigned int only_if_these_are_not_specified; unsigned int only_if_these_are_not_specified;
unsigned int mutually_exclusive_with; unsigned int mutually_exclusive_with;
}; };
#endif #endif
#define AI_SPP_SPATIAL_SORT "$Spat" #define AI_SPP_SPATIAL_SORT "$Spat"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** The BaseProcess defines a common interface for all post processing steps. /** The BaseProcess defines a common interface for all post processing steps.
* A post processing step is run after a successful import if the caller * A post processing step is run after a successful import if the caller
* specified the corresponding flag when calling ReadFile(). * specified the corresponding flag when calling ReadFile().
* Enum #aiPostProcessSteps defines which flags are available. * Enum #aiPostProcessSteps defines which flags are available.
* After a successful import the Importer iterates over its internal array * After a successful import the Importer iterates over its internal array
* of processes and calls IsActive() on each process to evaluate if the step * of processes and calls IsActive() on each process to evaluate if the step
* should be executed. If the function returns true, the class' Execute() * should be executed. If the function returns true, the class' Execute()
* function is called subsequently. * function is called subsequently.
*/ */
class ASSIMP_API_WINONLY BaseProcess class ASSIMP_API_WINONLY BaseProcess
{ {
friend class Importer; friend class Importer;
public: public:
/** Constructor to be privately used by Importer */ /** Constructor to be privately used by Importer */
BaseProcess(); BaseProcess();
/** Destructor, private as well */ /** Destructor, private as well */
virtual ~BaseProcess(); virtual ~BaseProcess();
public: public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the processing step is present in the given flag. /** Returns whether the processing step is present in the given flag.
* @param pFlags The processing flags the importer was called with. A * @param pFlags The processing flags the importer was called with. A
* bitwise combination of #aiPostProcessSteps. * bitwise combination of #aiPostProcessSteps.
* @return true if the process is present in this flag fields, * @return true if the process is present in this flag fields,
* false if not. * false if not.
*/ */
virtual bool IsActive( unsigned int pFlags) const = 0; virtual bool IsActive( unsigned int pFlags) const = 0;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Check whether this step expects its input vertex data to be /** Check whether this step expects its input vertex data to be
* in verbose format. */ * in verbose format. */
virtual bool RequireVerboseFormat() const; virtual bool RequireVerboseFormat() const;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Executes the post processing step on the given imported data. /** Executes the post processing step on the given imported data.
* The function deletes the scene if the postprocess step fails ( * The function deletes the scene if the postprocess step fails (
* the object pointer will be set to NULL). * the object pointer will be set to NULL).
* @param pImp Importer instance (pImp->mScene must be valid) * @param pImp Importer instance (pImp->mScene must be valid)
*/ */
void ExecuteOnScene( Importer* pImp); void ExecuteOnScene( Importer* pImp);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Called prior to ExecuteOnScene(). /** Called prior to ExecuteOnScene().
* The function is a request to the process to update its configuration * The function is a request to the process to update its configuration
* basing on the Importer's configuration property list. * basing on the Importer's configuration property list.
*/ */
virtual void SetupProperties(const Importer* pImp); virtual void SetupProperties(const Importer* pImp);
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Executes the post processing step on the given imported data. /** Executes the post processing step on the given imported data.
* A process should throw an ImportErrorException* if it fails. * A process should throw an ImportErrorException* if it fails.
* This method must be implemented by deriving classes. * This method must be implemented by deriving classes.
* @param pScene The imported data to work at. * @param pScene The imported data to work at.
*/ */
virtual void Execute( aiScene* pScene) = 0; virtual void Execute( aiScene* pScene) = 0;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Assign a new SharedPostProcessInfo to the step. This object /** Assign a new SharedPostProcessInfo to the step. This object
* allows multiple postprocess steps to share data. * allows multiple postprocess steps to share data.
* @param sh May be NULL * @param sh May be NULL
*/ */
inline void SetSharedData(SharedPostProcessInfo* sh) { inline void SetSharedData(SharedPostProcessInfo* sh) {
shared = sh; shared = sh;
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Get the shared data that is assigned to the step. /** Get the shared data that is assigned to the step.
*/ */
inline SharedPostProcessInfo* GetSharedData() { inline SharedPostProcessInfo* GetSharedData() {
return shared; return shared;
} }
protected: protected:
/** See the doc of #SharedPostProcessInfo for more details */ /** See the doc of #SharedPostProcessInfo for more details */
SharedPostProcessInfo* shared; SharedPostProcessInfo* shared;
/** Currently active progress handler */ /** Currently active progress handler */
ProgressHandler* progress; ProgressHandler* progress;
}; };
} // end of namespace Assimp } // end of namespace Assimp
#endif // AI_BASEPROCESS_H_INC #endif // AI_BASEPROCESS_H_INC

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,101 +45,108 @@ 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 {
void Bitmap::Save(aiTexture* texture, IOStream* file) { void Bitmap::Save(aiTexture* texture, IOStream* file) {
if(file != NULL) { if(file != NULL) {
Header header; Header header;
DIB dib; DIB dib;
dib.size = DIB::dib_size; dib.size = DIB::dib_size;
dib.width = texture->mWidth; dib.width = texture->mWidth;
dib.height = texture->mHeight; dib.height = texture->mHeight;
dib.planes = 1; dib.planes = 1;
dib.bits_per_pixel = 8 * mBytesPerPixel; dib.bits_per_pixel = 8 * mBytesPerPixel;
dib.compression = 0; dib.compression = 0;
dib.image_size = (((dib.width * mBytesPerPixel) + 3) & 0x0000FFFC) * dib.height; dib.image_size = (((dib.width * mBytesPerPixel) + 3) & 0x0000FFFC) * dib.height;
dib.x_resolution = 0; dib.x_resolution = 0;
dib.y_resolution = 0; dib.y_resolution = 0;
dib.nb_colors = 0; dib.nb_colors = 0;
dib.nb_important_colors = 0; dib.nb_important_colors = 0;
header.type = 0x4D42; // 'BM' header.type = 0x4D42; // 'BM'
header.offset = Header::header_size + DIB::dib_size; header.offset = Header::header_size + DIB::dib_size;
header.size = header.offset + dib.image_size; header.size = header.offset + dib.image_size;
header.reserved1 = 0; header.reserved1 = 0;
header.reserved2 = 0; header.reserved2 = 0;
WriteHeader(header, file); WriteHeader(header, file);
WriteDIB(dib, file); WriteDIB(dib, file);
WriteData(texture, file); WriteData(texture, file);
} }
} }
template<typename T> template<typename T>
inline std::size_t Copy(uint8_t* data, T& field) { inline std::size_t Copy(uint8_t* data, T& field) {
std::memcpy(data, &AI_BE(field), sizeof(field)); return sizeof(field); #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);
#endif
}
void Bitmap::WriteHeader(Header& header, IOStream* file) { void Bitmap::WriteHeader(Header& header, IOStream* file) {
uint8_t data[Header::header_size]; uint8_t data[Header::header_size];
std::size_t offset = 0; std::size_t offset = 0;
offset += Copy(&data[offset], header.type); offset += Copy(&data[offset], header.type);
offset += Copy(&data[offset], header.size); offset += Copy(&data[offset], header.size);
offset += Copy(&data[offset], header.reserved1); offset += Copy(&data[offset], header.reserved1);
offset += Copy(&data[offset], header.reserved2); offset += Copy(&data[offset], header.reserved2);
offset += Copy(&data[offset], header.offset); offset += Copy(&data[offset], header.offset);
file->Write(data, Header::header_size, 1); file->Write(data, Header::header_size, 1);
} }
void Bitmap::WriteDIB(DIB& dib, IOStream* file) { void Bitmap::WriteDIB(DIB& dib, IOStream* file) {
uint8_t data[DIB::dib_size]; uint8_t data[DIB::dib_size];
std::size_t offset = 0; std::size_t offset = 0;
offset += Copy(&data[offset], dib.size); offset += Copy(&data[offset], dib.size);
offset += Copy(&data[offset], dib.width); offset += Copy(&data[offset], dib.width);
offset += Copy(&data[offset], dib.height); offset += Copy(&data[offset], dib.height);
offset += Copy(&data[offset], dib.planes); offset += Copy(&data[offset], dib.planes);
offset += Copy(&data[offset], dib.bits_per_pixel); offset += Copy(&data[offset], dib.bits_per_pixel);
offset += Copy(&data[offset], dib.compression); offset += Copy(&data[offset], dib.compression);
offset += Copy(&data[offset], dib.image_size); offset += Copy(&data[offset], dib.image_size);
offset += Copy(&data[offset], dib.x_resolution); offset += Copy(&data[offset], dib.x_resolution);
offset += Copy(&data[offset], dib.y_resolution); offset += Copy(&data[offset], dib.y_resolution);
offset += Copy(&data[offset], dib.nb_colors); offset += Copy(&data[offset], dib.nb_colors);
offset += Copy(&data[offset], dib.nb_important_colors); offset += Copy(&data[offset], dib.nb_important_colors);
file->Write(data, DIB::dib_size, 1); file->Write(data, DIB::dib_size, 1);
} }
void Bitmap::WriteData(aiTexture* texture, IOStream* file) { void Bitmap::WriteData(aiTexture* texture, IOStream* file) {
static const std::size_t padding_offset = 4; static const std::size_t padding_offset = 4;
static const uint8_t padding_data[padding_offset] = {0x0, 0x0, 0x0, 0x0}; static const uint8_t padding_data[padding_offset] = {0x0, 0x0, 0x0, 0x0};
unsigned int padding = (padding_offset - ((mBytesPerPixel * texture->mWidth) % padding_offset)) % padding_offset; unsigned int padding = (padding_offset - ((mBytesPerPixel * texture->mWidth) % padding_offset)) % padding_offset;
uint8_t pixel[mBytesPerPixel]; uint8_t pixel[mBytesPerPixel];
for(std::size_t i = 0; i < texture->mHeight; ++i) { for(std::size_t i = 0; i < texture->mHeight; ++i) {
for(std::size_t j = 0; j < texture->mWidth; ++j) { for(std::size_t j = 0; j < texture->mWidth; ++j) {
const aiTexel& texel = texture->pcData[(texture->mHeight - i - 1) * texture->mWidth + j]; // Bitmap files are stored in bottom-up format const aiTexel& texel = texture->pcData[(texture->mHeight - i - 1) * texture->mWidth + j]; // Bitmap files are stored in bottom-up format
pixel[0] = texel.r; pixel[0] = texel.r;
pixel[1] = texel.g; pixel[1] = texel.g;
pixel[2] = texel.b; pixel[2] = texel.b;
pixel[3] = texel.a; pixel[3] = texel.a;
file->Write(pixel, mBytesPerPixel, 1); file->Write(pixel, mBytesPerPixel, 1);
} }
file->Write(padding_data, padding, 1); file->Write(padding_data, padding, 1);
} }
} }
} }

View File

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

View File

@ -5,8 +5,8 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2013, assimp team Copyright (c) 2006-2013, 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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
@ -23,16 +23,16 @@ following 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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
@ -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
@ -53,7 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp namespace Assimp
{ {
template< > const std::string LogFunctions< BlenderBMeshConverter >::log_prefix = "BLEND_BMESH: "; template< > const std::string LogFunctions< BlenderBMeshConverter >::log_prefix = "BLEND_BMESH: ";
} }
using namespace Assimp; using namespace Assimp;
@ -62,142 +61,142 @@ using namespace Assimp::Formatter;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
BlenderBMeshConverter::BlenderBMeshConverter( const Mesh* mesh ): BlenderBMeshConverter::BlenderBMeshConverter( const Mesh* mesh ):
BMesh( mesh ), BMesh( mesh ),
triMesh( NULL ) triMesh( NULL )
{ {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
BlenderBMeshConverter::~BlenderBMeshConverter( ) BlenderBMeshConverter::~BlenderBMeshConverter( )
{ {
DestroyTriMesh( ); DestroyTriMesh( );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool BlenderBMeshConverter::ContainsBMesh( ) const bool BlenderBMeshConverter::ContainsBMesh( ) const
{ {
// TODO - Should probably do some additional verification here // TODO - Should probably do some additional verification here
return BMesh->totpoly && BMesh->totloop && BMesh->totvert; return BMesh->totpoly && BMesh->totloop && BMesh->totvert;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const Mesh* BlenderBMeshConverter::TriangulateBMesh( ) const Mesh* BlenderBMeshConverter::TriangulateBMesh( )
{ {
AssertValidMesh( ); AssertValidMesh( );
AssertValidSizes( ); AssertValidSizes( );
PrepareTriMesh( ); PrepareTriMesh( );
for ( int i = 0; i < BMesh->totpoly; ++i ) for ( int i = 0; i < BMesh->totpoly; ++i )
{ {
const MPoly& poly = BMesh->mpoly[ i ]; const MPoly& poly = BMesh->mpoly[ i ];
ConvertPolyToFaces( poly ); ConvertPolyToFaces( poly );
} }
return triMesh; return triMesh;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::AssertValidMesh( ) void BlenderBMeshConverter::AssertValidMesh( )
{ {
if ( !ContainsBMesh( ) ) if ( !ContainsBMesh( ) )
{ {
ThrowException( "BlenderBMeshConverter requires a BMesh with \"polygons\" - please call BlenderBMeshConverter::ContainsBMesh to check this first" ); ThrowException( "BlenderBMeshConverter requires a BMesh with \"polygons\" - please call BlenderBMeshConverter::ContainsBMesh to check this first" );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::AssertValidSizes( ) void BlenderBMeshConverter::AssertValidSizes( )
{ {
if ( BMesh->totpoly != static_cast<int>( BMesh->mpoly.size( ) ) ) if ( BMesh->totpoly != static_cast<int>( BMesh->mpoly.size( ) ) )
{ {
ThrowException( "BMesh poly array has incorrect size" ); ThrowException( "BMesh poly array has incorrect size" );
} }
if ( BMesh->totloop != static_cast<int>( BMesh->mloop.size( ) ) ) if ( BMesh->totloop != static_cast<int>( BMesh->mloop.size( ) ) )
{ {
ThrowException( "BMesh loop array has incorrect size" ); ThrowException( "BMesh loop array has incorrect size" );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::PrepareTriMesh( ) void BlenderBMeshConverter::PrepareTriMesh( )
{ {
if ( triMesh ) if ( triMesh )
{ {
DestroyTriMesh( ); DestroyTriMesh( );
} }
triMesh = new Mesh( *BMesh ); triMesh = new Mesh( *BMesh );
triMesh->totface = 0; triMesh->totface = 0;
triMesh->mface.clear( ); triMesh->mface.clear( );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::DestroyTriMesh( ) void BlenderBMeshConverter::DestroyTriMesh( )
{ {
delete triMesh; delete triMesh;
triMesh = NULL; triMesh = NULL;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::ConvertPolyToFaces( const MPoly& poly ) void BlenderBMeshConverter::ConvertPolyToFaces( const MPoly& poly )
{ {
const MLoop* polyLoop = &BMesh->mloop[ poly.loopstart ]; const MLoop* polyLoop = &BMesh->mloop[ poly.loopstart ];
if ( poly.totloop == 3 || poly.totloop == 4 ) if ( poly.totloop == 3 || poly.totloop == 4 )
{ {
AddFace( polyLoop[ 0 ].v, polyLoop[ 1 ].v, polyLoop[ 2 ].v, poly.totloop == 4 ? polyLoop[ 3 ].v : 0 ); AddFace( polyLoop[ 0 ].v, polyLoop[ 1 ].v, polyLoop[ 2 ].v, poly.totloop == 4 ? polyLoop[ 3 ].v : 0 );
// UVs are optional, so only convert when present. // UVs are optional, so only convert when present.
if ( BMesh->mloopuv.size() ) if ( BMesh->mloopuv.size() )
{ {
if ( (poly.loopstart + poly.totloop ) >= static_cast<int>( BMesh->mloopuv.size() ) ) if ( (poly.loopstart + poly.totloop ) > static_cast<int>( BMesh->mloopuv.size() ) )
{ {
ThrowException( "BMesh uv loop array has incorrect size" ); ThrowException( "BMesh uv loop array has incorrect size" );
} }
const MLoopUV* loopUV = &BMesh->mloopuv[ poly.loopstart ]; const MLoopUV* loopUV = &BMesh->mloopuv[ poly.loopstart ];
AddTFace( loopUV[ 0 ].uv, loopUV[ 1 ].uv, loopUV[ 2 ].uv, poly.totloop == 4 ? loopUV[ 3 ].uv : 0 ); AddTFace( loopUV[ 0 ].uv, loopUV[ 1 ].uv, loopUV[ 2 ].uv, poly.totloop == 4 ? loopUV[ 3 ].uv : 0 );
} }
} }
else if ( poly.totloop > 4 ) else if ( poly.totloop > 4 )
{ {
#if ASSIMP_BLEND_WITH_GLU_TESSELLATE #if ASSIMP_BLEND_WITH_GLU_TESSELLATE
BlenderTessellatorGL tessGL( *this ); BlenderTessellatorGL tessGL( *this );
tessGL.Tessellate( polyLoop, poly.totloop, triMesh->mvert ); tessGL.Tessellate( polyLoop, poly.totloop, triMesh->mvert );
#elif ASSIMP_BLEND_WITH_POLY_2_TRI #elif ASSIMP_BLEND_WITH_POLY_2_TRI
BlenderTessellatorP2T tessP2T( *this ); BlenderTessellatorP2T tessP2T( *this );
tessP2T.Tessellate( polyLoop, poly.totloop, triMesh->mvert ); tessP2T.Tessellate( polyLoop, poly.totloop, triMesh->mvert );
#endif #endif
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::AddFace( int v1, int v2, int v3, int v4 ) void BlenderBMeshConverter::AddFace( int v1, int v2, int v3, int v4 )
{ {
MFace face; MFace face;
face.v1 = v1; face.v1 = v1;
face.v2 = v2; face.v2 = v2;
face.v3 = v3; face.v3 = v3;
face.v4 = v4; face.v4 = v4;
// TODO - Work out how materials work // TODO - Work out how materials work
face.mat_nr = 0; face.mat_nr = 0;
triMesh->mface.push_back( face ); triMesh->mface.push_back( face );
triMesh->totface = triMesh->mface.size( ); triMesh->totface = static_cast<int>(triMesh->mface.size( ));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderBMeshConverter::AddTFace( const float* uv1, const float *uv2, const float *uv3, const float* uv4 ) void BlenderBMeshConverter::AddTFace( const float* uv1, const float *uv2, const float *uv3, const float* uv4 )
{ {
MTFace mtface; MTFace mtface;
memcpy( &mtface.uv[ 0 ], uv1, sizeof(float) * 2 ); memcpy( &mtface.uv[ 0 ], uv1, sizeof(float) * 2 );
memcpy( &mtface.uv[ 1 ], uv2, sizeof(float) * 2 ); memcpy( &mtface.uv[ 1 ], uv2, sizeof(float) * 2 );
memcpy( &mtface.uv[ 2 ], uv3, sizeof(float) * 2 ); memcpy( &mtface.uv[ 2 ], uv3, sizeof(float) * 2 );
if ( uv4 ) if ( uv4 )
{ {
memcpy( &mtface.uv[ 3 ], uv4, sizeof(float) * 2 ); memcpy( &mtface.uv[ 3 ], uv4, sizeof(float) * 2 );
} }
triMesh->mtface.push_back( mtface ); triMesh->mtface.push_back( mtface );
} }
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER #endif // ASSIMP_BUILD_NO_BLEND_IMPORTER

View File

@ -5,8 +5,8 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2013, assimp team Copyright (c) 2006-2013, 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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
@ -23,16 +23,16 @@ following 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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
@ -48,46 +48,46 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp namespace Assimp
{ {
// TinyFormatter.h // TinyFormatter.h
namespace Formatter namespace Formatter
{ {
template < typename T,typename TR, typename A > class basic_formatter; template < typename T,typename TR, typename A > class basic_formatter;
typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format; typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format;
} }
// BlenderScene.h // BlenderScene.h
namespace Blender namespace Blender
{ {
struct Mesh; struct Mesh;
struct MPoly; struct MPoly;
struct MLoop; struct MLoop;
} }
class BlenderBMeshConverter: public LogFunctions< BlenderBMeshConverter > class BlenderBMeshConverter: public LogFunctions< BlenderBMeshConverter >
{ {
public: public:
BlenderBMeshConverter( const Blender::Mesh* mesh ); BlenderBMeshConverter( const Blender::Mesh* mesh );
~BlenderBMeshConverter( ); ~BlenderBMeshConverter( );
bool ContainsBMesh( ) const; bool ContainsBMesh( ) const;
const Blender::Mesh* TriangulateBMesh( ); const Blender::Mesh* TriangulateBMesh( );
private: private:
void AssertValidMesh( ); void AssertValidMesh( );
void AssertValidSizes( ); void AssertValidSizes( );
void PrepareTriMesh( ); void PrepareTriMesh( );
void DestroyTriMesh( ); void DestroyTriMesh( );
void ConvertPolyToFaces( const Blender::MPoly& poly ); void ConvertPolyToFaces( const Blender::MPoly& poly );
void AddFace( int v1, int v2, int v3, int v4 = 0 ); void AddFace( int v1, int v2, int v3, int v4 = 0 );
void AddTFace( const float* uv1, const float* uv2, const float *uv3, const float* uv4 = 0 ); void AddTFace( const float* uv1, const float* uv2, const float *uv3, const float* uv4 = 0 );
const Blender::Mesh* BMesh; const Blender::Mesh* BMesh;
Blender::Mesh* triMesh; Blender::Mesh* triMesh;
friend class BlenderTessellatorGL; friend class BlenderTessellatorGL;
friend class BlenderTessellatorP2T; friend class BlenderTessellatorP2T;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -1,372 +1,374 @@
/* /*
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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer. following disclaimer.
* Redistributions in binary form must reproduce the above * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other following disclaimer in the documentation and/or other
materials provided with the distribution. materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its * Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products contributors may be used to endorse or promote products
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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file BlenderDNA.cpp /** @file BlenderDNA.cpp
* @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"
#include "StreamReader.h" #include "StreamReader.h"
#include "fast_atof.h" #include "fast_atof.h"
using namespace Assimp; 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]);
} }
struct Type { struct Type {
size_t size; size_t size;
std::string name; std::string name;
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void DNAParser :: Parse () void DNAParser::Parse ()
{ {
StreamReaderAny& stream = *db.reader.get(); StreamReaderAny& stream = *db.reader.get();
DNA& dna = db.dna; DNA& dna = db.dna;
if(!match4(stream,"SDNA")) { if(!match4(stream,"SDNA")) {
throw DeadlyImportError("BlenderDNA: Expected SDNA chunk"); throw DeadlyImportError("BlenderDNA: Expected SDNA chunk");
} }
// name dictionary // name dictionary
if(!match4(stream,"NAME")) { if(!match4(stream,"NAME")) {
throw DeadlyImportError("BlenderDNA: Expected NAME field"); throw DeadlyImportError("BlenderDNA: Expected NAME field");
} }
std::vector<std::string> names (stream.GetI4()); std::vector<std::string> names (stream.GetI4());
for_each(std::string& s, names) { for(std::string& s : names) {
while (char c = stream.GetI1()) { while (char c = stream.GetI1()) {
s += c; s += c;
} }
} }
// type dictionary // type dictionary
for (;stream.GetCurrentPos() & 0x3; stream.GetI1()); for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
if(!match4(stream,"TYPE")) { if(!match4(stream,"TYPE")) {
throw DeadlyImportError("BlenderDNA: Expected TYPE field"); throw DeadlyImportError("BlenderDNA: Expected TYPE field");
} }
std::vector<Type> types (stream.GetI4()); std::vector<Type> types (stream.GetI4());
for_each(Type& s, types) { for(Type& s : types) {
while (char c = stream.GetI1()) { while (char c = stream.GetI1()) {
s.name += c; s.name += c;
} }
} }
// type length dictionary // type length dictionary
for (;stream.GetCurrentPos() & 0x3; stream.GetI1()); for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
if(!match4(stream,"TLEN")) { if(!match4(stream,"TLEN")) {
throw DeadlyImportError("BlenderDNA: Expected TLEN field"); throw DeadlyImportError("BlenderDNA: Expected TLEN field");
} }
for_each(Type& s, types) { for(Type& s : types) {
s.size = stream.GetI2(); s.size = stream.GetI2();
} }
// structures dictionary // structures dictionary
for (;stream.GetCurrentPos() & 0x3; stream.GetI1()); for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
if(!match4(stream,"STRC")) { if(!match4(stream,"STRC")) {
throw DeadlyImportError("BlenderDNA: Expected STRC field"); throw DeadlyImportError("BlenderDNA: Expected STRC field");
} }
size_t end = stream.GetI4(), fields = 0; size_t end = stream.GetI4(), fields = 0;
dna.structures.reserve(end); dna.structures.reserve(end);
for(size_t i = 0; i != end; ++i) { for(size_t i = 0; i != end; ++i) {
uint16_t n = stream.GetI2(); uint16_t n = stream.GetI2();
if (n >= types.size()) { if (n >= types.size()) {
throw DeadlyImportError((format(), throw DeadlyImportError((format(),
"BlenderDNA: Invalid type index in structure name" ,n, "BlenderDNA: Invalid type index in structure name" ,n,
" (there are only ", types.size(), " entries)" " (there are only ", types.size(), " entries)"
)); ));
} }
// maintain separate indexes // maintain separate indexes
dna.indices[types[n].name] = dna.structures.size(); dna.indices[types[n].name] = dna.structures.size();
dna.structures.push_back(Structure()); dna.structures.push_back(Structure());
Structure& s = dna.structures.back(); Structure& s = dna.structures.back();
s.name = types[n].name; s.name = types[n].name;
//s.index = dna.structures.size()-1; //s.index = dna.structures.size()-1;
n = stream.GetI2(); n = stream.GetI2();
s.fields.reserve(n); s.fields.reserve(n);
size_t offset = 0; size_t offset = 0;
for (size_t m = 0; m < n; ++m, ++fields) { for (size_t m = 0; m < n; ++m, ++fields) {
uint16_t j = stream.GetI2(); uint16_t j = stream.GetI2();
if (j >= types.size()) { if (j >= types.size()) {
throw DeadlyImportError((format(), throw DeadlyImportError((format(),
"BlenderDNA: Invalid type index in structure field ", j, "BlenderDNA: Invalid type index in structure field ", j,
" (there are only ", types.size(), " entries)" " (there are only ", types.size(), " entries)"
)); ));
} }
s.fields.push_back(Field()); s.fields.push_back(Field());
Field& f = s.fields.back(); Field& f = s.fields.back();
f.offset = offset; f.offset = offset;
f.type = types[j].name; f.type = types[j].name;
f.size = types[j].size; f.size = types[j].size;
j = stream.GetI2(); j = stream.GetI2();
if (j >= names.size()) { if (j >= names.size()) {
throw DeadlyImportError((format(), throw DeadlyImportError((format(),
"BlenderDNA: Invalid name index in structure field ", j, "BlenderDNA: Invalid name index in structure field ", j,
" (there are only ", names.size(), " entries)" " (there are only ", names.size(), " entries)"
)); ));
} }
f.name = names[j]; f.name = names[j];
f.flags = 0u; f.flags = 0u;
// pointers always specify the size of the pointee instead of their own. // pointers always specify the size of the pointee instead of their own.
// The pointer asterisk remains a property of the lookup name. // The pointer asterisk remains a property of the lookup name.
if (f.name[0] == '*') { if (f.name[0] == '*') {
f.size = db.i64bit ? 8 : 4; f.size = db.i64bit ? 8 : 4;
f.flags |= FieldFlag_Pointer; f.flags |= FieldFlag_Pointer;
} }
// arrays, however, specify the size of a single element so we // arrays, however, specify the size of a single element so we
// need to parse the (possibly multi-dimensional) array declaration // need to parse the (possibly multi-dimensional) array declaration
// in order to obtain the actual size of the array in the file. // in order to obtain the actual size of the array in the file.
// Also we need to alter the lookup name to include no array // Also we need to alter the lookup name to include no array
// brackets anymore or size fixup won't work (if our size does // brackets anymore or size fixup won't work (if our size does
// not match the size read from the DNA). // not match the size read from the DNA).
if (*f.name.rbegin() == ']') { if (*f.name.rbegin() == ']') {
const std::string::size_type rb = f.name.find('['); const std::string::size_type rb = f.name.find('[');
if (rb == std::string::npos) { if (rb == std::string::npos) {
throw DeadlyImportError((format(), throw DeadlyImportError((format(),
"BlenderDNA: Encountered invalid array declaration ", "BlenderDNA: Encountered invalid array declaration ",
f.name f.name
)); ));
} }
f.flags |= FieldFlag_Array; f.flags |= FieldFlag_Array;
DNA::ExtractArraySize(f.name,f.array_sizes); DNA::ExtractArraySize(f.name,f.array_sizes);
f.name = f.name.substr(0,rb); f.name = f.name.substr(0,rb);
f.size *= f.array_sizes[0] * f.array_sizes[1]; f.size *= f.array_sizes[0] * f.array_sizes[1];
} }
// maintain separate indexes // maintain separate indexes
s.indices[f.name] = s.fields.size()-1; s.indices[f.name] = s.fields.size()-1;
offset += f.size; offset += f.size;
} }
s.size = offset; s.size = offset;
} }
DefaultLogger::get()->debug((format(),"BlenderDNA: Got ",dna.structures.size(), DefaultLogger::get()->debug((format(),"BlenderDNA: Got ",dna.structures.size(),
" structures with totally ",fields," fields")); " structures with totally ",fields," fields"));
#ifdef ASSIMP_BUILD_BLENDER_DEBUG #ifdef ASSIMP_BUILD_BLENDER_DEBUG
dna.DumpToFile(); dna.DumpToFile();
#endif #endif
dna.AddPrimitiveStructures(); dna.AddPrimitiveStructures();
dna.RegisterConverters(); dna.RegisterConverters();
} }
#ifdef ASSIMP_BUILD_BLENDER_DEBUG #ifdef ASSIMP_BUILD_BLENDER_DEBUG
#include <fstream> #include <fstream>
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void DNA :: DumpToFile() void DNA :: DumpToFile()
{ {
// we dont't bother using the VFS here for this is only for debugging. // we dont't bother using the VFS here for this is only for debugging.
// (and all your bases are belong to us). // (and all your bases are belong to us).
std::ofstream f("dna.txt"); std::ofstream f("dna.txt");
if (f.fail()) { if (f.fail()) {
DefaultLogger::get()->error("Could not dump dna to dna.txt"); DefaultLogger::get()->error("Could not dump dna to dna.txt");
return; return;
} }
f << "Field format: type name offset size" << "\n"; f << "Field format: type name offset size" << "\n";
f << "Structure format: name size" << "\n"; f << "Structure format: name size" << "\n";
for_each(const Structure& s, structures) { for(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";
} }
DefaultLogger::get()->info("BlenderDNA: Dumped dna to dna.txt"); f << std::flush;
}
#endif DefaultLogger::get()->info("BlenderDNA: Dumped dna to dna.txt");
}
// ------------------------------------------------------------------------------------------------ #endif
/*static*/ void DNA :: ExtractArraySize(
const std::string& out, // ------------------------------------------------------------------------------------------------
size_t array_sizes[2] /*static*/ void DNA :: ExtractArraySize(
) const std::string& out,
{ size_t array_sizes[2]
array_sizes[0] = array_sizes[1] = 1; )
std::string::size_type pos = out.find('['); {
if (pos++ == std::string::npos) { array_sizes[0] = array_sizes[1] = 1;
return; std::string::size_type pos = out.find('[');
} if (pos++ == std::string::npos) {
array_sizes[0] = strtoul10(&out[pos]); return;
}
pos = out.find('[',pos); array_sizes[0] = strtoul10(&out[pos]);
if (pos++ == std::string::npos) {
return; pos = out.find('[',pos);
} if (pos++ == std::string::npos) {
array_sizes[1] = strtoul10(&out[pos]); return;
} }
array_sizes[1] = strtoul10(&out[pos]);
// ------------------------------------------------------------------------------------------------ }
boost::shared_ptr< ElemBase > DNA :: ConvertBlobToStructure(
const Structure& structure, // ------------------------------------------------------------------------------------------------
const FileDatabase& db std::shared_ptr< ElemBase > DNA :: ConvertBlobToStructure(
) const const Structure& structure,
{ const FileDatabase& db
std::map<std::string, FactoryPair >::const_iterator it = converters.find(structure.name); ) const
if (it == converters.end()) { {
return boost::shared_ptr< ElemBase >(); std::map<std::string, FactoryPair >::const_iterator it = converters.find(structure.name);
} if (it == converters.end()) {
return std::shared_ptr< ElemBase >();
boost::shared_ptr< ElemBase > ret = (structure.*((*it).second.first))(); }
(structure.*((*it).second.second))(ret,db);
std::shared_ptr< ElemBase > ret = (structure.*((*it).second.first))();
return ret; (structure.*((*it).second.second))(ret,db);
}
return ret;
// ------------------------------------------------------------------------------------------------ }
DNA::FactoryPair DNA :: GetBlobToStructureConverter(
const Structure& structure, // ------------------------------------------------------------------------------------------------
const FileDatabase& /*db*/ DNA::FactoryPair DNA :: GetBlobToStructureConverter(
) const const Structure& structure,
{ const FileDatabase& /*db*/
std::map<std::string, FactoryPair>::const_iterator it = converters.find(structure.name); ) const
return it == converters.end() ? FactoryPair() : (*it).second; {
} std::map<std::string, FactoryPair>::const_iterator it = converters.find(structure.name);
return it == converters.end() ? FactoryPair() : (*it).second;
// basing on http://www.blender.org/development/architecture/notes-on-sdna/ }
// ------------------------------------------------------------------------------------------------
void DNA :: AddPrimitiveStructures() // basing on http://www.blender.org/development/architecture/notes-on-sdna/
{ // ------------------------------------------------------------------------------------------------
// NOTE: these are just dummies. Their presence enforces void DNA :: AddPrimitiveStructures()
// Structure::Convert<target_type> to be called on these {
// empty structures. These converters are special // NOTE: these are just dummies. Their presence enforces
// overloads which scan the name of the structure and // Structure::Convert<target_type> to be called on these
// perform the required data type conversion if one // empty structures. These converters are special
// of these special names is found in the structure // overloads which scan the name of the structure and
// in question. // perform the required data type conversion if one
// of these special names is found in the structure
indices["int"] = structures.size(); // in question.
structures.push_back( Structure() );
structures.back().name = "int"; indices["int"] = structures.size();
structures.back().size = 4; structures.push_back( Structure() );
structures.back().name = "int";
indices["short"] = structures.size(); structures.back().size = 4;
structures.push_back( Structure() );
structures.back().name = "short"; indices["short"] = structures.size();
structures.back().size = 2; structures.push_back( Structure() );
structures.back().name = "short";
structures.back().size = 2;
indices["char"] = structures.size();
structures.push_back( Structure() );
structures.back().name = "char"; indices["char"] = structures.size();
structures.back().size = 1; structures.push_back( Structure() );
structures.back().name = "char";
structures.back().size = 1;
indices["float"] = structures.size();
structures.push_back( Structure() );
structures.back().name = "float"; indices["float"] = structures.size();
structures.back().size = 4; structures.push_back( Structure() );
structures.back().name = "float";
structures.back().size = 4;
indices["double"] = structures.size();
structures.push_back( Structure() );
structures.back().name = "double"; indices["double"] = structures.size();
structures.back().size = 8; structures.push_back( Structure() );
structures.back().name = "double";
// no long, seemingly. structures.back().size = 8;
}
// no long, seemingly.
// ------------------------------------------------------------------------------------------------ }
void SectionParser :: Next()
{ // ------------------------------------------------------------------------------------------------
stream.SetCurrentPos(current.start + current.size); void SectionParser :: Next()
{
const char tmp[] = { stream.SetCurrentPos(current.start + current.size);
stream.GetI1(),
stream.GetI1(), const char tmp[] = {
stream.GetI1(), (const char)stream.GetI1(),
stream.GetI1() (const char)stream.GetI1(),
}; (const char)stream.GetI1(),
current.id = std::string(tmp,tmp[3]?4:tmp[2]?3:tmp[1]?2:1); (const char)stream.GetI1()
};
current.size = stream.GetI4(); current.id = std::string(tmp,tmp[3]?4:tmp[2]?3:tmp[1]?2:1);
current.address.val = ptr64 ? stream.GetU8() : stream.GetU4();
current.size = stream.GetI4();
current.dna_index = stream.GetI4(); current.address.val = ptr64 ? stream.GetU8() : stream.GetU4();
current.num = stream.GetI4();
current.dna_index = stream.GetI4();
current.start = stream.GetCurrentPos(); current.num = stream.GetI4();
if (stream.GetRemainingSizeToLimit() < current.size) {
throw DeadlyImportError("BLEND: invalid size of file block"); current.start = stream.GetCurrentPos();
} if (stream.GetRemainingSizeToLimit() < current.size) {
throw DeadlyImportError("BLEND: invalid size of file block");
#ifdef ASSIMP_BUILD_BLENDER_DEBUG }
DefaultLogger::get()->debug(current.id);
#endif #ifdef ASSIMP_BUILD_BLENDER_DEBUG
} DefaultLogger::get()->debug(current.id);
#endif
}
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,183 +1,201 @@
/* /*
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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer. following disclaimer.
* Redistributions in binary form must reproduce the above * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other following disclaimer in the documentation and/or other
materials provided with the distribution. materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its * Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products contributors may be used to endorse or promote products
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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file BlenderIntermediate.h /** @file BlenderIntermediate.h
* @brief Internal utility structures for the BlenderLoader. It also serves * @brief Internal utility structures for the BlenderLoader. It also serves
* as master include file for the whole (internal) Blender subsystem. * as master include file for the whole (internal) Blender subsystem.
*/ */
#ifndef INCLUDED_AI_BLEND_INTERMEDIATE_H #ifndef INCLUDED_AI_BLEND_INTERMEDIATE_H
#define INCLUDED_AI_BLEND_INTERMEDIATE_H #define INCLUDED_AI_BLEND_INTERMEDIATE_H
#include "BlenderLoader.h" #include "BlenderLoader.h"
#include "BlenderDNA.h" #include "BlenderDNA.h"
#include "BlenderScene.h" #include "BlenderScene.h"
#include "BlenderSceneGen.h" #include "BlenderSceneGen.h"
#include <deque>
#define for_each(x,y) BOOST_FOREACH(x,y) #include "./../include/assimp/material.h"
namespace Assimp { struct aiTexture;
namespace Blender {
namespace Assimp {
// -------------------------------------------------------------------- namespace Blender {
/** Mini smart-array to avoid pulling in even more boost stuff. usable with vector and deque */
// -------------------------------------------------------------------- // --------------------------------------------------------------------
template <template <typename,typename> class TCLASS, typename T> /** Mini smart-array to avoid pulling in even more boost stuff. usable with vector and deque */
struct TempArray { // --------------------------------------------------------------------
typedef TCLASS< T*,std::allocator<T*> > mywrap; template <template <typename,typename> class TCLASS, typename T>
struct TempArray {
TempArray() { typedef TCLASS< T*,std::allocator<T*> > mywrap;
}
TempArray() {
~TempArray () { }
for_each(T* elem, arr) {
delete elem; ~TempArray () {
} for(T* elem : arr) {
} delete elem;
}
void dismiss() { }
arr.clear();
} void dismiss() {
arr.clear();
mywrap* operator -> () { }
return &arr;
} mywrap* operator -> () {
return &arr;
operator mywrap& () { }
return arr;
} operator mywrap& () {
return arr;
operator const mywrap& () const { }
return arr;
} operator const mywrap& () const {
return arr;
mywrap& get () { }
return arr;
} mywrap& get () {
return arr;
const mywrap& get () const { }
return arr;
} const mywrap& get () const {
return arr;
T* operator[] (size_t idx) const { }
return arr[idx];
} T* operator[] (size_t idx) const {
return arr[idx];
T*& operator[] (size_t idx) { }
return arr[idx];
} T*& operator[] (size_t idx) {
return arr[idx];
private: }
// no copy semantics
void operator= (const TempArray&) { private:
} // no copy semantics
void operator= (const TempArray&) {
TempArray(const TempArray& arr) { }
}
TempArray(const TempArray& arr) {
private: }
mywrap arr;
}; private:
mywrap arr;
#ifdef _MSC_VER };
# pragma warning(disable:4351)
#endif #ifdef _MSC_VER
// -------------------------------------------------------------------- # pragma warning(disable:4351)
/** ConversionData acts as intermediate storage location for #endif
* the various ConvertXXX routines in BlenderImporter.*/
// -------------------------------------------------------------------- struct ObjectCompare {
struct ConversionData bool operator() (const Object* left, const Object* right) const {
{ return ::strncmp(left->id.name, right->id.name, strlen( left->id.name ) ) == 0;
ConversionData(const FileDatabase& db) }
: sentinel_cnt() };
, next_texture()
, db(db) // When keeping objects in sets, sort them by their name.
{} typedef std::set<const Object*, ObjectCompare> ObjectSet;
std::set<const Object*> objects; // --------------------------------------------------------------------
/** ConversionData acts as intermediate storage location for
TempArray <std::vector, aiMesh> meshes; * the various ConvertXXX routines in BlenderImporter.*/
TempArray <std::vector, aiCamera> cameras; // --------------------------------------------------------------------
TempArray <std::vector, aiLight> lights; struct ConversionData
TempArray <std::vector, aiMaterial> materials; {
TempArray <std::vector, aiTexture> textures; ConversionData(const FileDatabase& db)
: sentinel_cnt()
// set of all materials referenced by at least one mesh in the scene , next_texture()
std::deque< boost::shared_ptr< Material > > materials_raw; , db(db)
{}
// counter to name sentinel textures inserted as substitutes for procedural textures.
unsigned int sentinel_cnt; struct ObjectCompare {
bool operator() (const Object* left, const Object* right) const {
// next texture ID for each texture type, respectively return ::strncmp( left->id.name, right->id.name, strlen( left->id.name ) ) == 0;
unsigned int next_texture[aiTextureType_UNKNOWN+1]; }
};
// original file data
const FileDatabase& db; ObjectSet objects;
};
#ifdef _MSC_VER TempArray <std::vector, aiMesh> meshes;
# pragma warning(default:4351) TempArray <std::vector, aiCamera> cameras;
#endif TempArray <std::vector, aiLight> lights;
TempArray <std::vector, aiMaterial> materials;
// ------------------------------------------------------------------------------------------------ TempArray <std::vector, aiTexture> textures;
inline const char* GetTextureTypeDisplayString(Tex::Type t)
{ // set of all materials referenced by at least one mesh in the scene
switch (t) { std::deque< std::shared_ptr< Material > > materials_raw;
case Tex::Type_CLOUDS : return "Clouds";
case Tex::Type_WOOD : return "Wood"; // counter to name sentinel textures inserted as substitutes for procedural textures.
case Tex::Type_MARBLE : return "Marble"; unsigned int sentinel_cnt;
case Tex::Type_MAGIC : return "Magic";
case Tex::Type_BLEND : return "Blend"; // next texture ID for each texture type, respectively
case Tex::Type_STUCCI : return "Stucci"; unsigned int next_texture[aiTextureType_UNKNOWN+1];
case Tex::Type_NOISE : return "Noise";
case Tex::Type_PLUGIN : return "Plugin"; // original file data
case Tex::Type_MUSGRAVE : return "Musgrave"; const FileDatabase& db;
case Tex::Type_VORONOI : return "Voronoi"; };
case Tex::Type_DISTNOISE : return "DistortedNoise"; #ifdef _MSC_VER
case Tex::Type_ENVMAP : return "EnvMap"; # pragma warning(default:4351)
case Tex::Type_IMAGE : return "Image"; #endif
default:
break; // ------------------------------------------------------------------------------------------------
} inline const char* GetTextureTypeDisplayString(Tex::Type t)
return "<Unknown>"; {
} switch (t) {
case Tex::Type_CLOUDS : return "Clouds";
} // ! Blender case Tex::Type_WOOD : return "Wood";
} // ! Assimp case Tex::Type_MARBLE : return "Marble";
case Tex::Type_MAGIC : return "Magic";
#endif // ! INCLUDED_AI_BLEND_INTERMEDIATE_H case Tex::Type_BLEND : return "Blend";
case Tex::Type_STUCCI : return "Stucci";
case Tex::Type_NOISE : return "Noise";
case Tex::Type_PLUGIN : return "Plugin";
case Tex::Type_MUSGRAVE : return "Musgrave";
case Tex::Type_VORONOI : return "Voronoi";
case Tex::Type_DISTNOISE : return "DistortedNoise";
case Tex::Type_ENVMAP : return "EnvMap";
case Tex::Type_IMAGE : return "Image";
default:
break;
}
return "<Unknown>";
}
} // ! Blender
} // ! Assimp
#endif // ! INCLUDED_AI_BLEND_INTERMEDIATE_H

File diff suppressed because it is too large Load Diff

View File

@ -1,223 +1,238 @@
/* /*
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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer. following disclaimer.
* Redistributions in binary form must reproduce the above * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other following disclaimer in the documentation and/or other
materials provided with the distribution. materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its * Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products contributors may be used to endorse or promote products
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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file BlenderLoader.h /** @file BlenderLoader.h
* @brief Declaration of the Blender 3D (*.blend) importer class. * @brief Declaration of the Blender 3D (*.blend) importer class.
*/ */
#ifndef INCLUDED_AI_BLEND_LOADER_H #ifndef INCLUDED_AI_BLEND_LOADER_H
#define INCLUDED_AI_BLEND_LOADER_H #define INCLUDED_AI_BLEND_LOADER_H
#include "BaseImporter.h" #include "BaseImporter.h"
#include "LogAux.h" #include "LogAux.h"
#include <memory>
namespace Assimp {
struct aiNode;
// TinyFormatter.h struct aiMesh;
namespace Formatter { struct aiLight;
template <typename T,typename TR, typename A> class basic_formatter; struct aiCamera;
typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format; struct aiMaterial;
}
namespace Assimp {
// BlenderDNA.h
namespace Blender { // TinyFormatter.h
class FileDatabase; namespace Formatter {
struct ElemBase; template <typename T,typename TR, typename A> class basic_formatter;
} typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
}
// BlenderScene.h
namespace Blender { // BlenderDNA.h
struct Scene; namespace Blender {
struct Object; class FileDatabase;
struct Mesh; struct ElemBase;
struct Camera; }
struct Lamp;
struct MTex; // BlenderScene.h
struct Image; namespace Blender {
struct Material; struct Scene;
} struct Object;
struct Mesh;
// BlenderIntermediate.h struct Camera;
namespace Blender { struct Lamp;
struct ConversionData; struct MTex;
template <template <typename,typename> class TCLASS, typename T> struct TempArray; struct Image;
} struct Material;
}
// BlenderModifier.h
namespace Blender { // BlenderIntermediate.h
class BlenderModifierShowcase; namespace Blender {
class BlenderModifier; struct ConversionData;
} template <template <typename,typename> class TCLASS, typename T> struct TempArray;
}
// BlenderModifier.h
// ------------------------------------------------------------------------------------------- namespace Blender {
/** Load blenders official binary format. The actual file structure (the `DNA` how they class BlenderModifierShowcase;
* call it is outsourced to BlenderDNA.cpp/BlenderDNA.h. This class only performs the class BlenderModifier;
* conversion from intermediate format to aiScene. */ }
// -------------------------------------------------------------------------------------------
class BlenderImporter : public BaseImporter, public LogFunctions<BlenderImporter>
{
public: // -------------------------------------------------------------------------------------------
BlenderImporter(); /** Load blenders official binary format. The actual file structure (the `DNA` how they
~BlenderImporter(); * call it is outsourced to BlenderDNA.cpp/BlenderDNA.h. This class only performs the
* conversion from intermediate format to aiScene. */
// -------------------------------------------------------------------------------------------
public: class BlenderImporter : public BaseImporter, public LogFunctions<BlenderImporter>
{
// -------------------- public:
bool CanRead( const std::string& pFile, BlenderImporter();
IOSystem* pIOHandler, ~BlenderImporter();
bool checkSig
) const; public:
protected: // --------------------
bool CanRead( const std::string& pFile,
// -------------------- IOSystem* pIOHandler,
const aiImporterDesc* GetInfo () const; bool checkSig
) const;
// --------------------
void GetExtensionList(std::set<std::string>& app); protected:
// -------------------- // --------------------
void SetupProperties(const Importer* pImp); const aiImporterDesc* GetInfo () const;
// -------------------- // --------------------
void InternReadFile( const std::string& pFile, void GetExtensionList(std::set<std::string>& app);
aiScene* pScene,
IOSystem* pIOHandler // --------------------
); void SetupProperties(const Importer* pImp);
// -------------------- // --------------------
void ParseBlendFile(Blender::FileDatabase& out, void InternReadFile( const std::string& pFile,
boost::shared_ptr<IOStream> stream aiScene* pScene,
); IOSystem* pIOHandler
);
// --------------------
void ExtractScene(Blender::Scene& out, // --------------------
const Blender::FileDatabase& file void ParseBlendFile(Blender::FileDatabase& out,
); std::shared_ptr<IOStream> stream
);
// --------------------
void ConvertBlendFile(aiScene* out, // --------------------
const Blender::Scene& in, void ExtractScene(Blender::Scene& out,
const Blender::FileDatabase& file const Blender::FileDatabase& file
); );
private: // --------------------
void ConvertBlendFile(aiScene* out,
// -------------------- const Blender::Scene& in,
aiNode* ConvertNode(const Blender::Scene& in, const Blender::FileDatabase& file
const Blender::Object* obj, );
Blender::ConversionData& conv_info,
const aiMatrix4x4& parentTransform private:
);
// --------------------
// -------------------- aiNode* ConvertNode(const Blender::Scene& in,
void ConvertMesh(const Blender::Scene& in, const Blender::Object* obj,
const Blender::Object* obj, Blender::ConversionData& conv_info,
const Blender::Mesh* mesh, const aiMatrix4x4& parentTransform
Blender::ConversionData& conv_data, );
Blender::TempArray<std::vector,aiMesh>& temp
); // --------------------
void ConvertMesh(const Blender::Scene& in,
// -------------------- const Blender::Object* obj,
aiLight* ConvertLight(const Blender::Scene& in, const Blender::Mesh* mesh,
const Blender::Object* obj, Blender::ConversionData& conv_data,
const Blender::Lamp* mesh, Blender::TempArray<std::vector,aiMesh>& temp
Blender::ConversionData& conv_data );
);
// --------------------
// -------------------- aiLight* ConvertLight(const Blender::Scene& in,
aiCamera* ConvertCamera(const Blender::Scene& in, const Blender::Object* obj,
const Blender::Object* obj, const Blender::Lamp* mesh,
const Blender::Camera* mesh, Blender::ConversionData& conv_data
Blender::ConversionData& conv_data );
);
// --------------------
// -------------------- aiCamera* ConvertCamera(const Blender::Scene& in,
void BuildMaterials( const Blender::Object* obj,
Blender::ConversionData& conv_data const Blender::Camera* mesh,
) ; Blender::ConversionData& conv_data
);
// --------------------
void ResolveTexture( // --------------------
aiMaterial* out, void BuildDefaultMaterial(
const Blender::Material* mat, Blender::ConversionData& conv_data
const Blender::MTex* tex, );
Blender::ConversionData& conv_data
); void AddBlendParams(
aiMaterial* result,
// -------------------- const Blender::Material* source
void ResolveImage( );
aiMaterial* out,
const Blender::Material* mat, void BuildMaterials(
const Blender::MTex* tex, Blender::ConversionData& conv_data
const Blender::Image* img, );
Blender::ConversionData& conv_data
); // --------------------
void ResolveTexture(
void AddSentinelTexture( aiMaterial* out,
aiMaterial* out, const Blender::Material* mat,
const Blender::Material* mat, const Blender::MTex* tex,
const Blender::MTex* tex, Blender::ConversionData& conv_data
Blender::ConversionData& conv_data );
);
// --------------------
private: // static stuff, mostly logging and error reporting. void ResolveImage(
aiMaterial* out,
// -------------------- const Blender::Material* mat,
static void CheckActualType(const Blender::ElemBase* dt, const Blender::MTex* tex,
const char* check const Blender::Image* img,
); Blender::ConversionData& conv_data
);
// --------------------
static void NotSupportedObjectType(const Blender::Object* obj, void AddSentinelTexture(
const char* type aiMaterial* out,
); const Blender::Material* mat,
const Blender::MTex* tex,
Blender::ConversionData& conv_data
private: );
Blender::BlenderModifierShowcase* modifier_cache; private: // static stuff, mostly logging and error reporting.
}; // !class BlenderImporter // --------------------
static void CheckActualType(const Blender::ElemBase* dt,
} // end of namespace Assimp const char* check
#endif // AI_UNREALIMPORTER_H_INC );
// --------------------
static void NotSupportedObjectType(const Blender::Object* obj,
const char* type
);
private:
Blender::BlenderModifierShowcase* modifier_cache;
}; // !class BlenderImporter
} // end of namespace Assimp
#endif // AI_UNREALIMPORTER_H_INC

View File

@ -1,324 +1,323 @@
/* /*
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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer. following disclaimer.
* Redistributions in binary form must reproduce the above * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other following disclaimer in the documentation and/or other
materials provided with the distribution. materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its * Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products contributors may be used to endorse or promote products
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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 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 <functional> #include <memory>
using namespace Assimp; #include <functional>
using namespace Assimp::Blender;
using namespace Assimp;
template <typename T> BlenderModifier* god() { using namespace Assimp::Blender;
return new T();
} template <typename T> BlenderModifier* god() {
return new T();
// add all available modifiers here }
typedef BlenderModifier* (*fpCreateModifier)();
static const fpCreateModifier creators[] = { // add all available modifiers here
&god<BlenderModifier_Mirror>, typedef BlenderModifier* (*fpCreateModifier)();
&god<BlenderModifier_Subdivision>, static const fpCreateModifier creators[] = {
&god<BlenderModifier_Mirror>,
NULL // sentinel &god<BlenderModifier_Subdivision>,
};
NULL // sentinel
// ------------------------------------------------------------------------------------------------ };
// just testing out some new macros to simplify logging
#define ASSIMP_LOG_WARN_F(string,...)\ // ------------------------------------------------------------------------------------------------
DefaultLogger::get()->warn((Formatter::format(string),__VA_ARGS__)) // just testing out some new macros to simplify logging
#define ASSIMP_LOG_WARN_F(string,...)\
#define ASSIMP_LOG_ERROR_F(string,...)\ DefaultLogger::get()->warn((Formatter::format(string),__VA_ARGS__))
DefaultLogger::get()->error((Formatter::format(string),__VA_ARGS__))
#define ASSIMP_LOG_ERROR_F(string,...)\
#define ASSIMP_LOG_DEBUG_F(string,...)\ DefaultLogger::get()->error((Formatter::format(string),__VA_ARGS__))
DefaultLogger::get()->debug((Formatter::format(string),__VA_ARGS__))
#define ASSIMP_LOG_DEBUG_F(string,...)\
#define ASSIMP_LOG_INFO_F(string,...)\ DefaultLogger::get()->debug((Formatter::format(string),__VA_ARGS__))
DefaultLogger::get()->info((Formatter::format(string),__VA_ARGS__))
#define ASSIMP_LOG_INFO_F(string,...)\
DefaultLogger::get()->info((Formatter::format(string),__VA_ARGS__))
#define ASSIMP_LOG_WARN(string)\
DefaultLogger::get()->warn(string)
#define ASSIMP_LOG_WARN(string)\
#define ASSIMP_LOG_ERROR(string)\ DefaultLogger::get()->warn(string)
DefaultLogger::get()->error(string)
#define ASSIMP_LOG_ERROR(string)\
#define ASSIMP_LOG_DEBUG(string)\ DefaultLogger::get()->error(string)
DefaultLogger::get()->debug(string)
#define ASSIMP_LOG_DEBUG(string)\
#define ASSIMP_LOG_INFO(string)\ DefaultLogger::get()->debug(string)
DefaultLogger::get()->info(string)
#define ASSIMP_LOG_INFO(string)\
DefaultLogger::get()->info(string)
// ------------------------------------------------------------------------------------------------
struct SharedModifierData : ElemBase
{ // ------------------------------------------------------------------------------------------------
ModifierData modifier; struct SharedModifierData : ElemBase
}; {
ModifierData modifier;
// ------------------------------------------------------------------------------------------------ };
void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_data, const Scene& in, const Object& orig_object )
{ // ------------------------------------------------------------------------------------------------
size_t cnt = 0u, ful = 0u; void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_data, const Scene& in, const Object& orig_object )
{
// NOTE: this cast is potentially unsafe by design, so we need to perform type checks before size_t cnt = 0u, ful = 0u;
// 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 // NOTE: this cast is potentially unsafe by design, so we need to perform type checks before
// structures is at offset sizeof(vftable) with no padding. // we're allowed to dereference the pointers without risking to crash. We might still be
const SharedModifierData* cur = boost::static_pointer_cast<const SharedModifierData> ( orig_object.modifiers.first.get() ); // invoking UB btw - we're assuming that the ModifierData member of the respective modifier
for (; cur; cur = boost::static_pointer_cast<const SharedModifierData> ( cur->modifier.next.get() ), ++ful) { // structures is at offset sizeof(vftable) with no padding.
ai_assert(cur->dna_type); const SharedModifierData* cur = static_cast<const SharedModifierData *> ( orig_object.modifiers.first.get() );
for (; cur; cur = static_cast<const SharedModifierData *> ( cur->modifier.next.get() ), ++ful) {
const Structure* s = conv_data.db.dna.Get( cur->dna_type ); ai_assert(cur->dna_type);
if (!s) {
ASSIMP_LOG_WARN_F("BlendModifier: could not resolve DNA name: ",cur->dna_type); const Structure* s = conv_data.db.dna.Get( cur->dna_type );
continue; if (!s) {
} ASSIMP_LOG_WARN_F("BlendModifier: could not resolve DNA name: ",cur->dna_type);
continue;
// this is a common trait of all XXXMirrorData structures in BlenderDNA }
const Field* f = s->Get("modifier");
if (!f || f->offset != 0) { // this is a common trait of all XXXMirrorData structures in BlenderDNA
ASSIMP_LOG_WARN("BlendModifier: expected a `modifier` member at offset 0"); const Field* f = s->Get("modifier");
continue; if (!f || f->offset != 0) {
} ASSIMP_LOG_WARN("BlendModifier: expected a `modifier` member at offset 0");
continue;
s = conv_data.db.dna.Get( f->type ); }
if (!s || s->name != "ModifierData") {
ASSIMP_LOG_WARN("BlendModifier: expected a ModifierData structure as first member"); s = conv_data.db.dna.Get( f->type );
continue; if (!s || s->name != "ModifierData") {
} ASSIMP_LOG_WARN("BlendModifier: expected a ModifierData structure as first member");
continue;
// now, we can be sure that we should be fine to dereference *cur* as }
// ModifierData (with the above note).
const ModifierData& dat = cur->modifier; // now, we can be sure that we should be fine to dereference *cur* as
// ModifierData (with the above note).
const fpCreateModifier* curgod = creators; const ModifierData& dat = cur->modifier;
std::vector< BlenderModifier* >::iterator curmod = cached_modifiers->begin(), endmod = cached_modifiers->end();
const fpCreateModifier* curgod = creators;
for (;*curgod;++curgod,++curmod) { // allocate modifiers on the fly std::vector< BlenderModifier* >::iterator curmod = cached_modifiers->begin(), endmod = cached_modifiers->end();
if (curmod == endmod) {
cached_modifiers->push_back((*curgod)()); for (;*curgod;++curgod,++curmod) { // allocate modifiers on the fly
if (curmod == endmod) {
endmod = cached_modifiers->end(); cached_modifiers->push_back((*curgod)());
curmod = endmod-1;
} endmod = cached_modifiers->end();
curmod = endmod-1;
BlenderModifier* const modifier = *curmod; }
if(modifier->IsActive(dat)) {
modifier->DoIt(out,conv_data,*boost::static_pointer_cast<const ElemBase>(cur),in,orig_object); BlenderModifier* const modifier = *curmod;
cnt++; if(modifier->IsActive(dat)) {
modifier->DoIt(out,conv_data,*static_cast<const ElemBase *>(cur),in,orig_object);
curgod = NULL; cnt++;
break;
} curgod = NULL;
} break;
if (curgod) { }
ASSIMP_LOG_WARN_F("Couldn't find a handler for modifier: ",dat.name); }
} if (curgod) {
} ASSIMP_LOG_WARN_F("Couldn't find a handler for modifier: ",dat.name);
}
// Even though we managed to resolve some or all of the modifiers on this }
// object, we still can't say whether our modifier implementations were
// able to fully do their job. // Even though we managed to resolve some or all of the modifiers on this
if (ful) { // object, we still can't say whether our modifier implementations were
ASSIMP_LOG_DEBUG_F("BlendModifier: found handlers for ",cnt," of ",ful," modifiers on `",orig_object.id.name, // able to fully do their job.
"`, check log messages above for errors"); if (ful) {
} ASSIMP_LOG_DEBUG_F("BlendModifier: found handlers for ",cnt," of ",ful," modifiers on `",orig_object.id.name,
} "`, check log messages above for errors");
}
}
// ------------------------------------------------------------------------------------------------
bool BlenderModifier_Mirror :: IsActive (const ModifierData& modin)
{ // ------------------------------------------------------------------------------------------------
return modin.type == ModifierData::eModifierType_Mirror; bool BlenderModifier_Mirror :: IsActive (const ModifierData& modin)
} {
return modin.type == ModifierData::eModifierType_Mirror;
// ------------------------------------------------------------------------------------------------ }
void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier,
const Scene& /*in*/, // ------------------------------------------------------------------------------------------------
const Object& orig_object ) void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier,
{ const Scene& /*in*/,
// hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers() const Object& orig_object )
const MirrorModifierData& mir = static_cast<const MirrorModifierData&>(orig_modifier); {
ai_assert(mir.modifier.type == ModifierData::eModifierType_Mirror); // hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
const MirrorModifierData& mir = static_cast<const MirrorModifierData&>(orig_modifier);
conv_data.meshes->reserve(conv_data.meshes->size() + out.mNumMeshes); ai_assert(mir.modifier.type == ModifierData::eModifierType_Mirror);
// XXX not entirely correct, mirroring on two axes results in 4 distinct objects in blender ... conv_data.meshes->reserve(conv_data.meshes->size() + out.mNumMeshes);
// take all input meshes and clone them // XXX not entirely correct, mirroring on two axes results in 4 distinct objects in blender ...
for (unsigned int i = 0; i < out.mNumMeshes; ++i) {
aiMesh* mesh; // take all input meshes and clone them
SceneCombiner::Copy(&mesh,conv_data.meshes[out.mMeshes[i]]); for (unsigned int i = 0; i < out.mNumMeshes; ++i) {
aiMesh* mesh;
const float xs = mir.flag & MirrorModifierData::Flags_AXIS_X ? -1.f : 1.f; SceneCombiner::Copy(&mesh,conv_data.meshes[out.mMeshes[i]]);
const float ys = mir.flag & MirrorModifierData::Flags_AXIS_Y ? -1.f : 1.f;
const float zs = mir.flag & MirrorModifierData::Flags_AXIS_Z ? -1.f : 1.f; const float xs = mir.flag & MirrorModifierData::Flags_AXIS_X ? -1.f : 1.f;
const float ys = mir.flag & MirrorModifierData::Flags_AXIS_Y ? -1.f : 1.f;
if (mir.mirror_ob) { const float zs = mir.flag & MirrorModifierData::Flags_AXIS_Z ? -1.f : 1.f;
const aiVector3D center( mir.mirror_ob->obmat[3][0],mir.mirror_ob->obmat[3][1],mir.mirror_ob->obmat[3][2] );
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { if (mir.mirror_ob) {
aiVector3D& v = mesh->mVertices[i]; const aiVector3D center( mir.mirror_ob->obmat[3][0],mir.mirror_ob->obmat[3][1],mir.mirror_ob->obmat[3][2] );
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
v.x = center.x + xs*(center.x - v.x); aiVector3D& v = mesh->mVertices[i];
v.y = center.y + ys*(center.y - v.y);
v.z = center.z + zs*(center.z - v.z); v.x = center.x + xs*(center.x - v.x);
} v.y = center.y + ys*(center.y - v.y);
} v.z = center.z + zs*(center.z - v.z);
else { }
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { }
aiVector3D& v = mesh->mVertices[i]; else {
v.x *= xs;v.y *= ys;v.z *= zs; for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
} aiVector3D& v = mesh->mVertices[i];
} v.x *= xs;v.y *= ys;v.z *= zs;
}
if (mesh->mNormals) { }
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
aiVector3D& v = mesh->mNormals[i]; if (mesh->mNormals) {
v.x *= xs;v.y *= ys;v.z *= zs; for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
} aiVector3D& v = mesh->mNormals[i];
} v.x *= xs;v.y *= ys;v.z *= zs;
}
if (mesh->mTangents) { }
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
aiVector3D& v = mesh->mTangents[i]; if (mesh->mTangents) {
v.x *= xs;v.y *= ys;v.z *= zs; for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
} aiVector3D& v = mesh->mTangents[i];
} v.x *= xs;v.y *= ys;v.z *= zs;
}
if (mesh->mBitangents) { }
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
aiVector3D& v = mesh->mBitangents[i]; if (mesh->mBitangents) {
v.x *= xs;v.y *= ys;v.z *= zs; for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
} aiVector3D& v = mesh->mBitangents[i];
} v.x *= xs;v.y *= ys;v.z *= zs;
}
const float us = mir.flag & MirrorModifierData::Flags_MIRROR_U ? -1.f : 1.f; }
const float vs = mir.flag & MirrorModifierData::Flags_MIRROR_V ? -1.f : 1.f;
const float us = mir.flag & MirrorModifierData::Flags_MIRROR_U ? -1.f : 1.f;
for (unsigned int n = 0; mesh->HasTextureCoords(n); ++n) { const float vs = mir.flag & MirrorModifierData::Flags_MIRROR_V ? -1.f : 1.f;
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
aiVector3D& v = mesh->mTextureCoords[n][i]; for (unsigned int n = 0; mesh->HasTextureCoords(n); ++n) {
v.x *= us;v.y *= vs; for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
} aiVector3D& v = mesh->mTextureCoords[n][i];
} v.x *= us;v.y *= vs;
}
// Only reverse the winding order if an odd number of axes were mirrored. }
if (xs * ys * zs < 0) {
for( unsigned int i = 0; i < mesh->mNumFaces; i++) { // Only reverse the winding order if an odd number of axes were mirrored.
aiFace& face = mesh->mFaces[i]; if (xs * ys * zs < 0) {
for( unsigned int fi = 0; fi < face.mNumIndices / 2; ++fi) for( unsigned int i = 0; i < mesh->mNumFaces; i++) {
std::swap( face.mIndices[fi], face.mIndices[face.mNumIndices - 1 - fi]); aiFace& face = mesh->mFaces[i];
} for( unsigned int fi = 0; fi < face.mNumIndices / 2; ++fi)
} std::swap( face.mIndices[fi], face.mIndices[face.mNumIndices - 1 - fi]);
}
conv_data.meshes->push_back(mesh); }
}
unsigned int* nind = new unsigned int[out.mNumMeshes*2]; conv_data.meshes->push_back(mesh);
}
std::copy(out.mMeshes,out.mMeshes+out.mNumMeshes,nind); unsigned int* nind = new unsigned int[out.mNumMeshes*2];
std::transform(out.mMeshes,out.mMeshes+out.mNumMeshes,nind+out.mNumMeshes,
std::bind1st(std::plus< unsigned int >(),out.mNumMeshes)); std::copy(out.mMeshes,out.mMeshes+out.mNumMeshes,nind);
std::transform(out.mMeshes,out.mMeshes+out.mNumMeshes,nind+out.mNumMeshes,
delete[] out.mMeshes; std::bind1st(std::plus< unsigned int >(),out.mNumMeshes));
out.mMeshes = nind;
out.mNumMeshes *= 2; delete[] out.mMeshes;
out.mMeshes = nind;
ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Mirror` modifier to `", out.mNumMeshes *= 2;
orig_object.id.name,"`");
} ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Mirror` modifier to `",
orig_object.id.name,"`");
}
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------ bool BlenderModifier_Subdivision :: IsActive (const ModifierData& modin)
bool BlenderModifier_Subdivision :: IsActive (const ModifierData& modin) {
{ return modin.type == ModifierData::eModifierType_Subsurf;
return modin.type == ModifierData::eModifierType_Subsurf; }
}
// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------ void BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier,
void BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier, const Scene& /*in*/,
const Scene& /*in*/, const Object& orig_object )
const Object& orig_object ) {
{ // hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
// hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers() const SubsurfModifierData& mir = static_cast<const SubsurfModifierData&>(orig_modifier);
const SubsurfModifierData& mir = static_cast<const SubsurfModifierData&>(orig_modifier); ai_assert(mir.modifier.type == ModifierData::eModifierType_Subsurf);
ai_assert(mir.modifier.type == ModifierData::eModifierType_Subsurf);
Subdivider::Algorithm algo;
Subdivider::Algorithm algo; switch (mir.subdivType)
switch (mir.subdivType) {
{ case SubsurfModifierData::TYPE_CatmullClarke:
case SubsurfModifierData::TYPE_CatmullClarke: algo = Subdivider::CATMULL_CLARKE;
algo = Subdivider::CATMULL_CLARKE; break;
break;
case SubsurfModifierData::TYPE_Simple:
case SubsurfModifierData::TYPE_Simple: ASSIMP_LOG_WARN("BlendModifier: The `SIMPLE` subdivision algorithm is not currently implemented, using Catmull-Clarke");
ASSIMP_LOG_WARN("BlendModifier: The `SIMPLE` subdivision algorithm is not currently implemented, using Catmull-Clarke"); algo = Subdivider::CATMULL_CLARKE;
algo = Subdivider::CATMULL_CLARKE; break;
break;
default:
default: ASSIMP_LOG_WARN_F("BlendModifier: Unrecognized subdivision algorithm: ",mir.subdivType);
ASSIMP_LOG_WARN_F("BlendModifier: Unrecognized subdivision algorithm: ",mir.subdivType); return;
return; };
};
std::unique_ptr<Subdivider> subd(Subdivider::Create(algo));
boost::scoped_ptr<Subdivider> subd(Subdivider::Create(algo)); ai_assert(subd);
ai_assert(subd);
aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes];
aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes]; std::unique_ptr<aiMesh*[]> tempmeshes(new aiMesh*[out.mNumMeshes]());
boost::scoped_array<aiMesh*> tempmeshes(new aiMesh*[out.mNumMeshes]());
subd->Subdivide(meshes,out.mNumMeshes,tempmeshes.get(),std::max( mir.renderLevels, mir.levels ),true);
subd->Subdivide(meshes,out.mNumMeshes,tempmeshes.get(),std::max( mir.renderLevels, mir.levels ),true); std::copy(tempmeshes.get(),tempmeshes.get()+out.mNumMeshes,meshes);
std::copy(tempmeshes.get(),tempmeshes.get()+out.mNumMeshes,meshes);
ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Subdivision` modifier to `",
ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Subdivision` modifier to `", orig_object.id.name,"`");
orig_object.id.name,"`"); }
}
#endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
#endif

View File

@ -1,155 +1,156 @@
/* /*
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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer. following disclaimer.
* Redistributions in binary form must reproduce the above * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other following disclaimer in the documentation and/or other
materials provided with the distribution. materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its * Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products contributors may be used to endorse or promote products
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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file BlenderModifier.h /** @file BlenderModifier.h
* @brief Declare dedicated helper classes to simulate some blender modifiers (i.e. mirror) * @brief Declare dedicated helper classes to simulate some blender modifiers (i.e. mirror)
*/ */
#ifndef INCLUDED_AI_BLEND_MODIFIER_H #ifndef INCLUDED_AI_BLEND_MODIFIER_H
#define INCLUDED_AI_BLEND_MODIFIER_H #define INCLUDED_AI_BLEND_MODIFIER_H
#include "BlenderIntermediate.h" #include "BlenderIntermediate.h"
#include "TinyFormatter.h" #include "TinyFormatter.h"
namespace Assimp {
namespace Blender { namespace Assimp {
namespace Blender {
// -------------------------------------------------------------------------------------------
/** Dummy base class for all blender modifiers. Modifiers are reused between imports, so // -------------------------------------------------------------------------------------------
* they should be stateless and not try to cache model data. */ /** Dummy base class for all blender modifiers. Modifiers are reused between imports, so
// ------------------------------------------------------------------------------------------- * they should be stateless and not try to cache model data. */
class BlenderModifier // -------------------------------------------------------------------------------------------
{ class BlenderModifier
public: {
public:
virtual ~BlenderModifier() { virtual ~BlenderModifier() {
} // empty
}
public:
public:
// --------------------
/** Check if *this* modifier is active, given a ModifierData& block.*/ // --------------------
virtual bool IsActive( const ModifierData& /*modin*/) { /** Check if *this* modifier is active, given a ModifierData& block.*/
return false; virtual bool IsActive( const ModifierData& /*modin*/) {
} return false;
}
// --------------------
/** Apply the modifier to a given output node. The original data used // --------------------
* to construct the node is given as well. Not called unless IsActive() /** Apply the modifier to a given output node. The original data used
* was called and gave positive response. */ * to construct the node is given as well. Not called unless IsActive()
virtual void DoIt(aiNode& /*out*/, * was called and gave positive response. */
ConversionData& /*conv_data*/, virtual void DoIt(aiNode& /*out*/,
const ElemBase& orig_modifier, ConversionData& /*conv_data*/,
const Scene& /*in*/, const ElemBase& orig_modifier,
const Object& /*orig_object*/ const Scene& /*in*/,
) { const Object& /*orig_object*/
DefaultLogger::get()->warn((Formatter::format("This modifier is not supported, skipping: "),orig_modifier.dna_type)); ) {
return; DefaultLogger::get()->warn((Formatter::format("This modifier is not supported, skipping: "),orig_modifier.dna_type));
} return;
}; }
};
// -------------------------------------------------------------------------------------------
/** Manage all known modifiers and instance and apply them if necessary */ // -------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------- /** Manage all known modifiers and instance and apply them if necessary */
class BlenderModifierShowcase // -------------------------------------------------------------------------------------------
{ class BlenderModifierShowcase
public: {
public:
// --------------------
/** Apply all requested modifiers provided we support them. */ // --------------------
void ApplyModifiers(aiNode& out, /** Apply all requested modifiers provided we support them. */
ConversionData& conv_data, void ApplyModifiers(aiNode& out,
const Scene& in, ConversionData& conv_data,
const Object& orig_object const Scene& in,
); const Object& orig_object
);
private:
private:
TempArray< std::vector,BlenderModifier > cached_modifiers;
}; TempArray< std::vector,BlenderModifier > cached_modifiers;
};
// MODIFIERS
// MODIFIERS
// -------------------------------------------------------------------------------------------
/** Mirror modifier. Status: implemented. */ // -------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------- /** Mirror modifier. Status: implemented. */
class BlenderModifier_Mirror : public BlenderModifier // -------------------------------------------------------------------------------------------
{ class BlenderModifier_Mirror : public BlenderModifier
public: {
public:
// --------------------
virtual bool IsActive( const ModifierData& modin); // --------------------
virtual bool IsActive( const ModifierData& modin);
// --------------------
virtual void DoIt(aiNode& out, // --------------------
ConversionData& conv_data, virtual void DoIt(aiNode& out,
const ElemBase& orig_modifier, ConversionData& conv_data,
const Scene& in, const ElemBase& orig_modifier,
const Object& orig_object const Scene& in,
) ; const Object& orig_object
}; ) ;
};
// -------------------------------------------------------------------------------------------
/** Subdivision modifier. Status: dummy. */ // -------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------- /** Subdivision modifier. Status: dummy. */
class BlenderModifier_Subdivision : public BlenderModifier // -------------------------------------------------------------------------------------------
{ class BlenderModifier_Subdivision : public BlenderModifier
public: {
public:
// --------------------
virtual bool IsActive( const ModifierData& modin); // --------------------
virtual bool IsActive( const ModifierData& modin);
// --------------------
virtual void DoIt(aiNode& out, // --------------------
ConversionData& conv_data, virtual void DoIt(aiNode& out,
const ElemBase& orig_modifier, ConversionData& conv_data,
const Scene& in, const ElemBase& orig_modifier,
const Object& orig_object const Scene& in,
) ; const Object& orig_object
}; ) ;
};
}}
#endif // !INCLUDED_AI_BLEND_MODIFIER_H }}
#endif // !INCLUDED_AI_BLEND_MODIFIER_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,253 +1,255 @@
/* /*
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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer. following disclaimer.
* Redistributions in binary form must reproduce the above * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other following disclaimer in the documentation and/or other
materials provided with the distribution. materials provided with the distribution.
* Neither the name of the ASSIMP team, nor the names of its * Neither the name of the ASSIMP team, nor the names of its
contributors may be used to endorse or promote products contributors may be used to endorse or promote products
derived from this software without specific prior derived from this software without specific prior
written permission of the ASSIMP Development Team. written permission of the ASSIMP Development 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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/** @file BlenderSceneGen.h /** @file BlenderSceneGen.h
* @brief MACHINE GENERATED BY ./scripts/BlenderImporter/genblenddna.py * @brief MACHINE GENERATED BY ./scripts/BlenderImporter/genblenddna.py
*/ */
#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 {
template <> void Structure :: Convert<Object> ( namespace Blender {
Object& dest,
const FileDatabase& db template <> void Structure :: Convert<Object> (
) const Object& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<Group> ( ;
Group& dest,
const FileDatabase& db template <> void Structure :: Convert<Group> (
) const Group& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<MTex> ( ;
MTex& dest,
const FileDatabase& db template <> void Structure :: Convert<MTex> (
) const MTex& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<TFace> ( ;
TFace& dest,
const FileDatabase& db template <> void Structure :: Convert<TFace> (
) const TFace& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<SubsurfModifierData> ( ;
SubsurfModifierData& dest,
const FileDatabase& db template <> void Structure :: Convert<SubsurfModifierData> (
) const SubsurfModifierData& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<MFace> ( ;
MFace& dest,
const FileDatabase& db template <> void Structure :: Convert<MFace> (
) const MFace& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<Lamp> ( ;
Lamp& dest,
const FileDatabase& db template <> void Structure :: Convert<Lamp> (
) const Lamp& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<MDeformWeight> ( ;
MDeformWeight& dest,
const FileDatabase& db template <> void Structure :: Convert<MDeformWeight> (
) const MDeformWeight& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<PackedFile> ( ;
PackedFile& dest,
const FileDatabase& db template <> void Structure :: Convert<PackedFile> (
) const PackedFile& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<Base> ( ;
Base& dest,
const FileDatabase& db template <> void Structure :: Convert<Base> (
) const Base& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<MTFace> ( ;
MTFace& dest,
const FileDatabase& db template <> void Structure :: Convert<MTFace> (
) const MTFace& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<Material> ( ;
Material& dest,
const FileDatabase& db template <> void Structure :: Convert<Material> (
) const Material& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<MTexPoly> ( ;
MTexPoly& dest,
const FileDatabase& db template <> void Structure :: Convert<MTexPoly> (
) const MTexPoly& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<Mesh> ( ;
Mesh& dest,
const FileDatabase& db template <> void Structure :: Convert<Mesh> (
) const Mesh& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<MDeformVert> ( ;
MDeformVert& dest,
const FileDatabase& db template <> void Structure :: Convert<MDeformVert> (
) const MDeformVert& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<World> ( ;
World& dest,
const FileDatabase& db template <> void Structure :: Convert<World> (
) const World& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<MLoopCol> ( ;
MLoopCol& dest,
const FileDatabase& db template <> void Structure :: Convert<MLoopCol> (
) const MLoopCol& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<MVert> ( ;
MVert& dest,
const FileDatabase& db template <> void Structure :: Convert<MVert> (
) const MVert& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<MEdge> ( ;
MEdge& dest,
const FileDatabase& db template <> void Structure :: Convert<MEdge> (
) const MEdge& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<MLoopUV> ( ;
MLoopUV& dest,
const FileDatabase& db template <> void Structure :: Convert<MLoopUV> (
) const MLoopUV& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<GroupObject> ( ;
GroupObject& dest,
const FileDatabase& db template <> void Structure :: Convert<GroupObject> (
) const GroupObject& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<ListBase> ( ;
ListBase& dest,
const FileDatabase& db template <> void Structure :: Convert<ListBase> (
) const ListBase& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<MLoop> ( ;
MLoop& dest,
const FileDatabase& db template <> void Structure :: Convert<MLoop> (
) const MLoop& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<ModifierData> ( ;
ModifierData& dest,
const FileDatabase& db template <> void Structure :: Convert<ModifierData> (
) const ModifierData& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<ID> ( ;
ID& dest,
const FileDatabase& db template <> void Structure :: Convert<ID> (
) const ID& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<MCol> ( ;
MCol& dest,
const FileDatabase& db template <> void Structure :: Convert<MCol> (
) const MCol& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<MPoly> ( ;
MPoly& dest,
const FileDatabase& db template <> void Structure :: Convert<MPoly> (
) const MPoly& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<Scene> ( ;
Scene& dest,
const FileDatabase& db template <> void Structure :: Convert<Scene> (
) const Scene& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<Library> ( ;
Library& dest,
const FileDatabase& db template <> void Structure :: Convert<Library> (
) const Library& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<Tex> ( ;
Tex& dest,
const FileDatabase& db template <> void Structure :: Convert<Tex> (
) const Tex& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<Camera> ( ;
Camera& dest,
const FileDatabase& db template <> void Structure :: Convert<Camera> (
) const Camera& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<MirrorModifierData> ( ;
MirrorModifierData& dest,
const FileDatabase& db template <> void Structure :: Convert<MirrorModifierData> (
) const MirrorModifierData& dest,
; const FileDatabase& db
) const
template <> void Structure :: Convert<Image> ( ;
Image& dest,
const FileDatabase& db template <> void Structure :: Convert<Image> (
) const Image& dest,
; const FileDatabase& db
) const
;
}
}
}
#endif }
#endif

View File

@ -2,11 +2,11 @@
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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
@ -23,16 +23,16 @@ following 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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
@ -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,13 +50,15 @@ 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
namspace Assimp namspace Assimp
{ {
template< > const std::string LogFunctions< BlenderTessellatorGL >::log_prefix = "BLEND_TESS_GL: "; template< > const std::string LogFunctions< BlenderTessellatorGL >::log_prefix = "BLEND_TESS_GL: ";
} }
using namespace Assimp; using namespace Assimp;
@ -69,7 +70,7 @@ using namespace Assimp::Blender;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
BlenderTessellatorGL::BlenderTessellatorGL( BlenderBMeshConverter& converter ): BlenderTessellatorGL::BlenderTessellatorGL( BlenderBMeshConverter& converter ):
converter( &converter ) converter( &converter )
{ {
} }
@ -81,167 +82,167 @@ BlenderTessellatorGL::~BlenderTessellatorGL( )
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices ) void BlenderTessellatorGL::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
{ {
AssertVertexCount( vertexCount ); AssertVertexCount( vertexCount );
std::vector< VertexGL > polyLoopGL; std::vector< VertexGL > polyLoopGL;
GenerateLoopVerts( polyLoopGL, polyLoop, vertexCount, vertices ); GenerateLoopVerts( polyLoopGL, polyLoop, vertexCount, vertices );
TessDataGL tessData; TessDataGL tessData;
Tesssellate( polyLoopGL, tessData ); Tesssellate( polyLoopGL, tessData );
TriangulateDrawCalls( tessData ); TriangulateDrawCalls( tessData );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::AssertVertexCount( int vertexCount ) void BlenderTessellatorGL::AssertVertexCount( int vertexCount )
{ {
if ( vertexCount <= 4 ) if ( vertexCount <= 4 )
{ {
ThrowException( "Expected more than 4 vertices for tessellation" ); ThrowException( "Expected more than 4 vertices for tessellation" );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::GenerateLoopVerts( std::vector< VertexGL >& polyLoopGL, const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices ) void BlenderTessellatorGL::GenerateLoopVerts( std::vector< VertexGL >& polyLoopGL, const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
{ {
for ( int i = 0; i < vertexCount; ++i ) for ( int i = 0; i < vertexCount; ++i )
{ {
const MLoop& loopItem = polyLoop[ i ]; const MLoop& loopItem = polyLoop[ i ];
const MVert& vertex = vertices[ loopItem.v ]; const MVert& vertex = vertices[ loopItem.v ];
polyLoopGL.push_back( VertexGL( vertex.co[ 0 ], vertex.co[ 1 ], vertex.co[ 2 ], loopItem.v, BLEND_TESS_MAGIC ) ); polyLoopGL.push_back( VertexGL( vertex.co[ 0 ], vertex.co[ 1 ], vertex.co[ 2 ], loopItem.v, BLEND_TESS_MAGIC ) );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::Tesssellate( std::vector< VertexGL >& polyLoopGL, TessDataGL& tessData ) void BlenderTessellatorGL::Tesssellate( std::vector< VertexGL >& polyLoopGL, TessDataGL& tessData )
{ {
GLUtesselator* tessellator = gluNewTess( ); GLUtesselator* tessellator = gluNewTess( );
gluTessCallback( tessellator, GLU_TESS_BEGIN_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateBegin ) ); gluTessCallback( tessellator, GLU_TESS_BEGIN_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateBegin ) );
gluTessCallback( tessellator, GLU_TESS_END_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEnd ) ); gluTessCallback( tessellator, GLU_TESS_END_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEnd ) );
gluTessCallback( tessellator, GLU_TESS_VERTEX_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateVertex ) ); gluTessCallback( tessellator, GLU_TESS_VERTEX_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateVertex ) );
gluTessCallback( tessellator, GLU_TESS_COMBINE_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateCombine ) ); gluTessCallback( tessellator, GLU_TESS_COMBINE_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateCombine ) );
gluTessCallback( tessellator, GLU_TESS_EDGE_FLAG_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEdgeFlag ) ); gluTessCallback( tessellator, GLU_TESS_EDGE_FLAG_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEdgeFlag ) );
gluTessCallback( tessellator, GLU_TESS_ERROR_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateError ) ); gluTessCallback( tessellator, GLU_TESS_ERROR_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateError ) );
gluTessProperty( tessellator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO ); gluTessProperty( tessellator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO );
gluTessBeginPolygon( tessellator, &tessData ); gluTessBeginPolygon( tessellator, &tessData );
gluTessBeginContour( tessellator ); gluTessBeginContour( tessellator );
for ( unsigned int i = 0; i < polyLoopGL.size( ); ++i ) for ( unsigned int i = 0; i < polyLoopGL.size( ); ++i )
{ {
gluTessVertex( tessellator, reinterpret_cast< GLdouble* >( &polyLoopGL[ i ] ), &polyLoopGL[ i ] ); gluTessVertex( tessellator, reinterpret_cast< GLdouble* >( &polyLoopGL[ i ] ), &polyLoopGL[ i ] );
} }
gluTessEndContour( tessellator ); gluTessEndContour( tessellator );
gluTessEndPolygon( tessellator ); gluTessEndPolygon( tessellator );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TriangulateDrawCalls( const TessDataGL& tessData ) void BlenderTessellatorGL::TriangulateDrawCalls( const TessDataGL& tessData )
{ {
// NOTE - Because we are supplying a callback to GLU_TESS_EDGE_FLAG_DATA we don't technically // NOTE - Because we are supplying a callback to GLU_TESS_EDGE_FLAG_DATA we don't technically
// need support for GL_TRIANGLE_STRIP and GL_TRIANGLE_FAN but we'll keep it here in case // need support for GL_TRIANGLE_STRIP and GL_TRIANGLE_FAN but we'll keep it here in case
// GLU tessellate changes or tristrips and fans are wanted. // GLU tessellate changes or 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 )
{ {
const DrawCallGL& drawCallGL = tessData.drawCalls[ i ]; const DrawCallGL& drawCallGL = tessData.drawCalls[ i ];
const VertexGL* vertices = &tessData.vertices[ drawCallGL.baseVertex ]; const VertexGL* vertices = &tessData.vertices[ drawCallGL.baseVertex ];
if ( drawCallGL.drawMode == GL_TRIANGLES ) if ( drawCallGL.drawMode == GL_TRIANGLES )
{ {
MakeFacesFromTris( vertices, drawCallGL.vertexCount ); MakeFacesFromTris( vertices, drawCallGL.vertexCount );
} }
else if ( drawCallGL.drawMode == GL_TRIANGLE_STRIP ) else if ( drawCallGL.drawMode == GL_TRIANGLE_STRIP )
{ {
MakeFacesFromTriStrip( vertices, drawCallGL.vertexCount ); MakeFacesFromTriStrip( vertices, drawCallGL.vertexCount );
} }
else if ( drawCallGL.drawMode == GL_TRIANGLE_FAN ) else if ( drawCallGL.drawMode == GL_TRIANGLE_FAN )
{ {
MakeFacesFromTriFan( vertices, drawCallGL.vertexCount ); MakeFacesFromTriFan( vertices, drawCallGL.vertexCount );
} }
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::MakeFacesFromTris( const VertexGL* vertices, int vertexCount ) void BlenderTessellatorGL::MakeFacesFromTris( const VertexGL* vertices, int vertexCount )
{ {
int triangleCount = vertexCount / 3; 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;
converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index ); converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::MakeFacesFromTriStrip( const VertexGL* vertices, int vertexCount ) void BlenderTessellatorGL::MakeFacesFromTriStrip( const VertexGL* vertices, int vertexCount )
{ {
int triangleCount = vertexCount - 2; 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;
converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index ); converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::MakeFacesFromTriFan( const VertexGL* vertices, int vertexCount ) void BlenderTessellatorGL::MakeFacesFromTriFan( const VertexGL* vertices, int vertexCount )
{ {
int triangleCount = vertexCount - 2; 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;
converter->AddFace( vertices[ 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index ); converter->AddFace( vertices[ 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TessellateBegin( GLenum drawModeGL, void* userData ) void BlenderTessellatorGL::TessellateBegin( GLenum drawModeGL, void* userData )
{ {
TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData ); TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData );
tessData.drawCalls.push_back( DrawCallGL( drawModeGL, tessData.vertices.size( ) ) ); tessData.drawCalls.push_back( DrawCallGL( drawModeGL, tessData.vertices.size( ) ) );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TessellateEnd( void* ) void BlenderTessellatorGL::TessellateEnd( void* )
{ {
// Do nothing // Do nothing
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TessellateVertex( const void* vtxData, void* userData ) void BlenderTessellatorGL::TessellateVertex( const void* vtxData, void* userData )
{ {
TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData ); TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData );
const VertexGL& vertex = *reinterpret_cast< const VertexGL* >( vtxData ); const VertexGL& vertex = *reinterpret_cast< const VertexGL* >( vtxData );
if ( vertex.magic != BLEND_TESS_MAGIC ) if ( vertex.magic != BLEND_TESS_MAGIC )
{ {
ThrowException( "Point returned by GLU Tessellate was probably not one of ours. This indicates we need a new way to store vertex information" ); ThrowException( "Point returned by GLU Tessellate was probably not one of ours. This indicates we need a new way to store vertex information" );
} }
tessData.vertices.push_back( vertex ); tessData.vertices.push_back( vertex );
if ( tessData.drawCalls.size( ) == 0 ) if ( tessData.drawCalls.size( ) == 0 )
{ {
ThrowException( "\"Vertex\" callback received before \"Begin\"" ); ThrowException( "\"Vertex\" callback received before \"Begin\"" );
} }
++( tessData.drawCalls.back( ).vertexCount ); ++( tessData.drawCalls.back( ).vertexCount );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TessellateCombine( const GLdouble intersection[ 3 ], const GLdouble* [ 4 ], const GLfloat [ 4 ], GLdouble** out, void* userData ) void BlenderTessellatorGL::TessellateCombine( const GLdouble intersection[ 3 ], const GLdouble* [ 4 ], const GLfloat [ 4 ], GLdouble** out, void* userData )
{ {
ThrowException( "Intersected polygon loops are not yet supported" ); ThrowException( "Intersected polygon loops are not yet supported" );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TessellateEdgeFlag( GLboolean, void* ) void BlenderTessellatorGL::TessellateEdgeFlag( GLboolean, void* )
{ {
// Do nothing // Do nothing
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorGL::TessellateError( GLenum errorCode, void* ) void BlenderTessellatorGL::TessellateError( GLenum errorCode, void* )
{ {
ThrowException( reinterpret_cast< const char* >( gluErrorString( errorCode ) ) ); ThrowException( reinterpret_cast< const char* >( gluErrorString( errorCode ) ) );
} }
#endif // ASSIMP_BLEND_WITH_GLU_TESSELLATE #endif // ASSIMP_BLEND_WITH_GLU_TESSELLATE
@ -250,7 +251,7 @@ void BlenderTessellatorGL::TessellateError( GLenum errorCode, void* )
namespace Assimp namespace Assimp
{ {
template< > const std::string LogFunctions< BlenderTessellatorP2T >::log_prefix = "BLEND_TESS_P2T: "; template< > const std::string LogFunctions< BlenderTessellatorP2T >::log_prefix = "BLEND_TESS_P2T: ";
} }
using namespace Assimp; using namespace Assimp;
@ -258,7 +259,7 @@ using namespace Assimp::Blender;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
BlenderTessellatorP2T::BlenderTessellatorP2T( BlenderBMeshConverter& converter ): BlenderTessellatorP2T::BlenderTessellatorP2T( BlenderBMeshConverter& converter ):
converter( &converter ) converter( &converter )
{ {
} }
@ -270,178 +271,173 @@ BlenderTessellatorP2T::~BlenderTessellatorP2T( )
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices ) void BlenderTessellatorP2T::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
{ {
AssertVertexCount( vertexCount ); AssertVertexCount( vertexCount );
// NOTE - We have to hope that points in a Blender polygon are roughly on the same plane. // NOTE - We have to hope that points in a Blender polygon are roughly on the same plane.
// There may be some triangulation artifacts if they are wildly different. // There may be some triangulation artifacts if they are wildly different.
std::vector< PointP2T > points; std::vector< PointP2T > points;
Copy3DVertices( polyLoop, vertexCount, vertices, points ); Copy3DVertices( polyLoop, vertexCount, vertices, points );
PlaneP2T plane = FindLLSQPlane( points ); PlaneP2T plane = FindLLSQPlane( points );
aiMatrix4x4 transform = GeneratePointTransformMatrix( plane ); aiMatrix4x4 transform = GeneratePointTransformMatrix( plane );
TransformAndFlattenVectices( transform, points ); TransformAndFlattenVectices( transform, points );
std::vector< p2t::Point* > pointRefs; std::vector< p2t::Point* > pointRefs;
ReferencePoints( points, pointRefs ); ReferencePoints( points, pointRefs );
p2t::CDT cdt( pointRefs ); p2t::CDT cdt( pointRefs );
cdt.Triangulate( ); cdt.Triangulate( );
std::vector< p2t::Triangle* > triangles = cdt.GetTriangles( ); std::vector< p2t::Triangle* > triangles = cdt.GetTriangles( );
MakeFacesFromTriangles( triangles ); MakeFacesFromTriangles( triangles );
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::AssertVertexCount( int vertexCount ) void BlenderTessellatorP2T::AssertVertexCount( int vertexCount )
{ {
if ( vertexCount <= 4 ) if ( vertexCount <= 4 )
{ {
ThrowException( "Expected more than 4 vertices for tessellation" ); ThrowException( "Expected more than 4 vertices for tessellation" );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::Copy3DVertices( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices, std::vector< PointP2T >& points ) const void BlenderTessellatorP2T::Copy3DVertices( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices, std::vector< PointP2T >& points ) const
{ {
points.resize( vertexCount ); points.resize( vertexCount );
for ( int i = 0; i < vertexCount; ++i ) for ( int i = 0; i < vertexCount; ++i )
{ {
const MLoop& loop = polyLoop[ i ]; const MLoop& loop = polyLoop[ i ];
const MVert& vert = vertices[ loop.v ]; const MVert& vert = vertices[ loop.v ];
PointP2T& point = points[ i ]; PointP2T& point = points[ i ];
point.point3D.Set( vert.co[ 0 ], vert.co[ 1 ], vert.co[ 2 ] ); point.point3D.Set( vert.co[ 0 ], vert.co[ 1 ], vert.co[ 2 ] );
point.index = loop.v; point.index = loop.v;
point.magic = BLEND_TESS_MAGIC; point.magic = BLEND_TESS_MAGIC;
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
aiMatrix4x4 BlenderTessellatorP2T::GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const aiMatrix4x4 BlenderTessellatorP2T::GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const
{ {
aiVector3D sideA( 1.0f, 0.0f, 0.0f ); aiVector3D sideA( 1.0f, 0.0f, 0.0f );
if ( fabs( plane.normal * sideA ) > 0.999f ) if ( std::fabs( plane.normal * sideA ) > 0.999f )
{ {
sideA = aiVector3D( 0.0f, 1.0f, 0.0f ); sideA = aiVector3D( 0.0f, 1.0f, 0.0f );
} }
aiVector3D sideB( plane.normal ^ sideA ); aiVector3D sideB( plane.normal ^ sideA );
sideB.Normalize( ); sideB.Normalize( );
sideA = sideB ^ plane.normal; sideA = sideB ^ plane.normal;
aiMatrix4x4 result; aiMatrix4x4 result;
result.a1 = sideA.x; result.a1 = sideA.x;
result.a2 = sideA.y; result.a2 = sideA.y;
result.a3 = sideA.z; result.a3 = sideA.z;
result.b1 = sideB.x; result.b1 = sideB.x;
result.b2 = sideB.y; result.b2 = sideB.y;
result.b3 = sideB.z; result.b3 = sideB.z;
result.c1 = plane.normal.x; result.c1 = plane.normal.x;
result.c2 = plane.normal.y; result.c2 = plane.normal.y;
result.c3 = plane.normal.z; result.c3 = plane.normal.z;
result.a4 = plane.centre.x; result.a4 = plane.centre.x;
result.b4 = plane.centre.y; result.b4 = plane.centre.y;
result.c4 = plane.centre.z; result.c4 = plane.centre.z;
result.Inverse( ); result.Inverse( );
return result; return result;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const void BlenderTessellatorP2T::TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const
{ {
for ( unsigned int i = 0; i < vertices.size( ); ++i ) for ( 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;
point.point2D.set( point.point3D.y, point.point3D.z ); point.point2D.set( point.point3D.y, point.point3D.z );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const void BlenderTessellatorP2T::ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const
{ {
pointRefs.resize( points.size( ) ); pointRefs.resize( points.size( ) );
for ( unsigned int i = 0; i < points.size( ); ++i ) for ( 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 ) )
{ {
ThrowException( "Point returned by poly2tri was probably not one of ours. This indicates we need a new way to store vertex information" ); ThrowException( "Point returned by poly2tri was probably not one of ours. This indicates we need a new way to store vertex information" );
} }
return pointStruct; return pointStruct;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void BlenderTessellatorP2T::MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const void BlenderTessellatorP2T::MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const
{ {
for ( unsigned int i = 0; i < triangles.size( ); ++i ) for ( size_t i = 0; i < triangles.size( ); ++i )
{ {
p2t::Triangle& Triangle = *triangles[ i ]; p2t::Triangle& Triangle = *triangles[ i ];
PointP2T& pointA = GetActualPointStructure( *Triangle.GetPoint( 0 ) ); PointP2T& pointA = GetActualPointStructure( *Triangle.GetPoint( 0 ) );
PointP2T& pointB = GetActualPointStructure( *Triangle.GetPoint( 1 ) ); PointP2T& pointB = GetActualPointStructure( *Triangle.GetPoint( 1 ) );
PointP2T& pointC = GetActualPointStructure( *Triangle.GetPoint( 2 ) ); PointP2T& pointC = GetActualPointStructure( *Triangle.GetPoint( 2 ) );
converter->AddFace( pointA.index, pointB.index, pointC.index ); converter->AddFace( pointA.index, pointB.index, pointC.index );
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
inline float p2tMax( float a, float b ) inline float p2tMax( float a, float b )
{ {
return a > b ? a : b; return a > b ? a : b;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html // Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
float BlenderTessellatorP2T::FindLargestMatrixElem( const aiMatrix3x3& mtx ) const float BlenderTessellatorP2T::FindLargestMatrixElem( const aiMatrix3x3& mtx ) const
{ {
float result = 0.0f; float result = 0.0f;
for ( int x = 0; x < 3; ++x ) for ( 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 );
} }
} }
return result; return result;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// 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;
} }
} }
return result; return result;
} }
@ -449,70 +445,70 @@ aiMatrix3x3 BlenderTessellatorP2T::ScaleMatrix( const aiMatrix3x3& mtx, float sc
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html // Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
aiVector3D BlenderTessellatorP2T::GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const aiVector3D BlenderTessellatorP2T::GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const
{ {
float scale = FindLargestMatrixElem( mtx ); 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;
aiVector3D v( 1.0f ); aiVector3D v( 1.0f );
aiVector3D lastV = v; aiVector3D lastV = v;
for ( int i = 0; i < 100; ++i ) for ( int i = 0; i < 100; ++i )
{ {
v = mc * v; v = mc * v;
v.Normalize( ); v.Normalize( );
if ( ( v - lastV ).SquareLength( ) < 1e-16f ) if ( ( v - lastV ).SquareLength( ) < 1e-16f )
{ {
break; break;
} }
lastV = v; lastV = v;
} }
return v; return v;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html // Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
PlaneP2T BlenderTessellatorP2T::FindLLSQPlane( const std::vector< PointP2T >& points ) const PlaneP2T BlenderTessellatorP2T::FindLLSQPlane( const std::vector< PointP2T >& points ) const
{ {
PlaneP2T result; PlaneP2T result;
aiVector3D sum( 0.0f ); aiVector3D sum( 0.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;
sumXY += offset.x * offset.y; sumXY += offset.x * offset.y;
sumXZ += offset.x * offset.z; sumXZ += offset.x * offset.z;
sumYY += offset.y * offset.y; sumYY += offset.y * offset.y;
sumYZ += offset.y * offset.z; sumYZ += offset.y * offset.z;
sumZZ += offset.z * offset.z; sumZZ += offset.z * offset.z;
} }
aiMatrix3x3 mtx( sumXX, sumXY, sumXZ, sumXY, sumYY, sumYZ, sumXZ, sumYZ, sumZZ ); aiMatrix3x3 mtx( sumXX, sumXY, sumXZ, sumXY, sumYY, sumYZ, sumXZ, sumYZ, sumZZ );
float det = mtx.Determinant( ); const ai_real det = mtx.Determinant( );
if ( det == 0.0f ) if ( det == 0.0f )
{ {
result.normal = aiVector3D( 0.0f ); result.normal = aiVector3D( 0.0f );
} }
else else
{ {
aiMatrix3x3 invMtx = mtx; aiMatrix3x3 invMtx = mtx;
invMtx.Inverse( ); invMtx.Inverse( );
result.normal = GetEigenVectorFromLargestEigenValue( invMtx ); result.normal = GetEigenVectorFromLargestEigenValue( invMtx );
} }
return result; return result;
} }
#endif // ASSIMP_BLEND_WITH_POLY_2_TRI #endif // ASSIMP_BLEND_WITH_POLY_2_TRI

View File

@ -2,11 +2,11 @@
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,
with or without modification, are permitted provided that the with or without modification, are permitted provided that the
following conditions are met: following conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
@ -23,16 +23,16 @@ following 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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
@ -46,15 +46,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Use these to toggle between GLU Tessellate or poly2tri // Use these to toggle between GLU Tessellate or poly2tri
// Note (acg) keep GLU Tesselate disabled by default - if it is turned on, // Note (acg) keep GLU Tesselate disabled by default - if it is turned on,
// assimp needs to be linked against GLU, which is currently not yet // assimp needs to be linked against GLU, which is currently not yet
// made configurable in CMake and potentially not wanted by most users // made configurable in CMake and potentially not wanted by most users
// as it requires a Gl environment. // as it requires a Gl environment.
#ifndef ASSIMP_BLEND_WITH_GLU_TESSELLATE #ifndef ASSIMP_BLEND_WITH_GLU_TESSELLATE
# define ASSIMP_BLEND_WITH_GLU_TESSELLATE 0 # define ASSIMP_BLEND_WITH_GLU_TESSELLATE 0
#endif #endif
#ifndef ASSIMP_BLEND_WITH_POLY_2_TRI #ifndef ASSIMP_BLEND_WITH_POLY_2_TRI
# define ASSIMP_BLEND_WITH_POLY_2_TRI 1 # define ASSIMP_BLEND_WITH_POLY_2_TRI 1
#endif #endif
#include "LogAux.h" #include "LogAux.h"
@ -68,74 +68,74 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp namespace Assimp
{ {
class BlenderBMeshConverter; class BlenderBMeshConverter;
// TinyFormatter.h // TinyFormatter.h
namespace Formatter namespace Formatter
{ {
template < typename T,typename TR, typename A > class basic_formatter; template < typename T,typename TR, typename A > class basic_formatter;
typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format; typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format;
} }
// BlenderScene.h // BlenderScene.h
namespace Blender namespace Blender
{ {
struct MLoop; struct MLoop;
struct MVert; struct MVert;
struct VertexGL struct VertexGL
{ {
GLdouble X; GLdouble X;
GLdouble Y; GLdouble Y;
GLdouble Z; GLdouble Z;
int index; int index;
int magic; int magic;
VertexGL( GLdouble X, GLdouble Y, GLdouble Z, int index, int magic ): X( X ), Y( Y ), Z( Z ), index( index ), magic( magic ) { } VertexGL( GLdouble X, GLdouble Y, GLdouble Z, int index, int magic ): X( X ), Y( Y ), Z( Z ), index( index ), magic( magic ) { }
}; };
struct DrawCallGL struct DrawCallGL
{ {
GLenum drawMode; GLenum drawMode;
int baseVertex; int baseVertex;
int vertexCount; int vertexCount;
DrawCallGL( GLenum drawMode, int baseVertex ): drawMode( drawMode ), baseVertex( baseVertex ), vertexCount( 0 ) { } DrawCallGL( GLenum drawMode, int baseVertex ): drawMode( drawMode ), baseVertex( baseVertex ), vertexCount( 0 ) { }
}; };
struct TessDataGL struct TessDataGL
{ {
std::vector< DrawCallGL > drawCalls; std::vector< DrawCallGL > drawCalls;
std::vector< VertexGL > vertices; std::vector< VertexGL > vertices;
}; };
} }
class BlenderTessellatorGL: public LogFunctions< BlenderTessellatorGL > class BlenderTessellatorGL: public LogFunctions< BlenderTessellatorGL >
{ {
public: public:
BlenderTessellatorGL( BlenderBMeshConverter& converter ); BlenderTessellatorGL( BlenderBMeshConverter& converter );
~BlenderTessellatorGL( ); ~BlenderTessellatorGL( );
void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices ); void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
private: private:
void AssertVertexCount( int vertexCount ); void AssertVertexCount( int vertexCount );
void GenerateLoopVerts( std::vector< Blender::VertexGL >& polyLoopGL, const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices ); void GenerateLoopVerts( std::vector< Blender::VertexGL >& polyLoopGL, const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
void Tesssellate( std::vector< Blender::VertexGL >& polyLoopGL, Blender::TessDataGL& tessData ); void Tesssellate( std::vector< Blender::VertexGL >& polyLoopGL, Blender::TessDataGL& tessData );
void TriangulateDrawCalls( const Blender::TessDataGL& tessData ); void TriangulateDrawCalls( const Blender::TessDataGL& tessData );
void MakeFacesFromTris( const Blender::VertexGL* vertices, int vertexCount ); void MakeFacesFromTris( const Blender::VertexGL* vertices, int vertexCount );
void MakeFacesFromTriStrip( const Blender::VertexGL* vertices, int vertexCount ); void MakeFacesFromTriStrip( const Blender::VertexGL* vertices, int vertexCount );
void MakeFacesFromTriFan( const Blender::VertexGL* vertices, int vertexCount ); void MakeFacesFromTriFan( const Blender::VertexGL* vertices, int vertexCount );
static void TessellateBegin( GLenum drawModeGL, void* userData ); static void TessellateBegin( GLenum drawModeGL, void* userData );
static void TessellateEnd( void* userData ); static void TessellateEnd( void* userData );
static void TessellateVertex( const void* vtxData, void* userData ); static void TessellateVertex( const void* vtxData, void* userData );
static void TessellateCombine( const GLdouble intersection[ 3 ], const GLdouble* [ 4 ], const GLfloat [ 4 ], GLdouble** out, void* userData ); static void TessellateCombine( const GLdouble intersection[ 3 ], const GLdouble* [ 4 ], const GLfloat [ 4 ], GLdouble** out, void* userData );
static void TessellateEdgeFlag( GLboolean edgeFlag, void* userData ); static void TessellateEdgeFlag( GLboolean edgeFlag, void* userData );
static void TessellateError( GLenum errorCode, void* userData ); static void TessellateError( GLenum errorCode, void* userData );
BlenderBMeshConverter* converter; BlenderBMeshConverter* converter;
}; };
} // end of namespace Assimp } // end of namespace Assimp
#endif // ASSIMP_BLEND_WITH_GLU_TESSELLATE #endif // ASSIMP_BLEND_WITH_GLU_TESSELLATE
@ -146,61 +146,61 @@ namespace Assimp
namespace Assimp namespace Assimp
{ {
class BlenderBMeshConverter; class BlenderBMeshConverter;
// TinyFormatter.h // TinyFormatter.h
namespace Formatter namespace Formatter
{ {
template < typename T,typename TR, typename A > class basic_formatter; template < typename T,typename TR, typename A > class basic_formatter;
typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format; typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format;
} }
// BlenderScene.h // BlenderScene.h
namespace Blender namespace Blender
{ {
struct MLoop; struct MLoop;
struct MVert; struct MVert;
struct PointP2T struct PointP2T
{ {
aiVector3D point3D; aiVector3D point3D;
p2t::Point point2D; p2t::Point point2D;
int magic; int magic;
int index; int index;
}; };
struct PlaneP2T struct PlaneP2T
{ {
aiVector3D centre; aiVector3D centre;
aiVector3D normal; aiVector3D normal;
}; };
} }
class BlenderTessellatorP2T: public LogFunctions< BlenderTessellatorP2T > class BlenderTessellatorP2T: public LogFunctions< BlenderTessellatorP2T >
{ {
public: public:
BlenderTessellatorP2T( BlenderBMeshConverter& converter ); BlenderTessellatorP2T( BlenderBMeshConverter& converter );
~BlenderTessellatorP2T( ); ~BlenderTessellatorP2T( );
void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices ); void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
private: private:
void AssertVertexCount( int vertexCount ); void AssertVertexCount( int vertexCount );
void Copy3DVertices( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices, std::vector< Blender::PointP2T >& targetVertices ) const; void Copy3DVertices( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices, std::vector< Blender::PointP2T >& targetVertices ) const;
aiMatrix4x4 GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const; aiMatrix4x4 GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const;
void TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const; void TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const;
void ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const; void ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const;
inline Blender::PointP2T& GetActualPointStructure( p2t::Point& point ) const; inline Blender::PointP2T& GetActualPointStructure( p2t::Point& point ) const;
void MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const; void MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const;
// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html // Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
float FindLargestMatrixElem( const aiMatrix3x3& mtx ) const; float FindLargestMatrixElem( const aiMatrix3x3& mtx ) const;
aiMatrix3x3 ScaleMatrix( const aiMatrix3x3& mtx, float scale ) const; aiMatrix3x3 ScaleMatrix( const aiMatrix3x3& mtx, float scale ) const;
aiVector3D GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const; aiVector3D GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const;
Blender::PlaneP2T FindLLSQPlane( const std::vector< Blender::PointP2T >& points ) const; Blender::PlaneP2T FindLLSQPlane( const std::vector< Blender::PointP2T >& points ) const;
BlenderBMeshConverter* converter; BlenderBMeshConverter* converter;
}; };
} // end of namespace Assimp } // end of namespace Assimp
#endif // ASSIMP_BLEND_WITH_POLY_2_TRI #endif // ASSIMP_BLEND_WITH_POLY_2_TRI

View File

@ -1,326 +1,336 @@
/* /*
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
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,
with or without modification, are permitted provided that the following with or without modification, are permitted provided that the following
conditions are met: conditions are met:
* Redistributions of source code must retain the above * Redistributions of source code must retain the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer. following disclaimer.
* Redistributions in binary form must reproduce the above * Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other following disclaimer in the documentation and/or other
materials provided with the distribution. materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its * Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products contributors may be used to endorse or promote products
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,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
*/ */
/** @file Provides cheat implementations for IOSystem and IOStream to /** @file Provides cheat implementations for IOSystem and IOStream to
* redirect exporter output to a blob chain.*/ * redirect exporter output to a blob chain.*/
#ifndef AI_BLOBIOSYSTEM_H_INCLUDED #ifndef AI_BLOBIOSYSTEM_H_INCLUDED
#define AI_BLOBIOSYSTEM_H_INCLUDED #define AI_BLOBIOSYSTEM_H_INCLUDED
namespace Assimp { #include "./../include/assimp/IOStream.hpp"
class BlobIOSystem; #include "./../include/assimp/cexport.h"
#include "./../include/assimp/IOSystem.hpp"
// -------------------------------------------------------------------------------------------- #include "./../include/assimp/DefaultLogger.hpp"
/** Redirect IOStream to a blob */ #include <stdint.h>
// -------------------------------------------------------------------------------------------- #include <set>
class BlobIOStream : public IOStream #include <vector>
{
public: namespace Assimp {
class BlobIOSystem;
BlobIOStream(BlobIOSystem* creator, const std::string& file, size_t initial = 4096)
: buffer() // --------------------------------------------------------------------------------------------
, cur_size() /** Redirect IOStream to a blob */
, file_size() // --------------------------------------------------------------------------------------------
, cursor() class BlobIOStream : public IOStream
, initial(initial) {
, file(file) public:
, creator(creator)
{ BlobIOStream(BlobIOSystem* creator, const std::string& file, size_t initial = 4096)
} : buffer()
, cur_size()
, file_size()
virtual ~BlobIOStream(); , cursor()
, initial(initial)
public: , file(file)
, creator(creator)
// ------------------------------------------------------------------- {
aiExportDataBlob* GetBlob() }
{
aiExportDataBlob* blob = new aiExportDataBlob();
blob->size = file_size; virtual ~BlobIOStream();
blob->data = buffer;
public:
buffer = NULL;
// -------------------------------------------------------------------
return blob; aiExportDataBlob* GetBlob()
} {
aiExportDataBlob* blob = new aiExportDataBlob();
blob->size = file_size;
public: blob->data = buffer;
buffer = NULL;
// -------------------------------------------------------------------
virtual size_t Read( void *, return blob;
size_t, }
size_t )
{
return 0; public:
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
virtual size_t Write(const void* pvBuffer, virtual size_t Read( void *,
size_t pSize, size_t,
size_t pCount) size_t )
{ {
pSize *= pCount; return 0;
if (cursor + pSize > cur_size) { }
Grow(cursor + pSize);
} // -------------------------------------------------------------------
virtual size_t Write(const void* pvBuffer,
memcpy(buffer+cursor, pvBuffer, pSize); size_t pSize,
cursor += pSize; size_t pCount)
{
file_size = std::max(file_size,cursor); pSize *= pCount;
return pCount; if (cursor + pSize > cur_size) {
} Grow(cursor + pSize);
}
// -------------------------------------------------------------------
virtual aiReturn Seek(size_t pOffset, memcpy(buffer+cursor, pvBuffer, pSize);
aiOrigin pOrigin) cursor += pSize;
{
switch(pOrigin) file_size = std::max(file_size,cursor);
{ return pCount;
case aiOrigin_CUR: }
cursor += pOffset;
// -------------------------------------------------------------------
case aiOrigin_END: virtual aiReturn Seek(size_t pOffset,
cursor = file_size - pOffset; aiOrigin pOrigin)
{
case aiOrigin_SET: switch(pOrigin)
cursor = pOffset; {
break; case aiOrigin_CUR:
cursor += pOffset;
default: break;
return AI_FAILURE;
} case aiOrigin_END:
cursor = file_size - pOffset;
if (cursor > file_size) { break;
Grow(cursor);
} case aiOrigin_SET:
cursor = pOffset;
file_size = std::max(cursor,file_size); break;
return AI_SUCCESS;
} default:
return AI_FAILURE;
// ------------------------------------------------------------------- }
virtual size_t Tell() const
{ if (cursor > file_size) {
return cursor; Grow(cursor);
} }
// ------------------------------------------------------------------- file_size = std::max(cursor,file_size);
virtual size_t FileSize() const return AI_SUCCESS;
{ }
return file_size;
} // -------------------------------------------------------------------
virtual size_t Tell() const
// ------------------------------------------------------------------- {
virtual void Flush() return cursor;
{ }
// ignore
} // -------------------------------------------------------------------
virtual size_t FileSize() const
{
return file_size;
private: }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
void Grow(size_t need = 0) virtual void Flush()
{ {
// 1.5 and phi are very heap-friendly growth factors (the first // ignore
// allows for frequent re-use of heap blocks, the second }
// forms a fibonacci sequence with similar characteristics -
// since this heavily depends on the heap implementation
// and other factors as well, i'll just go with 1.5 since
// it is quicker to compute). private:
size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) ));
// -------------------------------------------------------------------
const uint8_t* const old = buffer; void Grow(size_t need = 0)
buffer = new uint8_t[new_size]; {
// 1.5 and phi are very heap-friendly growth factors (the first
if (old) { // allows for frequent re-use of heap blocks, the second
memcpy(buffer,old,cur_size); // forms a fibonacci sequence with similar characteristics -
delete[] old; // since this heavily depends on the heap implementation
} // and other factors as well, i'll just go with 1.5 since
// it is quicker to compute).
cur_size = new_size; size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) ));
}
const uint8_t* const old = buffer;
private: buffer = new uint8_t[new_size];
uint8_t* buffer; if (old) {
size_t cur_size,file_size, cursor, initial; memcpy(buffer,old,cur_size);
delete[] old;
const std::string file; }
BlobIOSystem* const creator;
}; cur_size = new_size;
}
#define AI_BLOBIO_MAGIC "$blobfile" private:
// -------------------------------------------------------------------------------------------- uint8_t* buffer;
/** Redirect IOSystem to a blob */ size_t cur_size,file_size, cursor, initial;
// --------------------------------------------------------------------------------------------
class BlobIOSystem : public IOSystem const std::string file;
{ BlobIOSystem* const creator;
};
friend class BlobIOStream;
typedef std::pair<std::string, aiExportDataBlob*> BlobEntry;
#define AI_BLOBIO_MAGIC "$blobfile"
public:
// --------------------------------------------------------------------------------------------
BlobIOSystem() /** Redirect IOSystem to a blob */
{ // --------------------------------------------------------------------------------------------
} class BlobIOSystem : public IOSystem
{
virtual ~BlobIOSystem()
{ friend class BlobIOStream;
BOOST_FOREACH(BlobEntry& blobby, blobs) { typedef std::pair<std::string, aiExportDataBlob*> BlobEntry;
delete blobby.second;
} public:
}
BlobIOSystem()
public: {
}
// -------------------------------------------------------------------
const char* GetMagicFileName() const virtual ~BlobIOSystem()
{ {
return AI_BLOBIO_MAGIC; for(BlobEntry& blobby : blobs) {
} delete blobby.second;
}
}
// -------------------------------------------------------------------
aiExportDataBlob* GetBlobChain() public:
{
// one must be the master // -------------------------------------------------------------------
aiExportDataBlob* master = NULL, *cur; const char* GetMagicFileName() const
BOOST_FOREACH(const BlobEntry& blobby, blobs) { {
if (blobby.first == AI_BLOBIO_MAGIC) { return AI_BLOBIO_MAGIC;
master = blobby.second; }
break;
}
} // -------------------------------------------------------------------
if (!master) { aiExportDataBlob* GetBlobChain()
DefaultLogger::get()->error("BlobIOSystem: no data written or master file was not closed properly."); {
return NULL; // one must be the master
} aiExportDataBlob* master = NULL, *cur;
for(const BlobEntry& blobby : blobs) {
master->name.Set(""); if (blobby.first == AI_BLOBIO_MAGIC) {
master = blobby.second;
cur = master; break;
BOOST_FOREACH(const BlobEntry& blobby, blobs) { }
if (blobby.second == master) { }
continue; if (!master) {
} DefaultLogger::get()->error("BlobIOSystem: no data written or master file was not closed properly.");
return NULL;
cur->next = blobby.second; }
cur = cur->next;
master->name.Set("");
// extract the file extension from the file written
const std::string::size_type s = blobby.first.find_first_of('.'); cur = master;
cur->name.Set(s == std::string::npos ? blobby.first : blobby.first.substr(s+1)); for(const BlobEntry& blobby : blobs) {
} if (blobby.second == master) {
continue;
// give up blob ownership }
blobs.clear();
return master; cur->next = blobby.second;
} cur = cur->next;
public: // extract the file extension from the file written
const std::string::size_type s = blobby.first.find_first_of('.');
// ------------------------------------------------------------------- cur->name.Set(s == std::string::npos ? blobby.first : blobby.first.substr(s+1));
virtual bool Exists( const char* pFile) const { }
return created.find(std::string(pFile)) != created.end();
} // give up blob ownership
blobs.clear();
return master;
// ------------------------------------------------------------------- }
virtual char getOsSeparator() const {
return '/'; public:
}
// -------------------------------------------------------------------
virtual bool Exists( const char* pFile) const {
// ------------------------------------------------------------------- return created.find(std::string(pFile)) != created.end();
virtual IOStream* Open(const char* pFile, }
const char* pMode)
{
if (pMode[0] != 'w') { // -------------------------------------------------------------------
return NULL; virtual char getOsSeparator() const {
} return '/';
}
created.insert(std::string(pFile));
return new BlobIOStream(this,std::string(pFile));
} // -------------------------------------------------------------------
virtual IOStream* Open(const char* pFile,
// ------------------------------------------------------------------- const char* pMode)
virtual void Close( IOStream* pFile) {
{ if (pMode[0] != 'w') {
delete pFile; return NULL;
} }
private: created.insert(std::string(pFile));
return new BlobIOStream(this,std::string(pFile));
// ------------------------------------------------------------------- }
void OnDestruct(const std::string& filename, BlobIOStream* child)
{ // -------------------------------------------------------------------
// we don't know in which the files are closed, so we virtual void Close( IOStream* pFile)
// can't reliably say that the first must be the master {
// file ... delete pFile;
blobs.push_back( BlobEntry(filename,child->GetBlob()) ); }
}
private:
private:
std::set<std::string> created; // -------------------------------------------------------------------
std::vector< BlobEntry > blobs; void OnDestruct(const std::string& filename, BlobIOStream* child)
}; {
// we don't know in which the files are closed, so we
// can't reliably say that the first must be the master
// -------------------------------------------------------------------------------------------- // file ...
BlobIOStream :: ~BlobIOStream() blobs.push_back( BlobEntry(filename,child->GetBlob()) );
{ }
creator->OnDestruct(file,this);
delete[] buffer; private:
} std::set<std::string> created;
std::vector< BlobEntry > blobs;
};
} // end Assimp
#endif // --------------------------------------------------------------------------------------------
BlobIOStream :: ~BlobIOStream()
{
creator->OnDestruct(file,this);
delete[] buffer;
}
} // end Assimp
#endif

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

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