diff --git a/.gitattributes b/.gitattributes index 2cf91cfb3..f3df90d38 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,7 +2,21 @@ *.cpp text eol=lf *.h text eol=lf *.c text eol=lf +*.cc text eol=lf +*.cpp text eol=lf +*.rc text eol=lf *.hpp text eol=lf *.txt text eol=lf *.cmake text eol=lf *.sh text eol=lf +CHANGES text eol=lf +CREDITS text eol=lf +LICENSE text eol=lf +Readme.md text eol=lf +# make sure that repo-specific settings (.gitignore, CI-setup,...) +# are excluded from the source-package generated via 'git archive' +.git* export-ignore +/.travis* export-ignore +/.coveralls* export-ignore +appveyor.yml export-ignore + diff --git a/.gitignore b/.gitignore index 664708a90..12cd76a87 100644 --- a/.gitignore +++ b/.gitignore @@ -81,3 +81,5 @@ lib64/assimp-vc120-mtd.ilk lib64/assimp-vc120-mtd.exp lib64/assimp-vc120-mt.exp xcuserdata + +cmake-build-debug diff --git a/.travis.sh b/.travis.sh index c2852855f..fb42bd40d 100755 --- a/.travis.sh +++ b/.travis.sh @@ -1,16 +1,66 @@ -function generate() -{ - cmake -G "Unix Makefiles" -DASSIMP_NO_EXPORT=$TRAVIS_NO_EXPORT -DBUILD_SHARED_LIBS=$SHARED_BUILD -DASSIMP_COVERALLS=$ENABLE_COVERALLS -} +#--------------------------------------------------------------------------- +#Open Asset Import Library (assimp) +#--------------------------------------------------------------------------- +# Copyright (c) 2006-2017, assimp team +# +# License see LICENSE file +# +function generate() { + OPTIONS="-DASSIMP_WERROR=ON" + if [ "$DISABLE_EXPORTERS" = "YES" ] ; then + OPTIONS="$OPTIONS -DASSIMP_NO_EXPORT=YES" + else + OPTIONS="$OPTIONS -DASSIMP_NO_EXPORT=NO" + fi + + if [ "$SHARED_BUILD" = "ON" ] ; then + OPTIONS="$OPTIONS -DBUILD_SHARED_LIBS=ON" + else + OPTIONS="$OPTIONS -DBUILD_SHARED_LIBS=OFF" + fi + + if [ "$ENABLE_COVERALLS" = "ON" ] ; then + OPTIONS="$OPTIONS -DASSIMP_COVERALLS=ON" + else + OPTIONS="$OPTIONS -DASSIMP_COVERALLS=OFF" + fi + + if [ "$ASAN" = "ON" ] ; then + OPTIONS="$OPTIONS -DASSIMP_ASAN=ON" + else + OPTIONS="$OPTIONS -DASSIMP_ASAN=OFF" + fi + + if [ "$UBSAN" = "ON" ] ; then + OPTIONS="$OPTIONS -DASSIMP_UBSAN=ON" + fi + + cmake -G "Unix Makefiles" $OPTIONS +} +# build and run unittests, if not android if [ $ANDROID ]; then ant -v -Dmy.dir=${TRAVIS_BUILD_DIR} -f ${TRAVIS_BUILD_DIR}/port/jassimp/build.xml ndk-jni -else +fi +if [ "$TRAVIS_OS_NAME" = "linux" ]; then + if [ $ANALYZE = "ON" ] ; then + if [ "$CC" = "clang" ]; then + scan-build cmake -G "Unix Makefiles" -DBUILD_SHARED_LIBS=OFF -DASSIMP_BUILD_TESTS=OFF + scan-build --status-bugs make -j2 + else + cppcheck --version + generate \ + && cppcheck --error-exitcode=1 -j2 -Iinclude -Icode code 2> cppcheck.txt + if [ -s cppcheck.txt ]; then + cat cppcheck.txt + exit 1 + fi + fi + 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) + && (cd test/unit; ../../bin/unit) + fi fi diff --git a/.travis.yml b/.travis.yml index 66523f6a3..9265dfb38 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,58 +1,74 @@ +sudo: required +language: cpp + +cache: ccache + before_install: - - sudo apt-get update -qq - - sudo apt-get install cmake - - sudo apt-get install cmake python3 - - if [ $LINUX ]; then sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; fi + - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq && sudo apt-get install cmake cppcheck && sudo apt-get install cmake python3 && sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- ; fi + - 'if [ "$TRAVIS_OS_NAME" = "osx" ]; then + if brew ls --versions cmake > /dev/null; then + echo cmake already installed.; + else + brew install cmake; + fi; + brew install python3; + brew install homebrew/x11/freeglut; + 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 + - if [ "$TRAVIS_OS_NAME" = "linux" ]; then 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 ; fi -branches: - only: - - master +os: + - linux -env: - global: - - secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc=" - - PV=r8e PLATF=linux-x86_64 NDK_HOME=${TRAVIS_BUILD_DIR}/android-ndk-${PV} PATH=${PATH}:${NDK_HOME} - 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 - compiler: - gcc - clang +env: + global: + # COVERITY_SCAN_TOKEN + - secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc=" + - PV=r8e PLATF=linux-x86_64 NDK_HOME=${TRAVIS_BUILD_DIR}/android-ndk-${PV} PATH=${PATH}:${NDK_HOME} + +matrix: + include: + - os: linux + compiler: clang + env: ANALYZE=ON + - os: linux + compiler: clang + env: ASAN=ON + - os: linux + compiler: clang + env: UBSAN=ON + - os: linux + compiler: clang + env: SHARED_BUILD=ON + - os: linux + compiler: gcc + env: ANALYZE=ON + - os: linux + compiler: gcc + env: DISABLE_EXPORTERS=YES ENABLE_COVERALLS=ON + - os: linux + compiler: gcc + env: SHARED_BUILD=ON + install: - if [ $ANDROID ]; then wget -c http://dl.google.com/android/ndk/android-ndk-${PV}-${PLATF}.tar.bz2 && tar xf android-ndk-${PV}-${PLATF}.tar.bz2 ; fi before_script: - - cd ${TRAVIS_BUILD_DIR} # init coverage to 0 (optional) - - lcov --directory . --zerocounters + - if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && lcov --directory . --zerocounters ; fi 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 + - if [ "$TRAVIS_OS_NAME" = "linux" ]; then 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 ; fi addons: coverity_scan: diff --git a/CHANGES b/CHANGES index 0c734162b..d5faab2e0 100644 --- a/CHANGES +++ b/CHANGES @@ -1,173 +1,349 @@ ----------------------------------------------------------------------- -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) - -FEATURES: - - Support for FBX 2013 and newer, binary and ASCII (this is partly - work from Google Summer of Code 2012) - - Support for OGRE binary mesh and skeleton format - - Updated BLEND support for newer Blender versions - - Support for arbitrary meta data, used to hold FBX and DAE metadata - - OBJ Export now produces smaller files - - Meshes can now have names, this is supported by the major importers - - Improved IFC geometry generation - - M3 support has been removed - -FIXES/HOUSEKEEPING: - - Hundreds of bugfixes in all parts of the library - - CMake is now the primary build system - -API COMPATIBILITY: - - 3.1.1 is not binary compatible to 3.0 due to aiNode::mMetaData - and aiMesh::mName - - Export interface has been cleaned up and unified - - Other than that no relevant changes - - -3.0 (2012-07-07) - -FEATURES: - - new export interface similar to the import API. - - Supported export formats: Collada, OBJ, PLY and STL - - added new import formats: XGL/ZGL, M3 (experimental) - - new postprocessing steps: Debone - - vastly improved IFC (Industry Foundation Classes) support - - introduced API to query importer meta information (such as supported - format versions, full name, maintainer info). - - reworked Ogre XML import - - C-API now supports per-import properties - -FIXES/HOUSEKEEPING: - - - hundreds of bugfixes in all parts of the library - - unified naming and cleanup of public headers - - improved CMake build system - - templatized math library - - reduce dependency on boost.thread, only remaining spot - is synchronization for the C logging API - -API COMPATIBILITY: - - renamed headers, export interface, C API properties and meta data - prevent compatibility with code written for 2.0, but in - most cases these can be easily resolved - - Note: 3.0 is not binary compatible with 2.0 - - - - -2.0 (2010-11-21) - -FEATURES: - - Add support for static Blender (*.blend) scenes - - Add support for Q3BSP scenes - - Add a windows-based OpenGL sample featuring texturing & basic materials - - Add an experimental progress feedback interface. - - Vastly improved performance (up to 500%, depending on mesh size and - spatial structure) in some expensive postprocessing steps - - AssimpView now uses a reworked layout which leaves more space - to the scene hierarchy window - - - Add C# bindings ('Assimp.NET') - - Keep BSD-licensed and otherwise free test files in separate - folders (./test/models and ./test/models-nonbsd). - -FIXES: - - Many Collada bugfixes, improve fault tolerance - - Fix possible crashes in the Obj loader - - Improve the Ogre XML loader - - OpenGL-sample now works with MinGW - - Fix Importer::FindLoader failing on uppercase file extensions - - Fix flawed path handling when locating external files - - Limit the maximum number of vertices, faces, face indices and - weights that Assimp is able to handle. This is to avoid - crashes due to overflowing counters. - - - Updated XCode project files - - Further CMAKE build improvements - - -API CHANGES: - - Add data structures for vertex-based animations (These are not - currently used, however ...) - - Some Assimp::Importer methods are const now. - - - - - -1.1 (2010-04-17) -This is the list of relevant changes from the 1.0 (r412) release to 1.1 (r700). - -FEATURES: - - Vastly improved Collada support - - Add MS3D (Milkshape 3D) support - - Add support for Ogre XML static meshes - - Add experimental COB (TrueSpace) support - - Automatic test suite to quickly locate regressions - - D bindings (`dAssimp`) - - Python 2.n bindings (`PyAssimp`) - - Add basic support for Unicode input files (utf8, utf16 and utf32) - - Add further utilities to the `assimp` tool (xml/binary dumps, quick file stats) - - Switch to a CMAKE-based build system including an install target for unix'es - - Automatic evaluation of subdivision surfaces for some formats. - - Add `Importer::ReadFileFromMemory` and the corresponding C-API `aiReadFileFromMemory` - - Expose further math utilities via the C-API (i.e. `aiMultiplyMatrix4`) - - - Move noboost files away from the public include directory - - Many, many bugfixes and improvements in existing loaders and postprocessing steps - - Documentation improved and clarified in many places. - - Add a sample on using Assimp in conjunction with OpenGL - - - Distribution/packaging: comfortable SDK installer for Windows - - Distribution/packaging: improved release packages for other architectures - -CRITICAL FIXES: - - Resolve problems with clashing heap managers, STL ABIs and runtime libraries (win32) - - Fix automatic detection of file type if no file extension is given - - Improved exception safety and robustness, prevent leaking of exceptions through the C interface - - Fix possible heap corruption due to material properties pulled in incorrectly - - Avoid leaking in certain error scenarios - - Fix 64 bit compatibility problems in some loaders (i.e. MDL) - -BREAKING API CHANGES: - - None - - -MINOR API BEHAVIOUR CHANGES: - - Change quaternion orientation to suit to the more common convention (-w). - - aiString is utf8 now. Not yet consistent, however. +---------------------------------------------------------------------- +CHANGELOG +---------------------------------------------------------------------- +4.0.1 (2017-07-28) + - FIXES/HOUSEKEEPING: + - fix version test. + - Not compiling when using ASSIMP_DOUBLE_PRECISION + - Added support for python3 + - Check if cmake is installed with brew + - Low performance in OptimizeMeshesProcess::ProcessNode with huge numbers of meshes + - Elapsed seconds not shown correctly + - StreamReader: fix out-of-range exception + - PPdPmdParser: fix compilation for clang + + +4.0.0 (2017-07-18) + +FEATURES: + - Double precision support provided ( available via cmake option ) + - QT-Widget based assimp-viewer ( works for windows, linux, osx ) + - Open3DGC codec supported by glFT-importer + - glTF: Read and write transparency values + - Add Triangulate post-processing step to glTF exporters + - Update rapidjson to v1.0.2 + - Added method to append new metadata to structure + - Unittests: intoduce a prototype model differ + - X3D support + - AMF support + - Lugdunum3D support + - Obj-Importer: obj-homogeneous_coords support + - Obj-Importer: new streaming handling + - Added support for 64 bit version header introduced in FbxSdk2016 + - Travis: enable coverall support. + - PyAssimp: New version of the pyASSIMP 3D viewer, with much improved 3D controls + - Morph animation support for collada + - Added support for parameters Ni and Tf in OBJ/MTL file format + - aiScene: add method to add children + - Added new option to IFC importer to control tessellation angle + removed unused IFC option + - aiMetaData: introduce aiMetaData::Dealloc + - Samples: add a DX11 example + - travis ci: test on OXS ( XCode 6.3 ) as well + - travis ci: enable sudo support. + - openddlparser: integrate release v0.4.0 + - aiMetaData: Added support for metadata in assbin format + +FIXES/HOUSEKEEPING: + - Introduce usage of #pragma statement + - Put cmake-scripts into their own folder + - Fix install pathes ( issue 938 ) + - Fix object_compare in blender importer( issue 946 ) + - Fix OSX compilation error + - Fix unzip path when no other version was found ( issue 967 ) + - Set _FILE_OFFSET_BITS=64 for 32-bit linux ( issue 975 ) + - Fix constructor for radjson on OSX + - Use Assimp namespace to fix build for big-endian architectures + - Add -fPIC to C Flags for 64bit linux Shared Object builds + - MDLLoader: fix resource leak. + - MakeVerboseFormat: fix invalid delete statement + - IFC: fix possible use after free access bug + - ComputeUVMappingprocess: add missing initialization for scalar value + - Fix invalid release of mat + mesh + - IrrImporter: Fix release functions + - Split mesh before exporting gltf ( issue 995 ) + - 3MFImporter: add source group for visual studio + - IFC: Switch generated file to 2 files to fix issue related to and ( issue 1084 ) + - OBJParser: set material index when changing current material + - OBJ: check for null mesh before updating material index + - add vertex color export support ( issue 809 ) + - Fix memory leak in Collada importer ( issue 1169 ) + - add stp to the list of supported extensions for step-files ( issue 1183 ) + - fix clang build ( Issue-1169 ) + - fix for FreeBSD + - Import FindPkgMacros to main CMake Configuration + - Extended support for tessellation parameter to more IFC shapes + - defensice handling of utf-8 decode issues ( issue 1211 ) + - Fixed compiler error on clang 4.0 running on OSX + - use test extension for exported test files ( issue 1228 ) + - Set UVW index material properties for OBJ files + - Fixed no member named 'atop' in global namespace issue for Android NDK compilation + - Apply mechanism to decide use for IrrXML external or internal + - Fix static init ordering bug in OpenGEX importer + - GLTF exporter: ensure animation accessors have same count + - GLTF exporter: convert animation time from ticks to seconds + - Add support for reading texture coordinates from PLY meshes with properties named 'texture_u' and 'texture_v' + - Added TokensForSearch in BlenderLoader to allow CanRead return true for in-memory files. + - fix wrong delete ( issue 1266 ) + - OpenGEX: fix invalid handling with color4 token ( issue 1262 ) + - LWOLoader: fix link in loader description + - Fix error when custom CMAKE_C_FLAGS is specified + - Fast-atof: log overflow errors + - Obj-Importer: do not break when detecting an overflow ( issue 1244 ) + - Obj-Importer: fix parsing of multible line data definitions + - Fixed bug where IFC models with multiple IFCSite only loaded 1 site instead of the complete model + - PLYImporter: - optimize memory and speed on ply importer / change parser to use a file stream - manage texture path in ply + import - manage texture coords on faces in ply import - correction on point cloud faces generation + - Utf8: integrate new lib ( issue 1158 ) + - fixed CMAKE_MODULE_PATH overwriting previous values + - OpenGEX: Fixed bug in material color processing ( issue 1271 ) + - SceneCombiner: move header for scenecombiner to public folder. + - GLTF exporter: ensure buffer view byte offsets are correctly aligned + - X3D importer: Added EXPORT and IMPORT to the list of ignored XML tags + - X3D Exporter: fixed missing attributes + - X3D importer: Fixed import of normals for the single index / normal per vertex case + - X3D importer: Fixed handling of inlined files + - X3D importer: fixed whitespace handling (issue 1202) + - X3D importer: Fixed iterator on MSVC 2015 + - X3D importer: Fixed problems with auto, override and regex on older compilers + - X3D importer: Fixed missing header file + - X3D importer: Fixed path handling + - X3D importer: Implemented support for binary X3D files + - fix build without 3DS ( issue 1319 ) + - pyassimp: Fixed indices for IndexedTriangleFanSet, IndexedTriangleSet and IndexedTriangleStripSet + - Fixes parameters to pyassimp.load + - Obj-Importe: Fixed texture bug due simultaneously using 'usemtl' and 'usemap' attributes + - check if all exporters are disabled ( issue 1320 ) + - Remove std functions deprecated by C++11. + - X-Importer: make it deal with lines + - use correct path for compilers ( issue 1335 ) + - Collada: add workaround to deal with polygon with holes + - update python readme + - Use unique node names when loading Collada files + - Fixed many FBX bugs + +API COMPATIBILITY: + - Changed ABI-compatibility to v3.3.1, please rebuild your precompiled libraries ( see issue 1182 ) + - VS2010 outdated + +3.3.1 (2016-07-08) + +FIXES/HOUSEKEEPING: + - Setup of default precision for 17 exporters + - Fix xcode project files + - Fix BlenderTesselator: offsetof operator + - Invalid version in cmake file + - Update pstdint.h to latest greatest + + +3.3.0 (2016-07-05) + +FEATURES: + - C++11 support enabled + - New regression-test-UI + - Experimental glTF-importer support + - OpenGEX: add support for cameras and lights + - C4D: update to latest Melange-SDK + - Add a gitter channel + - Coverity check enabled + - Switch to <...> include brackets for public headers + - Enable export by pyAssimp + - CI: check windows build + - Add functionality to perform a singlepost-processing step + - many more, just check the history + +FIXES/HOUSEKEEPING: + - Fix of many resource leaks in unittests and main lib + - Fix iOS-buildfor X64 + - Choosing zlib manually for cmake + - many more, just check the history + + +3.2.1 (2016-010-10) + +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) + +FEATURES: + - Support for FBX 2013 and newer, binary and ASCII (this is partly + work from Google Summer of Code 2012) + - Support for OGRE binary mesh and skeleton format + - Updated BLEND support for newer Blender versions + - Support for arbitrary meta data, used to hold FBX and DAE metadata + - OBJ Export now produces smaller files + - Meshes can now have names, this is supported by the major importers + - Improved IFC geometry generation + - M3 support has been removed + +FIXES/HOUSEKEEPING: + - Hundreds of bugfixes in all parts of the library + - CMake is now the primary build system + +API COMPATIBILITY: + - 3.1.1 is not binary compatible to 3.0 due to aiNode::mMetaData + and aiMesh::mName + - Export interface has been cleaned up and unified + - Other than that no relevant changes + + +3.0 (2012-07-07) + +FEATURES: + - new export interface similar to the import API. + - Supported export formats: Collada, OBJ, PLY and STL + - added new import formats: XGL/ZGL, M3 (experimental) + - new postprocessing steps: Debone + - vastly improved IFC (Industry Foundation Classes) support + - introduced API to query importer meta information (such as supported + format versions, full name, maintainer info). + - reworked Ogre XML import + - C-API now supports per-import properties + +FIXES/HOUSEKEEPING: + + - hundreds of bugfixes in all parts of the library + - unified naming and cleanup of public headers + - improved CMake build system + - templatized math library + - reduce dependency on boost.thread, only remaining spot + is synchronization for the C logging API + +API COMPATIBILITY: + - renamed headers, export interface, C API properties and meta data + prevent compatibility with code written for 2.0, but in + most cases these can be easily resolved + - Note: 3.0 is not binary compatible with 2.0 + + +2.0 (2010-11-21) + +FEATURES: + - Add support for static Blender (*.blend) scenes + - Add support for Q3BSP scenes + - Add a windows-based OpenGL sample featuring texturing & basic materials + - Add an experimental progress feedback interface. + - Vastly improved performance (up to 500%, depending on mesh size and + spatial structure) in some expensive postprocessing steps + - AssimpView now uses a reworked layout which leaves more space + to the scene hierarchy window + + - Add C# bindings ('Assimp.NET') + - Keep BSD-licensed and otherwise free test files in separate + folders (./test/models and ./test/models-nonbsd). + +FIXES: + - Many Collada bugfixes, improve fault tolerance + - Fix possible crashes in the Obj loader + - Improve the Ogre XML loader + - OpenGL-sample now works with MinGW + - Fix Importer::FindLoader failing on uppercase file extensions + - Fix flawed path handling when locating external files + - Limit the maximum number of vertices, faces, face indices and + weights that Assimp is able to handle. This is to avoid + crashes due to overflowing counters. + + - Updated XCode project files + - Further CMAKE build improvements + + +API CHANGES: + - Add data structures for vertex-based animations (These are not + currently used, however ...) + - Some Assimp::Importer methods are const now. + + +1.1 (2010-04-17) +This is the list of relevant changes from the 1.0 (r412) release to 1.1 (r700). + +FEATURES: + - Vastly improved Collada support + - Add MS3D (Milkshape 3D) support + - Add support for Ogre XML static meshes + - Add experimental COB (TrueSpace) support + - Automatic test suite to quickly locate regressions + - D bindings (`dAssimp`) + - Python 2.n bindings (`PyAssimp`) + - Add basic support for Unicode input files (utf8, utf16 and utf32) + - Add further utilities to the `assimp` tool (xml/binary dumps, quick file stats) + - Switch to a CMAKE-based build system including an install target for unix'es + - Automatic evaluation of subdivision surfaces for some formats. + - Add `Importer::ReadFileFromMemory` and the corresponding C-API `aiReadFileFromMemory` + - Expose further math utilities via the C-API (i.e. `aiMultiplyMatrix4`) + + - Move noboost files away from the public include directory + - Many, many bugfixes and improvements in existing loaders and postprocessing steps + - Documentation improved and clarified in many places. + - Add a sample on using Assimp in conjunction with OpenGL + + - Distribution/packaging: comfortable SDK installer for Windows + - Distribution/packaging: improved release packages for other architectures + +CRITICAL FIXES: + - Resolve problems with clashing heap managers, STL ABIs and runtime libraries (win32) + - Fix automatic detection of file type if no file extension is given + - Improved exception safety and robustness, prevent leaking of exceptions through the C interface + - Fix possible heap corruption due to material properties pulled in incorrectly + - Avoid leaking in certain error scenarios + - Fix 64 bit compatibility problems in some loaders (i.e. MDL) + +BREAKING API CHANGES: + - None - + +MINOR API BEHAVIOUR CHANGES: + - Change quaternion orientation to suit to the more common convention (-w). + - aiString is utf8 now. Not yet consistent, however. diff --git a/CMakeLists.txt b/CMakeLists.txt index a8f3d2488..dd2317cca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,6 @@ # Open Asset Import Library (assimp) # ---------------------------------------------------------------------- -# -# Copyright (c) 2006-2016, assimp team +# Copyright (c) 2006-2017, assimp team # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -33,10 +32,9 @@ # 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 ) +CMAKE_MINIMUM_REQUIRED( VERSION 2.8 ) PROJECT( Assimp ) # All supported options ############################################### @@ -44,6 +42,10 @@ OPTION( BUILD_SHARED_LIBS "Build package with shared libraries." ON ) +OPTION( BUILD_FRAMEWORK + "Build package as Mac OS X Framework bundle." + OFF +) OPTION( ASSIMP_DOUBLE_PRECISION "Set to ON to enable double precision processing" OFF @@ -64,11 +66,11 @@ OPTION( ASSIMP_BUILD_ZLIB "Build your own zlib" OFF ) -option( ASSIMP_BUILD_ASSIMP_TOOLS +OPTION( ASSIMP_BUILD_ASSIMP_TOOLS "If the supplementary tools for Assimp are built in addition to the library." ON ) -option ( ASSIMP_BUILD_SAMPLES +OPTION ( ASSIMP_BUILD_SAMPLES "If the official samples are built as well (needs Glut)." OFF ) @@ -77,34 +79,66 @@ OPTION ( ASSIMP_BUILD_TESTS ON ) OPTION ( ASSIMP_COVERALLS - "Eańable this to measure test coverage." - OFF + "Enable this to measure test coverage." + OFF +) +OPTION ( ASSIMP_WERROR + "Treat warnings as errors." + OFF +) +OPTION ( ASSIMP_ASAN + "Enable AddressSanitizer." + OFF +) +OPTION ( ASSIMP_UBSAN + "Enable Undefined Behavior sanitizer." + OFF +) +OPTION ( SYSTEM_IRRXML + "Use system installed Irrlicht/IrrXML library." + OFF +) +OPTION ( BUILD_DOCS + "Build documentation using Doxygen." + OFF ) +if (WIN32) + ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN ) +endif() + IF(MSVC) - set (CMAKE_PREFIX_PATH "D:\\libs\\devil") + SET (CMAKE_PREFIX_PATH "D:\\libs\\devil") OPTION( ASSIMP_INSTALL_PDB "Install MSVC debug files." ON ) ENDIF(MSVC) +IF (BUILD_FRAMEWORK) + SET (BUILD_SHARED_LIBS ON) + MESSAGE(STATUS "Framework bundle building enabled") +ENDIF(BUILD_FRAMEWORK) + IF(NOT BUILD_SHARED_LIBS) + MESSAGE(STATUS "Shared libraries disabled") SET(LINK_SEARCH_START_STATIC TRUE) +ELSE() + MESSAGE(STATUS "Shared libraries enabled") 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_MAJOR 4) +SET (ASSIMP_VERSION_MINOR 1) +SET (ASSIMP_VERSION_PATCH 0) SET (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}) -SET (ASSIMP_SOVERSION 3) +SET (ASSIMP_SOVERSION 4) SET (PROJECT_VERSION "${ASSIMP_VERSION}") -SET(ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources") +SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" ) # Needed for openddl_parser config, no use of c++11 at this moment -add_definitions( -DOPENDDL_NO_USE_CPP11 ) +ADD_DEFINITIONS( -DOPENDDL_NO_USE_CPP11 ) set_property( GLOBAL PROPERTY CXX_STANDARD 11 ) # Get the current working branch @@ -126,68 +160,103 @@ EXECUTE_PROCESS( ) IF(NOT GIT_COMMIT_HASH) - SET(GIT_COMMIT_HASH 0) + SET(GIT_COMMIT_HASH 0) ENDIF(NOT GIT_COMMIT_HASH) IF(ASSIMP_DOUBLE_PRECISION) - ADD_DEFINITIONS(-DASSIMP_DOUBLE_PRECISION) + ADD_DEFINITIONS(-DASSIMP_DOUBLE_PRECISION) ENDIF(ASSIMP_DOUBLE_PRECISION) -configure_file( +CONFIGURE_FILE( ${CMAKE_CURRENT_LIST_DIR}/revision.h.in ${CMAKE_CURRENT_BINARY_DIR}/revision.h ) -configure_file( +CONFIGURE_FILE( ${CMAKE_CURRENT_LIST_DIR}/include/assimp/config.h.in - ${CMAKE_CURRENT_LIST_DIR}/include/assimp/config.h + ${CMAKE_CURRENT_BINARY_DIR}/include/assimp/config.h ) -include_directories( +INCLUDE_DIRECTORIES( ./ + include ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/include ) -SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" ) +LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" ) 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 ) + # Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit linux + IF( ${OPERATING_SYSTEM} MATCHES "Android") + ELSE() + IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux + #ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 ) + ENDIF() 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() + # Use GNUInstallDirs for Unix predefined directories + INCLUDE(GNUInstallDirs) +ENDIF( UNIX ) + + +# Grouped compiler settings +IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW) # hide all not-exported symbols - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -Wall -std=c++0x" ) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -fPIC -Wall -std=c++0x") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + SET(LIBSTDC++_LIBRARIES -lstdc++) ELSEIF(MSVC) # enable multi-core compilation with MSVC 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" ) + + # disable "elements of array '' will be default initialized" warning on MSVC2013 + IF(MSVC12) + add_compile_options(/wd4351) + ENDIF() +ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" ) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -fPIC -Wall -Wno-long-long -std=c++11" ) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") 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__ ) + SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall -Wno-long-long -std=c++11" ) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + 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") + MESSAGE(STATUS "Coveralls enabled") + 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() -INCLUDE (FindPkgConfig) -INCLUDE_DIRECTORIES( include ) +if (ASSIMP_WERROR) + MESSAGE(STATUS "Treating warnings as errors") + IF (MSVC) + add_compile_options(/WX) + ELSE() + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror") + ENDIF() +endif() +if (ASSIMP_ASAN) + MESSAGE(STATUS "AddressSanitizer enabled") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address") +endif() + +if (ASSIMP_UBSAN) + MESSAGE(STATUS "Undefined Behavior sanitizer enabled") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all") +endif() + +INCLUDE (FindPkgMacros) INCLUDE (PrecompiledHeader) # If this is an in-source build (CMAKE_SOURCE_DIR == CMAKE_BINARY_DIR), @@ -217,20 +286,25 @@ ENDIF() # Only generate this target if no higher-level project already has IF (NOT TARGET uninstall) # add make uninstall capability - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) + CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") ENDIF() # 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-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.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) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT}) FIND_PACKAGE( DirectX ) -IF( CMAKE_COMPILER_IS_GNUCXX ) - SET(LIBSTDC++_LIBRARIES -lstdc++) -ENDIF( CMAKE_COMPILER_IS_GNUCXX ) +IF( BUILD_DOCS ) + add_subdirectory(doc) +ENDIF( BUILD_DOCS ) + +# Look for system installed irrXML +IF ( SYSTEM_IRRXML ) + find_package( IrrXML REQUIRED ) +ENDIF( SYSTEM_IRRXML ) # Search for external dependencies, and build them from source if not found # Search for zlib @@ -240,9 +314,9 @@ ENDIF( NOT ASSIMP_BUILD_ZLIB ) IF( NOT ZLIB_FOUND ) message(STATUS "compiling zlib from souces") - include(CheckIncludeFile) - include(CheckTypeSize) - include(CheckFunctionExists) + INCLUDE(CheckIncludeFile) + INCLUDE(CheckTypeSize) + INCLUDE(CheckFunctionExists) # compile from sources add_subdirectory(contrib/zlib) SET(ZLIB_FOUND 1) @@ -255,9 +329,7 @@ ENDIF(NOT ZLIB_FOUND) INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) # Search for unzip -IF (PKG_CONFIG_FOUND) - PKG_CHECK_MODULES(UNZIP minizip) -ENDIF (PKG_CONFIG_FOUND) +use_pkgconfig(UNZIP minizip) IF ( ASSIMP_NO_EXPORT ) ADD_DEFINITIONS( -DASSIMP_BUILD_NO_EXPORT) @@ -328,6 +400,8 @@ ELSE (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER ) ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) +ADD_SUBDIRECTORY(contrib) + ADD_SUBDIRECTORY( code/ ) IF ( ASSIMP_BUILD_ASSIMP_TOOLS ) IF ( WIN32 AND DirectX_D3DX9_LIBRARY ) @@ -335,7 +409,7 @@ IF ( ASSIMP_BUILD_ASSIMP_TOOLS ) IF ( ASSIMP_BUILD_ASSIMP_VIEW ) ADD_SUBDIRECTORY( tools/assimp_view/ ) ENDIF ( ASSIMP_BUILD_ASSIMP_VIEW ) - ENDIF ( WIN32 ) + ENDIF ( WIN32 AND DirectX_D3DX9_LIBRARY ) ADD_SUBDIRECTORY( tools/assimp_cmd/ ) @@ -431,29 +505,41 @@ IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES) 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 (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) + 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) + if(MSVC12 OR MSVC14) + add_custom_target(UpdateAssimpLibsDebugSymbolsAndDLLs COMMENT "Copying Assimp Libraries ..." VERBATIM) + IF(CMAKE_GENERATOR MATCHES "^Visual Studio") + 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) + ELSE() + ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/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/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/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/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/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/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/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/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM) + ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb ${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM) + ENDIF() + ENDIF(MSVC12 OR MSVC14) ENDIF (WIN32) diff --git a/CREDITS b/CREDITS index 1cfe4f640..df41c482d 100644 --- a/CREDITS +++ b/CREDITS @@ -1,160 +1,168 @@ -=============================================================== -Open Asset Import Library (Assimp) -Developers and Contributors -=============================================================== - -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. - -- 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 (Design). - -- Thomas Schulze, -X-, Collada-, BVH-Loader, Postprocessing framework. Data structure & Interface design, documentation. - -- Kim Kulling, -Obj-, Q3BSD-, OpenGEX-Loader, Logging system, CMake-build-environment, Linux-build, Website ( Admin ), Coverity ( Admin ), Glitter ( Admin ). - -- R.Schmidt, -Linux build, eclipse support. - -- Matthias Gubisch, -Assimp.net -Visual Studio 9 support, bugfixes. - -- Mark Sibly -B3D-Loader, Assimp testing - -- Jonathan Klein -Ogre Loader, VC2010 fixes and CMake fixes. - -- Sebastian Hempel, -PyAssimp (first version) -Compile-Bugfixes for mingw, add environment for static library support in make. - -- Jonathan Pokrass -Supplied a bugfix concerning the scaling in the md3 loader. - -- Andrew Galante, -Submitted patches to make Assimp compile with GCC-4, a makefile and the xcode3 workspace. - -- Andreas Nagel -First Assimp testing & verification under Windows Vista 64 Bit. - -- Marius Schr�der -Allowed us to use many of his models for screenshots and testing. - -- Christian Schubert -Supplied various XFiles for testing purposes. - -- Tizian Wieland -Searched the web for hundreds of test models for internal use - -- John Connors -Supplied patches for linux and SCons. - -- T. R. -The GUY who performed some of the CSM mocaps. - -- Andy Maloney -Contributed fixes for the documentation and the doxygen markup - -- Zhao Lei -Contributed several bugfixes fixing memory leaks and improving float parsing - -- sueastside -Updated PyAssimp to the latest Assimp data structures and provided a script to keep the Python binding up-to-date. - -- Tobias Rittig -Collada testing with Cinema 4D - -- Brad Grantham -Improvements in OpenGL-Sample. - -- Robert Ramirez -Add group loading feature to Obj-Loader. - -- Chris Maiwald -Many bugreports, improving Assimp's portability, regular testing & feedback. - -- Stepan Hrbek -Bugreport and fix for a obj-materialloader crash. - -- David Nadlinger -D bindings, CMake install support. - -- Dario Accornero -Contributed several patches regarding Mac OS/XCode targets, bug reports. - -- Martin Walser (Samhayne) -Contributed the 'SimpleTexturedOpenGl' sample. - -- Matthias Fauconneau -Contributed a fix for the Q3-BSP loader. - -- J�rgen P. Tjern� -Contributed updated and improved xcode workspaces - -- drparallax -Contributed the /samples/SimpleAssimpViewX sample - -- Carsten Fuchs -Contributed a fix for the Normalize method in aiQuaternion. - -- dbburgess -Contributes a Android-specific build issue: log the hardware architecture for ARM. - -- alfiereinre7 -Contributes a obj-fileparser fix: missing tokens in the obj-token list. - -- Roman Kharitonov -Contributes a fix for the configure script environment. - -- Ed Diana -Contributed AssimpDelphi (/port/AssimpDelphi). - -- rdb -Contributes a bundle of fixes and improvements for the bsp-importer. - -- Mick P -For contributing the De-bone postprocessing step and filing various bug reports. - -- Rosen Diankov -Contributed patches to build assimp debian packages using cmake. - -- Mark Page -Contributed a patch to fix the VertexTriangleAdjacency postprocessing step. - -- IOhannes -Contributed the Debian build fixes ( architecture macro ). - -- gellule -Several LWO and LWS fixes (pivoting). - -- Marcel Metz -GCC/Linux fixes for the SimpleOpenGL sample. - -- Brian Miller -Bugfix for a compiler fix for iOS on arm. - -- S�verin Lemaignan -Rewrite of PyAssimp, distutils and Python3 support - -- albert-wang -Bugfixes for the collada parser - -- Ya ping Jin -Bugfixes for uv-tanget calculation. - -- Jonne Nauha -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 - - +=============================================================== +Open Asset Import Library (Assimp) +Developers and Contributors +=============================================================== + +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. + +- 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 (Design). + +- Thomas Schulze, +X-, Collada-, BVH-Loader, Postprocessing framework. Data structure & Interface design, documentation. + +- Kim Kulling, +Obj-, Q3BSD-, OpenGEX-Loader, Logging system, CMake-build-environment, Linux-build, Website ( Admin ), Coverity ( Admin ), Glitter ( Admin ). + +- R.Schmidt, +Linux build, eclipse support. + +- Matthias Gubisch, +Assimp.net +Visual Studio 9 support, bugfixes. + +- Mark Sibly +B3D-Loader, Assimp testing + +- Jonathan Klein +Ogre Loader, VC2010 fixes and CMake fixes. + +- Sebastian Hempel, +PyAssimp (first version) +Compile-Bugfixes for mingw, add environment for static library support in make. + +- Jonathan Pokrass +Supplied a bugfix concerning the scaling in the md3 loader. + +- Andrew Galante, +Submitted patches to make Assimp compile with GCC-4, a makefile and the xcode3 workspace. + +- Andreas Nagel +First Assimp testing & verification under Windows Vista 64 Bit. + +- Marius Schr�der +Allowed us to use many of his models for screenshots and testing. + +- Christian Schubert +Supplied various XFiles for testing purposes. + +- Tizian Wieland +Searched the web for hundreds of test models for internal use + +- John Connors +Supplied patches for linux and SCons. + +- T. R. +The GUY who performed some of the CSM mocaps. + +- Andy Maloney +Contributed fixes for the documentation and the doxygen markup + +- Zhao Lei +Contributed several bugfixes fixing memory leaks and improving float parsing + +- sueastside +Updated PyAssimp to the latest Assimp data structures and provided a script to keep the Python binding up-to-date. + +- Tobias Rittig +Collada testing with Cinema 4D + +- Brad Grantham +Improvements in OpenGL-Sample. + +- Robert Ramirez +Add group loading feature to Obj-Loader. + +- Chris Maiwald +Many bugreports, improving Assimp's portability, regular testing & feedback. + +- Stepan Hrbek +Bugreport and fix for a obj-materialloader crash. + +- David Nadlinger +D bindings, CMake install support. + +- Dario Accornero +Contributed several patches regarding Mac OS/XCode targets, bug reports. + +- Martin Walser (Samhayne) +Contributed the 'SimpleTexturedOpenGl' sample. + +- Matthias Fauconneau +Contributed a fix for the Q3-BSP loader. + +- Jørgen P. Tjernø +Contributed updated and improved xcode workspaces + +- drparallax +Contributed the /samples/SimpleAssimpViewX sample + +- Carsten Fuchs +Contributed a fix for the Normalize method in aiQuaternion. + +- dbburgess +Contributes a Android-specific build issue: log the hardware architecture for ARM. + +- alfiereinre7 +Contributes a obj-fileparser fix: missing tokens in the obj-token list. + +- Roman Kharitonov +Contributes a fix for the configure script environment. + +- Ed Diana +Contributed AssimpDelphi (/port/AssimpDelphi). + +- rdb +Contributes a bundle of fixes and improvements for the bsp-importer. + +- Mick P +For contributing the De-bone postprocessing step and filing various bug reports. + +- Rosen Diankov +Contributed patches to build assimp debian packages using cmake. + +- Mark Page +Contributed a patch to fix the VertexTriangleAdjacency postprocessing step. + +- IOhannes +Contributed the Debian build fixes ( architecture macro ). + +- gellule +Several LWO and LWS fixes (pivoting). + +- Marcel Metz +GCC/Linux fixes for the SimpleOpenGL sample. + +- Brian Miller +Bugfix for a compiler fix for iOS on arm. + +- Séverin Lemaignan +Rewrite of PyAssimp, distutils and Python3 support + +- albert-wang +Bugfixes for the collada parser + +- Ya ping Jin +Bugfixes for uv-tanget calculation. + +- Jonne Nauha +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 + +For a more detailed list just check: https://github.com/assimp/assimp/network/members + +Patreons: +- migenius +- Marcus +- Cort +- elect +- Steffen + diff --git a/LICENSE b/LICENSE index c8e47b34a..262606aff 100644 --- a/LICENSE +++ b/LICENSE @@ -1,78 +1,78 @@ -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. - - - -****************************************************************************** - -AN EXCEPTION applies to all files in the ./test/models-nonbsd folder. -These are 3d models for testing purposes, from various free sources -on the internet. They are - unless otherwise stated - copyright of -their respective creators, which may impose additional requirements -on the use of their work. For any of these models, see -.source.txt for more legal information. Contact us if you -are a copyright holder and believe that we credited you inproperly or -if you don't want your files to appear in the repository. - - -****************************************************************************** - -Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors -http://code.google.com/p/poly2tri/ - -All rights reserved. -Redistribution and use 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 Poly2Tri nor the names of its contributors may be - used to endorse or promote products derived from this software without specific - prior written permission. - -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. +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. + + + +****************************************************************************** + +AN EXCEPTION applies to all files in the ./test/models-nonbsd folder. +These are 3d models for testing purposes, from various free sources +on the internet. They are - unless otherwise stated - copyright of +their respective creators, which may impose additional requirements +on the use of their work. For any of these models, see +.source.txt for more legal information. Contact us if you +are a copyright holder and believe that we credited you inproperly or +if you don't want your files to appear in the repository. + + +****************************************************************************** + +Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors +http://code.google.com/p/poly2tri/ + +All rights reserved. +Redistribution and use 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 Poly2Tri nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +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. diff --git a/Readme.md b/Readme.md index 3f57060ad..1f6c4118f 100644 --- a/Readme.md +++ b/Readme.md @@ -1,140 +1,170 @@ -Open Asset Import Library (assimp) -================================== - -[![Linux Build Status](https://travis-ci.org/assimp/assimp.png)](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) - - Coverity Scan Build Status - -[![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master) -
- -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. - -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)
-__[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.__ - -#### Supported file formats #### - -A full list [is here](http://assimp.sourceforge.net/main_features_formats.html). -__Importers__: - -- 3DS -- BLEND (Blender) -- DAE/Collada -- FBX -- IFC-STEP -- ASE -- DXF -- HMP -- MD2 -- MD3 -- MD5 -- MDC -- MDL -- NFF -- PLY -- STL -- X -- OBJ -- OpenGEX -- SMD -- LWO -- LXO -- LWS -- TER -- AC3D -- MS3D -- COB -- Q3BSP -- XGL -- CSM -- BVH -- B3D -- NDO -- Ogre Binary -- Ogre XML -- Q3D -- ASSBIN (Assimp custom format) -- glTF (partial) -- 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) - -__Exporters__: - -- DAE (Collada) -- STL -- OBJ -- PLY -- X -- 3DS -- JSON (for WebGl, via https://github.com/acgessler/assimp2json) -- ASSBIN -- STEP -- 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) - -#### Repository structure #### -Open Asset Import Library is implemented in C++. The directory structure is: - - /code Source code - /contrib Third-party libraries - /doc Documentation (doxysource and pre-compiled docs) - /include Public header C and C++ header files - /scripts Scripts used to generate the loading code for some formats - /port Ports to other languages and scripts to maintain those. - /test Unit- and regression tests, test suite of models - /tools Tools (old assimp viewer, command line `assimp`) - /samples A small number of samples to illustrate possible - use cases for Assimp - /workspaces Build environments for vc,xcode,... (deprecated, - CMake has superseeded all legacy build options!) - - -### Where to get help ### -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). - -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. - -For development discussions, there is also a (very low-volume) mailing list, _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)
- -### Contributing ### -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. - -### Donate ### -If you like assimp, consider buying us a beer (or two): -[Donate](http://sourceforge.net/donate/index.php?group_id=226462) - -### License ### -Our license is based on the modified, __3-clause BSD__-License. - -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. -For the legal details, see the `LICENSE` file. - -### Why this name ### -Sorry, we're germans :-), no english native speakers ... +Open Asset Import Library (assimp) +================================== +A library to import and export various 3d-model-formats including scene-post-processing to generate missing render data. +### Current build status ### +[![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) + + Coverity Scan Build Status + +[![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master) +[![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) +
+ +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. + +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 repo containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [Github Assimp Releases](https://github.com/assimp/assimp/releases). + +Monthly donations via Patreon: +
[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/assimp) + +
+ +One-off donations via PayPal: +
[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4) + +
+ +Please check our Wiki as well: https://github.com/assimp/assimp/wiki + +#### Supported file formats #### + +A full list [is here](http://assimp.org/main_features_formats.html). +__Importers__: +- 3D +- 3DS +- 3MF +- AC +- AC3D +- ACC +- AMJ +- ASE +- ASK +- B3D; +- BLEND (Blender) +- BVH +- COB +- CMS +- DAE/Collada +- DXF +- ENFF +- FBX +- glTF 1.0 + GLB +- glTF 2.0 +- HMB +- IFC-STEP +- IRR / IRRMESH +- LWO +- LWS +- LXO +- MD2 +- MD3 +- MD5 +- MDC +- MDL +- MESH / MESH.XML +- MOT +- MS3D +- NDO +- NFF +- OBJ +- OFF +- OGEX +- PLY +- PMX +- PRJ +- Q3O +- Q3S +- RAW +- SCN +- SIB +- SMD +- STL +- STP +- TER +- UC +- VTA +- X +- X3D +- XGL +- ZGL + +Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default): + +- C4D (https://github.com/assimp/assimp/wiki/Cinema4D-&-Melange) + +__Exporters__: + +- DAE (Collada) +- STL +- OBJ +- PLY +- X +- 3DS +- JSON (for WebGl, via https://github.com/acgessler/assimp2json) +- ASSBIN +- STEP +- glTF 1.0 (partial) +- glTF 2.0 (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) +* [Unity 3d Plugin](https://www.assetstore.unity3d.com/en/#!/content/91777) +* [JVM](https://github.com/kotlin-graphics/assimp) Full jvm port (currently supported obj, ply, stl, collada, md2) + +### Other tools ### +[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities. + +#### Repository structure #### +Open Asset Import Library is implemented in C++. The directory structure is: + + /code Source code + /contrib Third-party libraries + /doc Documentation (doxysource and pre-compiled docs) + /include Public header C and C++ header files + /scripts Scripts used to generate the loading code for some formats + /port Ports to other languages and scripts to maintain those. + /test Unit- and regression tests, test suite of models + /tools Tools (old assimp viewer, command line `assimp`) + /samples A small number of samples to illustrate possible + use cases for Assimp + /workspaces Build environments for vc,xcode,... (deprecated, + CMake has superseeded all legacy build options!) + + +### 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. +(CHMs for Windows are included in some release packages and should be located right here in the root folder). + +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. + +For development discussions, there is also a (very low-volume) mailing list, _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)
+ +### Contributing ### +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. + +### License ### +Our license is based on the modified, __3-clause BSD__-License. + +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. +For the legal details, see the `LICENSE` file. + +### Why this name ### +Sorry, we're germans :-), no english native speakers ... diff --git a/appveyor.yml b/appveyor.yml index 991cf5bc1..1b87286f6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -10,33 +10,54 @@ branches: only: - master +matrix: + fast_finish: true + +image: + - Visual Studio 2013 + - Visual Studio 2015 + - Visual Studio 2017 + 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 ) ) ) + - Win32 + - x64 + +configuration: Release 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) - + - set PATH=C:\Ruby24-x64\bin;%PATH% + - set CMAKE_DEFINES -DASSIMP_WERROR=ON + - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2013" set CMAKE_GENERATOR_NAME=Visual Studio 12 2013 + - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015 + - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017 + - if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64 + - cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%" + +cache: + - code\assimp.dir\%CONFIGURATION% + - contrib\zlib\zlibstatic.dir\%CONFIGURATION% + - contrib\zlib\zlib.dir\%CONFIGURATION% + - tools\assimp_cmd\assimp_cmd.dir\%CONFIGURATION% + - tools\assimp_view\assimp_viewer.dir\%CONFIGURATION% + - test\unit.dir\%CONFIGURATION% + - bin\.mtime_cache + +before_build: + - ruby scripts\AppVeyor\mtime_cache -g scripts\AppVeyor\cacheglobs.txt -c bin\.mtime_cache\cache.json + +build: + parallel: true + project: Assimp.sln + after_build: - - 7z a assimp.7z c:\projects\assimp\bin\release\* c:\projects\assimp\lib\release\* + - 7z a assimp.7z bin\%CONFIGURATION%\* lib\%CONFIGURATION%\* +test_script: + - cmd: bin\%CONFIGURATION%\unit.exe --gtest_output=xml:testout.xml + +on_finish: + - ps: (new-object net.webclient).UploadFile("https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\testout.xml)) + artifacts: - path: assimp.7z name: assimp_lib diff --git a/assimp-config-version.cmake.in b/assimp-config-version.cmake.in index ff48b4822..923a38798 100644 --- a/assimp-config-version.cmake.in +++ b/assimp-config-version.cmake.in @@ -1,8 +1,43 @@ +# Open Asset Import Library (assimp) +# ---------------------------------------------------------------------- +# Copyright (c) 2006-2017, 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( PACKAGE_VERSION "@ASSIMP_VERSION@" ) if( "${PACKAGE_FIND_VERSION}" VERSION_EQUAL "@ASSIMP_VERSION@") set(PACKAGE_VERSION_EXACT 1) endif() -if( "${PACKAGE_FIND_VERSION_MAJOR}.${PACKAGE_FIND_VERSION_MINOR}" EQUAL "@ASSIMP_SOVERSION@" ) +if( "${PACKAGE_FIND_VERSION_MAJOR}.${PACKAGE_FIND_VERSION_MINOR}" EQUAL "@ASSIMP_VERSION@" ) set(PACKAGE_VERSION_COMPATIBLE 1) elseif( "${PACKAGE_FIND_VERSION_MAJOR}" EQUAL "@ASSIMP_VERSION_MAJOR@" ) # for now backward compatible if minor version is less diff --git a/assimp.pc.in b/assimp.pc.in index 5b2139e6d..02cf59dc4 100644 --- a/assimp.pc.in +++ b/assimp.pc.in @@ -1,7 +1,7 @@ prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@CMAKE_INSTALL_PREFIX@/ 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@ Name: @CMAKE_PROJECT_NAME@ Description: Import various well-known 3D model formats in an uniform manner. diff --git a/cmake-modules/CoverallsGenerateGcov.cmake b/cmake-modules/CoverallsGenerateGcov.cmake index ba506e3d4..104737164 100644 --- a/cmake-modules/CoverallsGenerateGcov.cmake +++ b/cmake-modules/CoverallsGenerateGcov.cmake @@ -310,7 +310,7 @@ foreach (GCOV_FILE ${GCOV_FILES}) 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 _ + # (We first open the file and replace all occurrences 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 @@ -329,7 +329,7 @@ foreach (GCOV_FILE ${GCOV_FILES}) # 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). + # which also happens to be the same as the CMake list delimiter). file(READ ${GCOV_SRC_PATH} GCOV_FILE_SOURCE) string(REPLACE "\\" "\\\\" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}") diff --git a/cmake-modules/FindDevIL.cmake b/cmake-modules/FindDevIL.cmake new file mode 100644 index 000000000..381a75dd2 --- /dev/null +++ b/cmake-modules/FindDevIL.cmake @@ -0,0 +1,72 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#.rst: +# FindDevIL +# --------- +# +# +# +# This module locates the developer's image library. +# http://openil.sourceforge.net/ +# +# This module sets: +# +# :: +# +# IL_LIBRARIES - the name of the IL library. These include the full path to +# the core DevIL library. This one has to be linked into the +# application. +# ILU_LIBRARIES - the name of the ILU library. Again, the full path. This +# library is for filters and effects, not actual loading. It +# doesn't have to be linked if the functionality it provides +# is not used. +# ILUT_LIBRARIES - the name of the ILUT library. Full path. This part of the +# library interfaces with OpenGL. It is not strictly needed +# in applications. +# IL_INCLUDE_DIR - where to find the il.h, ilu.h and ilut.h files. +# IL_FOUND - this is set to TRUE if all the above variables were set. +# This will be set to false if ILU or ILUT are not found, +# even if they are not needed. In most systems, if one +# library is found all the others are as well. That's the +# way the DevIL developers release it. + +# TODO: Add version support. +# Tested under Linux and Windows (MSVC) + +#include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) +include(FindPackageHandleStandardArgs) + +find_path(IL_INCLUDE_DIR il.h + PATH_SUFFIXES include IL + DOC "The path to the directory that contains il.h" +) + +#message("IL_INCLUDE_DIR is ${IL_INCLUDE_DIR}") + +find_library(IL_LIBRARIES + NAMES IL DEVIL + PATH_SUFFIXES lib64 lib lib32 + DOC "The file that corresponds to the base il library." +) + +#message("IL_LIBRARIES is ${IL_LIBRARIES}") + +find_library(ILUT_LIBRARIES + NAMES ILUT + PATH_SUFFIXES lib64 lib lib32 + DOC "The file that corresponds to the il (system?) utility library." +) + +#message("ILUT_LIBRARIES is ${ILUT_LIBRARIES}") + +find_library(ILU_LIBRARIES + NAMES ILU + PATH_SUFFIXES lib64 lib lib32 + DOC "The file that corresponds to the il utility library." +) + +#message("ILU_LIBRARIES is ${ILU_LIBRARIES}") + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(IL DEFAULT_MSG + IL_LIBRARIES IL_INCLUDE_DIR) diff --git a/cmake-modules/FindIrrXML.cmake b/cmake-modules/FindIrrXML.cmake new file mode 100644 index 000000000..5434e0b86 --- /dev/null +++ b/cmake-modules/FindIrrXML.cmake @@ -0,0 +1,17 @@ +# Find IrrXMl from irrlicht project +# +# Find LibIrrXML headers and library +# +# IRRXML_FOUND - IrrXML found +# IRRXML_INCLUDE_DIR - Headers location +# IRRXML_LIBRARY - IrrXML main library + +find_path(IRRXML_INCLUDE_DIR irrXML.h + PATH_SUFFIXES include/irrlicht include/irrxml) +find_library(IRRXML_LIBRARY IrrXML) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(IrrXML REQUIRED_VARS IRRXML_INCLUDE_DIR IRRXML_LIBRARY) + + +mark_as_advanced(IRRXML_INCLUDE_DIR IRRXML_LIBRARY) diff --git a/cmake-modules/FindPkgMacros.cmake b/cmake-modules/FindPkgMacros.cmake index e67d8dc62..074cce352 100644 --- a/cmake-modules/FindPkgMacros.cmake +++ b/cmake-modules/FindPkgMacros.cmake @@ -59,10 +59,13 @@ endmacro(clear_if_changed) # Try to get some hints from pkg-config, if available macro(use_pkgconfig PREFIX PKGNAME) - find_package(PkgConfig) - if (PKG_CONFIG_FOUND) - pkg_check_modules(${PREFIX} ${PKGNAME}) - endif () + # Android does not support PKG_CONFIG so we disable it + IF ( NOT ANDROID ) + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(${PREFIX} ${PKGNAME}) + endif () + ENDIF ( NOT ANDROID ) endmacro (use_pkgconfig) # Couple a set of release AND debug libraries (or frameworks) diff --git a/cmake-modules/FindZLIB.cmake b/cmake-modules/FindZLIB.cmake index f6806b4ee..95eb51547 100644 --- a/cmake-modules/FindZLIB.cmake +++ b/cmake-modules/FindZLIB.cmake @@ -11,7 +11,7 @@ # Once done, this will define # # 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 include(FindPkgMacros) diff --git a/code/3DSConverter.cpp b/code/3DSConverter.cpp index 8390dd216..820c28f90 100644 --- a/code/3DSConverter.cpp +++ b/code/3DSConverter.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -55,18 +56,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; +static const unsigned int NotSet = 0xcdcdcdcd; + // ------------------------------------------------------------------------------------------------ // Setup final material indices, generae a default material if necessary void Discreet3DSImporter::ReplaceDefaultMaterial() { - // Try to find an existing material that matches the // typical default material setting: // - no textures // - diffuse color (in grey!) // NOTE: This is here to workaround the fact that some // exporters are writing a default material, too. - unsigned int idx = 0xcdcdcdcd; + unsigned int idx( NotSet ); for (unsigned int i = 0; i < mScene->mMaterials.size();++i) { std::string s = mScene->mMaterials[i].mName; @@ -92,7 +94,9 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() } idx = i; } - if (0xcdcdcdcd == idx)idx = (unsigned int)mScene->mMaterials.size(); + if ( NotSet == idx ) { + idx = ( unsigned int )mScene->mMaterials.size(); + } // now iterate through all meshes and through all faces and // find all faces that are using the default material diff --git a/code/3DSExporter.cpp b/code/3DSExporter.cpp index 1d49a536b..2f561fcd6 100644 --- a/code/3DSExporter.cpp +++ b/code/3DSExporter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -38,14 +39,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ - #ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_3DS_EXPORTER #include "3DSExporter.h" #include "3DSLoader.h" #include "3DSHelper.h" -#include "SceneCombiner.h" +#include #include "SplitLargeMeshes.h" #include "StringComparison.h" #include @@ -150,7 +150,7 @@ namespace { // ------------------------------------------------------------------------------------------------ // Worker function for exporting a scene to 3DS. Prototyped and registered in Exporter.cpp -void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) +void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { std::shared_ptr outfile (pIOSystem->Open(pFile, "wb")); if(!outfile) { @@ -209,6 +209,12 @@ Discreet3DSExporter:: Discreet3DSExporter(std::shared_ptr outfile, con } } +// ------------------------------------------------------------------------------------------------ +Discreet3DSExporter::~Discreet3DSExporter() { + // empty +} + + // ------------------------------------------------------------------------------------------------ int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling_level) { diff --git a/code/3DSExporter.h b/code/3DSExporter.h index 4d9b39d53..fc02e2390 100644 --- a/code/3DSExporter.h +++ b/code/3DSExporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -48,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "StreamWriter.h" -#include "./../include/assimp/material.h" +#include struct aiScene; struct aiNode; @@ -59,23 +60,21 @@ namespace Assimp { // ------------------------------------------------------------------------------------------------ -/** Helper class to export a given scene to a 3DS file. */ +/** + * @brief Helper class to export a given scene to a 3DS file. + */ // ------------------------------------------------------------------------------------------------ -class Discreet3DSExporter -{ +class Discreet3DSExporter { public: Discreet3DSExporter(std::shared_ptr outfile, const aiScene* pScene); + ~Discreet3DSExporter(); private: - void WriteMeshes(); void WriteMaterials(); void WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags); - void WriteFaceMaterialChunk(const aiMesh& mesh); - int WriteHierarchy(const aiNode& node, int level, int sibling_level); - void WriteString(const std::string& s); void WriteString(const aiString& s); void WriteColor(const aiColor3D& color); @@ -83,7 +82,6 @@ private: void WritePercentChunk(double f); private: - const aiScene* const scene; StreamWriterLE writer; @@ -94,6 +92,6 @@ private: }; -} +} // Namespace Assimp -#endif +#endif // AI_3DSEXPORTER_H_INC diff --git a/code/3DSHelper.h b/code/3DSHelper.h index 7a2ad3f8a..9e701c3dd 100644 --- a/code/3DSHelper.h +++ b/code/3DSHelper.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -43,15 +44,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_3DSFILEHELPER_H_INC #define AI_3DSFILEHELPER_H_INC - #include "SpatialSort.h" #include "SmoothingGroups.h" #include "StringUtils.h" #include "qnan.h" -#include "./../include/assimp/material.h" -#include "./../include/assimp/camera.h" -#include "./../include/assimp/light.h" -#include "./../include/assimp/anim.h" +#include +#include +#include +#include #include //sprintf namespace Assimp { @@ -63,16 +63,19 @@ namespace D3DS { /** Discreet3DS class: Helper class for loading 3ds files. Defines chunks * and data structures. */ -class Discreet3DS -{ +class Discreet3DS { private: - inline Discreet3DS() {} + Discreet3DS() { + // empty + } + + ~Discreet3DS() { + // empty + } public: - //! data structure for a single chunk in a .3ds file - struct Chunk - { + struct Chunk { uint16_t Flag; uint32_t Size; } PACK_STRUCT; diff --git a/code/3DSLoader.cpp b/code/3DSLoader.cpp index b19d37f4c..704884a57 100644 --- a/code/3DSLoader.cpp +++ b/code/3DSLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -54,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include "StringComparison.h" using namespace Assimp; @@ -1379,7 +1381,7 @@ void Discreet3DSImporter::ParseColorChunk( aiColor3D* out, bool acceptPercent ) bGamma = true; case Discreet3DS::CHUNK_RGBF: - if (sizeof(ai_real) * 3 > diff) { + if (sizeof(float) * 3 > diff) { *out = clrError; return; } diff --git a/code/3DSLoader.h b/code/3DSLoader.h index 26b2a935e..0e377180b 100644 --- a/code/3DSLoader.h +++ b/code/3DSLoader.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/3MFXmlTags.h b/code/3MFXmlTags.h new file mode 100644 index 000000000..7e47422f1 --- /dev/null +++ b/code/3MFXmlTags.h @@ -0,0 +1,89 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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. + +---------------------------------------------------------------------- +*/ +#pragma once + +namespace Assimp { +namespace D3MF { + +namespace XmlTag { + static const std::string model = "model"; + static const std::string model_unit = "unit"; + static const std::string metadata = "metadata"; + static const std::string resources = "resources"; + static const std::string object = "object"; + static const std::string mesh = "mesh"; + static const std::string vertices = "vertices"; + static const std::string vertex = "vertex"; + static const std::string triangles = "triangles"; + static const std::string triangle = "triangle"; + static const std::string x = "x"; + static const std::string y = "y"; + static const std::string z = "z"; + static const std::string v1 = "v1"; + static const std::string v2 = "v2"; + static const std::string v3 = "v3"; + static const std::string id = "id"; + static const std::string name = "name"; + static const std::string type = "type"; + static const std::string build = "build"; + static const std::string item = "item"; + static const std::string objectid = "objectid"; + static const std::string transform = "transform"; + + static const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml"; + static const std::string ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels"; + static const std::string SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types"; + static const std::string SCHEMA_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships"; + static const std::string RELS_RELATIONSHIP_CONTAINER = "Relationships"; + static const std::string RELS_RELATIONSHIP_NODE = "Relationship"; + static const std::string RELS_ATTRIB_TARGET = "Target"; + static const std::string RELS_ATTRIB_TYPE = "Type"; + static const std::string RELS_ATTRIB_ID = "Id"; + static const std::string PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel"; + static const std::string PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket"; + static const std::string PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture"; + static const std::string PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; + static const std::string PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; + +} + +} // Namespace D3MF +} // Namespace Assimp diff --git a/code/ACLoader.cpp b/code/ACLoader.cpp index c040d6bbd..a30baa75a 100644 --- a/code/ACLoader.cpp +++ b/code/ACLoader.cpp @@ -4,7 +4,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -60,6 +61,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include using namespace Assimp; diff --git a/code/ACLoader.h b/code/ACLoader.h index 52563adad..4b202b77a 100644 --- a/code/ACLoader.h +++ b/code/ACLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/AMFImporter.cpp b/code/AMFImporter.cpp index 62cbbf6c5..e9211fe53 100644 --- a/code/AMFImporter.cpp +++ b/code/AMFImporter.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -51,11 +52,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AMFImporter_Macro.hpp" #include "fast_atof.h" -#include "DefaultIOSystem.h" +#include // Header files, stdlib. #include -#include namespace Assimp { @@ -353,7 +353,7 @@ static bool ParseHelper_Decode_Base64_IsBase64(const char pChar) void AMFImporter::ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector& pOutputData) const { // With help from - // RenИ Nyffenegger http://www.adp-gmbh.ch/cpp/common/base64.html + // René Nyffenegger http://www.adp-gmbh.ch/cpp/common/base64.html const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; uint8_t tidx = 0; diff --git a/code/AMFImporter.hpp b/code/AMFImporter.hpp index 64f9e6230..47ddc073b 100644 --- a/code/AMFImporter.hpp +++ b/code/AMFImporter.hpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -52,9 +53,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AMFImporter_Node.hpp" // Header files, Assimp. -#include "assimp/DefaultLogger.hpp" -#include "assimp/importerdesc.h" -#include "assimp/ProgressHandler.hpp" +#include +#include #include "assimp/types.h" #include "BaseImporter.h" #include "irrXMLWrapper.h" @@ -135,18 +135,18 @@ private: }; /// \struct SPP_Texture - /// Data type for postprocessing step. More suitable container for 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; - decltype(aiTexture::achFormatHint) FormatHint; - uint8_t* Data; + size_t Width, Height, Depth; + bool Tiled; + char FormatHint[ 9 ];// 8 for string + 1 for terminator. + uint8_t *Data; }; /// \struct SComplexFace - /// Data type for postprocessing step. Contain face data. + /// Data type for post-processing step. Contain face data. struct SComplexFace { aiFace Face;///< Face vertices. @@ -249,7 +249,7 @@ private: /// \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 + /// converted texture will be returned. Conversion: 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. @@ -378,7 +378,7 @@ private: void XML_CheckNode_MustHaveChildren(); /// \fn bool XML_CheckNode_NameEqual(const std::string& pNodeName) - /// Chek if current node name is equal to pNodeName. + /// Check 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; } diff --git a/code/AMFImporter_Geometry.cpp b/code/AMFImporter_Geometry.cpp index 493d06bff..afba3f2bc 100644 --- a/code/AMFImporter_Geometry.cpp +++ b/code/AMFImporter_Geometry.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/AMFImporter_Macro.hpp b/code/AMFImporter_Macro.hpp index 973e17490..b7c0f9863 100644 --- a/code/AMFImporter_Macro.hpp +++ b/code/AMFImporter_Macro.hpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/AMFImporter_Material.cpp b/code/AMFImporter_Material.cpp index 4550f6fe2..d15099fac 100644 --- a/code/AMFImporter_Material.cpp +++ b/code/AMFImporter_Material.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/AMFImporter_Node.hpp b/code/AMFImporter_Node.hpp index f8c3a7933..522e6ccca 100644 --- a/code/AMFImporter_Node.hpp +++ b/code/AMFImporter_Node.hpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -59,18 +60,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /// \class CAMFImporter_NodeElement /// Base class for elements of nodes. -class CAMFImporter_NodeElement -{ - /***********************************************/ - /******************** Types ********************/ - /***********************************************/ +class CAMFImporter_NodeElement { public: - - /// \enum EType /// Define what data type contain node element. - enum EType - { + enum EType { ENET_Color, ///< Color element: . ENET_Constellation,///< Grouping element: . ENET_Coordinates, ///< Coordinates element: . @@ -91,52 +85,37 @@ public: 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. + CAMFImporter_NodeElement* Parent;///< Parent element. If nullptr then this node is root. std::list Child;///< Child elements. - /***********************************************/ - /****************** Functions ******************/ - /***********************************************/ +public: /// Destructor, virtual.. + virtual ~CAMFImporter_NodeElement() { + // empty + } 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) - {} - + : Type(pType) + , ID() + , Parent(pParent) + , Child() { + // empty + } };// class IAMFImporter_NodeElement /// \struct CAMFImporter_NodeElement_Constellation @@ -158,7 +137,7 @@ struct CAMFImporter_NodeElement_Instance : public CAMFImporter_NodeElement { /****************** Variables ******************/ - std::string ObjectID;///< ID of object for instanciation. + std::string ObjectID;///< ID of object for instantiation. /// \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; @@ -399,25 +378,23 @@ struct CAMFImporter_NodeElement_Triangle : public CAMFImporter_NodeElement };// struct CAMFImporter_NodeElement_Triangle -/// \struct CAMFImporter_NodeElement_Texture /// Structure that define texture node. -struct CAMFImporter_NodeElement_Texture : public CAMFImporter_NodeElement -{ - /****************** Variables ******************/ - +struct CAMFImporter_NodeElement_Texture : public CAMFImporter_NodeElement { size_t Width, Height, Depth;///< Size of the texture. std::vector 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) - {} - + : CAMFImporter_NodeElement(ENET_Texture, pParent) + , Width( 0 ) + , Height( 0 ) + , Depth( 0 ) + , Data() + , Tiled( false ){ + // empty + } };// struct CAMFImporter_NodeElement_Texture #endif // INCLUDED_AI_AMF_IMPORTER_NODE_H diff --git a/code/AMFImporter_Postprocess.cpp b/code/AMFImporter_Postprocess.cpp index e328551c3..991eb97e7 100644 --- a/code/AMFImporter_Postprocess.cpp +++ b/code/AMFImporter_Postprocess.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -49,20 +50,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AMFImporter.hpp" // Header files, Assimp. -#include "SceneCombiner.h" +#include #include "StandardShapes.h" #include "StringUtils.h" // Header files, stdlib. -#include #include namespace Assimp { -aiColor4D AMFImporter::SPP_Material::GetColor(const float pX, const float pY, const float pZ) const +aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*pY*/, const float /*pZ*/) const { -aiColor4D tcol; + aiColor4D tcol; // Check if stored data are supported. if(Composition.size() != 0) @@ -93,8 +93,8 @@ aiColor4D tcol; void AMFImporter::PostprocessHelper_CreateMeshDataArray(const CAMFImporter_NodeElement_Mesh& pNodeElement, std::vector& pVertexCoordinateArray, std::vector& pVertexColorArray) const { -CAMFImporter_NodeElement_Vertices* vn = nullptr; -size_t col_idx; + CAMFImporter_NodeElement_Vertices* vn = nullptr; + size_t col_idx; // All data stored in "vertices", search for it. for(CAMFImporter_NodeElement* ne_child: pNodeElement.Child) @@ -142,8 +142,8 @@ size_t col_idx; 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; + size_t TextureConverted_Index; + std::string TextureConverted_ID; // check input data if(pID_R.empty() && pID_G.empty() && pID_B.empty() && pID_A.empty()) @@ -261,20 +261,31 @@ std::string TextureConverted_ID; 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++; } + if(!pID_R.empty() && nullptr != src_texture[ 0 ] ) { + tex_size += src_texture[0]->Data.size(); step++, off_g++, off_b++; + } + if(!pID_G.empty() && nullptr != src_texture[ 1 ] ) { + tex_size += src_texture[1]->Data.size(); step++, off_b++; + } + if(!pID_B.empty() && nullptr != src_texture[ 2 ] ) { + tex_size += src_texture[2]->Data.size(); step++; + } + if(!pID_A.empty() && nullptr != src_texture[ 3 ] ) { + tex_size += src_texture[3]->Data.size(); step++; + } - // Create target array. + // 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); + for(size_t idx_target = pOffset, idx_src = 0; idx_target < tex_size; idx_target += pStep, idx_src++) { + CAMFImporter_NodeElement_Texture* tex = src_texture[pSrcTexNum]; + ai_assert(tex); + converted_texture.Data[idx_target] = tex->Data.at(idx_src); + } } };// auto CopyTextureData = [&](const size_t pOffset, const size_t pStep, const uint8_t pSrcTexNum) -> void @@ -293,19 +304,19 @@ std::string TextureConverted_ID; void AMFImporter::PostprocessHelper_SplitFacesByTextureID(std::list& pInputList, std::list >& 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; + 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; + 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; -}; + return true; + }; pOutputList_Separated.clear(); if(pInputList.size() == 0) return; @@ -678,7 +689,6 @@ std::list mesh_idx; tmesh->mNumVertices = static_cast(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)); diff --git a/code/ASELoader.cpp b/code/ASELoader.cpp index ed01c17e1..65935f48f 100644 --- a/code/ASELoader.cpp +++ b/code/ASELoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -45,6 +46,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER +#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER + // internal headers #include "ASELoader.h" #include "StringComparison.h" @@ -54,6 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include @@ -1017,6 +1021,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector& avOutMesh // convert bones, if existing if (!mesh.mBones.empty()) { + ai_assert(avOutputBones); // check whether there is a vertex weight for this vertex index if (iIndex2 < mesh.mBoneVertices.size()) { @@ -1318,4 +1323,6 @@ bool ASEImporter::GenerateNormals(ASE::Mesh& mesh) { return false; } +#endif // ASSIMP_BUILD_NO_3DS_IMPORTER + #endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER diff --git a/code/ASELoader.h b/code/ASELoader.h index b775fc6bb..8a8d4faa4 100644 --- a/code/ASELoader.h +++ b/code/ASELoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -46,12 +47,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BaseImporter.h" #include +#include "ASEParser.h" struct aiNode; -#include "ASEParser.h" namespace Assimp { +#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER // -------------------------------------------------------------------------------- /** Importer class for the 3DS ASE ASCII format. @@ -62,9 +64,6 @@ public: ASEImporter(); ~ASEImporter(); - -public: - // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. * See BaseImporter::CanRead() for details. @@ -200,6 +199,9 @@ protected: bool noSkeletonMesh; }; +#endif // ASSIMP_BUILD_NO_3DS_IMPORTER + } // end of namespace Assimp + #endif // AI_3DSIMPORTER_H_INC diff --git a/code/ASEParser.cpp b/code/ASEParser.cpp index 3b3b696e5..7de80a2d8 100644 --- a/code/ASEParser.cpp +++ b/code/ASEParser.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -45,11 +46,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER +#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER // internal headers #include "TextureTransform.h" #include "ASELoader.h" -#include "MaterialSystem.h" #include "fast_atof.h" #include @@ -1135,7 +1136,7 @@ void Parser::ParseLV3ScaleAnimationBlock(ASE::Animation& anim) bool b = false; // For the moment we're just reading the three floats - - // we ignore the �dditional information for bezier's and TCBs + // we ignore the additional information for bezier's and TCBs // simple scaling keyframe if (TokenMatch(filePtr,"CONTROL_SCALE_SAMPLE" ,20)) @@ -1181,7 +1182,7 @@ void Parser::ParseLV3PosAnimationBlock(ASE::Animation& anim) bool b = false; // For the moment we're just reading the three floats - - // we ignore the �dditional information for bezier's and TCBs + // we ignore the additional information for bezier's and TCBs // simple scaling keyframe if (TokenMatch(filePtr,"CONTROL_POS_SAMPLE" ,18)) @@ -1227,7 +1228,7 @@ void Parser::ParseLV3RotAnimationBlock(ASE::Animation& anim) bool b = false; // For the moment we're just reading the floats - - // we ignore the �dditional information for bezier's and TCBs + // we ignore the additional information for bezier's and TCBs // simple scaling keyframe if (TokenMatch(filePtr,"CONTROL_ROT_SAMPLE" ,18)) @@ -1858,7 +1859,7 @@ void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh) ++filePtr; // Face entry - if (TokenMatch(filePtr,"MESH_CFACE" ,11)) + if (TokenMatch(filePtr,"MESH_CFACE" ,10)) { unsigned int aiValues[3]; unsigned int iIndex = 0; @@ -2151,4 +2152,6 @@ void Parser::ParseLV4MeshLong(unsigned int& iOut) iOut = strtoul10(filePtr,&filePtr); } +#endif // ASSIMP_BUILD_NO_3DS_IMPORTER + #endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER diff --git a/code/ASEParser.h b/code/ASEParser.h index 095d089d4..db64f2a16 100644 --- a/code/ASEParser.h +++ b/code/ASEParser.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -48,6 +49,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER + // for some helper routines like IsSpace() #include "ParsingUtils.h" #include "qnan.h" @@ -661,4 +664,6 @@ public: } // Namespace ASE } // Namespace ASSIMP +#endif // ASSIMP_BUILD_NO_3DS_IMPORTER + #endif // !! include guard diff --git a/code/AssbinExporter.cpp b/code/AssbinExporter.cpp index fcb32c70a..bcac2e08f 100644 --- a/code/AssbinExporter.cpp +++ b/code/AssbinExporter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -138,6 +139,17 @@ inline size_t Write(IOStream * stream, const aiVector3D& v) return t; } +// ----------------------------------------------------------------------------------- +// Serialize a color value +template <> +inline size_t Write(IOStream * stream, const aiColor3D& v) +{ + size_t t = Write(stream,v.r); + t += Write(stream,v.g); + t += Write(stream,v.b); + return t; +} + // ----------------------------------------------------------------------------------- // Serialize a color value template <> @@ -159,6 +171,7 @@ inline size_t Write(IOStream * stream, const aiQuaternion& v) t += Write(stream,v.x); t += Write(stream,v.y); t += Write(stream,v.z); + ai_assert(t == 16); return 16; } @@ -324,10 +337,13 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size) { AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE ); + unsigned int nb_metadata = (node->mMetaData != NULL ? node->mMetaData->mNumProperties : 0); + Write(&chunk,node->mName); Write(&chunk,node->mTransformation); Write(&chunk,node->mNumChildren); Write(&chunk,node->mNumMeshes); + Write(&chunk,nb_metadata); for (unsigned int i = 0; i < node->mNumMeshes;++i) { Write(&chunk,node->mMeshes[i]); @@ -336,6 +352,44 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size) for (unsigned int i = 0; i < node->mNumChildren;++i) { WriteBinaryNode( &chunk, node->mChildren[i] ); } + + for (unsigned int i = 0; i < nb_metadata; ++i) { + const aiString& key = node->mMetaData->mKeys[i]; + aiMetadataType type = node->mMetaData->mValues[i].mType; + void* value = node->mMetaData->mValues[i].mData; + + Write(&chunk, key); + Write(&chunk, type); + + switch (type) { + case AI_BOOL: + Write(&chunk, *((bool*) value)); + break; + case AI_INT32: + Write(&chunk, *((int32_t*) value)); + break; + case AI_UINT64: + Write(&chunk, *((uint64_t*) value)); + break; + case AI_FLOAT: + Write(&chunk, *((float*) value)); + break; + case AI_DOUBLE: + Write(&chunk, *((double*) value)); + break; + case AI_AISTRING: + Write(&chunk, *((aiString*) value)); + break; + case AI_AIVECTOR3D: + Write(&chunk, *((aiVector3D*) value)); + break; +#ifdef SWIG + case FORCE_32BIT: +#endif // SWIG + default: + break; + } + } } // ----------------------------------------------------------------------------------- @@ -597,9 +651,9 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size) Write(&chunk,l->mAttenuationQuadratic); } - Write(&chunk,(const aiVector3D&)l->mColorDiffuse); - Write(&chunk,(const aiVector3D&)l->mColorSpecular); - Write(&chunk,(const aiVector3D&)l->mColorAmbient); + Write(&chunk,l->mColorDiffuse); + Write(&chunk,l->mColorSpecular); + Write(&chunk,l->mColorAmbient); if (l->mType == aiLightSource_SPOT) { Write(&chunk,l->mAngleInnerCone); @@ -757,7 +811,7 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size) } }; -void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) +void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { AssbinExport exporter; exporter.WriteBinaryDump( pFile, pIOSystem, pScene ); diff --git a/code/AssbinExporter.h b/code/AssbinExporter.h index 4a0219c04..55bb9fc82 100644 --- a/code/AssbinExporter.h +++ b/code/AssbinExporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/AssbinLoader.cpp b/code/AssbinLoader.cpp index 7a17d5ad5..a7044c119 100644 --- a/code/AssbinLoader.cpp +++ b/code/AssbinLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -54,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #ifdef ASSIMP_BUILD_NO_OWN_ZLIB # include @@ -196,9 +198,9 @@ template void ReadBounds( IOStream * stream, T* /*p*/, unsigned int stream->Seek( sizeof(T) * n, aiOrigin_CUR ); } -void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node ) -{ +void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node, aiNode* parent ) { uint32_t chunkID = Read(stream); + (void)(chunkID); ai_assert(chunkID == ASSBIN_CHUNK_AINODE); /*uint32_t size =*/ Read(stream); @@ -208,29 +210,72 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node ) (*node)->mTransformation = Read(stream); (*node)->mNumChildren = Read(stream); (*node)->mNumMeshes = Read(stream); + unsigned int nb_metadata = Read(stream); - if ((*node)->mNumMeshes) - { + if(parent) { + (*node)->mParent = parent; + } + + if ((*node)->mNumMeshes) { (*node)->mMeshes = new unsigned int[(*node)->mNumMeshes]; for (unsigned int i = 0; i < (*node)->mNumMeshes; ++i) { (*node)->mMeshes[i] = Read(stream); } } - if ((*node)->mNumChildren) - { + if ((*node)->mNumChildren) { (*node)->mChildren = new aiNode*[(*node)->mNumChildren]; for (unsigned int i = 0; i < (*node)->mNumChildren; ++i) { - ReadBinaryNode( stream, &(*node)->mChildren[i] ); + ReadBinaryNode( stream, &(*node)->mChildren[i], *node ); } } + if ( nb_metadata > 0 ) { + (*node)->mMetaData = aiMetadata::Alloc(nb_metadata); + for (unsigned int i = 0; i < nb_metadata; ++i) { + (*node)->mMetaData->mKeys[i] = Read(stream); + (*node)->mMetaData->mValues[i].mType = (aiMetadataType) Read(stream); + void* data( nullptr ); + + switch ((*node)->mMetaData->mValues[i].mType) { + case AI_BOOL: + data = new bool(Read(stream)); + break; + case AI_INT32: + data = new int32_t(Read(stream)); + break; + case AI_UINT64: + data = new uint64_t(Read(stream)); + break; + case AI_FLOAT: + data = new float(Read(stream)); + break; + case AI_DOUBLE: + data = new double(Read(stream)); + break; + case AI_AISTRING: + data = new aiString(Read(stream)); + break; + case AI_AIVECTOR3D: + data = new aiVector3D(Read(stream)); + break; +#ifndef SWIG + case FORCE_32BIT: +#endif // SWIG + default: + break; + } + + (*node)->mMetaData->mValues[i].mData = data; + } + } } // ----------------------------------------------------------------------------------- void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b ) { uint32_t chunkID = Read(stream); + (void)(chunkID); ai_assert(chunkID == ASSBIN_CHUNK_AIBONE); /*uint32_t size =*/ Read(stream); @@ -255,6 +300,7 @@ void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b ) void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) { uint32_t chunkID = Read(stream); + (void)(chunkID); ai_assert(chunkID == ASSBIN_CHUNK_AIMESH); /*uint32_t size =*/ Read(stream); @@ -380,6 +426,7 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh ) void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop) { uint32_t chunkID = Read(stream); + (void)(chunkID); ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIALPROPERTY); /*uint32_t size =*/ Read(stream); @@ -397,6 +444,7 @@ void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialPro void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat) { uint32_t chunkID = Read(stream); + (void)(chunkID); ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIAL); /*uint32_t size =*/ Read(stream); @@ -419,6 +467,7 @@ void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat) void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd) { uint32_t chunkID = Read(stream); + (void)(chunkID); ai_assert(chunkID == ASSBIN_CHUNK_AINODEANIM); /*uint32_t size =*/ Read(stream); @@ -468,6 +517,7 @@ void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd) void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim ) { uint32_t chunkID = Read(stream); + (void)(chunkID); ai_assert(chunkID == ASSBIN_CHUNK_AIANIMATION); /*uint32_t size =*/ Read(stream); @@ -489,6 +539,7 @@ void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim ) void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex) { uint32_t chunkID = Read(stream); + (void)(chunkID); ai_assert(chunkID == ASSBIN_CHUNK_AITEXTURE); /*uint32_t size =*/ Read(stream); @@ -513,6 +564,7 @@ void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex) void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l ) { uint32_t chunkID = Read(stream); + (void)(chunkID); ai_assert(chunkID == ASSBIN_CHUNK_AILIGHT); /*uint32_t size =*/ Read(stream); @@ -540,6 +592,7 @@ void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l ) void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam ) { uint32_t chunkID = Read(stream); + (void)(chunkID); ai_assert(chunkID == ASSBIN_CHUNK_AICAMERA); /*uint32_t size =*/ Read(stream); @@ -556,6 +609,7 @@ void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam ) void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) { uint32_t chunkID = Read(stream); + (void)(chunkID); ai_assert(chunkID == ASSBIN_CHUNK_AISCENE); /*uint32_t size =*/ Read(stream); @@ -569,7 +623,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene ) // Read node graph scene->mRootNode = new aiNode[1]; - ReadBinaryNode( stream, &scene->mRootNode ); + ReadBinaryNode( stream, &scene->mRootNode, (aiNode*)NULL ); // Read all meshes if (scene->mNumMeshes) diff --git a/code/AssbinLoader.h b/code/AssbinLoader.h index e8c8dd0cb..2eb7a6488 100644 --- a/code/AssbinLoader.h +++ b/code/AssbinLoader.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -46,7 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_ASSBINIMPORTER_H_INC #include "BaseImporter.h" -#include struct aiMesh; struct aiNode; @@ -71,7 +71,6 @@ class AssbinImporter : public BaseImporter private: bool shortened; bool compressed; -protected: public: virtual bool CanRead( @@ -86,7 +85,7 @@ public: IOSystem* pIOHandler ); void ReadBinaryScene( IOStream * stream, aiScene* pScene ); - void ReadBinaryNode( IOStream * stream, aiNode** mRootNode ); + void ReadBinaryNode( IOStream * stream, aiNode** mRootNode, aiNode* parent ); void ReadBinaryMesh( IOStream * stream, aiMesh* mesh ); void ReadBinaryBone( IOStream * stream, aiBone* bone ); void ReadBinaryMaterial(IOStream * stream, aiMaterial* mat); diff --git a/code/Assimp.cpp b/code/Assimp.cpp index 092c40979..9269f905e 100644 --- a/code/Assimp.cpp +++ b/code/Assimp.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -65,8 +66,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ------------------------------------------------------------------------------------------------ using namespace Assimp; -namespace Assimp -{ +namespace Assimp { // underlying structure for aiPropertyStore typedef BatchLoader::PropertyMap PropertyMap; @@ -109,12 +109,11 @@ static std::mutex gLogStreamMutex; // ------------------------------------------------------------------------------------------------ // Custom LogStream implementation for the C-API -class LogToCallbackRedirector : public LogStream -{ +class LogToCallbackRedirector : public LogStream { public: explicit LogToCallbackRedirector(const aiLogStream& s) - : stream (s) { - ai_assert(NULL != s.callback); + : stream (s) { + ai_assert(NULL != s.callback); } ~LogToCallbackRedirector() { @@ -145,8 +144,7 @@ private: }; // ------------------------------------------------------------------------------------------------ -void ReportSceneNotFoundError() -{ +void ReportSceneNotFoundError() { DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. " "The C-API does not accept scenes produced by the C++ API and vice versa"); @@ -155,22 +153,18 @@ void ReportSceneNotFoundError() // ------------------------------------------------------------------------------------------------ // Reads the given file and returns its content. -const aiScene* aiImportFile( const char* pFile, unsigned int pFlags) -{ +const aiScene* aiImportFile( const char* pFile, unsigned int pFlags) { return aiImportFileEx(pFile,pFlags,NULL); } // ------------------------------------------------------------------------------------------------ -const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, aiFileIO* pFS) -{ +const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, aiFileIO* pFS) { return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL); } // ------------------------------------------------------------------------------------------------ -const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags, - aiFileIO* pFS, - const aiPropertyStore* props) -{ +const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags, + aiFileIO* pFS, const aiPropertyStore* props) { ai_assert(NULL != pFile); const aiScene* scene = NULL; @@ -189,7 +183,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl pimpl->mMatrixProperties = pp->matrices; } // setup a custom IO system if necessary - if (pFS) { + if (pFS) { imp->SetIOHandler( new CIOSystemWrapper (pFS) ); } @@ -200,8 +194,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl if( scene) { ScenePrivateData* priv = const_cast( ScenePriv(scene) ); priv->mOrigImporter = imp; - } - else { + } else { // if failed, extract error code and destroy the import gLastErrorString = imp->GetErrorString(); delete imp; @@ -209,6 +202,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl // return imported data. If the import failed the pointer is NULL anyways ASSIMP_END_EXCEPTION_REGION(const aiScene*); + return scene; } diff --git a/code/AssimpCExport.cpp b/code/AssimpCExport.cpp index fff9d8e21..b8d3264a1 100644 --- a/code/AssimpCExport.cpp +++ b/code/AssimpCExport.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -44,8 +45,9 @@ Assimp C export interface. See Exporter.cpp for some notes. */ #ifndef ASSIMP_BUILD_NO_EXPORT + #include "CInterfaceIOWrapper.h" -#include "SceneCombiner.h" +#include #include "ScenePrivate.h" #include diff --git a/code/AssxmlExporter.cpp b/code/AssxmlExporter.cpp index c50f1985b..90ed66701 100644 --- a/code/AssxmlExporter.cpp +++ b/code/AssxmlExporter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -41,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ASSXML exporter main code */ #include -#include "./../include/assimp/version.h" +#include #include "ProcessHelper.h" #include #include @@ -630,7 +631,7 @@ void WriteDump(const aiScene* scene, IOStream* io, bool shortened) { } // end of namespace AssxmlExport -void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) +void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { IOStream * out = pIOSystem->Open( pFile, "wt" ); if (!out) return; diff --git a/code/AssxmlExporter.h b/code/AssxmlExporter.h index ba9921f70..9694f74a3 100644 --- a/code/AssxmlExporter.h +++ b/code/AssxmlExporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/B3DImporter.cpp b/code/B3DImporter.cpp index d28d41518..bc888fb66 100644 --- a/code/B3DImporter.cpp +++ b/code/B3DImporter.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -56,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include - +#include using namespace Assimp; using namespace std; @@ -81,6 +82,20 @@ static const aiImporterDesc desc = { //#define DEBUG_B3D +template +void DeleteAllBarePointers(std::vector& x) +{ + for(auto p : x) + { + delete p; + } +} + +B3DImporter::~B3DImporter() +{ + DeleteAllBarePointers(_animations); +} + // ------------------------------------------------------------------------------------------------ bool B3DImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const{ @@ -156,7 +171,8 @@ int B3DImporter::ReadByte(){ // ------------------------------------------------------------------------------------------------ int B3DImporter::ReadInt(){ if( _pos+4<=_buf.size() ){ - int n=*(int*)&_buf[_pos]; + int n; + memcpy(&n, &_buf[_pos], 4); _pos+=4; return n; } @@ -167,7 +183,8 @@ int B3DImporter::ReadInt(){ // ------------------------------------------------------------------------------------------------ float B3DImporter::ReadFloat(){ if( _pos+4<=_buf.size() ){ - float n=*(float*)&_buf[_pos]; + float n; + memcpy(&n, &_buf[_pos], 4); _pos+=4; return n; } @@ -557,13 +574,19 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){ void B3DImporter::ReadBB3D( aiScene *scene ){ _textures.clear(); + _materials.clear(); _vertices.clear(); + _meshes.clear(); + DeleteAllBarePointers(_nodes); _nodes.clear(); + _nodeAnims.clear(); + + DeleteAllBarePointers(_animations); _animations.clear(); string t=ReadChunk(); diff --git a/code/B3DImporter.h b/code/B3DImporter.h index 92ddc0272..94644edd4 100644 --- a/code/B3DImporter.h +++ b/code/B3DImporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -48,7 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "BaseImporter.h" -#include #include struct aiNodeAnim; @@ -59,6 +59,8 @@ namespace Assimp{ class B3DImporter : public BaseImporter{ public: + B3DImporter() = default; + virtual ~B3DImporter(); virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const; diff --git a/code/BVHLoader.cpp b/code/BVHLoader.cpp index e5821fdaf..c20cbec4e 100644 --- a/code/BVHLoader.cpp +++ b/code/BVHLoader.cpp @@ -4,7 +4,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -51,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "TinyFormatter.h" #include #include +#include using namespace Assimp; using namespace Assimp::Formatter; diff --git a/code/BVHLoader.h b/code/BVHLoader.h index 8a163d1e7..6a89e1aaf 100644 --- a/code/BVHLoader.h +++ b/code/BVHLoader.h @@ -4,7 +4,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/BaseImporter.cpp b/code/BaseImporter.cpp index 3d53bc089..b9b9eeb71 100644 --- a/code/BaseImporter.cpp +++ b/code/BaseImporter.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -50,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include #include @@ -87,12 +89,12 @@ aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, FileSystemFilter filter(pFile,pIOHandler); // create a scene object to hold the data - ScopeGuard sc(new aiScene()); + std::unique_ptr sc(new aiScene()); // dispatch importing try { - InternReadFile( pFile, sc, &filter); + InternReadFile( pFile, sc.get(), &filter); } catch( const std::exception& err ) { // extract error description @@ -102,8 +104,7 @@ aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, } // return what we gathered from the import. - sc.dismiss(); - return sc; + return sc.release(); } // ------------------------------------------------------------------------------------------------ @@ -301,24 +302,13 @@ void BaseImporter::GetExtensionList(std::set& extensions) return false; } -#include "../contrib/ConvertUTF/ConvertUTF.h" - -// ------------------------------------------------------------------------------------------------ -void ReportResult(ConversionResult res) -{ - if(res == sourceExhausted) { - DefaultLogger::get()->error("Source ends with incomplete character sequence, transformation to UTF-8 fails"); - } - else if(res == sourceIllegal) { - DefaultLogger::get()->error("Source contains illegal character sequence, transformation to UTF-8 fails"); - } -} +#include "../contrib/utf8cpp/source/utf8.h" // ------------------------------------------------------------------------------------------------ // Convert to UTF8 data void BaseImporter::ConvertToUTF8(std::vector& data) { - ConversionResult result; + //ConversionResult result; if(data.size() < 8) { throw DeadlyImportError("File is too small"); } @@ -331,7 +321,8 @@ void BaseImporter::ConvertToUTF8(std::vector& data) data.resize(data.size()-3); return; } - + + // UTF 32 BE with BOM if(*((uint32_t*)&data.front()) == 0xFFFE0000) { @@ -345,21 +336,10 @@ void BaseImporter::ConvertToUTF8(std::vector& data) if(*((uint32_t*)&data.front()) == 0x0000FFFE) { DefaultLogger::get()->debug("Found UTF-32 BOM ..."); - const uint32_t* sstart = (uint32_t*)&data.front()+1, *send = (uint32_t*)&data.back()+1; - char* dstart,*dend; std::vector output; - do { - output.resize(output.size()?output.size()*3/2:data.size()/2); - dstart = &output.front(),dend = &output.back()+1; - - result = ConvertUTF32toUTF8((const UTF32**)&sstart,(const UTF32*)send,(UTF8**)&dstart,(UTF8*)dend,lenientConversion); - } while(result == targetExhausted); - - ReportResult(result); - - // copy to output buffer. - const size_t outlen = (size_t)(dstart-&output.front()); - data.assign(output.begin(),output.begin()+outlen); + int *ptr = (int*)&data[ 0 ]; + int *end = ptr + ( data.size() / sizeof(int) ) +1; + utf8::utf32to8( ptr, end, back_inserter(output)); return; } @@ -376,21 +356,8 @@ void BaseImporter::ConvertToUTF8(std::vector& data) if(*((uint16_t*)&data.front()) == 0xFEFF) { DefaultLogger::get()->debug("Found UTF-16 BOM ..."); - const uint16_t* sstart = (uint16_t*)&data.front()+1, *send = (uint16_t*)(&data.back()+1); - char* dstart,*dend; - std::vector output; - do { - output.resize(output.size()?output.size()*3/2:data.size()*3/4); - dstart = &output.front(),dend = &output.back()+1; - - result = ConvertUTF16toUTF8((const UTF16**)&sstart,(const UTF16*)send,(UTF8**)&dstart,(UTF8*)dend,lenientConversion); - } while(result == targetExhausted); - - ReportResult(result); - - // copy to output buffer. - const size_t outlen = (size_t)(dstart-&output.front()); - data.assign(output.begin(),output.begin()+outlen); + std::vector output; + utf8::utf16to8(data.begin(), data.end(), back_inserter(output)); return; } } diff --git a/code/BaseImporter.h b/code/BaseImporter.h index 7c8932a3f..b424d2f83 100644 --- a/code/BaseImporter.h +++ b/code/BaseImporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -44,14 +45,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Exceptional.h" -#include -#include #include #include #include #include struct aiScene; +struct aiImporterDesc; namespace Assimp { @@ -61,47 +61,10 @@ class BaseProcess; 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])) -// --------------------------------------------------------------------------- -template -struct ScopeGuard -{ - explicit ScopeGuard(T* obj) : obj(obj), mdismiss() {} - ~ScopeGuard () throw() { - if (!mdismiss) { - delete obj; - } - obj = NULL; - } - - T* dismiss() { - mdismiss=true; - return obj; - } - - operator T*() { - return obj; - } - - T* operator -> () { - return obj; - } - -private: - // no copying allowed. - ScopeGuard(); - ScopeGuard( const ScopeGuard & ); - ScopeGuard &operator = ( const ScopeGuard & ); - - T* obj; - bool mdismiss; -}; - - // --------------------------------------------------------------------------- /** FOR IMPORTER PLUGINS ONLY: The BaseImporter defines a common interface @@ -194,14 +157,11 @@ public: const Importer* pImp ); - // ------------------------------------------------------------------- /** Called by #Importer::GetImporterInfo to get a description of * some loader features. Importers must provide this information. */ virtual const aiImporterDesc* GetInfo() const = 0; - - // ------------------------------------------------------------------- /** Called by #Importer::GetExtensionList for each loaded importer. * Take the extension list contained in the structure returned by @@ -317,7 +277,7 @@ public: // static utilities * @param Size of one token, in bytes. Maximally 16 bytes. * @return true if one of the given tokens was found * - * @note For convinence, the check is also performed for the + * @note For convenience, the check is also performed for the * byte-swapped variant of all tokens (big endian). Only for * tokens of size 2,4. */ diff --git a/code/BaseProcess.cpp b/code/BaseProcess.cpp index 580f89cdb..9e175d315 100644 --- a/code/BaseProcess.cpp +++ b/code/BaseProcess.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/BaseProcess.h b/code/BaseProcess.h index 148f07284..aa873f717 100644 --- a/code/BaseProcess.h +++ b/code/BaseProcess.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -43,8 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_BASEPROCESS_H #include - -#include #include "GenericProperty.h" struct aiScene; diff --git a/code/Bitmap.cpp b/code/Bitmap.cpp index ae6d62083..76994513e 100644 --- a/code/Bitmap.cpp +++ b/code/Bitmap.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -101,7 +102,7 @@ namespace Assimp { offset += Copy(&data[offset], header.size); offset += Copy(&data[offset], header.reserved1); offset += Copy(&data[offset], header.reserved2); - offset += Copy(&data[offset], header.offset); + Copy(&data[offset], header.offset); file->Write(data, Header::header_size, 1); } @@ -121,7 +122,7 @@ namespace Assimp { offset += Copy(&data[offset], dib.x_resolution); offset += Copy(&data[offset], dib.y_resolution); offset += Copy(&data[offset], dib.nb_colors); - offset += Copy(&data[offset], dib.nb_important_colors); + Copy(&data[offset], dib.nb_important_colors); file->Write(data, DIB::dib_size, 1); } diff --git a/code/Bitmap.h b/code/Bitmap.h index ad29783ce..96c994dbe 100644 --- a/code/Bitmap.h +++ b/code/Bitmap.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -50,93 +51,71 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include + struct aiTexture; namespace Assimp { class IOStream; + class Bitmap { +protected: - protected: + struct Header { + uint16_t type; + uint32_t size; + uint16_t reserved1; + uint16_t reserved2; + uint32_t offset; - struct Header { + // 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). + static const std::size_t header_size = + sizeof(uint16_t) + // type + sizeof(uint32_t) + // size + sizeof(uint16_t) + // reserved1 + sizeof(uint16_t) + // reserved2 + sizeof(uint32_t); // offset + }; - uint16_t type; + struct DIB { + uint32_t size; + int32_t width; + int32_t height; + uint16_t planes; + uint16_t bits_per_pixel; + uint32_t compression; + uint32_t image_size; + int32_t x_resolution; + int32_t y_resolution; + uint32_t nb_colors; + uint32_t nb_important_colors; - uint32_t size; + // 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). + static const std::size_t dib_size = + sizeof(uint32_t) + // size + sizeof(int32_t) + // width + sizeof(int32_t) + // height + sizeof(uint16_t) + // planes + sizeof(uint16_t) + // bits_per_pixel + sizeof(uint32_t) + // compression + sizeof(uint32_t) + // image_size + sizeof(int32_t) + // x_resolution + sizeof(int32_t) + // y_resolution + sizeof(uint32_t) + // nb_colors + sizeof(uint32_t); // nb_important_colors + }; - uint16_t reserved1; + static const std::size_t mBytesPerPixel = 4; - uint16_t reserved2; - - uint32_t offset; - - // 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). - static const std::size_t header_size = - sizeof(uint16_t) + // type - sizeof(uint32_t) + // size - sizeof(uint16_t) + // reserved1 - sizeof(uint16_t) + // reserved2 - sizeof(uint32_t); // offset - - }; - - struct DIB { - - uint32_t size; - - int32_t width; - - int32_t height; - - uint16_t planes; - - uint16_t bits_per_pixel; - - uint32_t compression; - - uint32_t image_size; - - int32_t x_resolution; - - int32_t y_resolution; - - uint32_t nb_colors; - - uint32_t nb_important_colors; - - // 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). - static const std::size_t dib_size = - sizeof(uint32_t) + // size - sizeof(int32_t) + // width - sizeof(int32_t) + // height - sizeof(uint16_t) + // planes - sizeof(uint16_t) + // bits_per_pixel - sizeof(uint32_t) + // compression - sizeof(uint32_t) + // image_size - sizeof(int32_t) + // x_resolution - sizeof(int32_t) + // y_resolution - sizeof(uint32_t) + // nb_colors - sizeof(uint32_t); // nb_important_colors - - }; - - static const std::size_t mBytesPerPixel = 4; - - public: - - static void Save(aiTexture* texture, IOStream* file); - - protected: - - static void WriteHeader(Header& header, IOStream* file); - - static void WriteDIB(DIB& dib, IOStream* file); - - static void WriteData(aiTexture* texture, IOStream* file); +public: + static void Save(aiTexture* texture, IOStream* file); +protected: + static void WriteHeader(Header& header, IOStream* file); + static void WriteDIB(DIB& dib, IOStream* file); + static void WriteData(aiTexture* texture, IOStream* file); }; } diff --git a/code/BlenderBMesh.cpp b/code/BlenderBMesh.cpp index c328947ae..8a13819a6 100644 --- a/code/BlenderBMesh.cpp +++ b/code/BlenderBMesh.cpp @@ -52,7 +52,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { - template< > const std::string LogFunctions< BlenderBMeshConverter >::log_prefix = "BLEND_BMESH: "; + template< > const char* LogFunctions< BlenderBMeshConverter >::Prefix() + { + static auto prefix = "BLEND_BMESH: "; + return prefix; + } } using namespace Assimp; diff --git a/code/BlenderDNA.cpp b/code/BlenderDNA.cpp index e8f335bce..23ece913f 100644 --- a/code/BlenderDNA.cpp +++ b/code/BlenderDNA.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -48,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BlenderDNA.h" #include "StreamReader.h" #include "fast_atof.h" +#include "TinyFormatter.h" using namespace Assimp; using namespace Assimp::Blender; diff --git a/code/BlenderDNA.h b/code/BlenderDNA.h index 135e38d60..bac8d78bc 100644 --- a/code/BlenderDNA.h +++ b/code/BlenderDNA.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -46,12 +47,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_BLEND_DNA_H #include "BaseImporter.h" -#include "TinyFormatter.h" #include "StreamReader.h" #include #include #include - +#include // enable verbose log output. really verbose, so be careful. #ifdef ASSIMP_BUILD_DEBUG @@ -92,6 +92,12 @@ struct Error : DeadlyImportError { * descendents. It serves as base class for all data structure fields. */ // ------------------------------------------------------------------------------- struct ElemBase { + ElemBase() + : dna_type(nullptr) + { + // empty + } + virtual ~ElemBase() { // empty } @@ -253,10 +259,7 @@ public: * a compiler complain is the result. * @param dest Destination value to be written * @param db File database, including input stream. */ - template inline void Convert (T& dest, - const FileDatabase& db) const; - - + template void Convert (T& dest, const FileDatabase& db) const; // -------------------------------------------------------- // generic converter diff --git a/code/BlenderDNA.inl b/code/BlenderDNA.inl index 7397e291b..c65ea81bc 100644 --- a/code/BlenderDNA.inl +++ b/code/BlenderDNA.inl @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -46,9 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_BLEND_DNA_INL #include +#include "TinyFormatter.h" namespace Assimp { - namespace Blender { +namespace Blender { //-------------------------------------------------------------------------------- const Field& Structure :: operator [] (const std::string& ss) const @@ -583,11 +585,14 @@ template <> inline void Structure :: Convert (int& dest,const FileDataba } // ------------------------------------------------------------------------------------------------ -template <> inline void Structure :: Convert (short& dest,const FileDatabase& db) const +template<> inline void Structure :: Convert (short& dest,const FileDatabase& db) const { // automatic rescaling from short to float and vice versa (seems to be used by normals) if (name == "float") { - dest = static_cast(db.reader->GetF4() * 32767.f); + float f = db.reader->GetF4(); + if ( f > 1.0f ) + f = 1.0f; + dest = static_cast( f * 32767.f); //db.reader->IncPtr(-4); return; } diff --git a/code/BlenderIntermediate.h b/code/BlenderIntermediate.h index 0290185de..c6f9cba1e 100644 --- a/code/BlenderIntermediate.h +++ b/code/BlenderIntermediate.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -48,9 +49,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BlenderLoader.h" #include "BlenderDNA.h" #include "BlenderScene.h" -#include "BlenderSceneGen.h" #include -#include "./../include/assimp/material.h" +#include struct aiTexture; @@ -110,7 +110,7 @@ namespace Blender { void operator= (const TempArray&) { } - TempArray(const TempArray& arr) { + TempArray(const TempArray& /*arr*/) { } private: diff --git a/code/BlenderLoader.cpp b/code/BlenderLoader.cpp index 0e6c016de..824954f56 100644 --- a/code/BlenderLoader.cpp +++ b/code/BlenderLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -54,12 +55,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BlenderBMesh.h" #include "StringUtils.h" #include -#include "StringComparison.h" +#include +#include "StringComparison.h" #include "StreamReader.h" #include "MemoryIOWrapper.h" + #include -#include // zlib is needed for compressed blend files @@ -72,7 +74,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif namespace Assimp { - template<> const std::string LogFunctions::log_prefix = "BLEND: "; + template<> const char* LogFunctions::Prefix() + { + static auto prefix = "BLEND: "; + return prefix; + } } using namespace Assimp; @@ -96,8 +102,9 @@ static const aiImporterDesc blenderDesc = { // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer BlenderImporter::BlenderImporter() -: modifier_cache(new BlenderModifierShowcase()) -{} +: modifier_cache(new BlenderModifierShowcase()) { + // empty +} // ------------------------------------------------------------------------------------------------ // Destructor, private as well @@ -107,6 +114,7 @@ BlenderImporter::~BlenderImporter() } static const char* Tokens[] = { "BLENDER" }; +static const char* TokensForSearch[] = { "blender" }; // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. @@ -119,7 +127,7 @@ bool BlenderImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, b else if ((!extension.length() || checkSig) && pIOHandler) { // note: this won't catch compressed files - return SearchFileHeaderForToken(pIOHandler,pFile, Tokens,1); + return SearchFileHeaderForToken(pIOHandler,pFile, TokensForSearch,1); } return false; } @@ -145,8 +153,7 @@ void BlenderImporter::SetupProperties(const Importer* /*pImp*/) // nothing to be done for the moment } -struct free_it -{ +struct free_it { free_it(void* free) : free(free) {} ~free_it() { ::free(this->free); @@ -165,6 +172,7 @@ void BlenderImporter::InternReadFile( const std::string& pFile, free_it free_it_really(dest); #endif + FileDatabase file; std::shared_ptr stream(pIOHandler->Open(pFile,"rb")); if (!stream) { @@ -1140,7 +1148,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co // ------------------------------------------------------------------------------------------------ aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* cam, ConversionData& /*conv_data*/) { - ScopeGuard out(new aiCamera()); + std::unique_ptr out(new aiCamera()); out->mName = obj->id.name+2; out->mPosition = aiVector3D(0.f, 0.f, 0.f); out->mUp = aiVector3D(0.f, 1.f, 0.f); @@ -1151,13 +1159,13 @@ aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, out->mClipPlaneNear = cam->clipsta; out->mClipPlaneFar = cam->clipend; - return out.dismiss(); + return out.release(); } // ------------------------------------------------------------------------------------------------ aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, const Lamp* lamp, ConversionData& /*conv_data*/) { - ScopeGuard out(new aiLight()); + std::unique_ptr out(new aiLight()); out->mName = obj->id.name+2; switch (lamp->type) @@ -1195,7 +1203,7 @@ aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, c out->mColorAmbient = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy; out->mColorSpecular = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy; out->mColorDiffuse = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy; - return out.dismiss(); + return out.release(); } // ------------------------------------------------------------------------------------------------ @@ -1213,7 +1221,7 @@ aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, Convers ++it; } - ScopeGuard node(new aiNode(obj->id.name+2)); // skip over the name prefix 'OB' + std::unique_ptr node(new aiNode(obj->id.name+2)); // skip over the name prefix 'OB' if (obj->data) { switch (obj->type) { @@ -1297,14 +1305,14 @@ aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, Convers aiNode** nd = node->mChildren = new aiNode*[node->mNumChildren](); for (const Object* nobj :children) { *nd = ConvertNode(in,nobj,conv_data,node->mTransformation * parentTransform); - (*nd++)->mParent = node; + (*nd++)->mParent = node.get(); } } // apply modifiers modifier_cache->ApplyModifiers(*node,conv_data,in,*obj); - return node.dismiss(); + return node.release(); } #endif // ASSIMP_BUILD_NO_BLEND_IMPORTER diff --git a/code/BlenderLoader.h b/code/BlenderLoader.h index 505409260..66fff594b 100644 --- a/code/BlenderLoader.h +++ b/code/BlenderLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/BlenderModifier.cpp b/code/BlenderModifier.cpp index f903a1380..348df1f48 100644 --- a/code/BlenderModifier.cpp +++ b/code/BlenderModifier.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -42,10 +43,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of some blender modifiers (i.e subdivision, mirror). */ - #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER + #include "BlenderModifier.h" -#include "SceneCombiner.h" +#include #include "Subdivision.h" #include #include @@ -265,7 +266,7 @@ void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, co std::copy(out.mMeshes,out.mMeshes+out.mNumMeshes,nind); std::transform(out.mMeshes,out.mMeshes+out.mNumMeshes,nind+out.mNumMeshes, - std::bind1st(std::plus< unsigned int >(),out.mNumMeshes)); + [&out](unsigned int n) { return out.mNumMeshes + n; }); delete[] out.mMeshes; out.mMeshes = nind; @@ -309,7 +310,9 @@ void BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data std::unique_ptr subd(Subdivider::Create(algo)); ai_assert(subd); - + if ( conv_data.meshes->empty() ) { + return; + } aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes]; std::unique_ptr tempmeshes(new aiMesh*[out.mNumMeshes]()); diff --git a/code/BlenderModifier.h b/code/BlenderModifier.h index 1d176756e..9fa8c74ee 100644 --- a/code/BlenderModifier.h +++ b/code/BlenderModifier.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/BlenderScene.cpp b/code/BlenderScene.cpp index e522fad68..0e1dec7f3 100644 --- a/code/BlenderScene.cpp +++ b/code/BlenderScene.cpp @@ -44,9 +44,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER -#include "BlenderDNA.h" #include "BlenderScene.h" #include "BlenderSceneGen.h" +#include "BlenderDNA.h" using namespace Assimp; using namespace Assimp::Blender; @@ -59,7 +59,9 @@ template <> void Structure :: Convert ( { ReadField(dest.id,"id",db); - ReadField((int&)dest.type,"type",db); + int temp = 0; + ReadField(temp,"type",db); + dest.type = static_cast(temp); ReadFieldArray2(dest.obmat,"obmat",db); ReadFieldArray2(dest.parentinv,"parentinv",db); ReadFieldArray(dest.parsubstr,"parsubstr",db); @@ -100,14 +102,21 @@ template <> void Structure :: Convert ( ) const { - ReadField((short&)dest.mapto,"mapto",db); - ReadField((int&)dest.blendtype,"blendtype",db); + int temp_short = 0; + ReadField(temp_short,"mapto",db); + dest.mapto = static_cast(temp_short); + int temp = 0; + ReadField(temp,"blendtype",db); + dest.blendtype = static_cast(temp); ReadFieldPtr(dest.object,"*object",db); ReadFieldPtr(dest.tex,"*tex",db); ReadFieldArray(dest.uvname,"uvname",db); - ReadField((int&)dest.projx,"projx",db); - ReadField((int&)dest.projy,"projy",db); - ReadField((int&)dest.projz,"projz",db); + ReadField(temp,"projx",db); + dest.projx = static_cast(temp); + ReadField(temp,"projy",db); + dest.projy = static_cast(temp); + ReadField(temp,"projz",db); + dest.projx = static_cast(temp); ReadField(dest.mapping,"mapping",db); ReadFieldArray(dest.ofs,"ofs",db); ReadFieldArray(dest.size,"size",db); @@ -190,7 +199,9 @@ template <> void Structure :: Convert ( { ReadField(dest.id,"id",db); - ReadField((int&)dest.type,"type",db); + int temp = 0; + ReadField(temp,"type",db); + dest.type = static_cast(temp); ReadField(dest.flags,"flags",db); ReadField(dest.colormodel,"colormodel",db); ReadField(dest.totex,"totex",db); @@ -204,7 +215,8 @@ template <> void Structure :: Convert ( ReadField(dest.spotblend,"spotblend",db); ReadField(dest.att1,"att1",db); ReadField(dest.att2,"att2",db); - ReadField((int&)dest.falloff_type,"falloff_type",db); + ReadField(temp,"falloff_type",db); + dest.falloff_type = static_cast(temp); ReadField(dest.sun_brightness,"sun_brightness",db); ReadField(dest.area_size,"area_size",db); ReadField(dest.area_sizey,"area_sizey",db); @@ -522,7 +534,7 @@ template <> void Structure :: Convert ( ReadFieldArray(dest.co,"co",db); ReadFieldArray(dest.no,"no",db); ReadField(dest.flag,"flag",db); - ReadField(dest.mat_nr,"mat_nr",db); + //ReadField(dest.mat_nr,"mat_nr",db); ReadField(dest.bweight,"bweight",db); db.reader->IncPtr(size); @@ -693,8 +705,12 @@ template <> void Structure :: Convert ( const FileDatabase& db ) const { - ReadField((short&)dest.imaflag,"imaflag",db); - ReadField((int&)dest.type,"type",db); + short temp_short = 0; + ReadField(temp_short,"imaflag",db); + dest.imaflag = static_cast(temp_short); + int temp = 0; + ReadField(temp,"type",db); + dest.type = static_cast(temp); ReadFieldPtr(dest.ima,"*ima",db); db.reader->IncPtr(size); @@ -708,8 +724,11 @@ template <> void Structure :: Convert ( { ReadField(dest.id,"id",db); - ReadField((int&)dest.type,"type",db); - ReadField((int&)dest.flag,"flag",db); + int temp = 0; + ReadField(temp,"type",db); + dest.type = static_cast(temp); + ReadField(temp,"flag",db); + dest.flag = static_cast(temp); ReadField(dest.lens,"lens",db); ReadField(dest.sensor_x,"sensor_x",db); ReadField(dest.clipsta,"clipsta",db); diff --git a/code/BlenderScene.h b/code/BlenderScene.h index 04eb4bcad..86ab1f30c 100644 --- a/code/BlenderScene.h +++ b/code/BlenderScene.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -224,6 +225,14 @@ struct TFace : ElemBase { // ------------------------------------------------------------------------------- struct MTFace : ElemBase { + MTFace() + : flag(0) + , mode(0) + , tile(0) + , unwrap(0) + { + } + float uv[4][2] FAIL; char flag; short mode; @@ -616,6 +625,17 @@ struct Object : ElemBase { std::shared_ptr data FAIL; ListBase modifiers; + + Object() + : ElemBase() + , type( Type_EMPTY ) + , parent( nullptr ) + , track() + , proxy() + , proxy_from() + , data() { + // empty + } }; @@ -624,6 +644,15 @@ struct Base : ElemBase { Base* prev WARN; std::shared_ptr next WARN; std::shared_ptr object WARN; + + Base() + : ElemBase() + , prev( nullptr ) + , next() + , object() { + // empty + // empty + } }; // ------------------------------------------------------------------------------- @@ -635,8 +664,15 @@ struct Scene : ElemBase { std::shared_ptr basact WARN; ListBase base; -}; + Scene() + : ElemBase() + , camera() + , world() + , basact() { + // empty + } +}; // ------------------------------------------------------------------------------- struct Image : ElemBase { @@ -664,6 +700,11 @@ struct Image : ElemBase { short animspeed; short gen_x, gen_y, gen_type; + + Image() + : ElemBase() { + // empty + } }; // ------------------------------------------------------------------------------- @@ -751,6 +792,14 @@ struct Tex : ElemBase { //VoxelData *vd; //char use_nodes; + + Tex() + : ElemBase() + , imaflag( ImageFlags_INTERPOL ) + , type( Type_CLOUDS ) + , ima() { + // empty + } }; // ------------------------------------------------------------------------------- @@ -839,9 +888,13 @@ struct MTex : ElemBase { //float lifefac, sizefac, ivelfac, pvelfac; //float shadowfac; //float zenupfac, zendownfac, blendfac; + + MTex() + : ElemBase() { + // empty + } }; - - } +} } #endif diff --git a/code/BlenderTessellator.cpp b/code/BlenderTessellator.cpp index 60879b417..9f4c51048 100644 --- a/code/BlenderTessellator.cpp +++ b/code/BlenderTessellator.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -58,7 +59,11 @@ static const unsigned int BLEND_TESS_MAGIC = 0x83ed9ac3; namspace Assimp { - template< > const std::string LogFunctions< BlenderTessellatorGL >::log_prefix = "BLEND_TESS_GL: "; + template< > const char* LogFunctions< BlenderTessellatorGL >::Prefix() + { + static auto prefix = "BLEND_TESS_GL: "; + return prefix; + } } using namespace Assimp; @@ -251,7 +256,11 @@ void BlenderTessellatorGL::TessellateError( GLenum errorCode, void* ) namespace Assimp { - template< > const std::string LogFunctions< BlenderTessellatorP2T >::log_prefix = "BLEND_TESS_P2T: "; + template< > const char* LogFunctions< BlenderTessellatorP2T >::Prefix() + { + static auto prefix = "BLEND_TESS_P2T: "; + return prefix; + } } using namespace Assimp; diff --git a/code/BlenderTessellator.h b/code/BlenderTessellator.h index 530bd2c3e..47d3a4665 100644 --- a/code/BlenderTessellator.h +++ b/code/BlenderTessellator.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/BlobIOSystem.h b/code/BlobIOSystem.h index 6cd014254..f406ea0fe 100644 --- a/code/BlobIOSystem.h +++ b/code/BlobIOSystem.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -45,10 +46,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_BLOBIOSYSTEM_H_INCLUDED #define AI_BLOBIOSYSTEM_H_INCLUDED -#include "./../include/assimp/IOStream.hpp" -#include "./../include/assimp/cexport.h" -#include "./../include/assimp/IOSystem.hpp" -#include "./../include/assimp/DefaultLogger.hpp" +#include +#include +#include +#include #include #include #include diff --git a/code/ByteSwapper.h b/code/ByteSwapper.h index 37538e7cb..e5c7569f1 100644 --- a/code/ByteSwapper.h +++ b/code/ByteSwapper.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/C4DImporter.cpp b/code/C4DImporter.cpp index 252766ca6..1344f32fb 100644 --- a/code/C4DImporter.cpp +++ b/code/C4DImporter.cpp @@ -185,11 +185,11 @@ void C4DImporter::InternReadFile( const std::string& pFile, if(mesh->mMaterialIndex >= mat_count) { ++mat_count; - ScopeGuard def_material(new aiMaterial()); + std::unique_ptr def_material(new aiMaterial()); const aiString name(AI_DEFAULT_MATERIAL_NAME); def_material->AddProperty(&name, AI_MATKEY_NAME); - materials.push_back(def_material.dismiss()); + materials.push_back(def_material.release()); break; } } @@ -393,7 +393,7 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) // ------------------------------------------------------------------------------------------------ aiMesh* C4DImporter::ReadMesh(BaseObject* object) { - assert(object != NULL && object->GetType() == Opolygon); + ai_assert(object != NULL && object->GetType() == Opolygon); // based on Melange sample code PolygonObject* const polyObject = dynamic_cast(object); @@ -412,7 +412,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) const CPolygon* polys = polyObject->GetPolygonR(); ai_assert(polys != NULL); - ScopeGuard mesh(new aiMesh()); + std::unique_ptr mesh(new aiMesh()); mesh->mNumFaces = static_cast(polyCount); aiFace* face = mesh->mFaces = new aiFace[mesh->mNumFaces](); @@ -616,7 +616,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) } mesh->mMaterialIndex = ResolveMaterial(polyObject); - return mesh.dismiss(); + return mesh.release(); } @@ -635,7 +635,7 @@ unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj) TextureTag& ttag = dynamic_cast(*tag); BaseMaterial* const mat = ttag.GetMaterial(); - assert(mat != NULL); + ai_assert(mat != NULL); const MaterialMap::const_iterator it = material_mapping.find(mat); if(it == material_mapping.end()) { diff --git a/code/C4DImporter.h b/code/C4DImporter.h index 3ba2a17c6..4dea82161 100644 --- a/code/C4DImporter.h +++ b/code/C4DImporter.h @@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BaseImporter.h" #include "LogAux.h" -#include +#include struct aiNode; struct aiMesh; struct aiMaterial; diff --git a/code/CInterfaceIOWrapper.cpp b/code/CInterfaceIOWrapper.cpp index 0a80c1990..9de75b683 100644 --- a/code/CInterfaceIOWrapper.cpp +++ b/code/CInterfaceIOWrapper.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/CInterfaceIOWrapper.h b/code/CInterfaceIOWrapper.h index 0172fb49f..78cac0cf9 100644 --- a/code/CInterfaceIOWrapper.h +++ b/code/CInterfaceIOWrapper.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 3eafbdc62..4d02240da 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -1,7 +1,8 @@ # Open Asset Import Library (assimp) # ---------------------------------------------------------------------- # -# Copyright (c) 2006-2016, assimp team +# Copyright (c) 2006-2017, assimp team + # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -58,8 +59,9 @@ SET( PUBLIC_HEADERS ${HEADER_PATH}/camera.h ${HEADER_PATH}/color4.h ${HEADER_PATH}/color4.inl - ${HEADER_PATH}/config.h + ${CMAKE_CURRENT_BINARY_DIR}/../include/assimp/config.h ${HEADER_PATH}/defs.h + ${HEADER_PATH}/Defines.h ${HEADER_PATH}/cfileio.h ${HEADER_PATH}/light.h ${HEADER_PATH}/material.h @@ -93,6 +95,9 @@ SET( PUBLIC_HEADERS ${HEADER_PATH}/NullLogger.hpp ${HEADER_PATH}/cexport.h ${HEADER_PATH}/Exporter.hpp + ${HEADER_PATH}/DefaultIOStream.h + ${HEADER_PATH}/DefaultIOSystem.h + ${HEADER_PATH}/SceneCombiner.h ) SET( Core_SRCS @@ -125,9 +130,7 @@ SET( Common_SRCS ByteSwapper.h DefaultProgressHandler.h DefaultIOStream.cpp - DefaultIOStream.h DefaultIOSystem.cpp - DefaultIOSystem.h CInterfaceIOWrapper.cpp CInterfaceIOWrapper.h Hash.h @@ -147,13 +150,14 @@ SET( Common_SRCS SpatialSort.cpp SpatialSort.h SceneCombiner.cpp - SceneCombiner.h ScenePreprocessor.cpp ScenePreprocessor.h SkeletonMeshBuilder.cpp SkeletonMeshBuilder.h SplitByBoneCountProcess.cpp SplitByBoneCountProcess.h + ScaleProcess.cpp + ScaleProcess.h SmoothingGroups.h StandardShapes.cpp StandardShapes.h @@ -163,6 +167,7 @@ SET( Common_SRCS RemoveComments.h Subdivision.cpp Subdivision.h + scene.cpp Vertex.h LineSplitter.h TinyFormatter.h @@ -173,6 +178,8 @@ SET( Common_SRCS XMLTools.h Version.cpp IOStreamBuffer.h + CreateAnimMesh.h + CreateAnimMesh.cpp ) SOURCE_GROUP(Common FILES ${Common_SRCS}) @@ -184,10 +191,16 @@ IF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER ) SOURCE_GROUP( C4D FILES ${C4D_SRCS}) ENDIF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER ) +# if this variable is set to TRUE, the user can manually disable importers by setting +# ASSIMP_BUILD_XXX_IMPORTER to FALSE for each importer +# if this variable is set to FALSE, the user can manually enable importers by setting +# ASSIMP_BUILD_XXX_IMPORTER to TRUE for each importer +OPTION(ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_XXX_IMPORTER value" TRUE) + # macro to add the CMake Option ADD_ASSIMP_IMPORTER_ which enables compile of loader # this way selective loaders can be compiled (reduces filesize + compile time) MACRO(ADD_ASSIMP_IMPORTER name) - OPTION(ASSIMP_BUILD_${name}_IMPORTER "build the ${name} importer" TRUE) + OPTION(ASSIMP_BUILD_${name}_IMPORTER "build the ${name} importer" ${ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT}) IF(ASSIMP_BUILD_${name}_IMPORTER) LIST(APPEND ASSIMP_LOADER_SRCS ${ARGN}) SET(ASSIMP_IMPORTERS_ENABLED "${ASSIMP_IMPORTERS_ENABLED} ${name}") @@ -560,6 +573,9 @@ SET( PostProcessing_SRCS ) SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS}) +SET( IrrXML_SRCS irrXMLWrapper.h ) +SOURCE_GROUP( IrrXML FILES ${IrrXML_SRCS}) + ADD_ASSIMP_IMPORTER( Q3D Q3DLoader.cpp Q3DLoader.h @@ -634,6 +650,9 @@ ADD_ASSIMP_IMPORTER(X3D X3DImporter_Rendering.cpp X3DImporter_Shape.cpp X3DImporter_Texturing.cpp + FIReader.hpp + FIReader.cpp + X3DVocabulary.cpp ) ADD_ASSIMP_IMPORTER( GLTF @@ -645,13 +664,34 @@ ADD_ASSIMP_IMPORTER( GLTF glTFImporter.h glTFExporter.h glTFExporter.cpp + glTF2Asset.h + glTF2Asset.inl + glTF2AssetWriter.h + glTF2AssetWriter.inl + glTF2Importer.cpp + glTF2Importer.h + glTF2Exporter.h + glTF2Exporter.cpp ) ADD_ASSIMP_IMPORTER( 3MF D3MFImporter.h D3MFImporter.cpp + D3MFExporter.h + D3MFExporter.cpp D3MFOpcPackage.h D3MFOpcPackage.cpp + 3MFXmlTags.h +) + +ADD_ASSIMP_IMPORTER( MMD + MMDCpp14.h + MMDImporter.cpp + MMDImporter.h + MMDPmdParser.h + MMDPmxParser.h + MMDPmxParser.cpp + MMDVmdParser.h ) SET( Step_SRCS @@ -672,23 +712,6 @@ SET( Extra_SRCS ) SOURCE_GROUP( Extra FILES ${Extra_SRCS}) -SET( IrrXML_SRCS - irrXMLWrapper.h - ../contrib/irrXML/CXMLReaderImpl.h - ../contrib/irrXML/heapsort.h - ../contrib/irrXML/irrArray.h - ../contrib/irrXML/irrString.h - ../contrib/irrXML/irrTypes.h - ../contrib/irrXML/irrXML.cpp - ../contrib/irrXML/irrXML.h -) -SOURCE_GROUP( IrrXML FILES ${IrrXML_SRCS}) - -SET( ConvertUTF_SRCS - ../contrib/ConvertUTF/ConvertUTF.h - ../contrib/ConvertUTF/ConvertUTF.c -) -SOURCE_GROUP( ConvertUTF FILES ${ConvertUTF_SRCS}) SET( Clipper_SRCS ../contrib/clipper/clipper.hpp @@ -720,16 +743,26 @@ SET( unzip_SRCS ) SOURCE_GROUP( unzip FILES ${unzip_SRCS}) +SET( ziplib_SRCS + ../contrib/zip/src/miniz.h + ../contrib/zip/src/zip.c + ../contrib/zip/src/zip.h +) + +SOURCE_GROUP( ziplib FILES ${ziplib_SRCS} ) + SET ( openddl_parser_SRCS ../contrib/openddlparser/code/OpenDDLParser.cpp ../contrib/openddlparser/code/DDLNode.cpp ../contrib/openddlparser/code/OpenDDLCommon.cpp ../contrib/openddlparser/code/OpenDDLExport.cpp ../contrib/openddlparser/code/Value.cpp + ../contrib/openddlparser/code/OpenDDLStream.cpp ../contrib/openddlparser/include/openddlparser/OpenDDLParser.h ../contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h ../contrib/openddlparser/include/openddlparser/OpenDDLCommon.h ../contrib/openddlparser/include/openddlparser/OpenDDLExport.h + ../contrib/openddlparser/include/openddlparser/OpenDDLStream.h ../contrib/openddlparser/include/openddlparser/DDLNode.h ../contrib/openddlparser/include/openddlparser/Value.h ) @@ -824,12 +857,12 @@ SET( assimp_src # Third-party libraries ${IrrXML_SRCS} - ${ConvertUTF_SRCS} ${unzip_compile_SRCS} ${Poly2Tri_SRCS} ${Clipper_SRCS} ${openddl_parser_SRCS} ${open3dgc_SRCS} + ${ziplib_SRCS} # Necessary to show the headers in the project when using the VC++ generator: ${PUBLIC_HEADERS} @@ -839,7 +872,8 @@ SET( assimp_src ADD_DEFINITIONS( -DOPENDDLPARSER_BUILD ) INCLUDE_DIRECTORIES( - ../contrib/openddlparser/include + ${IRRXML_INCLUDE_DIR} + ../contrib/openddlparser/include ) IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) @@ -849,7 +883,7 @@ ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) ADD_LIBRARY( assimp ${assimp_src} ) -TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES} ) +TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES} ${IRRXML_LIBRARY} ) if(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM) set(ASSIMP_ANDROID_JNIIOSYSTEM_PATH port/AndroidJNI) @@ -892,8 +926,27 @@ SET_TARGET_PROPERTIES( assimp PROPERTIES ) if (APPLE) - SET_TARGET_PROPERTIES( assimp PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${ASSIMP_LIB_INSTALL_DIR}") -endif() + SET_TARGET_PROPERTIES( assimp PROPERTIES + INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${ASSIMP_LIB_INSTALL_DIR}" + ) + + if (BUILD_FRAMEWORK) + SET_TARGET_PROPERTIES( assimp PROPERTIES + FRAMEWORK TRUE + FRAMEWORK_VERSION C + MACOSX_FRAMEWORK_IDENTIFIER net.sf.assimp + PUBLIC_HEADER "${PUBLIC_HEADERS}" + ) + + # PUBLIC_HEADER option does not support directory structure creation + # add ./Compiler/*.h to assimp.framework via copy command + ADD_CUSTOM_COMMAND(TARGET assimp POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy_directory + "../${HEADER_PATH}/Compiler" + assimp.framework/Headers/Compiler + COMMENT "Copying public ./Compiler/ header files to framework bundle's Headers/Compiler/") + endif(BUILD_FRAMEWORK) +endif(APPLE) # Build against external unzip, or add ../contrib/unzip so # assimp can #include "unzip.h" @@ -913,9 +966,11 @@ INSTALL( TARGETS assimp LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR} + FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR} COMPONENT ${LIBASSIMP_COMPONENT}) INSTALL( FILES ${PUBLIC_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp COMPONENT assimp-dev) INSTALL( FILES ${COMPILER_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp/Compiler COMPONENT assimp-dev) + if (ASSIMP_ANDROID_JNIIOSYSTEM) INSTALL(FILES ${HEADER_PATH}/${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/AndroidJNIIOSystem.h DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR} @@ -923,14 +978,25 @@ if (ASSIMP_ANDROID_JNIIOSYSTEM) endif(ASSIMP_ANDROID_JNIIOSYSTEM) if(MSVC AND ASSIMP_INSTALL_PDB) - install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb - DESTINATION ${ASSIMP_LIB_INSTALL_DIR} - CONFIGURATIONS Debug - ) - install(FILES ${Assimp_BINARY_DIR}/code/RelWithDebInfo/assimp.pdb - DESTINATION ${ASSIMP_LIB_INSTALL_DIR} - CONFIGURATIONS RelWithDebInfo - ) + IF(CMAKE_GENERATOR MATCHES "^Visual Studio") + install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb + DESTINATION ${ASSIMP_LIB_INSTALL_DIR} + CONFIGURATIONS Debug + ) + install(FILES ${Assimp_BINARY_DIR}/code/RelWithDebInfo/assimp${LIBRARY_SUFFIX}.pdb + DESTINATION ${ASSIMP_LIB_INSTALL_DIR} + CONFIGURATIONS RelWithDebInfo + ) + ELSE() + install(FILES ${Assimp_BINARY_DIR}/code/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb + DESTINATION ${ASSIMP_LIB_INSTALL_DIR} + CONFIGURATIONS Debug + ) + install(FILES ${Assimp_BINARY_DIR}/code/assimp${LIBRARY_SUFFIX}.pdb + DESTINATION ${ASSIMP_LIB_INSTALL_DIR} + CONFIGURATIONS RelWithDebInfo + ) + ENDIF() endif () if (ASSIMP_COVERALLS) diff --git a/code/COBLoader.cpp b/code/COBLoader.cpp index 441dd1c56..a92e231a5 100644 --- a/code/COBLoader.cpp +++ b/code/COBLoader.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team All rights reserved. Redistribution and use of this software in source and binary forms, @@ -57,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include - +#include using namespace Assimp; using namespace Assimp::COB; @@ -941,20 +941,22 @@ void COBImporter::UnsupportedChunk_Binary( StreamReaderLE& reader, const ChunkIn // ------------------------------------------------------------------------------------------------ // tiny utility guard to aid me at staying within chunk boundaries. class chunk_guard { - public: - chunk_guard(const COB::ChunkInfo& nfo, StreamReaderLE& reader) - : nfo(nfo) - , reader(reader) - , cur(reader.GetCurrentPos()) - { + : nfo(nfo) + , reader(reader) + , cur(reader.GetCurrentPos()) { } ~chunk_guard() { // don't do anything if the size is not given if(nfo.size != static_cast(-1)) { - reader.IncPtr(static_cast(nfo.size)-reader.GetCurrentPos()+cur); + try { + reader.IncPtr( static_cast< int >( nfo.size ) - reader.GetCurrentPos() + cur ); + } catch ( DeadlyImportError e ) { + // out of limit so correct the value + reader.IncPtr( reader.GetReadLimit() ); + } } } diff --git a/code/COBLoader.h b/code/COBLoader.h index efccc448d..46dc86f62 100644 --- a/code/COBLoader.h +++ b/code/COBLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/COBScene.h b/code/COBScene.h index 0e27d1461..a1d6ebc27 100644 --- a/code/COBScene.h +++ b/code/COBScene.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -46,12 +47,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include "BaseImporter.h" -#include "./../include/assimp/material.h" +#include -namespace Assimp { - namespace COB { +namespace Assimp { +namespace COB { // ------------------ /** Represents a single vertex index in a face */ diff --git a/code/CSMLoader.cpp b/code/CSMLoader.cpp index 5f274c51f..eeb6986b0 100644 --- a/code/CSMLoader.cpp +++ b/code/CSMLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -57,7 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include - +#include using namespace Assimp; diff --git a/code/CSMLoader.h b/code/CSMLoader.h index 71abb7e91..55a632dc6 100644 --- a/code/CSMLoader.h +++ b/code/CSMLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/CalcTangentsProcess.cpp b/code/CalcTangentsProcess.cpp index c13ffcb24..2af16fcc0 100644 --- a/code/CalcTangentsProcess.cpp +++ b/code/CalcTangentsProcess.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/CalcTangentsProcess.h b/code/CalcTangentsProcess.h index 4a6122668..a22785639 100644 --- a/code/CalcTangentsProcess.h +++ b/code/CalcTangentsProcess.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp index 6c576a12d..4a10d5845 100644 --- a/code/ColladaExporter.cpp +++ b/code/ColladaExporter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -38,18 +39,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ - - #ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER -#include "ColladaExporter.h" +#include "ColladaExporter.h" #include "Bitmap.h" #include "fast_atof.h" -#include "SceneCombiner.h" -#include "DefaultIOSystem.h" +#include #include "StringUtils.h" #include "XMLTools.h" +#include #include #include #include @@ -59,6 +58,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include +#include using namespace Assimp; @@ -67,13 +68,17 @@ namespace Assimp // ------------------------------------------------------------------------------------------------ // Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp -void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) +void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { std::string path = DefaultIOSystem::absolutePath(std::string(pFile)); std::string file = DefaultIOSystem::completeBaseName(std::string(pFile)); // invoke the exporter ColladaExporter iDoTheExportThing( pScene, pIOSystem, path, file); + + if (iDoTheExportThing.mOutput.fail()) { + throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); + } // we're still here - export successfully completed. Write result to the given IOSYstem std::unique_ptr outfile (pIOSystem->Open(pFile,"wt")); @@ -103,7 +108,7 @@ ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, co // set up strings endstr = "\n"; - // start writing + // start writing the file WriteFile(); } @@ -133,8 +138,12 @@ void ColladaExporter::WriteFile() WriteLightsLibrary(); WriteMaterials(); WriteGeometryLibrary(); + WriteControllerLibrary(); WriteSceneLibrary(); + + // customized, Writes the animation library + WriteAnimationsLibrary(); // useless Collada fu at the end, just in case we haven't had enough indirections, yet. mOutput << startstr << "" << endstr; @@ -550,7 +559,7 @@ void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::strin std::stringstream imageUrlEncoded; for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it ) { - if( isalnum_C( (unsigned char) *it) || *it == ':' || *it == '_' || *it == '.' || *it == '/' || *it == '\\' ) + if( isalnum_C( (unsigned char) *it) || *it == ':' || *it == '_' || *it == '-' || *it == '.' || *it == '/' || *it == '\\' ) imageUrlEncoded << *it; else imageUrlEncoded << '%' << std::hex << size_t( (unsigned char) *it) << std::dec; @@ -652,7 +661,7 @@ void ColladaExporter::WriteMaterials() if( materialCountWithThisName == 0 ) { materials[a].name = name.C_Str(); } else { - materials[a].name = std::string(name.C_Str()) + to_string(materialCountWithThisName); + materials[a].name = std::string(name.C_Str()) + to_string(materialCountWithThisName); } } for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) { @@ -692,7 +701,6 @@ void ColladaExporter::WriteMaterials() materials[a].shininess.exist = mat->Get( AI_MATKEY_SHININESS, materials[a].shininess.value) == aiReturn_SUCCESS; materials[a].transparency.exist = mat->Get( AI_MATKEY_OPACITY, materials[a].transparency.value) == aiReturn_SUCCESS; - materials[a].transparency.value = materials[a].transparency.value; materials[a].index_refraction.exist = mat->Get( AI_MATKEY_REFRACTI, materials[a].index_refraction.value) == aiReturn_SUCCESS; } @@ -787,6 +795,177 @@ void ColladaExporter::WriteMaterials() } } +// ------------------------------------------------------------------------------------------------ +// Writes the controller library +void ColladaExporter::WriteControllerLibrary() +{ + mOutput << startstr << "" << endstr; + PushTag(); + + for( size_t a = 0; a < mScene->mNumMeshes; ++a) + WriteController( a); + + PopTag(); + mOutput << startstr << "" << endstr; +} + +// ------------------------------------------------------------------------------------------------ +// Writes a skin controller of the given mesh +void ColladaExporter::WriteController( size_t pIndex) +{ + const aiMesh* mesh = mScene->mMeshes[pIndex]; + const std::string idstr = GetMeshId( pIndex); + const std::string idstrEscaped = XMLEscape(idstr); + + if ( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) + return; + + if ( mesh->mNumBones == 0 ) + return; + + mOutput << startstr << ""<< endstr; + PushTag(); + + mOutput << startstr << "" << endstr; + PushTag(); + + // bind pose matrix + mOutput << startstr << "" << endstr; + PushTag(); + + // I think it is identity in general cases. + aiMatrix4x4 mat; + mOutput << startstr << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << endstr; + mOutput << startstr << mat.b1 << " " << mat.b2 << " " << mat.b3 << " " << mat.b4 << endstr; + mOutput << startstr << mat.c1 << " " << mat.c2 << " " << mat.c3 << " " << mat.c4 << endstr; + mOutput << startstr << mat.d1 << " " << mat.d2 << " " << mat.d3 << " " << mat.d4 << endstr; + + PopTag(); + mOutput << startstr << "" << endstr; + + mOutput << startstr << "" << endstr; + PushTag(); + + mOutput << startstr << "mNumBones << "\">"; + + for( size_t i = 0; i < mesh->mNumBones; ++i ) + mOutput << XMLEscape(mesh->mBones[i]->mName.C_Str()) << " "; + + mOutput << "" << endstr; + + mOutput << startstr << "" << endstr; + PushTag(); + + mOutput << startstr << "mNumBones << "\" stride=\"" << 1 << "\">" << endstr; + PushTag(); + + mOutput << startstr << "" << endstr; + + PopTag(); + mOutput << startstr << "" << endstr; + + PopTag(); + mOutput << startstr << "" << endstr; + + PopTag(); + mOutput << startstr << "" << endstr; + + std::vector bind_poses; + bind_poses.reserve(mesh->mNumBones * 16); + for(unsigned int i = 0; i < mesh->mNumBones; ++i) + for( unsigned int j = 0; j < 4; ++j) + bind_poses.insert(bind_poses.end(), mesh->mBones[i]->mOffsetMatrix[j], mesh->mBones[i]->mOffsetMatrix[j] + 4); + + WriteFloatArray( idstr + "-skin-bind_poses", FloatType_Mat4x4, (const ai_real*) bind_poses.data(), bind_poses.size() / 16); + + bind_poses.clear(); + + std::vector skin_weights; + skin_weights.reserve(mesh->mNumVertices * mesh->mNumBones); + for( size_t i = 0; i < mesh->mNumBones; ++i) + for( size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j) + skin_weights.push_back(mesh->mBones[i]->mWeights[j].mWeight); + + WriteFloatArray( idstr + "-skin-weights", FloatType_Weight, (const ai_real*) skin_weights.data(), skin_weights.size()); + + skin_weights.clear(); + + mOutput << startstr << "" << endstr; + PushTag(); + + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; + + PopTag(); + mOutput << startstr << "" << endstr; + + mOutput << startstr << "mNumVertices << "\">" << endstr; + PushTag(); + + mOutput << startstr << "" << endstr; + mOutput << startstr << "" << endstr; + + mOutput << startstr << ""; + + std::vector num_influences(mesh->mNumVertices, (ai_uint)0); + for( size_t i = 0; i < mesh->mNumBones; ++i) + for( size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j) + ++num_influences[mesh->mBones[i]->mWeights[j].mVertexId]; + + for( size_t i = 0; i < mesh->mNumVertices; ++i) + mOutput << num_influences[i] << " "; + + mOutput << "" << endstr; + + mOutput << startstr << ""; + + ai_uint joint_weight_indices_length = 0; + std::vector accum_influences; + accum_influences.reserve(num_influences.size()); + for( size_t i = 0; i < num_influences.size(); ++i) + { + accum_influences.push_back(joint_weight_indices_length); + joint_weight_indices_length += num_influences[i]; + } + + ai_uint weight_index = 0; + std::vector joint_weight_indices(2 * joint_weight_indices_length, (ai_int)-1); + for( unsigned int i = 0; i < mesh->mNumBones; ++i) + for( unsigned j = 0; j < mesh->mBones[i]->mNumWeights; ++j) + { + unsigned int vId = mesh->mBones[i]->mWeights[j].mVertexId; + for( ai_uint k = 0; k < num_influences[vId]; ++k) + { + if (joint_weight_indices[2 * (accum_influences[vId] + k)] == -1) + { + joint_weight_indices[2 * (accum_influences[vId] + k)] = i; + joint_weight_indices[2 * (accum_influences[vId] + k) + 1] = weight_index; + break; + } + } + ++weight_index; + } + + for( size_t i = 0; i < joint_weight_indices.size(); ++i) + mOutput << joint_weight_indices[i] << " "; + + num_influences.clear(); + accum_influences.clear(); + joint_weight_indices.clear(); + + mOutput << "" << endstr; + + PopTag(); + mOutput << startstr << "" << endstr; + + PopTag(); + mOutput << startstr << "" << endstr; + + PopTag(); + mOutput << startstr << "" << endstr; +} + // ------------------------------------------------------------------------------------------------ // Writes the geometry library void ColladaExporter::WriteGeometryLibrary() @@ -809,8 +988,8 @@ void ColladaExporter::WriteGeometry( size_t pIndex) const std::string idstr = GetMeshId( pIndex); const std::string idstrEscaped = XMLEscape(idstr); - if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) - return; + if ( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) + return; // opening tag mOutput << startstr << "" << endstr; @@ -843,22 +1022,10 @@ void ColladaExporter::WriteGeometry( size_t pIndex) } // assemble vertex structure + // Only write input for POSITION since we will write other as shared inputs in polygon definition mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; - if( mesh->HasNormals() ) - mOutput << startstr << "" << endstr; - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) - { - if( mesh->HasTextureCoords(static_cast(a)) ) - mOutput << startstr << "" << endstr; - } - for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) - { - if( mesh->HasVertexColors(static_cast(a) ) ) - mOutput << startstr << "" << endstr; - } - PopTag(); mOutput << startstr << "" << endstr; @@ -877,6 +1044,19 @@ void ColladaExporter::WriteGeometry( size_t pIndex) mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; + if( mesh->HasNormals() ) + mOutput << startstr << "" << endstr; + for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) + { + if( mesh->HasTextureCoords(static_cast(a)) ) + mOutput << startstr << "" << endstr; + } + for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) + { + if( mesh->HasVertexColors(static_cast(a) ) ) + mOutput << startstr << "" << endstr; + } + mOutput << startstr << "

"; for( size_t a = 0; a < mesh->mNumFaces; ++a ) { @@ -898,10 +1078,17 @@ void ColladaExporter::WriteGeometry( size_t pIndex) mOutput << startstr << "" << endstr; PushTag(); mOutput << startstr << "" << endstr; + if( mesh->HasNormals() ) + mOutput << startstr << "" << endstr; for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) { - if( mesh->HasTextureCoords(static_cast(a) ) ) - mOutput << startstr << "" << endstr; + if( mesh->HasTextureCoords(static_cast(a)) ) + mOutput << startstr << "" << endstr; + } + for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a ) + { + if( mesh->HasVertexColors(static_cast(a) ) ) + mOutput << startstr << "" << endstr; } mOutput << startstr << ""; @@ -943,6 +1130,9 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy case FloatType_TexCoord2: floatsPerElement = 2; break; case FloatType_TexCoord3: floatsPerElement = 3; break; case FloatType_Color: floatsPerElement = 3; break; + case FloatType_Mat4x4: floatsPerElement = 16; break; + case FloatType_Weight: floatsPerElement = 1; break; + case FloatType_Time: floatsPerElement = 1; break; default: return; } @@ -1011,7 +1201,21 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy mOutput << startstr << "" << endstr; mOutput << startstr << "" << endstr; break; - } + + case FloatType_Mat4x4: + mOutput << startstr << "" << endstr; + break; + + case FloatType_Weight: + mOutput << startstr << "" << endstr; + break; + + // customized, add animation related + case FloatType_Time: + mOutput << startstr << "" << endstr; + break; + + } PopTag(); mOutput << startstr << "" << endstr; @@ -1041,7 +1245,172 @@ void ColladaExporter::WriteSceneLibrary() PopTag(); mOutput << startstr << "" << endstr; } +// ------------------------------------------------------------------------------------------------ +void ColladaExporter::WriteAnimationLibrary(size_t pIndex) +{ + const aiAnimation * anim = mScene->mAnimations[pIndex]; + + if ( anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels ==0 ) + return; + + const std::string animation_name_escaped = XMLEscape( anim->mName.C_Str() ); + std::string idstr = anim->mName.C_Str(); + std::string ending = std::string( "AnimId" ) + to_string(pIndex); + if (idstr.length() >= ending.length()) { + if (0 != idstr.compare (idstr.length() - ending.length(), ending.length(), ending)) { + idstr = idstr + ending; + } + } else { + idstr = idstr + ending; + } + const std::string idstrEscaped = XMLEscape(idstr); + + mOutput << startstr << "" << endstr; + PushTag(); + + for (size_t a = 0; a < anim->mNumChannels; ++a) { + const aiNodeAnim * nodeAnim = anim->mChannels[a]; + + // sanity check + if ( nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys ) continue; + + { + const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-input"); + + std::vector frames; + for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { + frames.push_back(static_cast(nodeAnim->mPositionKeys[i].mTime)); + } + + WriteFloatArray( node_idstr , FloatType_Time, (const ai_real*) frames.data(), frames.size()); + frames.clear(); + } + + { + const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-output"); + + std::vector keyframes; + keyframes.reserve(nodeAnim->mNumPositionKeys * 16); + for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { + + aiVector3D Scaling = nodeAnim->mScalingKeys[i].mValue; + aiMatrix4x4 ScalingM; // identity + ScalingM[0][0] = Scaling.x; ScalingM[1][1] = Scaling.y; ScalingM[2][2] = Scaling.z; + + aiQuaternion RotationQ = nodeAnim->mRotationKeys[i].mValue; + aiMatrix4x4 s = aiMatrix4x4( RotationQ.GetMatrix() ); + aiMatrix4x4 RotationM(s.a1, s.a2, s.a3, 0, s.b1, s.b2, s.b3, 0, s.c1, s.c2, s.c3, 0, 0, 0, 0, 1); + + aiVector3D Translation = nodeAnim->mPositionKeys[i].mValue; + aiMatrix4x4 TranslationM; // identity + TranslationM[0][3] = Translation.x; TranslationM[1][3] = Translation.y; TranslationM[2][3] = Translation.z; + + // Combine the above transformations + aiMatrix4x4 mat = TranslationM * RotationM * ScalingM; + + for( unsigned int j = 0; j < 4; ++j) { + keyframes.insert(keyframes.end(), mat[j], mat[j] + 4); + } + } + + WriteFloatArray( node_idstr, FloatType_Mat4x4, (const ai_real*) keyframes.data(), keyframes.size() / 16); + } + + { + std::vector names; + for ( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { + if ( nodeAnim->mPreState == aiAnimBehaviour_DEFAULT + || nodeAnim->mPreState == aiAnimBehaviour_LINEAR + || nodeAnim->mPreState == aiAnimBehaviour_REPEAT + ) { + names.push_back( "LINEAR" ); + } else if (nodeAnim->mPostState == aiAnimBehaviour_CONSTANT) { + names.push_back( "STEP" ); + } + } + + const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-interpolation"); + std::string arrayId = node_idstr + "-array"; + + mOutput << startstr << "" << endstr; + PushTag(); + + // source array + mOutput << startstr << " "; + for( size_t a = 0; a < names.size(); ++a ) { + mOutput << names[a] << " "; + } + mOutput << "" << endstr; + + mOutput << startstr << "" << endstr; + PushTag(); + + mOutput << startstr << "" << endstr; + PushTag(); + + mOutput << startstr << "" << endstr; + + PopTag(); + mOutput << startstr << "" << endstr; + + PopTag(); + mOutput << startstr << "" << endstr; + + PopTag(); + mOutput << startstr << "" << endstr; + } + + } + + for (size_t a = 0; a < anim->mNumChannels; ++a) { + const aiNodeAnim * nodeAnim = anim->mChannels[a]; + + { + // samplers + const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-sampler"); + mOutput << startstr << "" << endstr; + PushTag(); + + mOutput << startstr << "mNodeName.data + std::string("_matrix-input") ) << "\"/>" << endstr; + mOutput << startstr << "mNodeName.data + std::string("_matrix-output") ) << "\"/>" << endstr; + mOutput << startstr << "mNodeName.data + std::string("_matrix-interpolation") ) << "\"/>" << endstr; + + PopTag(); + mOutput << startstr << "" << endstr; + } + } + + for (size_t a = 0; a < anim->mNumChannels; ++a) { + const aiNodeAnim * nodeAnim = anim->mChannels[a]; + + { + // channels + mOutput << startstr << "mNodeName.data + std::string("_matrix-sampler") ) << "\" target=\"" << XMLEscape(nodeAnim->mNodeName.data) << "/matrix\"/>" << endstr; + } + } + + PopTag(); + mOutput << startstr << "" << endstr; + +} +// ------------------------------------------------------------------------------------------------ +void ColladaExporter::WriteAnimationsLibrary() +{ + const std::string scene_name_escaped = XMLEscape(mScene->mRootNode->mName.C_Str()); + + if ( mScene->mNumAnimations > 0 ) { + mOutput << startstr << "" << endstr; + PushTag(); + + // start recursive write at the root node + for( size_t a = 0; a < mScene->mNumAnimations; ++a) + WriteAnimationLibrary( a ); + + PopTag(); + mOutput << startstr << "" << endstr; + } +} // ------------------------------------------------------------------------------------------------ // Helper to find a bone by name in the scene aiBone* findBone( const aiScene* scene, const char * name) { @@ -1057,6 +1426,59 @@ aiBone* findBone( const aiScene* scene, const char * name) { return NULL; } +// ------------------------------------------------------------------------------------------------ +const aiNode * findBoneNode( const aiNode* aNode, const aiBone* bone) +{ + if ( aNode && bone && aNode->mName == bone->mName ) { + return aNode; + } + + if ( aNode && bone ) { + for (unsigned int i=0; i < aNode->mNumChildren; ++i) { + aiNode * aChild = aNode->mChildren[i]; + const aiNode * foundFromChild = 0; + if ( aChild ) { + foundFromChild = findBoneNode( aChild, bone ); + if ( foundFromChild ) return foundFromChild; + } + } + } + + return NULL; +} + +const aiNode * findSkeletonRootNode( const aiScene* scene, const aiMesh * mesh) +{ + std::set topParentBoneNodes; + if ( mesh && mesh->mNumBones > 0 ) { + for (unsigned int i=0; i < mesh->mNumBones; ++i) { + aiBone * bone = mesh->mBones[i]; + + const aiNode * node = findBoneNode( scene->mRootNode, bone); + if ( node ) { + while ( node->mParent && findBone(scene, node->mParent->mName.C_Str() ) != 0 ) { + node = node->mParent; + } + topParentBoneNodes.insert( node ); + } + } + } + + if ( !topParentBoneNodes.empty() ) { + const aiNode * parentBoneNode = *topParentBoneNodes.begin(); + if ( topParentBoneNodes.size() == 1 ) { + return parentBoneNode; + } else { + for (auto it : topParentBoneNodes) { + if ( it->mParent ) return it->mParent; + } + return parentBoneNode; + } + } + + return NULL; +} + // ------------------------------------------------------------------------------------------------ // Recursively writes the given node void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) @@ -1072,16 +1494,34 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) // If the node is associated with a bone, it is a joint node (JOINT) // otherwise it is a normal node (NODE) const char * node_type; + bool is_joint, is_skeleton_root = false; if (NULL == findBone(pScene, pNode->mName.C_Str())) { node_type = "NODE"; + is_joint = false; } else { node_type = "JOINT"; + is_joint = true; + if(!pNode->mParent || NULL == findBone(pScene, pNode->mParent->mName.C_Str())) + is_skeleton_root = true; } const std::string node_name_escaped = XMLEscape(pNode->mName.data); + /* // customized, Note! the id field is crucial for inter-xml look up, it cannot be replaced with sid ?! mOutput << startstr - << "" << endstr; PushTag(); @@ -1089,7 +1529,11 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) // write transformation - we can directly put the matrix there // TODO: (thom) decompose into scale - rot - quad to allow addressing it by animations afterwards const aiMatrix4x4& mat = pNode->mTransformation; - mOutput << startstr << ""; + + // customized, sid should be 'matrix' to match with loader code. + //mOutput << startstr << ""; + mOutput << startstr << ""; + mOutput << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << " "; mOutput << mat.b1 << " " << mat.b2 << " " << mat.b3 << " " << mat.b4 << " "; mOutput << mat.c1 << " " << mat.c2 << " " << mat.c3 << " " << mat.c4 << " "; @@ -1117,33 +1561,56 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode) for( size_t a = 0; a < pNode->mNumMeshes; ++a ) { const aiMesh* mesh = mScene->mMeshes[pNode->mMeshes[a]]; - // do not instanciate mesh if empty. I wonder how this could happen - if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) - continue; - mOutput << startstr << "mMeshes[a])) << "\">" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "" << endstr; - PushTag(); - mOutput << startstr << "mMaterialIndex].name) << "\">" << endstr; - PushTag(); - for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) - { - if( mesh->HasTextureCoords( static_cast(a) ) ) - // semantic as in - // input_semantic as in - // input_set as in - mOutput << startstr << "" << endstr; - } - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; - PopTag(); - mOutput << startstr << "" << endstr; + // do not instantiate mesh if empty. I wonder how this could happen + if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 ) + continue; + + if( mesh->mNumBones == 0 ) + { + mOutput << startstr << "mMeshes[a])) << "\">" << endstr; + PushTag(); + } + else + { + mOutput << startstr + << "mMeshes[a])) << "-skin\">" + << endstr; + PushTag(); + + // note! this mFoundSkeletonRootNodeID some how affects animation, it makes the mesh attaches to armature skeleton root node. + // use the first bone to find skeleton root + const aiNode * skeletonRootBoneNode = findSkeletonRootNode( pScene, mesh ); + if ( skeletonRootBoneNode ) { + mFoundSkeletonRootNodeID = XMLEscape( skeletonRootBoneNode->mName.C_Str() ); + } + mOutput << startstr << "#" << mFoundSkeletonRootNodeID << "" << endstr; + } + mOutput << startstr << "" << endstr; + PushTag(); + mOutput << startstr << "" << endstr; + PushTag(); + mOutput << startstr << "mMaterialIndex].name) << "\">" << endstr; + PushTag(); + for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a ) + { + if( mesh->HasTextureCoords( static_cast(a) ) ) + // semantic as in + // input_semantic as in + // input_set as in + mOutput << startstr << "" << endstr; + } + PopTag(); + mOutput << startstr << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; + PopTag(); + mOutput << startstr << "" << endstr; + + PopTag(); + if( mesh->mNumBones == 0) + mOutput << startstr << "" << endstr; + else + mOutput << startstr << "" << endstr; } // recurse into subnodes diff --git a/code/ColladaExporter.h b/code/ColladaExporter.h index e8bd9b71f..e7a4a9b5d 100644 --- a/code/ColladaExporter.h +++ b/code/ColladaExporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -101,13 +102,21 @@ protected: void WriteSpotLight(const aiLight *const light); void WriteAmbienttLight(const aiLight *const light); + /// Writes the controller library + void WriteControllerLibrary(); + + /// Writes a skin controller of the given mesh + void WriteController( size_t pIndex); + /// Writes the geometry library void WriteGeometryLibrary(); /// Writes the given mesh void WriteGeometry( size_t pIndex); - enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color }; + //enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight }; + // customized to add animation related type + enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight, FloatType_Time }; /// Writes a float array of the given type void WriteFloatArray( const std::string& pIdString, FloatDataType pType, const ai_real* pData, size_t pElementCount); @@ -115,13 +124,21 @@ protected: /// Writes the scene library void WriteSceneLibrary(); + // customized, Writes the animation library + void WriteAnimationsLibrary(); + void WriteAnimationLibrary( size_t pIndex); + std::string mFoundSkeletonRootNodeID = "skeleton_root"; // will be replaced by found node id in the WriteNode call. + /// Recursively writes the given node void WriteNode( const aiScene* scene, aiNode* pNode); /// Enters a new xml element, which increases the indentation void PushTag() { startstr.append( " "); } /// Leaves an element, decreasing the indentation - void PopTag() { ai_assert( startstr.length() > 1); startstr.erase( startstr.length() - 2); } + void PopTag() { + ai_assert( startstr.length() > 1); + startstr.erase( startstr.length() - 2); + } /// Creates a mesh ID for the given mesh std::string GetMeshId( size_t pIndex) const { diff --git a/code/ColladaHelper.h b/code/ColladaHelper.h index a3cba264b..e691a6062 100644 --- a/code/ColladaHelper.h +++ b/code/ColladaHelper.h @@ -4,7 +4,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -43,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_COLLADAHELPER_H_INC #define AI_COLLADAHELPER_H_INC -#include #include #include #include @@ -89,6 +89,21 @@ enum InputType IT_Bitangent }; +/** Supported controller types */ +enum ControllerType +{ + Skin, + Morph +}; + +/** Supported morph methods */ +enum MorphMethod +{ + Normalized, + Relative +}; + + /** Contains all data for one of the different transformation types */ struct Transform { @@ -287,7 +302,7 @@ struct Accessor size_t mOffset; // in number of values size_t mStride; // Stride in number of values std::vector mParams; // names of the data streams in the accessors. Empty string tells to ignore. - size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, thats XYZ, for a color RGBA and so on. + size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, that's XYZ, for a color RGBA and so on. // For example, SubOffset[0] denotes which of the values inside the object is the vector X component. std::string mSource; // URL of the source array mutable const Data* mData; // Pointer to the source array, if resolved. NULL else @@ -380,6 +395,12 @@ enum PrimitiveType /** A skeleton controller to deform a mesh with the use of joints */ struct Controller { + // controller type + ControllerType mType; + + // Morphing method if type is Morph + MorphMethod mMethod; + // the URL of the mesh deformed by the controller. std::string mMeshId; @@ -402,6 +423,9 @@ struct Controller // JointIndex-WeightIndex pairs for all vertices std::vector< std::pair > mWeights; + + std::string mMorphTarget; + std::string mMorphWeight; }; /** A collada material. Pretty much the only member is a reference to an effect. */ @@ -577,6 +601,12 @@ struct AnimationChannel std::string mSourceTimes; /** Source URL of the value values. Collada calls them "output". */ std::string mSourceValues; + /** Source URL of the IN_TANGENT semantic values. */ + std::string mInTanValues; + /** Source URL of the OUT_TANGENT semantic values. */ + std::string mOutTanValues; + /** Source URL of the INTERPOLATION semantic values. */ + std::string mInterpolationValues; }; /** An animation. Container for 0-x animation channels or 0-x animations */ @@ -645,6 +675,7 @@ struct Animation struct ChannelEntry { const Collada::AnimationChannel* mChannel; ///> the source channel + std::string mTargetId; std::string mTransformId; // the ID of the transformation step of the node which is influenced size_t mTransformIndex; // Index into the node's transform chain to apply the channel to size_t mSubElement; // starting index inside the transform data diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index 5de48120c..d2141c374 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -49,20 +50,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include "ColladaParser.h" +#include +#include "ColladaParser.h" #include "fast_atof.h" #include "ParsingUtils.h" #include "SkeletonMeshBuilder.h" -#include "Defines.h" +#include "CreateAnimMesh.h" #include "time.h" #include "math.h" #include -#include #include -#include "Defines.h" - +#include using namespace Assimp; using namespace Assimp::Formatter; @@ -119,7 +119,7 @@ bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, boo * might be NULL and it's our duty to return true here. */ if (!pIOHandler)return true; - const char* tokens[] = {"collada"}; + const char* tokens[] = {"GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0; } - // ------------------------------------------------------------------------------------------------ // Get file extension list const aiImporterDesc* ColladaLoader::GetInfo () const @@ -150,6 +149,7 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I mMeshIndexByID.clear(); mMaterialIndexByName.clear(); mMeshes.clear(); + mTargetMeshes.clear(); newMats.clear(); mLights.clear(); mCameras.clear(); @@ -571,6 +571,21 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll } } +// ------------------------------------------------------------------------------------------------ +// Find mesh from either meshes or morph target meshes +aiMesh *ColladaLoader::findMesh(std::string meshid) +{ + for (unsigned int i = 0; i < mMeshes.size(); i++) + if (std::string(mMeshes[i]->mName.data) == meshid) + return mMeshes[i]; + + for (unsigned int i = 0; i < mTargetMeshes.size(); i++) + if (std::string(mTargetMeshes[i]->mName.data) == meshid) + return mTargetMeshes[i]; + + return NULL; +} + // ------------------------------------------------------------------------------------------------ // Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh, @@ -656,8 +671,70 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada:: face.mIndices[b] = static_cast(vertex++); } + // create morph target meshes if any + std::vector targetMeshes; + std::vector targetWeights; + Collada::MorphMethod method = Collada::Normalized; + + for(std::map::const_iterator it = pParser.mControllerLibrary.begin(); + it != pParser.mControllerLibrary.end(); it++) + { + const Collada::Controller &c = it->second; + const Collada::Mesh* baseMesh = pParser.ResolveLibraryReference( pParser.mMeshLibrary, c.mMeshId); + + if (c.mType == Collada::Morph && baseMesh->mName == pSrcMesh->mName) + { + const Collada::Accessor& targetAccessor = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, c.mMorphTarget); + const Collada::Accessor& weightAccessor = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, c.mMorphWeight); + const Collada::Data& targetData = pParser.ResolveLibraryReference( pParser.mDataLibrary, targetAccessor.mSource); + const Collada::Data& weightData = pParser.ResolveLibraryReference( pParser.mDataLibrary, weightAccessor.mSource); + + // take method + method = c.mMethod; + + if (!targetData.mIsStringArray) + throw DeadlyImportError( "target data must contain id. "); + if (weightData.mIsStringArray) + throw DeadlyImportError( "target weight data must not be textual "); + + for (unsigned int i = 0; i < targetData.mStrings.size(); ++i) + { + const Collada::Mesh* targetMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, targetData.mStrings.at(i)); + + aiMesh *aimesh = findMesh(targetMesh->mName); + if (!aimesh) + { + if (targetMesh->mSubMeshes.size() > 1) + throw DeadlyImportError( "Morhing target mesh must be a single"); + aimesh = CreateMesh(pParser, targetMesh, targetMesh->mSubMeshes.at(0), NULL, 0, 0); + mTargetMeshes.push_back(aimesh); + } + targetMeshes.push_back(aimesh); + } + for (unsigned int i = 0; i < weightData.mValues.size(); ++i) + targetWeights.push_back(weightData.mValues.at(i)); + } + } + if (targetMeshes.size() > 0 && targetWeights.size() == targetMeshes.size()) + { + std::vector animMeshes; + for (unsigned int i = 0; i < targetMeshes.size(); i++) + { + aiAnimMesh *animMesh = aiCreateAnimMesh(targetMeshes.at(i)); + animMesh->mWeight = targetWeights[i]; + animMeshes.push_back(animMesh); + } + dstMesh->mMethod = (method == Collada::Relative) + ? aiMorphingMethod_MORPH_RELATIVE + : aiMorphingMethod_MORPH_NORMALIZED; + dstMesh->mAnimMeshes = new aiAnimMesh*[animMeshes.size()]; + dstMesh->mNumAnimMeshes = static_cast(animMeshes.size()); + for (unsigned int i = 0; i < animMeshes.size(); i++) + dstMesh->mAnimMeshes[i] = animMeshes.at(i); + } + // create bones if given - if( pSrcController) + if( pSrcController && pSrcController->mType == Collada::Skin) { // refuse if the vertex count does not match // if( pSrcController->mWeightCounts.size() != dstMesh->mNumVertices) @@ -956,6 +1033,68 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars CreateAnimation( pScene, pParser, pSrcAnim, animName); } +struct MorphTimeValues +{ + float mTime; + struct key + { + float mWeight; + unsigned int mValue; + }; + std::vector mKeys; +}; + +void insertMorphTimeValue(std::vector &values, float time, float weight, unsigned int value) +{ + MorphTimeValues::key k; + k.mValue = value; + k.mWeight = weight; + if (values.size() == 0 || time < values[0].mTime) + { + MorphTimeValues val; + val.mTime = time; + val.mKeys.push_back(k); + values.insert(values.begin(), val); + return; + } + if (time > values.back().mTime) + { + MorphTimeValues val; + val.mTime = time; + val.mKeys.push_back(k); + values.insert(values.end(), val); + return; + } + for (unsigned int i = 0; i < values.size(); i++) + { + if (std::abs(time - values[i].mTime) < 1e-6f) + { + values[i].mKeys.push_back(k); + return; + } else if (time > values[i].mTime && time < values[i+1].mTime) + { + MorphTimeValues val; + val.mTime = time; + val.mKeys.push_back(k); + values.insert(values.begin() + i, val); + return; + } + } + // should not get here +} + +float getWeightAtKey(const std::vector &values, int key, unsigned int value) +{ + for (unsigned int i = 0; i < values[key].mKeys.size(); i++) + { + if (values[key].mKeys[i].mValue == value) + return values[key].mKeys[i].mWeight; + } + // no value at key found, try to interpolate if present at other keys. if not, return zero + // TODO: interpolation + return 0.0f; +} + // ------------------------------------------------------------------------------------------------ // Constructs the animation for the given source anim void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string& pName) @@ -965,6 +1104,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars CollectNodes( pScene->mRootNode, nodes); std::vector anims; + std::vector morphAnims; + for( std::vector::const_iterator nit = nodes.begin(); nit != nodes.end(); ++nit) { // find all the collada anim channels which refer to the current node @@ -988,7 +1129,20 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars // find the slash that separates the node name - there should be only one std::string::size_type slashPos = srcChannel.mTarget.find( '/'); if( slashPos == std::string::npos) + { + std::string::size_type targetPos = srcChannel.mTarget.find(srcNode->mID); + if (targetPos == std::string::npos) + continue; + + // not node transform, but something else. store as unknown animation channel for now + entry.mChannel = &(*cit); + entry.mTargetId = srcChannel.mTarget.substr(targetPos + pSrcAnim->mName.length(), + srcChannel.mTarget.length() - targetPos - pSrcAnim->mName.length()); + if (entry.mTargetId.front() == '-') + entry.mTargetId = entry.mTargetId.substr(1); + entries.push_back(entry); continue; + } if( srcChannel.mTarget.find( '/', slashPos+1) != std::string::npos) continue; std::string targetID = srcChannel.mTarget.substr( 0, slashPos); @@ -1068,8 +1222,14 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars if( srcNode->mTransforms[a].mID == entry.mTransformId) entry.mTransformIndex = a; - if( entry.mTransformIndex == SIZE_MAX) { - continue; + if( entry.mTransformIndex == SIZE_MAX) + { + if (entry.mTransformId.find("morph-weights") != std::string::npos) + { + entry.mTargetId = entry.mTransformId; + entry.mTransformId = ""; + } else + continue; } entry.mChannel = &(*cit); @@ -1213,49 +1373,125 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars // ai_assert( resultTrafos.size() > 0); // build an animation channel for the given node out of these trafo keys - if( !resultTrafos.empty() ) - { - aiNodeAnim* dstAnim = new aiNodeAnim; - dstAnim->mNodeName = nodeName; - dstAnim->mNumPositionKeys = static_cast(resultTrafos.size()); - dstAnim->mNumRotationKeys= static_cast(resultTrafos.size()); - dstAnim->mNumScalingKeys = static_cast(resultTrafos.size()); - dstAnim->mPositionKeys = new aiVectorKey[resultTrafos.size()]; - dstAnim->mRotationKeys = new aiQuatKey[resultTrafos.size()]; - dstAnim->mScalingKeys = new aiVectorKey[resultTrafos.size()]; + if( !resultTrafos.empty() ) + { + aiNodeAnim* dstAnim = new aiNodeAnim; + dstAnim->mNodeName = nodeName; + dstAnim->mNumPositionKeys = static_cast(resultTrafos.size()); + dstAnim->mNumRotationKeys = static_cast(resultTrafos.size()); + dstAnim->mNumScalingKeys = static_cast(resultTrafos.size()); + dstAnim->mPositionKeys = new aiVectorKey[resultTrafos.size()]; + dstAnim->mRotationKeys = new aiQuatKey[resultTrafos.size()]; + dstAnim->mScalingKeys = new aiVectorKey[resultTrafos.size()]; - for( size_t a = 0; a < resultTrafos.size(); ++a) - { - aiMatrix4x4 mat = resultTrafos[a]; - double time = double( mat.d4); // remember? time is stored in mat.d4 - mat.d4 = 1.0f; + for( size_t a = 0; a < resultTrafos.size(); ++a) + { + aiMatrix4x4 mat = resultTrafos[a]; + double time = double( mat.d4); // remember? time is stored in mat.d4 + mat.d4 = 1.0f; - dstAnim->mPositionKeys[a].mTime = time; - dstAnim->mRotationKeys[a].mTime = time; - dstAnim->mScalingKeys[a].mTime = time; - mat.Decompose( dstAnim->mScalingKeys[a].mValue, dstAnim->mRotationKeys[a].mValue, dstAnim->mPositionKeys[a].mValue); - } + dstAnim->mPositionKeys[a].mTime = time; + dstAnim->mRotationKeys[a].mTime = time; + dstAnim->mScalingKeys[a].mTime = time; + mat.Decompose( dstAnim->mScalingKeys[a].mValue, dstAnim->mRotationKeys[a].mValue, dstAnim->mPositionKeys[a].mValue); + } - anims.push_back( dstAnim); - } else - { - DefaultLogger::get()->warn( "Collada loader: found empty animation channel, ignored. Please check your exporter."); - } + anims.push_back( dstAnim); + } else + { + DefaultLogger::get()->warn( "Collada loader: found empty animation channel, ignored. Please check your exporter."); + } + + if( !entries.empty() && entries.front().mTimeAccessor->mCount > 0 ) + { + std::vector morphChannels; + for( std::vector::iterator it = entries.begin(); it != entries.end(); ++it) + { + Collada::ChannelEntry& e = *it; + + // skip non-transform types + if (e.mTargetId.empty()) + continue; + + if (e.mTargetId.find("morph-weights") != std::string::npos) + morphChannels.push_back(e); + } + if (morphChannels.size() > 0) + { + // either 1) morph weight animation count should contain morph target count channels + // or 2) one channel with morph target count arrays + // assume first + + aiMeshMorphAnim *morphAnim = new aiMeshMorphAnim; + morphAnim->mName.Set(nodeName); + + std::vector morphTimeValues; + + int morphAnimChannelIndex = 0; + for( std::vector::iterator it = morphChannels.begin(); it != morphChannels.end(); ++it) + { + Collada::ChannelEntry& e = *it; + std::string::size_type apos = e.mTargetId.find('('); + std::string::size_type bpos = e.mTargetId.find(')'); + if (apos == std::string::npos || bpos == std::string::npos) + // unknown way to specify weight -> ignore this animation + continue; + + // weight target can be in format Weight_M_N, Weight_N, WeightN, or some other way + // we ignore the name and just assume the channels are in the right order + for (unsigned int i = 0; i < e.mTimeData->mValues.size(); i++) + insertMorphTimeValue(morphTimeValues, e.mTimeData->mValues.at(i), e.mValueData->mValues.at(i), morphAnimChannelIndex); + + ++morphAnimChannelIndex; + } + + morphAnim->mNumKeys = static_cast(morphTimeValues.size()); + morphAnim->mKeys = new aiMeshMorphKey[morphAnim->mNumKeys]; + for (unsigned int key = 0; key < morphAnim->mNumKeys; key++) + { + morphAnim->mKeys[key].mNumValuesAndWeights = static_cast(morphChannels.size()); + morphAnim->mKeys[key].mValues = new unsigned int [morphChannels.size()]; + morphAnim->mKeys[key].mWeights = new double [morphChannels.size()]; + + morphAnim->mKeys[key].mTime = morphTimeValues[key].mTime; + for (unsigned int valueIndex = 0; valueIndex < morphChannels.size(); valueIndex++) + { + morphAnim->mKeys[key].mValues[valueIndex] = valueIndex; + morphAnim->mKeys[key].mWeights[valueIndex] = getWeightAtKey(morphTimeValues, key, valueIndex); + } + } + + morphAnims.push_back(morphAnim); + } + } } - if( !anims.empty()) + if( !anims.empty() || !morphAnims.empty()) { aiAnimation* anim = new aiAnimation; anim->mName.Set( pName); anim->mNumChannels = static_cast(anims.size()); - anim->mChannels = new aiNodeAnim*[anims.size()]; - std::copy( anims.begin(), anims.end(), anim->mChannels); + if (anim->mNumChannels > 0) + { + anim->mChannels = new aiNodeAnim*[anims.size()]; + std::copy( anims.begin(), anims.end(), anim->mChannels); + } + anim->mNumMorphMeshChannels = static_cast(morphAnims.size()); + if (anim->mNumMorphMeshChannels > 0) + { + anim->mMorphMeshChannels = new aiMeshMorphAnim*[anim->mNumMorphMeshChannels]; + std::copy( morphAnims.begin(), morphAnims.end(), anim->mMorphMeshChannels); + } anim->mDuration = 0.0f; for( size_t a = 0; a < anims.size(); ++a) { - anim->mDuration = std::max( anim->mDuration, anims[a]->mPositionKeys[anims[a]->mNumPositionKeys-1].mTime); - anim->mDuration = std::max( anim->mDuration, anims[a]->mRotationKeys[anims[a]->mNumRotationKeys-1].mTime); - anim->mDuration = std::max( anim->mDuration, anims[a]->mScalingKeys[anims[a]->mNumScalingKeys-1].mTime); + anim->mDuration = std::max( anim->mDuration, anims[a]->mPositionKeys[anims[a]->mNumPositionKeys-1].mTime); + anim->mDuration = std::max( anim->mDuration, anims[a]->mRotationKeys[anims[a]->mNumRotationKeys-1].mTime); + anim->mDuration = std::max( anim->mDuration, anims[a]->mScalingKeys[anims[a]->mNumScalingKeys-1].mTime); + } + for (size_t a = 0; a < morphAnims.size(); ++a) + { + anim->mDuration = std::max(anim->mDuration, morphAnims[a]->mKeys[morphAnims[a]->mNumKeys-1].mTime); } anim->mTicksPerSecond = 1; mAnims.push_back( anim); @@ -1383,7 +1619,7 @@ void ColladaLoader::FillMaterials( const ColladaParser& pParser, aiScene* /*pSce mat.AddProperty( &effect.mRefractIndex, 1, AI_MATKEY_REFRACTI); // transparency, a very hard one. seemingly not all files are following the - // specification here (1.0 transparency => completly opaque)... + // specification here (1.0 transparency => completely opaque)... // therefore, we let the opportunity for the user to manually invert // the transparency if necessary and we add preliminary support for RGB_ZERO mode if(effect.mTransparency >= 0.f && effect.mTransparency <= 1.f) { @@ -1489,6 +1725,8 @@ void ColladaLoader::BuildMaterials( ColladaParser& pParser, aiScene* /*pScene*/) aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pParser, const Collada::Effect& pEffect, const std::string& pName) { + aiString result; + // recurse through the param references until we end up at an image std::string name = pName; while( 1) @@ -1507,11 +1745,17 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name); if( imIt == pParser.mImageLibrary.end()) { - throw DeadlyImportError( format() << - "Collada: Unable to resolve effect texture entry \"" << pName << "\", ended up at ID \"" << name << "\"." ); - } + //missing texture should not stop the conversion + //throw DeadlyImportError( format() << + // "Collada: Unable to resolve effect texture entry \"" << pName << "\", ended up at ID \"" << name << "\"." ); - aiString result; + DefaultLogger::get()->warn("Collada: Unable to resolve effect texture entry \"" + pName + "\", ended up at ID \"" + name + "\"."); + + //set default texture file name + result.Set(name + ".jpg"); + ConvertPath(result); + return result; + } // if this is an embedded texture image setup an aiTexture for it if (imIt->second.mFileName.empty()) @@ -1659,14 +1903,13 @@ const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, c } // ------------------------------------------------------------------------------------------------ -// Finds a proper name for a node derived from the collada-node's properties +// Finds a proper unique name for a node derived from the collada-node's properties. +// The name must be unique for proper node-bone association. std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode) { - // now setup the name of the node. We take the name if not empty, otherwise the collada ID - // FIX: Workaround for XSI calling the instanced visual scene 'untitled' by default. - if (!pNode->mName.empty() && pNode->mName != "untitled") - return pNode->mName; - else if (!pNode->mID.empty()) + // Now setup the name of the assimp node. The collada name might not be + // unique, so we use the collada ID. + if (!pNode->mID.empty()) return pNode->mID; else if (!pNode->mSID.empty()) return pNode->mSID; diff --git a/code/ColladaLoader.h b/code/ColladaLoader.h index 716b437d8..8388ab01e 100644 --- a/code/ColladaLoader.h +++ b/code/ColladaLoader.h @@ -4,7 +4,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -117,6 +118,8 @@ protected: /** Builds meshes for the given node and references them */ void BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget); + + aiMesh *findMesh(std::string meshid); /** Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh */ aiMesh* CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh, @@ -223,6 +226,9 @@ protected: /** Accumulated meshes for the target scene */ std::vector mMeshes; + + /** Accumulated morph target meshes */ + std::vector mTargetMeshes; /** Temporary material list */ std::vector > newMats; diff --git a/code/ColladaParser.cpp b/code/ColladaParser.cpp index 70c5e95b4..2fe0f1e0a 100644 --- a/code/ColladaParser.cpp +++ b/code/ColladaParser.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -43,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of the Collada parser helper */ - #ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER #include @@ -224,7 +224,7 @@ void ColladaParser::ReadStructure() } // ------------------------------------------------------------------------------------------------ -// Reads asset informations such as coordinate system informations and legal blah +// Reads asset information such as coordinate system information and legal blah void ColladaParser::ReadAssetInfo() { if( mReader->isEmptyElement()) @@ -585,6 +585,12 @@ void ColladaParser::ReadAnimationSampler( Collada::AnimationChannel& pChannel) pChannel.mSourceTimes = source; else if( strcmp( semantic, "OUTPUT") == 0) pChannel.mSourceValues = source; + else if( strcmp( semantic, "IN_TANGENT") == 0) + pChannel.mInTanValues = source; + else if( strcmp( semantic, "OUT_TANGENT") == 0) + pChannel.mOutTanValues = source; + else if( strcmp( semantic, "INTERPOLATION") == 0) + pChannel.mInterpolationValues = source; if( !mReader->isEmptyElement()) SkipElement(); @@ -647,6 +653,9 @@ void ColladaParser::ReadControllerLibrary() // Reads a controller into the given mesh structure void ColladaParser::ReadController( Collada::Controller& pController) { + // initial values + pController.mType = Skin; + pController.mMethod = Normalized; while( mReader->read()) { if( mReader->getNodeType() == irr::io::EXN_ELEMENT) @@ -654,8 +663,15 @@ void ColladaParser::ReadController( Collada::Controller& pController) // two types of controllers: "skin" and "morph". Only the first one is relevant, we skip the other if( IsElement( "morph")) { - // should skip everything inside, so there's no danger of catching elements in between - SkipElement(); + pController.mType = Morph; + int baseIndex = GetAttribute("source"); + pController.mMeshId = mReader->getAttributeValue(baseIndex) + 1; + int methodIndex = GetAttribute("method"); + if (methodIndex > 0) { + const char *method = mReader->getAttributeValue(methodIndex); + if (strcmp(method, "RELATIVE") == 0) + pController.mMethod = Relative; + } } else if( IsElement( "skin")) { @@ -667,18 +683,18 @@ void ColladaParser::ReadController( Collada::Controller& pController) else if( IsElement( "bind_shape_matrix")) { // content is 16 floats to define a matrix... it seems to be important for some models - const char* content = GetTextContent(); + const char* content = GetTextContent(); - // read the 16 floats - for( unsigned int a = 0; a < 16; a++) - { - // read a number - content = fast_atoreal_move( content, pController.mBindShapeMatrix[a]); - // skip whitespace after it - SkipSpacesAndLineEnd( &content); - } + // read the 16 floats + for( unsigned int a = 0; a < 16; a++) + { + // read a number + content = fast_atoreal_move( content, pController.mBindShapeMatrix[a]); + // skip whitespace after it + SkipSpacesAndLineEnd( &content); + } - TestClosing( "bind_shape_matrix"); + TestClosing( "bind_shape_matrix"); } else if( IsElement( "source")) { @@ -693,6 +709,32 @@ void ColladaParser::ReadController( Collada::Controller& pController) { ReadControllerWeights( pController); } + else if ( IsElement( "targets" )) + { + while (mReader->read()) { + if( mReader->getNodeType() == irr::io::EXN_ELEMENT) { + if ( IsElement( "input")) { + int semanticsIndex = GetAttribute("semantic"); + int sourceIndex = GetAttribute("source"); + + const char *semantics = mReader->getAttributeValue(semanticsIndex); + const char *source = mReader->getAttributeValue(sourceIndex); + if (strcmp(semantics, "MORPH_TARGET") == 0) { + pController.mMorphTarget = source + 1; + } + else if (strcmp(semantics, "MORPH_WEIGHT") == 0) + { + pController.mMorphWeight = source + 1; + } + } + } else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { + if( strcmp( mReader->getNodeName(), "targets") == 0) + break; + else + ThrowException( "Expected end of element."); + } + } + } else { // ignore the rest @@ -703,7 +745,7 @@ void ColladaParser::ReadController( Collada::Controller& pController) { if( strcmp( mReader->getNodeName(), "controller") == 0) break; - else if( strcmp( mReader->getNodeName(), "skin") != 0) + else if( strcmp( mReader->getNodeName(), "skin") != 0 && strcmp( mReader->getNodeName(), "morph") != 0) ThrowException( "Expected end of element."); } } @@ -1592,7 +1634,7 @@ void ColladaParser::ReadEffectColor( aiColor4D& pColor, Sampler& pSampler) } else if( IsElement( "texture")) { - // get name of source textur/sampler + // get name of source texture/sampler int attrTex = GetAttribute( "texture"); pSampler.mName = mReader->getAttributeValue( attrTex); @@ -1823,7 +1865,7 @@ void ColladaParser::ReadMesh( Mesh* pMesh) ReadIndexData( pMesh); } else { - // ignore the rest + // ignore the restf SkipElement(); } } @@ -2173,8 +2215,9 @@ void ColladaParser::ReadIndexData( Mesh* pMesh) else if (IsElement("extra")) { SkipElement("extra"); - } else - { + } else if ( IsElement("ph")) { + SkipElement("ph"); + } else { ThrowException( format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <" << elementName << ">" ); } } @@ -2188,7 +2231,7 @@ void ColladaParser::ReadIndexData( Mesh* pMesh) } #ifdef ASSIMP_BUILD_DEBUG - if (primType != Prim_TriFans && primType != Prim_TriStrips && + if (primType != Prim_TriFans && primType != Prim_TriStrips && primType != Prim_LineStrip && primType != Prim_Lines) { // this is ONLY to workaround a bug in SketchUp 15.3.331 where it writes the wrong 'count' when it writes out the 'lines'. ai_assert(actualPrimitives == numPrimitives); } @@ -2311,9 +2354,9 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pP ThrowException( "Expected different index count in

element."); // find the data for all sources - for( std::vector::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it) + for( std::vector::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it) { - InputChannel& input = *it; + InputChannel& input = *it; if( input.mResolved) continue; @@ -2325,9 +2368,9 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pP acc->mData = &ResolveLibraryReference( mDataLibrary, acc->mSource); } // and the same for the per-index channels - for( std::vector::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it) - { - InputChannel& input = *it; + for( std::vector::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it) + { + InputChannel& input = *it; if( input.mResolved) continue; @@ -2357,6 +2400,10 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pP size_t numberOfVertices = indices.size() / numOffsets; numPrimitives = numberOfVertices - 2; } + if (pPrimType == Prim_LineStrip) { + size_t numberOfVertices = indices.size() / numOffsets; + numPrimitives = numberOfVertices - 1; + } pMesh->mFaceSize.reserve( numPrimitives); pMesh->mFacePosIndices.reserve( indices.size() / numOffsets); @@ -2373,6 +2420,11 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pP for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) CopyVertex(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); break; + case Prim_LineStrip: + numPoints = 2; + for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) + CopyVertex(currentVertex, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices); + break; case Prim_Triangles: numPoints = 3; for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++) @@ -2409,13 +2461,15 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector& pP return numPrimitives; } +///@note This function willn't work correctly if both PerIndex and PerVertex channels have same channels. +///For example if TEXCOORD present in both and tags this function will create wrong uv coordinates. +///It's not clear from COLLADA documentation is this allowed or not. For now only exporter fixed to avoid such behavior void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh* pMesh, std::vector& pPerIndexChannels, size_t currentPrimitive, const std::vector& indices){ // calculate the base offset of the vertex whose attributes we ant to copy size_t baseOffset = currentPrimitive * numOffsets * numPoints + currentVertex * numOffsets; // don't overrun the boundaries of the index list - size_t maxIndexRequested = baseOffset + numOffsets - 1; - ai_assert(maxIndexRequested < indices.size()); + ai_assert((baseOffset + numOffsets - 1) < indices.size()); // extract per-vertex channels using the global per-vertex offset for (std::vector::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it) diff --git a/code/ColladaParser.h b/code/ColladaParser.h index 5aa724063..941ab8414 100644 --- a/code/ColladaParser.h +++ b/code/ColladaParser.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- - Copyright (c) 2006-2016, assimp team + Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -49,7 +50,6 @@ #include "ColladaHelper.h" #include #include "TinyFormatter.h" -#include namespace Assimp { @@ -77,7 +77,7 @@ namespace Assimp /** Reads the structure of the file */ void ReadStructure(); - /** Reads asset informations such as coordinate system informations and legal blah */ + /** Reads asset information such as coordinate system information and legal blah */ void ReadAssetInfo(); /** Reads the animation library */ diff --git a/code/ComputeUVMappingProcess.cpp b/code/ComputeUVMappingProcess.cpp index 0fee43a70..c49666de8 100644 --- a/code/ComputeUVMappingProcess.cpp +++ b/code/ComputeUVMappingProcess.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/ComputeUVMappingProcess.h b/code/ComputeUVMappingProcess.h index db4287863..1de97961d 100644 --- a/code/ComputeUVMappingProcess.h +++ b/code/ComputeUVMappingProcess.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/ConvertToLHProcess.cpp b/code/ConvertToLHProcess.cpp index 017282796..6a43d5c2d 100644 --- a/code/ConvertToLHProcess.cpp +++ b/code/ConvertToLHProcess.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/ConvertToLHProcess.h b/code/ConvertToLHProcess.h index 0c5f91c96..130fdcafd 100644 --- a/code/ConvertToLHProcess.h +++ b/code/ConvertToLHProcess.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/CreateAnimMesh.cpp b/code/CreateAnimMesh.cpp new file mode 100644 index 000000000..094a414bf --- /dev/null +++ b/code/CreateAnimMesh.cpp @@ -0,0 +1,92 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (C) 2016 The Qt Company Ltd. +Copyright (c) 2006-2012, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#include "CreateAnimMesh.h" + +namespace Assimp { + +aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh) +{ + aiAnimMesh *animesh = new aiAnimMesh; + animesh->mVertices = NULL; + animesh->mNormals = NULL; + animesh->mTangents = NULL; + animesh->mBitangents = NULL; + animesh->mNumVertices = mesh->mNumVertices; + if (mesh->mVertices) { + animesh->mVertices = new aiVector3D[animesh->mNumVertices]; + std::memcpy(animesh->mVertices, mesh->mVertices, mesh->mNumVertices * sizeof(aiVector3D)); + } + if (mesh->mNormals) { + animesh->mNormals = new aiVector3D[animesh->mNumVertices]; + std::memcpy(animesh->mNormals, mesh->mNormals, mesh->mNumVertices * sizeof(aiVector3D)); + } + if (mesh->mTangents) { + animesh->mTangents = new aiVector3D[animesh->mNumVertices]; + std::memcpy(animesh->mTangents, mesh->mTangents, mesh->mNumVertices * sizeof(aiVector3D)); + } + if (mesh->mBitangents) { + animesh->mBitangents = new aiVector3D[animesh->mNumVertices]; + std::memcpy(animesh->mBitangents, mesh->mBitangents, mesh->mNumVertices * sizeof(aiVector3D)); + } + + for (int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) { + if (mesh->mColors[i]) { + animesh->mColors[i] = new aiColor4D[animesh->mNumVertices]; + std::memcpy(animesh->mColors[i], mesh->mColors[i], mesh->mNumVertices * sizeof(aiColor4D)); + } else { + animesh->mColors[i] = NULL; + } + } + + for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + if (mesh->mTextureCoords[i]) { + animesh->mTextureCoords[i] = new aiVector3D[animesh->mNumVertices]; + std::memcpy(animesh->mTextureCoords[i], mesh->mTextureCoords[i], mesh->mNumVertices * sizeof(aiVector3D)); + } else { + animesh->mTextureCoords[i] = NULL; + } + } + return animesh; +} + +} // end of namespace Assimp diff --git a/code/CreateAnimMesh.h b/code/CreateAnimMesh.h new file mode 100644 index 000000000..84cab8932 --- /dev/null +++ b/code/CreateAnimMesh.h @@ -0,0 +1,57 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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 CreateAnimMesh.h + * Create AnimMesh from Mesh + */ +#ifndef INCLUDED_AI_CREATE_ANIM_MESH_H +#define INCLUDED_AI_CREATE_ANIM_MESH_H + +#include + +namespace Assimp { + +/** Create aiAnimMesh from aiMesh. */ +aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh); + +} // end of namespace Assimp +#endif // INCLUDED_AI_CREATE_ANIM_MESH_H + diff --git a/code/D3MFExporter.cpp b/code/D3MFExporter.cpp new file mode 100644 index 000000000..229e3f261 --- /dev/null +++ b/code/D3MFExporter.cpp @@ -0,0 +1,328 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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. + +---------------------------------------------------------------------- +*/ +#ifndef ASSIMP_BUILD_NO_EXPORT +#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER + +#include "D3MFExporter.h" + +#include +#include +#include +#include +#include + +#include "Exceptional.h" +#include "3MFXmlTags.h" +#include "D3MFOpcPackage.h" + +#include + +namespace Assimp { + +void ExportScene3MF( const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/ ) { + if ( nullptr == pIOSystem ) { + throw DeadlyExportError( "Could not export 3MP archive: " + std::string( pFile ) ); + } + D3MF::D3MFExporter myExporter( pFile, pScene ); + if ( myExporter.validate() ) { + if ( pIOSystem->Exists( pFile ) ) { + if ( !pIOSystem->DeleteFile( pFile ) ) { + throw DeadlyExportError( "File exists, cannot override : " + std::string( pFile ) ); + } + } + bool ok = myExporter.exportArchive(pFile); + if ( !ok ) { + throw DeadlyExportError( "Could not export 3MP archive: " + std::string( pFile ) ); + } + } +} + +namespace D3MF { + +D3MFExporter::D3MFExporter( const char* pFile, const aiScene* pScene ) +: mArchiveName( pFile ) +, m_zipArchive( nullptr ) +, mScene( pScene ) +, mModelOutput() +, mRelOutput() +, mContentOutput() +, mBuildItems() +, mRelations() { + // empty +} + +D3MFExporter::~D3MFExporter() { + for ( size_t i = 0; i < mRelations.size(); ++i ) { + delete mRelations[ i ]; + } + mRelations.clear(); +} + +bool D3MFExporter::validate() { + if ( mArchiveName.empty() ) { + return false; + } + + if ( nullptr == mScene ) { + return false; + } + + return true; +} + +bool D3MFExporter::exportArchive( const char *file ) { + bool ok( true ); + + m_zipArchive = zip_open( file, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w' ); + if ( nullptr == m_zipArchive ) { + return false; + } + ok |= exportContentTypes(); + ok |= export3DModel(); + ok |= exportRelations(); + + zip_close( m_zipArchive ); + m_zipArchive = nullptr; + + return ok; +} + + +bool D3MFExporter::exportContentTypes() { + mContentOutput.clear(); + + mContentOutput << ""; + mContentOutput << std::endl; + mContentOutput << ""; + mContentOutput << std::endl; + mContentOutput << ""; + mContentOutput << std::endl; + mContentOutput << ""; + mContentOutput << std::endl; + mContentOutput << ""; + mContentOutput << std::endl; + exportContentTyp( XmlTag::CONTENT_TYPES_ARCHIVE ); + + return true; +} + +bool D3MFExporter::exportRelations() { + mRelOutput.clear(); + + mRelOutput << ""; + mRelOutput << std::endl; + mRelOutput << ""; + + for ( size_t i = 0; i < mRelations.size(); ++i ) { + mRelOutput << "target << "\" "; + mRelOutput << "Id=\"" << mRelations[i]->id << "\" "; + mRelOutput << "Type=\"" << mRelations[ i ]->type << "\" />"; + mRelOutput << std::endl; + } + mRelOutput << ""; + mRelOutput << std::endl; + + writeRelInfoToFile( "_rels", ".rels" ); + mRelOutput.flush(); + + return true; +} + +bool D3MFExporter::export3DModel() { + mModelOutput.clear(); + + writeHeader(); + mModelOutput << "<" << XmlTag::model << " " << XmlTag::model_unit << "=\"millimeter\"" + << "xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\">" + << std::endl; + mModelOutput << "<" << XmlTag::resources << ">"; + mModelOutput << std::endl; + + writeObjects(); + + + mModelOutput << ""; + mModelOutput << std::endl; + writeBuild(); + + mModelOutput << "\n"; + + OpcPackageRelationship *info = new OpcPackageRelationship; + info->id = "rel0"; + info->target = "/3D/3DModel.model"; + info->type = XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE; + mRelations.push_back( info ); + + writeModelToArchive( "3D", "3DModel.model" ); + mModelOutput.flush(); + + return true; +} + +void D3MFExporter::writeHeader() { + mModelOutput << ""; + mModelOutput << std::endl; +} + +void D3MFExporter::writeObjects() { + if ( nullptr == mScene->mRootNode ) { + return; + } + + aiNode *root = mScene->mRootNode; + for ( unsigned int i = 0; i < root->mNumChildren; ++i ) { + aiNode *currentNode( root->mChildren[ i ] ); + if ( nullptr == currentNode ) { + continue; + } + mModelOutput << "<" << XmlTag::object << " id=\"" << currentNode->mName.C_Str() << "\" type=\"model\">"; + mModelOutput << std::endl; + for ( unsigned int j = 0; j < currentNode->mNumMeshes; ++j ) { + aiMesh *currentMesh = mScene->mMeshes[ currentNode->mMeshes[ j ] ]; + if ( nullptr == currentMesh ) { + continue; + } + writeMesh( currentMesh ); + } + mBuildItems.push_back( i ); + + mModelOutput << ""; + mModelOutput << std::endl; + } +} + +void D3MFExporter::writeMesh( aiMesh *mesh ) { + if ( nullptr == mesh ) { + return; + } + + mModelOutput << "<" << XmlTag::mesh << ">" << std::endl; + mModelOutput << "<" << XmlTag::vertices << ">" << std::endl; + for ( unsigned int i = 0; i < mesh->mNumVertices; ++i ) { + writeVertex( mesh->mVertices[ i ] ); + } + mModelOutput << "" << std::endl; + + writeFaces( mesh ); + + mModelOutput << "" << std::endl; +} + +void D3MFExporter::writeVertex( const aiVector3D &pos ) { + mModelOutput << "<" << XmlTag::vertex << " x=\"" << pos.x << "\" y=\"" << pos.y << "\" z=\"" << pos.z << "\" />"; + mModelOutput << std::endl; +} + +void D3MFExporter::writeFaces( aiMesh *mesh ) { + if ( nullptr == mesh ) { + return; + } + + if ( !mesh->HasFaces() ) { + return; + } + mModelOutput << "<" << XmlTag::triangles << ">" << std::endl; + for ( unsigned int i = 0; i < mesh->mNumFaces; ++i ) { + aiFace ¤tFace = mesh->mFaces[ i ]; + mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[ 0 ] << "\" v2=\"" + << currentFace.mIndices[ 1 ] << "\" v3=\"" << currentFace.mIndices[ 2 ] << "\"/>"; + mModelOutput << std::endl; + } + mModelOutput << ""; + mModelOutput << std::endl; +} + +void D3MFExporter::writeBuild() { + mModelOutput << "<" << XmlTag::build << ">" << std::endl; + + for ( size_t i = 0; i < mBuildItems.size(); ++i ) { + mModelOutput << "<" << XmlTag::item << " objectid=\"" << i + 1 << "\"/>"; + mModelOutput << std::endl; + } + mModelOutput << ""; + mModelOutput << std::endl; +} + +void D3MFExporter::exportContentTyp( const std::string &filename ) { + if ( nullptr == m_zipArchive ) { + throw DeadlyExportError( "3MF-Export: Zip archive not valid, nullptr." ); + } + const std::string entry = filename; + zip_entry_open( m_zipArchive, entry.c_str() ); + + const std::string &exportTxt( mContentOutput.str() ); + zip_entry_write( m_zipArchive, exportTxt.c_str(), exportTxt.size() ); + + zip_entry_close( m_zipArchive ); +} + +void D3MFExporter::writeModelToArchive( const std::string &folder, const std::string &modelName ) { + if ( nullptr == m_zipArchive ) { + throw DeadlyExportError( "3MF-Export: Zip archive not valid, nullptr." ); + } + const std::string entry = folder + "/" + modelName; + zip_entry_open( m_zipArchive, entry.c_str() ); + + const std::string &exportTxt( mModelOutput.str() ); + zip_entry_write( m_zipArchive, exportTxt.c_str(), exportTxt.size() ); + + zip_entry_close( m_zipArchive ); +} + +void D3MFExporter::writeRelInfoToFile( const std::string &folder, const std::string &relName ) { + if ( nullptr == m_zipArchive ) { + throw DeadlyExportError( "3MF-Export: Zip archive not valid, nullptr." ); + } + const std::string entry = folder + "/" + relName; + zip_entry_open( m_zipArchive, entry.c_str() ); + + const std::string &exportTxt( mRelOutput.str() ); + zip_entry_write( m_zipArchive, exportTxt.c_str(), exportTxt.size() ); + + zip_entry_close( m_zipArchive ); +} + + +} // Namespace D3MF +} // Namespace Assimp + +#endif // ASSIMP_BUILD_NO_3MF_EXPORTER +#endif // ASSIMP_BUILD_NO_EXPORT diff --git a/code/D3MFExporter.h b/code/D3MFExporter.h new file mode 100644 index 000000000..b6be73976 --- /dev/null +++ b/code/D3MFExporter.h @@ -0,0 +1,103 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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. + +---------------------------------------------------------------------- +*/ +#pragma once + +#include +#include +#include +#include + +struct aiScene; +struct aiNode; +struct aiMaterial; +struct aiMesh; + +struct zip_t; + +namespace Assimp { + +class IOStream; + +namespace D3MF { + +#ifndef ASSIMP_BUILD_NO_EXPORT +#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER + +struct OpcPackageRelationship; + +class D3MFExporter { +public: + D3MFExporter( const char* pFile, const aiScene* pScene ); + ~D3MFExporter(); + bool validate(); + bool exportArchive( const char *file ); + bool exportContentTypes(); + bool exportRelations(); + bool export3DModel(); + +protected: + void writeHeader(); + void writeObjects(); + void writeMesh( aiMesh *mesh ); + void writeVertex( const aiVector3D &pos ); + void writeFaces( aiMesh *mesh ); + void writeBuild(); + void exportContentTyp( const std::string &filename ); + void writeModelToArchive( const std::string &folder, const std::string &modelName ); + void writeRelInfoToFile( const std::string &folder, const std::string &relName ); + +private: + std::string mArchiveName; + zip_t *m_zipArchive; + const aiScene *mScene; + std::ostringstream mModelOutput; + std::ostringstream mRelOutput; + std::ostringstream mContentOutput; + std::vector mBuildItems; + std::vector mRelations; +}; + +#endif // ASSIMP_BUILD_NO_3MF_EXPORTER +#endif // ASSIMP_BUILD_NO_EXPORT + +} // Namespace D3MF +} // Namespace Assimp + diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index d8c062de4..372416dbd 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -38,96 +39,57 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ +#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER + #include "D3MFImporter.h" #include -#include #include #include +#include #include "StringComparison.h" #include "StringUtils.h" - #include -#include #include #include -#include #include -#include #include -#include - -#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER - #include "D3MFOpcPackage.h" #include #include "irrXMLWrapper.h" +#include "3MFXmlTags.h" namespace Assimp { namespace D3MF { - -namespace XmlTag { - static const std::string model = "model"; - static const std::string metadata = "metadata"; - static const std::string resources = "resources"; - static const std::string object = "object"; - static const std::string mesh = "mesh"; - static const std::string vertices = "vertices"; - static const std::string vertex = "vertex"; - static const std::string triangles = "triangles"; - static const std::string triangle = "triangle"; - static const std::string x = "x"; - static const std::string y = "y"; - static const std::string z = "z"; - static const std::string v1 = "v1"; - static const std::string v2 = "v2"; - static const std::string v3 = "v3"; - static const std::string id = "id"; - static const std::string name = "name"; - static const std::string type = "type"; - static const std::string build = "build"; - static const std::string item = "item"; - static const std::string objectid = "objectid"; - static const std::string transform = "transform"; -} - - -class XmlSerializer -{ +class XmlSerializer { public: XmlSerializer(XmlReader* xmlReader) - : xmlReader(xmlReader) - { - + : xmlReader(xmlReader) { + // empty } - void ImportXml(aiScene* scene) - { - - scene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT; + ~XmlSerializer() { + // empty + } + void ImportXml(aiScene* scene) { scene->mRootNode = new aiNode(); std::vector children; - while(ReadToEndElement(D3MF::XmlTag::model)) - { - - if(xmlReader->getNodeName() == D3MF::XmlTag::object) - { + while(ReadToEndElement(D3MF::XmlTag::model)) { + if(xmlReader->getNodeName() == D3MF::XmlTag::object) { children.push_back(ReadObject(scene)); - } - else if(xmlReader->getNodeName() == D3MF::XmlTag::build) - { + } else if(xmlReader->getNodeName() == D3MF::XmlTag::build) { } } - if(scene->mRootNode->mName.length == 0) - scene->mRootNode->mName.Set("3MF"); - + if ( scene->mRootNode->mName.length == 0 ) { + scene->mRootNode->mName.Set( "3MF" ); + } scene->mNumMeshes = static_cast(meshes.size()); scene->mMeshes = new aiMesh*[scene->mNumMeshes](); @@ -138,13 +100,12 @@ public: scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren](); std::copy(children.begin(), children.end(), scene->mRootNode->mChildren); - } private: aiNode* ReadObject(aiScene* scene) { - ScopeGuard node(new aiNode()); + std::unique_ptr node(new aiNode()); std::vector meshIds; @@ -184,14 +145,12 @@ private: std::copy(meshIds.begin(), meshIds.end(), node->mMeshes); - return node.dismiss(); + return node.release(); } - aiMesh* ReadMesh() - { + aiMesh* ReadMesh() { aiMesh* mesh = new aiMesh(); - while(ReadToEndElement(D3MF::XmlTag::mesh)) { if(xmlReader->getNodeName() == D3MF::XmlTag::vertices) @@ -202,10 +161,8 @@ private: { ImportTriangles(mesh); } - } - return mesh; } @@ -226,12 +183,14 @@ private: std::copy(vertices.begin(), vertices.end(), mesh->mVertices); } + aiVector3D ReadVertex() { aiVector3D vertex; + vertex.x = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::x.c_str()), nullptr); vertex.y = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::y.c_str()), nullptr); - vertex.z = ai_strtof>(xmlReader->getAttributeValue(D3MF::XmlTag::z.c_str()), nullptr); + vertex.z = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::z.c_str()), nullptr); return vertex; } @@ -253,9 +212,7 @@ private: mesh->mFaces = new aiFace[mesh->mNumFaces]; mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - std::copy(faces.begin(), faces.end(), mesh->mFaces); - } aiFace ReadTriangle() @@ -272,7 +229,6 @@ private: } private: - bool ReadToStartElement(const std::string& startTag) { while(xmlReader->read()) @@ -312,12 +268,11 @@ private: private: std::vector meshes; XmlReader* xmlReader; - - }; } //namespace D3MF +static const std::string Extension = "3mf"; static const aiImporterDesc desc = { "3mf Importer", @@ -329,24 +284,22 @@ static const aiImporterDesc desc = { 0, 0, 0, - "3mf" + Extension.c_str() }; D3MFImporter::D3MFImporter() -{ - +: BaseImporter() { + // empty } -D3MFImporter::~D3MFImporter() -{ - +D3MFImporter::~D3MFImporter() { + // empty } -bool D3MFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const -{ +bool D3MFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const { const std::string extension = GetExtension(pFile); - if(extension == "3mf") { + if(extension == Extension ) { return true; } else if ( !extension.length() || checkSig ) { if (nullptr == pIOHandler ) { @@ -357,18 +310,15 @@ bool D3MFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool return false; } -void D3MFImporter::SetupProperties(const Importer *pImp) -{ - +void D3MFImporter::SetupProperties(const Importer * /*pImp*/) { + // empty } -const aiImporterDesc *D3MFImporter::GetInfo() const -{ +const aiImporterDesc *D3MFImporter::GetInfo() const { return &desc; } -void D3MFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) -{ +void D3MFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { D3MF::D3MFOpcPackage opcPackage(pIOHandler, pFile); std::unique_ptr xmlStream(new CIrrXML_IOStreamReader(opcPackage.RootStream())); diff --git a/code/D3MFImporter.h b/code/D3MFImporter.h index 36c6d53e4..604d73bd5 100644 --- a/code/D3MFImporter.h +++ b/code/D3MFImporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -41,28 +42,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_D3MFLOADER_H_INCLUDED #define AI_D3MFLOADER_H_INCLUDED -#include -#include - #include "BaseImporter.h" namespace Assimp { -class D3MFImporter : public BaseImporter -{ +class D3MFImporter : public BaseImporter { public: + // BaseImporter interface D3MFImporter(); ~D3MFImporter(); - - // BaseImporter interface -public: bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const; void SetupProperties(const Importer *pImp); const aiImporterDesc *GetInfo() const; protected: void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler); - }; -} + +} // Namespace Assimp + #endif // AI_D3MFLOADER_H_INCLUDED diff --git a/code/D3MFOpcPackage.cpp b/code/D3MFOpcPackage.cpp index df83e70f5..49143fee7 100644 --- a/code/D3MFOpcPackage.cpp +++ b/code/D3MFOpcPackage.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -38,6 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ +#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER #include "D3MFOpcPackage.h" #include "Exceptional.h" @@ -47,57 +49,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include #include #include #include #include -#include - -#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER - #include +#include "3MFXmlTags.h" namespace Assimp { namespace D3MF { -namespace XmlTag { - static const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml"; - static const std::string ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels"; - static const std::string SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types"; - static const std::string SCHEMA_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships"; - static const std::string RELS_RELATIONSHIP_CONTAINER = "Relationships"; - static const std::string RELS_RELATIONSHIP_NODE = "Relationship"; - static const std::string RELS_ATTRIB_TARGET = "Target"; - static const std::string RELS_ATTRIB_TYPE = "Type"; - static const std::string RELS_ATTRIB_ID = "Id"; - static const std::string PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel"; - static const std::string PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket"; - static const std::string PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture"; - static const std::string PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; - static const std::string PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; -} - class IOSystem2Unzip { - - public: - - static voidpf open(voidpf opaque, const char* filename, int mode); - - static uLong read(voidpf opaque, voidpf stream, void* buf, uLong size); - - static uLong write(voidpf opaque, voidpf stream, const void* buf, uLong size); - - static long tell(voidpf opaque, voidpf stream); - - static long seek(voidpf opaque, voidpf stream, uLong offset, int origin); - - static int close(voidpf opaque, voidpf stream); - - static int testerror(voidpf opaque, voidpf stream); - - static zlib_filefunc_def get(IOSystem* pIOHandler); +public: + static voidpf open(voidpf opaque, const char* filename, int mode); + static uLong read(voidpf opaque, voidpf stream, void* buf, uLong size); + static uLong write(voidpf opaque, voidpf stream, const void* buf, uLong size); + static long tell(voidpf opaque, voidpf stream); + static long seek(voidpf opaque, voidpf stream, uLong offset, int origin); + static int close(voidpf opaque, voidpf stream); + static int testerror(voidpf opaque, voidpf stream); + static zlib_filefunc_def get(IOSystem* pIOHandler); }; voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) { @@ -116,7 +90,6 @@ voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) { } } - return (voidpf) io_system->Open(filename, mode_fopen); } @@ -186,58 +159,51 @@ zlib_filefunc_def IOSystem2Unzip::get(IOSystem* pIOHandler) { return mapping; } - -class ZipFile : public IOStream -{ +class ZipFile : public IOStream { friend class D3MFZipArchive; public: explicit ZipFile(size_t size); - - ~ZipFile(); - + virtual ~ZipFile(); size_t Read(void* pvBuffer, size_t pSize, size_t pCount ); - size_t Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/); - size_t FileSize() const; - aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/); - size_t Tell() const; - void Flush(); private: - - void* m_Buffer; - + void *m_Buffer; size_t m_Size; - }; -ZipFile::ZipFile(size_t size) : m_Size(size) { +ZipFile::ZipFile(size_t size) +: m_Buffer( nullptr ) +, m_Size(size) { ai_assert(m_Size != 0); - - m_Buffer = malloc(m_Size); + m_Buffer = ::malloc(m_Size); } ZipFile::~ZipFile() { - free(m_Buffer); + ::free(m_Buffer); m_Buffer = NULL; } size_t ZipFile::Read(void* pvBuffer, size_t pSize, size_t pCount) { const size_t size = pSize * pCount; - assert(size <= m_Size); + ai_assert(size <= m_Size); std::memcpy(pvBuffer, m_Buffer, size); return size; } -size_t ZipFile::Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) { - return 0; +size_t ZipFile::Write(const void* pvBuffer, size_t size, size_t pCount ) { + const size_t size_to_write( size * pCount ); + if ( 0 == size_to_write ) { + return 0U; + } + return 0U; } size_t ZipFile::FileSize() const { @@ -256,55 +222,36 @@ void ZipFile::Flush() { // empty } - -class D3MFZipArchive : public IOSystem -{ +class D3MFZipArchive : public IOSystem { public: - static const unsigned int FileNameSize = 256; -public: - D3MFZipArchive(IOSystem* pIOHandler, const std::string & rFile); - ~D3MFZipArchive(); - bool Exists(const char* pFile) const; - char getOsSeparator() const; - IOStream* Open(const char* pFile, const char* pMode = "rb"); - void Close(IOStream* pFile); - bool isOpen() const; - void getFileList(std::vector &rFileList); private: - bool mapArchive(); private: - unzFile m_ZipFileHandle; - std::map m_ArchiveMap; - }; - // ------------------------------------------------------------------------------------------------ // Constructor. D3MFZipArchive::D3MFZipArchive(IOSystem* pIOHandler, const std::string& rFile) - : m_ZipFileHandle(NULL), m_ArchiveMap() -{ - if (! rFile.empty()) - { +: m_ZipFileHandle(NULL) +, m_ArchiveMap() { + if (! rFile.empty()) { zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler); m_ZipFileHandle = unzOpen2(rFile.c_str(), &mapping); - if(m_ZipFileHandle != NULL) { mapArchive(); } @@ -379,6 +326,7 @@ IOStream *D3MFZipArchive::Open(const char* pFile, const char* /*pMode*/) { // ------------------------------------------------------------------------------------------------ // Close a filestream. void D3MFZipArchive::Close(IOStream *pFile) { + (void)(pFile); ai_assert(pFile != NULL); // We don't do anything in case the file would be opened again in the future @@ -433,24 +381,12 @@ bool D3MFZipArchive::mapArchive() { // ------------------------------------------------------------------------------------------------ -struct OpcPackageRelationship -{ - std::string id; - std::string type; - std::string target; -}; - typedef std::shared_ptr OpcPackageRelationshipPtr; -class OpcPackageRelationshipReader -{ +class OpcPackageRelationshipReader { public: - - OpcPackageRelationshipReader(XmlReader* xmlReader) - { - - while(xmlReader->read()) - { + OpcPackageRelationshipReader(XmlReader* xmlReader) { + while(xmlReader->read()) { if(xmlReader->getNodeType() == irr::io::EXN_ELEMENT && xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_CONTAINER) { @@ -473,57 +409,68 @@ public: } } - void ParseAttributes(XmlReader*) - { - + void ParseAttributes(XmlReader*) { + // empty } - void ParseChildNode(XmlReader* xmlReader) - { + bool validateRels( OpcPackageRelationshipPtr &relPtr ) { + if ( relPtr->id.empty() || relPtr->type.empty() || relPtr->target.empty() ) { + return false; + } + return true; + } + + void ParseChildNode(XmlReader* xmlReader) { OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship()); - relPtr->id = xmlReader->getAttributeValue(XmlTag::RELS_ATTRIB_ID.c_str()); - relPtr->type = xmlReader->getAttributeValue(XmlTag::RELS_ATTRIB_TYPE.c_str()); - relPtr->target = xmlReader->getAttributeValue(XmlTag::RELS_ATTRIB_TARGET.c_str()); - - m_relationShips.push_back(relPtr); + relPtr->id = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_ID.c_str()); + relPtr->type = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TYPE.c_str()); + relPtr->target = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TARGET.c_str()); + if ( validateRels( relPtr ) ) { + m_relationShips.push_back( relPtr ); + } } + std::vector m_relationShips; }; // ------------------------------------------------------------------------------------------------ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile) - : m_RootStream(nullptr) -{ - zipArchive.reset(new D3MF::D3MFZipArchive( pIOHandler, rFile )); - if(!zipArchive->isOpen()) { +: mRootStream(nullptr) +, mZipArchive() { + mZipArchive.reset( new D3MF::D3MFZipArchive( pIOHandler, rFile ) ); + if(!mZipArchive->isOpen()) { throw DeadlyImportError("Failed to open file " + rFile+ "."); } std::vector fileList; - zipArchive->getFileList(fileList); + mZipArchive->getFileList(fileList); - for(auto& file: fileList){ + for (auto& file: fileList) { if(file == D3MF::XmlTag::ROOT_RELATIONSHIPS_ARCHIVE) { //PkgRelationshipReader pkgRelReader(file, archive); - ai_assert(zipArchive->Exists(file.c_str())); + ai_assert(mZipArchive->Exists(file.c_str())); - IOStream *fileStream = zipArchive->Open(file.c_str()); + IOStream *fileStream = mZipArchive->Open(file.c_str()); ai_assert(fileStream != nullptr); std::string rootFile = ReadPackageRootRelationship(fileStream); - if(rootFile.size() > 0 && rootFile[0] == '/') - rootFile = rootFile.substr(1); + if ( rootFile.size() > 0 && rootFile[ 0 ] == '/' ) { + rootFile = rootFile.substr( 1 ); + if ( rootFile[ 0 ] == '/' ) { + // deal with zipbug + rootFile = rootFile.substr( 1 ); + } + } DefaultLogger::get()->debug(rootFile); - m_RootStream = zipArchive->Open(rootFile.c_str()); - - ai_assert(m_RootStream != nullptr); - - - + mRootStream = mZipArchive->Open(rootFile.c_str()); + ai_assert( mRootStream != nullptr ); + if ( nullptr == mRootStream ) { + throw DeadlyExportError( "Cannot open rootfile in archive : " + rootFile ); + } // const size_t size = zipArchive->FileSize(); // m_Data.resize( size ); @@ -534,50 +481,40 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile) // m_Data.clear(); // return false; // } - zipArchive->Close( fileStream ); + mZipArchive->Close( fileStream ); - } - else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) - { + } else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) { } } } -D3MFOpcPackage::~D3MFOpcPackage() -{ - +D3MFOpcPackage::~D3MFOpcPackage() { + // empty } -IOStream* D3MFOpcPackage::RootStream() const -{ - return m_RootStream; +IOStream* D3MFOpcPackage::RootStream() const { + return mRootStream; } - -std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) -{ - +std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) { std::unique_ptr xmlStream(new CIrrXML_IOStreamReader(stream)); std::unique_ptr xml(irr::io::createIrrXMLReader(xmlStream.get())); OpcPackageRelationshipReader reader(xml.get()); - auto itr = std::find_if(reader.m_relationShips.begin(), reader.m_relationShips.end(), [](const OpcPackageRelationshipPtr& rel){ return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE; }); - - if(itr == reader.m_relationShips.end()) - throw DeadlyImportError("Cannot find" + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE); + throw DeadlyImportError("Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE); return (*itr)->target; } -} //namespace D3MF +} // Namespace D3MF -} +} // Namespace Assimp #endif //ASSIMP_BUILD_NO_3MF_IMPORTER diff --git a/code/D3MFOpcPackage.h b/code/D3MFOpcPackage.h index dd8a40aab..818415e9f 100644 --- a/code/D3MFOpcPackage.h +++ b/code/D3MFOpcPackage.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -41,33 +42,37 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef D3MFOPCPACKAGE_H #define D3MFOPCPACKAGE_H -#include #include #include #include "irrXMLWrapper.h" namespace Assimp { - namespace D3MF { typedef irr::io::IrrXMLReader XmlReader; typedef std::shared_ptr XmlReaderPtr; +struct OpcPackageRelationship { + std::string id; + std::string type; + std::string target; +}; + class D3MFZipArchive; -class D3MFOpcPackage -{ +class D3MFOpcPackage { public: D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile); ~D3MFOpcPackage(); - IOStream* RootStream() const; -private: + +protected: std::string ReadPackageRootRelationship(IOStream* stream); + private: - IOStream* m_RootStream; - std::unique_ptr zipArchive; + IOStream* mRootStream; + std::unique_ptr mZipArchive; }; } diff --git a/code/DXFHelper.h b/code/DXFHelper.h index 1947469a8..e16b7f1aa 100644 --- a/code/DXFHelper.h +++ b/code/DXFHelper.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/DXFLoader.cpp b/code/DXFLoader.cpp index ab5ca146c..1e932e509 100644 --- a/code/DXFLoader.cpp +++ b/code/DXFLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -54,6 +55,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "DXFHelper.h" #include #include +#include + #include using namespace Assimp; diff --git a/code/DXFLoader.h b/code/DXFLoader.h index 13af4cdec..64822e9e2 100644 --- a/code/DXFLoader.h +++ b/code/DXFLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -45,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_DXFLOADER_H_INCLUDED #include "BaseImporter.h" +#include namespace Assimp { namespace DXF { diff --git a/code/DeboneProcess.cpp b/code/DeboneProcess.cpp index 41941b4ac..b43dcad84 100644 --- a/code/DeboneProcess.cpp +++ b/code/DeboneProcess.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/DeboneProcess.h b/code/DeboneProcess.h index 5920473e2..8d4607bb9 100644 --- a/code/DeboneProcess.h +++ b/code/DeboneProcess.h @@ -1,8 +1,9 @@ - /* +/* Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/DefaultIOStream.cpp b/code/DefaultIOStream.cpp index 1907709e3..cce9af19d 100644 --- a/code/DefaultIOStream.cpp +++ b/code/DefaultIOStream.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -44,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -#include "DefaultIOStream.h" +#include #include #include @@ -126,7 +127,7 @@ size_t DefaultIOStream::FileSize() const if (0 != err) return 0; mCachedSize = (size_t) (fileStat.st_size); -#elif defined __GNUC__ || defined __APPLE__ || defined __MACH__ +#elif defined __GNUC__ || defined __APPLE__ || defined __MACH__ || defined __FreeBSD__ struct stat fileStat; int err = stat(mFilename.c_str(), &fileStat ); if (0 != err) diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index 8c44c8bd0..8687b0059 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -40,15 +41,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file Default implementation of IOSystem using the standard C file functions */ -#include "DefaultIOSystem.h" -#include "DefaultIOStream.h" #include "StringComparison.h" +#include +#include #include #include #include - #ifdef __unix__ #include #include diff --git a/code/DefaultLogger.cpp b/code/DefaultLogger.cpp index 5364bd8bc..b69e18ea9 100644 --- a/code/DefaultLogger.cpp +++ b/code/DefaultLogger.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -43,13 +44,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of DefaultLogger (and Logger) */ -#include "DefaultIOSystem.h" // Default log streams #include "Win32DebugLogStream.h" #include "StdOStreamLogStream.h" #include "FileLogStream.h" #include "StringUtils.h" + +#include #include #include #include @@ -251,8 +253,8 @@ void DefaultLogger::kill() // Debug message void DefaultLogger::OnDebug( const char* message ) { - if ( m_Severity == Logger::NORMAL ) - return; + if ( m_Severity == Logger::NORMAL ) + return; static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; char msg[Size]; diff --git a/code/DefaultProgressHandler.h b/code/DefaultProgressHandler.h index b729e4bfa..6cd872eaa 100644 --- a/code/DefaultProgressHandler.h +++ b/code/DefaultProgressHandler.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/Exceptional.h b/code/Exceptional.h index 3268423ef..5109b8f07 100644 --- a/code/Exceptional.h +++ b/code/Exceptional.h @@ -42,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_EXCEPTIONAL_H #include -#include "DefaultIOStream.h" +#include using std::runtime_error; #ifdef _MSC_VER diff --git a/code/Exporter.cpp b/code/Exporter.cpp index bdfea82b6..0281e4e99 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -52,9 +53,8 @@ Here we implement only the C++ interface (Assimp::Exporter). #ifndef ASSIMP_BUILD_NO_EXPORT -#include "DefaultIOSystem.h" #include "BlobIOSystem.h" -#include "SceneCombiner.h" +#include #include "BaseProcess.h" #include "Importer.h" // need this for GetPostProcessingStepInstanceList() @@ -64,11 +64,12 @@ Here we implement only the C++ interface (Assimp::Exporter). #include "Exceptional.h" #include "ScenePrivate.h" #include + +#include #include #include #include #include -#include namespace Assimp { @@ -82,6 +83,7 @@ void ExportSceneCollada(const char*,IOSystem*, const aiScene*, const ExportPrope void ExportSceneXFile(const char*,IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneStep(const char*,IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneObj(const char*,IOSystem*, const aiScene*, const ExportProperties*); +void ExportSceneObjNoMtl(const char*,IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneSTL(const char*,IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*, const ExportProperties*); void ExportScenePly(const char*,IOSystem*, const aiScene*, const ExportProperties*); @@ -89,30 +91,34 @@ void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*, const ExportPr void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneGLTF(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneGLB(const char*, IOSystem*, const aiScene*, const ExportProperties*); +void ExportSceneGLTF2(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*); void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*); +void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* ); // ------------------------------------------------------------------------------------------------ // global array of all export formats which Assimp supports in its current build Exporter::ExportFormatEntry gExporters[] = { #ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER - Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada), + Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada ), #endif #ifndef ASSIMP_BUILD_NO_X_EXPORTER Exporter::ExportFormatEntry( "x", "X Files", "x", &ExportSceneXFile, - aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs), + aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs ), #endif #ifndef ASSIMP_BUILD_NO_STEP_EXPORTER - Exporter::ExportFormatEntry( "stp", "Step Files", "stp", &ExportSceneStep, 0), + Exporter::ExportFormatEntry( "stp", "Step Files", "stp", &ExportSceneStep, 0 ), #endif #ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER Exporter::ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj, - aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */), + aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */ ), + Exporter::ExportFormatEntry( "objnomtl", "Wavefront OBJ format without material file", "obj", &ExportSceneObjNoMtl, + aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */ ), #endif #ifndef ASSIMP_BUILD_NO_STL_EXPORTER @@ -135,26 +141,32 @@ Exporter::ExportFormatEntry gExporters[] = #ifndef ASSIMP_BUILD_NO_3DS_EXPORTER Exporter::ExportFormatEntry( "3ds", "Autodesk 3DS (legacy)", "3ds" , &ExportScene3DS, - aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices), + aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices ), #endif #ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER Exporter::ExportFormatEntry( "gltf", "GL Transmission Format", "gltf", &ExportSceneGLTF, - aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType), + aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB, - aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType), + aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), + Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf2", &ExportSceneGLTF2, + aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ), #endif #ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER - Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0), + Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0 ), #endif #ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER - Exporter::ExportFormatEntry( "assxml", "Assxml Document", "assxml" , &ExportSceneAssxml, 0), + Exporter::ExportFormatEntry( "assxml", "Assxml Document", "assxml" , &ExportSceneAssxml, 0 ), #endif #ifndef ASSIMP_BUILD_NO_X3D_EXPORTER - Exporter::ExportFormatEntry( "x3d", "Extensible 3D", "x3d" , &ExportSceneX3D, 0), + Exporter::ExportFormatEntry( "x3d", "Extensible 3D", "x3d" , &ExportSceneX3D, 0 ), +#endif + +#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER + Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 ) #endif }; @@ -171,8 +183,10 @@ public: GetPostProcessingStepInstanceList(mPostProcessingSteps); // grab all built-in exporters - mExporters.resize(ASSIMP_NUM_EXPORTERS); - std::copy(gExporters,gExporters+ASSIMP_NUM_EXPORTERS,mExporters.begin()); + if ( 0 != ( ASSIMP_NUM_EXPORTERS ) ) { + mExporters.resize( ASSIMP_NUM_EXPORTERS ); + std::copy( gExporters, gExporters + ASSIMP_NUM_EXPORTERS, mExporters.begin() ); + } } ~ExporterPimpl() @@ -186,7 +200,6 @@ public: } public: - aiExportDataBlob* blob; std::shared_ptr< Assimp::IOSystem > mIOSystem; bool mIsDefaultIOHandler; @@ -201,65 +214,48 @@ public: std::vector mExporters; }; - } // end of namespace Assimp - - - - using namespace Assimp; - // ------------------------------------------------------------------------------------------------ Exporter :: Exporter() -: pimpl(new ExporterPimpl()) -{ +: pimpl(new ExporterPimpl()) { + // empty } - // ------------------------------------------------------------------------------------------------ -Exporter :: ~Exporter() -{ +Exporter::~Exporter() { FreeBlob(); delete pimpl; } - // ------------------------------------------------------------------------------------------------ -void Exporter :: SetIOHandler( IOSystem* pIOHandler) -{ +void Exporter::SetIOHandler( IOSystem* pIOHandler) { pimpl->mIsDefaultIOHandler = !pIOHandler; pimpl->mIOSystem.reset(pIOHandler); } - // ------------------------------------------------------------------------------------------------ -IOSystem* Exporter :: GetIOHandler() const -{ +IOSystem* Exporter::GetIOHandler() const { return pimpl->mIOSystem.get(); } - // ------------------------------------------------------------------------------------------------ -bool Exporter :: IsDefaultIOHandler() const -{ +bool Exporter::IsDefaultIOHandler() const { return pimpl->mIsDefaultIOHandler; } - // ------------------------------------------------------------------------------------------------ -const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const char* pFormatId, unsigned int, const ExportProperties* pProperties) -{ +const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const char* pFormatId, + unsigned int, const ExportProperties* /*pProperties*/ ) { if (pimpl->blob) { delete pimpl->blob; pimpl->blob = NULL; } - std::shared_ptr old = pimpl->mIOSystem; - BlobIOSystem* blobio = new BlobIOSystem(); pimpl->mIOSystem = std::shared_ptr( blobio ); @@ -274,10 +270,8 @@ const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const return pimpl->blob; } - // ------------------------------------------------------------------------------------------------ -bool IsVerboseFormat(const aiMesh* mesh) -{ +bool IsVerboseFormat(const aiMesh* mesh) { // avoid slow vector specialization std::vector seen(mesh->mNumVertices,0); for(unsigned int i = 0; i < mesh->mNumFaces; ++i) { @@ -292,10 +286,8 @@ bool IsVerboseFormat(const aiMesh* mesh) return true; } - // ------------------------------------------------------------------------------------------------ -bool IsVerboseFormat(const aiScene* pScene) -{ +bool IsVerboseFormat(const aiScene* pScene) { for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) { if(!IsVerboseFormat(pScene->mMeshes[i])) { return false; @@ -304,10 +296,8 @@ bool IsVerboseFormat(const aiScene* pScene) return true; } - // ------------------------------------------------------------------------------------------------ -aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing, const ExportProperties* pProperties) -{ +aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing, const ExportProperties* pProperties) { ASSIMP_BEGIN_EXCEPTION_REGION(); // when they create scenes from scratch, users will likely create them not in verbose @@ -320,9 +310,7 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const for (size_t i = 0; i < pimpl->mExporters.size(); ++i) { const Exporter::ExportFormatEntry& exp = pimpl->mExporters[i]; if (!strcmp(exp.mDescription.id,pFormatId)) { - try { - // Always create a full copy of the scene. We might optimize this one day, // but for now it is the most pragmatic way. aiScene* scenecopy_tmp = NULL; @@ -341,18 +329,17 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const ? (priv->mPPStepsApplied & ~nonIdempotentSteps) : 0u); - // If no extra postprocessing was specified, and we obtained this scene from an + // If no extra post-processing was specified, and we obtained this scene from an // Assimp importer, apply the reverse steps automatically. // TODO: either drop this, or document it. Otherwise it is just a bad surprise. //if (!pPreprocessing && priv) { // pp |= (nonIdempotentSteps & priv->mPPStepsApplied); //} - // If the input scene is not in verbose format, but there is at least postprocessing step that relies on it, + // If the input scene is not in verbose format, but there is at least post-processing step that relies on it, // we need to run the MakeVerboseFormat step first. bool must_join_again = false; if (!is_verbose_format) { - bool verbosify = false; for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) { BaseProcess* const p = pimpl->mPostProcessingSteps[a]; @@ -423,8 +410,7 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const ExportProperties emptyProperties; // Never pass NULL ExportProperties so Exporters don't have to worry. exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProperties ? pProperties : &emptyProperties); - } - catch (DeadlyExportError& err) { + } catch (DeadlyExportError& err) { pimpl->mError = err.what(); return AI_FAILURE; } @@ -434,67 +420,57 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const pimpl->mError = std::string("Found no exporter to handle this file format: ") + pFormatId; ASSIMP_END_EXCEPTION_REGION(aiReturn); + return AI_FAILURE; } - // ------------------------------------------------------------------------------------------------ -const char* Exporter :: GetErrorString() const -{ +const char* Exporter::GetErrorString() const { return pimpl->mError.c_str(); } // ------------------------------------------------------------------------------------------------ -void Exporter :: FreeBlob( ) -{ +void Exporter::FreeBlob() { delete pimpl->blob; pimpl->blob = NULL; pimpl->mError = ""; } - // ------------------------------------------------------------------------------------------------ -const aiExportDataBlob* Exporter :: GetBlob() const -{ +const aiExportDataBlob* Exporter::GetBlob() const { return pimpl->blob; } - // ------------------------------------------------------------------------------------------------ -const aiExportDataBlob* Exporter :: GetOrphanedBlob() const -{ +const aiExportDataBlob* Exporter::GetOrphanedBlob() const { const aiExportDataBlob* tmp = pimpl->blob; pimpl->blob = NULL; return tmp; } - // ------------------------------------------------------------------------------------------------ -size_t Exporter :: GetExportFormatCount() const -{ +size_t Exporter::GetExportFormatCount() const { return pimpl->mExporters.size(); } // ------------------------------------------------------------------------------------------------ -const aiExportFormatDesc* Exporter :: GetExportFormatDescription( size_t pIndex ) const -{ - if (pIndex >= GetExportFormatCount()) { +const aiExportFormatDesc* Exporter::GetExportFormatDescription( size_t index ) const { + if (index >= GetExportFormatCount()) { return NULL; } // Return from static storage if the requested index is built-in. - if (pIndex < sizeof(gExporters) / sizeof(gExporters[0])) { - return &gExporters[pIndex].mDescription; + if (index < sizeof(gExporters) / sizeof(gExporters[0])) { + return &gExporters[index].mDescription; } - return &pimpl->mExporters[pIndex].mDescription; + return &pimpl->mExporters[index].mDescription; } // ------------------------------------------------------------------------------------------------ -aiReturn Exporter :: RegisterExporter(const ExportFormatEntry& desc) -{ +aiReturn Exporter::RegisterExporter(const ExportFormatEntry& desc) { for(const ExportFormatEntry& e : pimpl->mExporters) { if (!strcmp(e.mDescription.id,desc.mDescription.id)) { return aiReturn_FAILURE; @@ -505,10 +481,8 @@ aiReturn Exporter :: RegisterExporter(const ExportFormatEntry& desc) return aiReturn_SUCCESS; } - // ------------------------------------------------------------------------------------------------ -void Exporter :: UnregisterExporter(const char* id) -{ +void Exporter::UnregisterExporter(const char* id) { for(std::vector::iterator it = pimpl->mExporters.begin(); it != pimpl->mExporters.end(); ++it) { if (!strcmp((*it).mDescription.id,id)) { pimpl->mExporters.erase(it); @@ -517,29 +491,29 @@ void Exporter :: UnregisterExporter(const char* id) } } -ExportProperties :: ExportProperties() {} - -ExportProperties::ExportProperties(const ExportProperties &other) - : mIntProperties(other.mIntProperties), - mFloatProperties(other.mFloatProperties), - mStringProperties(other.mStringProperties), - mMatrixProperties(other.mMatrixProperties) -{ - +// ------------------------------------------------------------------------------------------------ +ExportProperties::ExportProperties() { + // empty } +// ------------------------------------------------------------------------------------------------ +ExportProperties::ExportProperties(const ExportProperties &other) +: mIntProperties(other.mIntProperties) +, mFloatProperties(other.mFloatProperties) +, mStringProperties(other.mStringProperties) +, mMatrixProperties(other.mMatrixProperties) { + // empty +} // ------------------------------------------------------------------------------------------------ // Set a configuration property -bool ExportProperties :: SetPropertyInteger(const char* szName, int iValue) -{ +bool ExportProperties::SetPropertyInteger(const char* szName, int iValue) { return SetGenericProperty(mIntProperties, szName,iValue); } // ------------------------------------------------------------------------------------------------ // Set a configuration property -bool ExportProperties :: SetPropertyFloat(const char* szName, ai_real iValue) -{ +bool ExportProperties::SetPropertyFloat(const char* szName, ai_real iValue) { return SetGenericProperty(mFloatProperties, szName,iValue); } diff --git a/code/FBXAnimation.cpp b/code/FBXAnimation.cpp index 0758d4db7..6f9613f0d 100644 --- a/code/FBXAnimation.cpp +++ b/code/FBXAnimation.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -48,14 +49,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXParser.h" #include "FBXDocument.h" #include "FBXImporter.h" -#include "FBXImportSettings.h" #include "FBXDocumentUtil.h" -#include "FBXProperties.h" namespace Assimp { namespace FBX { - using namespace Util; +using namespace Util; // ------------------------------------------------------------------------------------------------ AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& /*doc*/) @@ -88,17 +87,16 @@ AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::s } } - // ------------------------------------------------------------------------------------------------ AnimationCurve::~AnimationCurve() { - + // empty } - // ------------------------------------------------------------------------------------------------ -AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc, - const char* const * target_prop_whitelist /*= NULL*/, size_t whitelist_size /*= 0*/) +AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, + const Document& doc, const char* const * target_prop_whitelist /*= NULL*/, + size_t whitelist_size /*= 0*/) : Object(id, element, name) , target() , doc(doc) @@ -155,18 +153,16 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false); } - // ------------------------------------------------------------------------------------------------ AnimationCurveNode::~AnimationCurveNode() { - + // empty } - // ------------------------------------------------------------------------------------------------ const AnimationCurveMap& AnimationCurveNode::Curves() const { - if(curves.empty()) { + if ( curves.empty() ) { // resolve attached animation curves const std::vector& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve"); @@ -196,7 +192,6 @@ const AnimationCurveMap& AnimationCurveNode::Curves() const return curves; } - // ------------------------------------------------------------------------------------------------ AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc) : Object(id, element, name) @@ -208,14 +203,12 @@ AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::s props = GetPropertyTable(doc,"AnimationLayer.FbxAnimLayer",element,sc, true); } - // ------------------------------------------------------------------------------------------------ AnimationLayer::~AnimationLayer() { - + // empty } - // ------------------------------------------------------------------------------------------------ AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/, size_t whitelist_size /*= 0*/) const @@ -299,14 +292,13 @@ AnimationStack::AnimationStack(uint64_t id, const Element& element, const std::s } } - // ------------------------------------------------------------------------------------------------ AnimationStack::~AnimationStack() { - + // empty } } //!FBX } //!Assimp -#endif +#endif // ASSIMP_BUILD_NO_FBX_IMPORTER diff --git a/code/FBXBinaryTokenizer.cpp b/code/FBXBinaryTokenizer.cpp index be73eaa95..cc2e734fc 100644 --- a/code/FBXBinaryTokenizer.cpp +++ b/code/FBXBinaryTokenizer.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -55,47 +56,46 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace FBX { -enum Flag -{ - e_unknown_0 = 1 << 0, - e_unknown_1 = 1 << 1, - e_unknown_2 = 1 << 2, - e_unknown_3 = 1 << 3, - e_unknown_4 = 1 << 4, - e_unknown_5 = 1 << 5, - e_unknown_6 = 1 << 6, - e_unknown_7 = 1 << 7, - e_unknown_8 = 1 << 8, - e_unknown_9 = 1 << 9, - e_unknown_10 = 1 << 10, - e_unknown_11 = 1 << 11, - e_unknown_12 = 1 << 12, - e_unknown_13 = 1 << 13, - e_unknown_14 = 1 << 14, - e_unknown_15 = 1 << 15, - e_unknown_16 = 1 << 16, - e_unknown_17 = 1 << 17, - e_unknown_18 = 1 << 18, - e_unknown_19 = 1 << 19, - e_unknown_20 = 1 << 20, - e_unknown_21 = 1 << 21, - e_unknown_22 = 1 << 22, - e_unknown_23 = 1 << 23, - e_flag_field_size_64_bit = 1 << 24, // Not sure what is - e_unknown_25 = 1 << 25, - e_unknown_26 = 1 << 26, - e_unknown_27 = 1 << 27, - e_unknown_28 = 1 << 28, - e_unknown_29 = 1 << 29, - e_unknown_30 = 1 << 30, - e_unknown_31 = 1 << 31 -}; - -bool check_flag(uint32_t flags, Flag to_check) -{ - return (flags & to_check) != 0; -} - +//enum Flag +//{ +// e_unknown_0 = 1 << 0, +// e_unknown_1 = 1 << 1, +// e_unknown_2 = 1 << 2, +// e_unknown_3 = 1 << 3, +// e_unknown_4 = 1 << 4, +// e_unknown_5 = 1 << 5, +// e_unknown_6 = 1 << 6, +// e_unknown_7 = 1 << 7, +// e_unknown_8 = 1 << 8, +// e_unknown_9 = 1 << 9, +// e_unknown_10 = 1 << 10, +// e_unknown_11 = 1 << 11, +// e_unknown_12 = 1 << 12, +// e_unknown_13 = 1 << 13, +// e_unknown_14 = 1 << 14, +// e_unknown_15 = 1 << 15, +// e_unknown_16 = 1 << 16, +// e_unknown_17 = 1 << 17, +// e_unknown_18 = 1 << 18, +// e_unknown_19 = 1 << 19, +// e_unknown_20 = 1 << 20, +// e_unknown_21 = 1 << 21, +// e_unknown_22 = 1 << 22, +// e_unknown_23 = 1 << 23, +// e_flag_field_size_64_bit = 1 << 24, // Not sure what is +// e_unknown_25 = 1 << 25, +// e_unknown_26 = 1 << 26, +// e_unknown_27 = 1 << 27, +// e_unknown_28 = 1 << 28, +// e_unknown_29 = 1 << 29, +// e_unknown_30 = 1 << 30, +// e_unknown_31 = 1 << 31 +//}; +// +//bool check_flag(uint32_t flags, Flag to_check) +//{ +// return (flags & to_check) != 0; +//} // ------------------------------------------------------------------------------------------------ Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int offset) : @@ -151,7 +151,8 @@ uint32_t ReadWord(const char* input, const char*& cursor, const char* end) TokenizeError("cannot ReadWord, out of bounds",input, cursor); } - uint32_t word = *reinterpret_cast(cursor); + uint32_t word; + memcpy(&word, cursor, 4); AI_SWAP4(word); cursor += k_to_read; @@ -160,8 +161,7 @@ uint32_t ReadWord(const char* input, const char*& cursor, const char* end) } // ------------------------------------------------------------------------------------------------ -uint64_t ReadDoubleWord(const char* input, const char*& cursor, const char* end) -{ +uint64_t ReadDoubleWord(const char* input, const char*& cursor, const char* end) { const size_t k_to_read = sizeof(uint64_t); if(Offset(cursor, end) < k_to_read) { TokenizeError("cannot ReadDoubleWord, out of bounds",input, cursor); @@ -175,7 +175,6 @@ uint64_t ReadDoubleWord(const char* input, const char*& cursor, const char* end) return dword; } - // ------------------------------------------------------------------------------------------------ uint8_t ReadByte(const char* input, const char*& cursor, const char* end) { @@ -342,10 +341,10 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input, // ------------------------------------------------------------------------------------------------ -bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, const char* end, uint32_t const flags) +bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, const char* end, bool const is64bits) { // the first word contains the offset at which this block ends - const uint64_t end_offset = /*check_flag(flags, e_flag_field_size_64_bit) ? ReadDoubleWord(input, cursor, end) : */ReadWord(input, cursor, end); + const uint64_t end_offset = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end); // we may get 0 if reading reached the end of the file - // fbx files have a mysterious extra footer which I don't know @@ -363,10 +362,10 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, } // the second data word contains the number of properties in the scope - const uint64_t prop_count = /*check_flag(flags, e_flag_field_size_64_bit) ? ReadDoubleWord(input, cursor, end) : */ReadWord(input, cursor, end); + const uint64_t prop_count = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end); // the third data word contains the length of the property list - const uint64_t prop_length = /*check_flag(flags, e_flag_field_size_64_bit) ? ReadDoubleWord(input, cursor, end) :*/ ReadWord(input, cursor, end); + const uint64_t prop_length = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end); // now comes the name of the scope/key const char* sbeg, *send; @@ -393,7 +392,7 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, // at the end of each nested block, there is a NUL record to indicate // that the sub-scope exists (i.e. to distinguish between P: and P : {}) // this NUL record is 13 bytes long on 32 bit version and 25 bytes long on 64 bit. - const size_t sentinel_block_length = /*check_flag(flags, e_flag_field_size_64_bit) ? (sizeof(uint64_t) * 3 + 1) : */(sizeof(uint32_t) * 3 + 1); + const size_t sentinel_block_length = is64bits ? (sizeof(uint64_t)* 3 + 1) : (sizeof(uint32_t)* 3 + 1); if (Offset(input, cursor) < end_offset) { if (end_offset - Offset(input, cursor) < sentinel_block_length) { @@ -404,7 +403,7 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, // XXX this is vulnerable to stack overflowing .. while(Offset(input, cursor) < end_offset - sentinel_block_length) { - ReadScope(output_tokens, input, cursor, input + end_offset - sentinel_block_length, flags); + ReadScope(output_tokens, input, cursor, input + end_offset - sentinel_block_length, is64bits); } output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) )); @@ -423,10 +422,10 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, return true; } - } // ------------------------------------------------------------------------------------------------ +// TODO: Test FBX Binary files newer than the 7500 version to check if the 64 bits address behaviour is consistent void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int length) { ai_assert(input); @@ -436,16 +435,28 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int le } //uint32_t offset = 0x15; - const char* cursor = input + 0x15; +/* const char* cursor = input + 0x15; const uint32_t flags = ReadWord(input, cursor, input + length); const uint8_t padding_0 = ReadByte(input, cursor, input + length); // unused - const uint8_t padding_1 = ReadByte(input, cursor, input + length); // unused + const uint8_t padding_1 = ReadByte(input, cursor, input + length); // unused*/ + if (strncmp(input,"Kaydara FBX Binary",18)) { + TokenizeError("magic bytes not found",0); + } + + const char* cursor = input + 18; + /*Result ignored*/ ReadByte(input, cursor, input + length); + /*Result ignored*/ ReadByte(input, cursor, input + length); + /*Result ignored*/ ReadByte(input, cursor, input + length); + /*Result ignored*/ ReadByte(input, cursor, input + length); + /*Result ignored*/ ReadByte(input, cursor, input + length); + const uint32_t version = ReadWord(input, cursor, input + length); + const bool is64bits = version >= 7500; while (cursor < input + length) { - if(!ReadScope(output_tokens, input, cursor, input + length, flags)) { + if (!ReadScope(output_tokens, input, cursor, input + length, is64bits)) { break; } } diff --git a/code/FBXCompileConfig.h b/code/FBXCompileConfig.h index 901f5b330..56aa1c787 100644 --- a/code/FBXCompileConfig.h +++ b/code/FBXCompileConfig.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -44,6 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INCLUDED_AI_FBX_COMPILECONFIG_H #define INCLUDED_AI_FBX_COMPILECONFIG_H +#include + // #if _MSC_VER > 1500 || (defined __GNUC___) # define ASSIMP_FBX_USE_UNORDERED_MULTIMAP @@ -63,4 +66,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # endif #endif -#endif +#endif // INCLUDED_AI_FBX_COMPILECONFIG_H diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 5148f23d5..24bdfdd11 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -54,11 +55,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "StringComparison.h" #include + #include #include - #include -#include #include namespace Assimp { @@ -436,6 +436,18 @@ private: aiScene* const out; const FBX::Document& doc; + + bool FindTextureIndexByFilename(const Video& video, unsigned int& index) { + index = 0; + const char* videoFileName = video.FileName().c_str(); + for (auto texture = textures_converted.begin(); texture != textures_converted.end(); ++texture) { + if (!strcmp(texture->first->FileName().c_str(), videoFileName)) { + index = texture->second; + return true; + } + } + return false; + } }; Converter::Converter( aiScene* out, const Document& doc ) @@ -553,7 +565,6 @@ void Converter::ConvertNodes( uint64_t id, aiNode& parent, const aiMatrix4x4& pa if ( !name_carrier ) { nodes_chain.push_back( new aiNode( original_name ) ); - name_carrier = nodes_chain.back(); } //setup metadata on newest node @@ -632,7 +643,6 @@ void Converter::ConvertCameras( const Model& model ) } } - void Converter::ConvertLight( const Model& model, const Light& light ) { lights.push_back( new aiLight() ); @@ -640,7 +650,7 @@ void Converter::ConvertLight( const Model& model, const Light& light ) out_light->mName.Set( FixNodeName( model.Name() ) ); - const float intensity = light.Intensity(); + const float intensity = light.Intensity() / 100.0f; const aiVector3D& col = light.Color(); out_light->mColorDiffuse = aiColor3D( col.x, col.y, col.z ); @@ -650,6 +660,11 @@ void Converter::ConvertLight( const Model& model, const Light& light ) out_light->mColorSpecular = out_light->mColorDiffuse; + //lights are defined along negative y direction + out_light->mPosition = aiVector3D(0.0f); + out_light->mDirection = aiVector3D(0.0f, -1.0f, 0.0f); + out_light->mUp = aiVector3D(0.0f, 0.0f, -1.0f); + switch ( light.LightType() ) { case Light::Type_Point: @@ -679,17 +694,23 @@ void Converter::ConvertLight( const Model& model, const Light& light ) ai_assert( false ); } - // XXX: how to best convert the near and far decay ranges? + float decay = light.DecayStart(); switch ( light.DecayType() ) { case Light::Decay_None: - out_light->mAttenuationConstant = 1.0f; + out_light->mAttenuationConstant = decay; + out_light->mAttenuationLinear = 0.0f; + out_light->mAttenuationQuadratic = 0.0f; break; case Light::Decay_Linear: - out_light->mAttenuationLinear = 1.0f; + out_light->mAttenuationConstant = 0.0f; + out_light->mAttenuationLinear = 2.0f / decay; + out_light->mAttenuationQuadratic = 0.0f; break; case Light::Decay_Quadratic: - out_light->mAttenuationQuadratic = 1.0f; + out_light->mAttenuationConstant = 0.0f; + out_light->mAttenuationLinear = 0.0f; + out_light->mAttenuationQuadratic = 2.0f / (decay * decay); break; case Light::Decay_Cubic: FBXImporter::LogWarn( "cannot represent cubic attenuation, set to Quadratic" ); @@ -708,10 +729,13 @@ void Converter::ConvertCamera( const Model& model, const Camera& cam ) out_camera->mName.Set( FixNodeName( model.Name() ) ); out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight(); - out_camera->mPosition = cam.Position(); - out_camera->mUp = cam.UpVector(); - out_camera->mLookAt = cam.InterestPosition() - out_camera->mPosition; + //cameras are defined along positive x direction + out_camera->mPosition = aiVector3D(0.0f); + out_camera->mLookAt = aiVector3D(1.0f, 0.0f, 0.0f); + out_camera->mUp = aiVector3D(0.0f, 1.0f, 0.0f); out_camera->mHorizontalFOV = AI_DEG_TO_RAD( cam.FieldOfView() ); + out_camera->mClipPlaneNear = cam.NearPlane(); + out_camera->mClipPlaneFar = cam.FarPlane(); } @@ -756,7 +780,6 @@ const char* Converter::NameTransformationComp( TransformationComp comp ) return NULL; } - const char* Converter::NameTransformationCompProperty( TransformationComp comp ) { switch ( comp ) @@ -904,7 +927,7 @@ bool Converter::NeedsComplexTransformationChain( const Model& model ) const TransformationComp comp = static_cast< TransformationComp >( i ); if ( comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation || - comp == TransformationComp_GeometricScaling || comp == TransformationComp_GeometricRotation || comp == TransformationComp_GeometricTranslation ) { + comp == TransformationComp_GeometricScaling || comp == TransformationComp_GeometricRotation || comp == TransformationComp_GeometricTranslation ) { continue; } @@ -922,8 +945,7 @@ std::string Converter::NameTransformationChainNode( const std::string& name, Tra return name + std::string( MAGIC_NODE_TAG ) + "_" + NameTransformationComp( comp ); } -void Converter::GenerateTransformationNodeChain( const Model& model, - std::vector& output_nodes ) +void Converter::GenerateTransformationNodeChain( const Model& model, std::vector& output_nodes ) { const PropertyTable& props = model.Props(); const Model::RotOrder rot = model.RotationOrder(); @@ -1038,6 +1060,10 @@ void Converter::GenerateTransformationNodeChain( const Model& model, continue; } + if ( comp == TransformationComp_PostRotation ) { + chain[ i ] = chain[ i ].Inverse(); + } + aiNode* nd = new aiNode(); output_nodes.push_back( nd ); @@ -1066,7 +1092,7 @@ void Converter::SetupNodeMetadata( const Model& model, aiNode& nd ) DirectPropertyMap unparsedProperties = props.GetUnparsedProperties(); // create metadata on node - std::size_t numStaticMetaData = 2; + const std::size_t numStaticMetaData = 2; aiMetadata* data = aiMetadata::Alloc( static_cast(unparsedProperties.size() + numStaticMetaData) ); nd.mMetaData = data; int index = 0; @@ -1735,7 +1761,7 @@ unsigned int Converter::ConvertVideo( const Video& video ) out_tex->mWidth = static_cast( video.ContentLength() ); // total data size out_tex->mHeight = 0; // fixed to 0 - // steal the data from the Video to avoid an additional copy + // steal the data from the Video to avoid an additional copy out_tex->pcData = reinterpret_cast( const_cast( video ).RelinquishContent() ); // try to extract a hint from the file extension @@ -1769,22 +1795,32 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap& path.Set( tex->RelativeFilename() ); const Video* media = tex->Media(); - if ( media != 0 && media->ContentLength() > 0 ) { - unsigned int index; + if (media != 0) { + bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found) + unsigned int index; - VideoMap::const_iterator it = textures_converted.find( media ); - if ( it != textures_converted.end() ) { - index = ( *it ).second; - } - else { - index = ConvertVideo( *media ); - textures_converted[ media ] = index; - } + VideoMap::const_iterator it = textures_converted.find(media); + if (it != textures_converted.end()) { + index = (*it).second; + textureReady = true; + } + else { + if (media->ContentLength() > 0) { + index = ConvertVideo(*media); + textures_converted[media] = index; + textureReady = true; + } + else if (doc.Settings().searchEmbeddedTextures) { //try to find the texture on the already-loaded textures by the filename, if the flag is on + textureReady = FindTextureIndexByFilename(*media, index); + } + } - // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) - path.data[ 0 ] = '*'; - path.length = 1 + ASSIMP_itoa10( path.data + 1, MAXLEN - 1, index ); - } + // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready + if (textureReady) { + path.data[0] = '*'; + path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index); + } + } out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, 0 ); @@ -2120,6 +2156,16 @@ void Converter::SetShadingPropertiesCommon( aiMaterial* out_mat, const PropertyT if ( ok ) { out_mat->AddProperty( &ShininessExponent, 1, AI_MATKEY_SHININESS ); } + + const float BumpFactor = PropertyGet(props, "BumpFactor", ok); + if (ok) { + out_mat->AddProperty(&BumpFactor, 1, AI_MATKEY_BUMPSCALING); + } + + const float DispFactor = PropertyGet(props, "DisplacementFactor", ok); + if (ok) { + out_mat->AddProperty(&DispFactor, 1, "$mat.displacementscaling", 0, 0); + } } @@ -2189,9 +2235,17 @@ void Converter::ConvertAnimations() } } +void Converter::RenameNode( const std::string& fixed_name, const std::string& new_name ) { + if ( node_names.find( fixed_name ) == node_names.end() ) { + FBXImporter::LogError( "Cannot rename node " + fixed_name + ", not existing."); + return; + } + + if ( node_names.find( new_name ) != node_names.end() ) { + FBXImporter::LogError( "Cannot rename node " + fixed_name + " to " + new_name +", name already existing." ); + return; + } -void Converter::RenameNode( const std::string& fixed_name, const std::string& new_name ) -{ ai_assert( node_names.find( fixed_name ) != node_names.end() ); ai_assert( node_names.find( new_name ) == node_names.end() ); @@ -2321,8 +2375,13 @@ void Converter::ConvertAnimationStack( const AnimationStack& st ) int64_t start_time = st.LocalStart(); int64_t stop_time = st.LocalStop(); - double start_timeF = CONVERT_FBX_TIME( start_time ); - double stop_timeF = CONVERT_FBX_TIME( stop_time ); + bool has_local_startstop = start_time != 0 || stop_time != 0; + if ( !has_local_startstop ) { + // no time range given, so accept every keyframe and use the actual min/max time + // the numbers are INT64_MIN/MAX, the 20000 is for safety because GenerateNodeAnimations uses an epsilon of 10000 + start_time = -9223372036854775807ll + 20000; + stop_time = 9223372036854775807ll - 20000; + } try { for( const NodeMap::value_type& kv : node_map ) { @@ -2354,30 +2413,27 @@ void Converter::ConvertAnimationStack( const AnimationStack& st ) return; } - //adjust relative timing for animation - { - double start_fps = start_timeF * anim_fps; + double start_time_fps = has_local_startstop ? (CONVERT_FBX_TIME(start_time) * anim_fps) : min_time; + double stop_time_fps = has_local_startstop ? (CONVERT_FBX_TIME(stop_time) * anim_fps) : max_time; - for ( unsigned int c = 0; c < anim->mNumChannels; c++ ) - { - aiNodeAnim* channel = anim->mChannels[ c ]; - for ( uint32_t i = 0; i < channel->mNumPositionKeys; i++ ) - channel->mPositionKeys[ i ].mTime -= start_fps; - for ( uint32_t i = 0; i < channel->mNumRotationKeys; i++ ) - channel->mRotationKeys[ i ].mTime -= start_fps; - for ( uint32_t i = 0; i < channel->mNumScalingKeys; i++ ) - channel->mScalingKeys[ i ].mTime -= start_fps; - } - - max_time -= min_time; + // adjust relative timing for animation + for ( unsigned int c = 0; c < anim->mNumChannels; c++ ) { + aiNodeAnim* channel = anim->mChannels[ c ]; + for ( uint32_t i = 0; i < channel->mNumPositionKeys; i++ ) + channel->mPositionKeys[ i ].mTime -= start_time_fps; + for ( uint32_t i = 0; i < channel->mNumRotationKeys; i++ ) + channel->mRotationKeys[ i ].mTime -= start_time_fps; + for ( uint32_t i = 0; i < channel->mNumScalingKeys; i++ ) + channel->mScalingKeys[ i ].mTime -= start_time_fps; } // for some mysterious reason, mDuration is simply the maximum key -- the // validator always assumes animations to start at zero. - anim->mDuration = ( stop_timeF - start_timeF ) * anim_fps; + anim->mDuration = stop_time_fps - start_time_fps; anim->mTicksPerSecond = anim_fps; } +#ifdef ASSIMP_BUILD_DEBUG // ------------------------------------------------------------------------------------------------ // sanity check whether the input is ok static void validateAnimCurveNodes( const std::vector& curves, @@ -2395,6 +2451,7 @@ static void validateAnimCurveNodes( const std::vector } } } +#endif // ASSIMP_BUILD_DEBUG // ------------------------------------------------------------------------------------------------ void Converter::GenerateNodeAnimations( std::vector& node_anims, @@ -2686,10 +2743,10 @@ aiNodeAnim* Converter::GenerateRotationNodeAnim( const std::string& name, double& max_time, double& min_time ) { - ScopeGuard na( new aiNodeAnim() ); + std::unique_ptr na( new aiNodeAnim() ); na->mNodeName.Set( name ); - ConvertRotationKeys( na, curves, layer_map, start, stop, max_time, min_time, target.RotationOrder() ); + ConvertRotationKeys( na.get(), curves, layer_map, start, stop, max_time, min_time, target.RotationOrder() ); // dummy scaling key na->mScalingKeys = new aiVectorKey[ 1 ]; @@ -2705,7 +2762,7 @@ aiNodeAnim* Converter::GenerateRotationNodeAnim( const std::string& name, na->mPositionKeys[ 0 ].mTime = 0.; na->mPositionKeys[ 0 ].mValue = aiVector3D(); - return na.dismiss(); + return na.release(); } aiNodeAnim* Converter::GenerateScalingNodeAnim( const std::string& name, @@ -2716,10 +2773,10 @@ aiNodeAnim* Converter::GenerateScalingNodeAnim( const std::string& name, double& max_time, double& min_time ) { - ScopeGuard na( new aiNodeAnim() ); + std::unique_ptr na( new aiNodeAnim() ); na->mNodeName.Set( name ); - ConvertScaleKeys( na, curves, layer_map, start, stop, max_time, min_time ); + ConvertScaleKeys( na.get(), curves, layer_map, start, stop, max_time, min_time ); // dummy rotation key na->mRotationKeys = new aiQuatKey[ 1 ]; @@ -2735,7 +2792,7 @@ aiNodeAnim* Converter::GenerateScalingNodeAnim( const std::string& name, na->mPositionKeys[ 0 ].mTime = 0.; na->mPositionKeys[ 0 ].mValue = aiVector3D(); - return na.dismiss(); + return na.release(); } @@ -2748,10 +2805,10 @@ aiNodeAnim* Converter::GenerateTranslationNodeAnim( const std::string& name, double& min_time, bool inverse ) { - ScopeGuard na( new aiNodeAnim() ); + std::unique_ptr na( new aiNodeAnim() ); na->mNodeName.Set( name ); - ConvertTranslationKeys( na, curves, layer_map, start, stop, max_time, min_time ); + ConvertTranslationKeys( na.get(), curves, layer_map, start, stop, max_time, min_time ); if ( inverse ) { for ( unsigned int i = 0; i < na->mNumPositionKeys; ++i ) { @@ -2773,7 +2830,7 @@ aiNodeAnim* Converter::GenerateTranslationNodeAnim( const std::string& name, na->mRotationKeys[ 0 ].mTime = 0.; na->mRotationKeys[ 0 ].mValue = aiQuaternion(); - return na.dismiss(); + return na.release(); } aiNodeAnim* Converter::GenerateSimpleNodeAnim( const std::string& name, @@ -2787,7 +2844,7 @@ aiNodeAnim* Converter::GenerateSimpleNodeAnim( const std::string& name, bool reverse_order ) { - ScopeGuard na( new aiNodeAnim() ); + std::unique_ptr na( new aiNodeAnim() ); na->mNodeName.Set( name ); const PropertyTable& props = target.Props(); @@ -2859,7 +2916,7 @@ aiNodeAnim* Converter::GenerateSimpleNodeAnim( const std::string& name, // which requires all of rotation, scaling and translation // to be set. if ( chain[ TransformationComp_Scaling ] != iter_end ) { - ConvertScaleKeys( na, ( *chain[ TransformationComp_Scaling ] ).second, + ConvertScaleKeys( na.get(), ( *chain[ TransformationComp_Scaling ] ).second, layer_map, start, stop, max_time, @@ -2875,7 +2932,7 @@ aiNodeAnim* Converter::GenerateSimpleNodeAnim( const std::string& name, } if ( chain[ TransformationComp_Rotation ] != iter_end ) { - ConvertRotationKeys( na, ( *chain[ TransformationComp_Rotation ] ).second, + ConvertRotationKeys( na.get(), ( *chain[ TransformationComp_Rotation ] ).second, layer_map, start, stop, max_time, @@ -2893,7 +2950,7 @@ aiNodeAnim* Converter::GenerateSimpleNodeAnim( const std::string& name, } if ( chain[ TransformationComp_Translation ] != iter_end ) { - ConvertTranslationKeys( na, ( *chain[ TransformationComp_Translation ] ).second, + ConvertTranslationKeys( na.get(), ( *chain[ TransformationComp_Translation ] ).second, layer_map, start, stop, max_time, @@ -2909,7 +2966,7 @@ aiNodeAnim* Converter::GenerateSimpleNodeAnim( const std::string& name, } } - return na.dismiss(); + return na.release(); } Converter::KeyFrameListList Converter::GetKeyframeList( const std::vector& nodes, int64_t start, int64_t stop ) @@ -3072,7 +3129,6 @@ void Converter::InterpolateKeys( aiVectorKey* valOut, const KeyTimeList& keys, c } } - void Converter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, const KeyFrameListList& inputs, const aiVector3D& def_value, double& maxTime, @@ -3093,7 +3149,6 @@ void Converter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, con valOut[ i ].mTime = temp[ i ].mTime; - GetRotationMatrix( order, temp[ i ].mValue, m ); aiQuaternion quat = aiQuaternion( aiMatrix3x3( m ) ); @@ -3112,7 +3167,6 @@ void Converter::InterpolateKeys( aiQuatKey* valOut, const KeyTimeList& keys, con } } - void Converter::ConvertTransformOrder_TRStoSRT( aiQuatKey* out_quat, aiVectorKey* out_scale, aiVectorKey* out_translation, const KeyFrameListList& scaling, @@ -3171,7 +3225,6 @@ void Converter::ConvertTransformOrder_TRStoSRT( aiQuatKey* out_quat, aiVectorKey } } - aiQuaternion Converter::EulerToQuaternion( const aiVector3D& rot, Model::RotOrder order ) { aiMatrix4x4 m; @@ -3180,7 +3233,6 @@ aiQuaternion Converter::EulerToQuaternion( const aiVector3D& rot, Model::RotOrde return aiQuaternion( aiMatrix3x3( m ) ); } - void Converter::ConvertScaleKeys( aiNodeAnim* na, const std::vector& nodes, const LayerMap& /*layers*/, int64_t start, int64_t stop, double& maxTime, @@ -3201,7 +3253,6 @@ void Converter::ConvertScaleKeys( aiNodeAnim* na, const std::vectormScalingKeys, keys, inputs, aiVector3D( 1.0f, 1.0f, 1.0f ), maxTime, minTime ); } - void Converter::ConvertTranslationKeys( aiNodeAnim* na, const std::vector& nodes, const LayerMap& /*layers*/, int64_t start, int64_t stop, @@ -3220,7 +3271,6 @@ void Converter::ConvertTranslationKeys( aiNodeAnim* na, const std::vectormPositionKeys, keys, inputs, aiVector3D( 0.0f, 0.0f, 0.0f ), maxTime, minTime ); } - void Converter::ConvertRotationKeys( aiNodeAnim* na, const std::vector& nodes, const LayerMap& /*layers*/, int64_t start, int64_t stop, @@ -3242,7 +3292,8 @@ void Converter::ConvertRotationKeys( aiNodeAnim* na, const std::vectormMeshes && !out->mNumMeshes ); + ai_assert( !out->mMeshes ); + ai_assert( !out->mNumMeshes ); // note: the trailing () ensures initialization with NULL - not // many C++ users seem to know this, so pointing it out to avoid diff --git a/code/FBXConverter.h b/code/FBXConverter.h index ddbbbbf25..8a62d8811 100644 --- a/code/FBXConverter.h +++ b/code/FBXConverter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/FBXDeformer.cpp b/code/FBXDeformer.cpp index 067a5e405..637144ab1 100644 --- a/code/FBXDeformer.cpp +++ b/code/FBXDeformer.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -47,9 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXParser.h" #include "FBXDocument.h" #include "FBXImporter.h" -#include "FBXImportSettings.h" #include "FBXDocumentUtil.h" -#include "FBXProperties.h" namespace Assimp { namespace FBX { diff --git a/code/FBXDocument.cpp b/code/FBXDocument.cpp index dafda6c98..9592bf31f 100644 --- a/code/FBXDocument.cpp +++ b/code/FBXDocument.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -55,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include - +#include namespace Assimp { namespace FBX { @@ -69,19 +70,13 @@ LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc) , id(id) , flags() { - + // empty } // ------------------------------------------------------------------------------------------------ LazyObject::~LazyObject() { - -} - -// ------------------------------------------------------------------------------------------------ -static void dumpObjectClassInfo( const char* obtype, const std::string &classtag ) { - DefaultLogger::get()->debug( "obtype: " + std::string(obtype )); - DefaultLogger::get()->debug( "Classtag: " + classtag ); + // empty } // ------------------------------------------------------------------------------------------------ @@ -237,16 +232,15 @@ Object::Object(uint64_t id, const Element& element, const std::string& name) , name(name) , id(id) { - + // empty } // ------------------------------------------------------------------------------------------------ Object::~Object() { - + // empty } - // ------------------------------------------------------------------------------------------------ FileGlobalSettings::FileGlobalSettings(const Document& doc, std::shared_ptr props) : props(props) @@ -297,11 +291,10 @@ Document::~Document() } // ------------------------------------------------------------------------------------------------ -static const int LowerSupportedVersion = 7100; -static const int UpperSupportedVersion = 7400; +static const unsigned int LowerSupportedVersion = 7100; +static const unsigned int UpperSupportedVersion = 7400; -void Document::ReadHeader() -{ +void Document::ReadHeader() { // Read ID objects from "Objects" section const Scope& sc = parser.GetRootScope(); const Element* const ehead = sc["FBXHeaderExtension"]; @@ -367,7 +360,6 @@ void Document::ReadGlobalSettings() globals.reset(new FileGlobalSettings(*this, props)); } - // ------------------------------------------------------------------------------------------------ void Document::ReadObjects() { @@ -393,7 +385,6 @@ void Document::ReadObjects() } const char* err; - const uint64_t id = ParseTokenAsID(*tok[0], err); if(err) { DOMError(err,el.second); @@ -475,8 +466,6 @@ void Document::ReadPropertyTemplates() } } - - // ------------------------------------------------------------------------------------------------ void Document::ReadConnections() { @@ -488,7 +477,6 @@ void Document::ReadConnections() } uint64_t insertionOrder = 0l; - const Scope& sconns = *econns->Compound(); const ElementCollection conns = sconns.GetCollection("C"); for(ElementMap::const_iterator it = conns.first; it != conns.second; ++it) { @@ -497,7 +485,9 @@ void Document::ReadConnections() // PP = property-property connection, ignored for now // (tokens: "PP", ID1, "Property1", ID2, "Property2") - if(type == "PP") continue; + if ( type == "PP" ) { + continue; + } const uint64_t src = ParseTokenAsID(GetRequiredToken(el,1)); const uint64_t dest = ParseTokenAsID(GetRequiredToken(el,2)); @@ -524,11 +514,10 @@ void Document::ReadConnections() } } - // ------------------------------------------------------------------------------------------------ const std::vector& Document::AnimationStacks() const { - if (!animationStacksResolved.empty() || !animationStacks.size()) { + if (!animationStacksResolved.empty() || animationStacks.empty()) { return animationStacksResolved; } @@ -546,7 +535,6 @@ const std::vector& Document::AnimationStacks() const return animationStacksResolved; } - // ------------------------------------------------------------------------------------------------ LazyObject* Document::GetObject(uint64_t id) const { @@ -557,8 +545,7 @@ LazyObject* Document::GetObject(uint64_t id) const #define MAX_CLASSNAMES 6 // ------------------------------------------------------------------------------------------------ -std::vector Document::GetConnectionsSequenced(uint64_t id, - const ConnectionMap& conns) const +std::vector Document::GetConnectionsSequenced(uint64_t id, const ConnectionMap& conns) const { std::vector temp; @@ -570,12 +557,11 @@ std::vector Document::GetConnectionsSequenced(uint64_t id, temp.push_back((*it).second); } - std::sort(temp.begin(), temp.end(), std::mem_fun(&Connection::Compare)); + std::sort(temp.begin(), temp.end(), std::mem_fn(&Connection::Compare)); return temp; // NRVO should handle this } - // ------------------------------------------------------------------------------------------------ std::vector Document::GetConnectionsSequenced(uint64_t id, bool is_src, const ConnectionMap& conns, @@ -584,17 +570,17 @@ std::vector Document::GetConnectionsSequenced(uint64_t id, bo { ai_assert(classnames); - ai_assert(count != 0 && count <= MAX_CLASSNAMES); + ai_assert( count != 0 ); + ai_assert( count <= MAX_CLASSNAMES); size_t lenghts[MAX_CLASSNAMES]; const size_t c = count; for (size_t i = 0; i < c; ++i) { - lenghts[i] = strlen(classnames[i]); + lenghts[ i ] = strlen(classnames[i]); } std::vector temp; - const std::pair range = conns.equal_range(id); @@ -622,53 +608,44 @@ std::vector Document::GetConnectionsSequenced(uint64_t id, bo temp.push_back((*it).second); } - std::sort(temp.begin(), temp.end(), std::mem_fun(&Connection::Compare)); + std::sort(temp.begin(), temp.end(), std::mem_fn(&Connection::Compare)); return temp; // NRVO should handle this } - // ------------------------------------------------------------------------------------------------ std::vector Document::GetConnectionsBySourceSequenced(uint64_t source) const { return GetConnectionsSequenced(source, ConnectionsBySource()); } - - // ------------------------------------------------------------------------------------------------ -std::vector Document::GetConnectionsBySourceSequenced(uint64_t dest, - const char* classname) const +std::vector Document::GetConnectionsBySourceSequenced(uint64_t dest, const char* classname) const { const char* arr[] = {classname}; return GetConnectionsBySourceSequenced(dest, arr,1); } - - // ------------------------------------------------------------------------------------------------ -std::vector Document::GetConnectionsBySourceSequenced(uint64_t source, - const char* const* classnames, size_t count) const +std::vector Document::GetConnectionsBySourceSequenced(uint64_t source, + const char* const* classnames, size_t count) const { return GetConnectionsSequenced(source, true, ConnectionsBySource(),classnames, count); } - // ------------------------------------------------------------------------------------------------ std::vector Document::GetConnectionsByDestinationSequenced(uint64_t dest, - const char* classname) const + const char* classname) const { const char* arr[] = {classname}; return GetConnectionsByDestinationSequenced(dest, arr,1); } - // ------------------------------------------------------------------------------------------------ std::vector Document::GetConnectionsByDestinationSequenced(uint64_t dest) const { return GetConnectionsSequenced(dest, ConnectionsByDestination()); } - // ------------------------------------------------------------------------------------------------ std::vector Document::GetConnectionsByDestinationSequenced(uint64_t dest, const char* const* classnames, size_t count) const @@ -677,10 +654,9 @@ std::vector Document::GetConnectionsByDestinationSequenced(ui return GetConnectionsSequenced(dest, false, ConnectionsByDestination(),classnames, count); } - // ------------------------------------------------------------------------------------------------ Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop, - const Document& doc) + const Document& doc) : insertionOrder(insertionOrder) , prop(prop) @@ -693,14 +669,12 @@ Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, co ai_assert(!dest || doc.Objects().find(dest) != doc.Objects().end()); } - // ------------------------------------------------------------------------------------------------ Connection::~Connection() { - + // empty } - // ------------------------------------------------------------------------------------------------ LazyObject& Connection::LazySourceObject() const { @@ -709,7 +683,6 @@ LazyObject& Connection::LazySourceObject() const return *lazy; } - // ------------------------------------------------------------------------------------------------ LazyObject& Connection::LazyDestinationObject() const { @@ -718,7 +691,6 @@ LazyObject& Connection::LazyDestinationObject() const return *lazy; } - // ------------------------------------------------------------------------------------------------ const Object* Connection::SourceObject() const { @@ -727,7 +699,6 @@ const Object* Connection::SourceObject() const return lazy->Get(); } - // ------------------------------------------------------------------------------------------------ const Object* Connection::DestinationObject() const { @@ -740,4 +711,3 @@ const Object* Connection::DestinationObject() const } // !Assimp #endif - diff --git a/code/FBXDocument.h b/code/FBXDocument.h index be67e32e6..a4e28b2aa 100644 --- a/code/FBXDocument.h +++ b/code/FBXDocument.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -240,6 +241,9 @@ public: fbx_simple_property(FilmWidth, float, 1.0f) fbx_simple_property(FilmHeight, float, 1.0f) + fbx_simple_property(NearPlane, float, 0.1f) + fbx_simple_property(FarPlane, float, 100.0f) + fbx_simple_property(FilmAspectRatio, float, 1.0f) fbx_simple_property(ApertureMode, int, 0) @@ -302,12 +306,12 @@ public: fbx_simple_property(DrawVolumetricLight, bool, true) fbx_simple_property(DrawGroundProjection, bool, true) fbx_simple_property(DrawFrontFacingVolumetricLight, bool, false) - fbx_simple_property(Intensity, float, 1.0f) + fbx_simple_property(Intensity, float, 100.0f) fbx_simple_property(InnerAngle, float, 0.0f) fbx_simple_property(OuterAngle, float, 45.0f) fbx_simple_property(Fog, int, 50) - fbx_simple_enum_property(DecayType, Decay, 0) - fbx_simple_property(DecayStart, int, 0) + fbx_simple_enum_property(DecayType, Decay, 2) + fbx_simple_property(DecayStart, float, 1.0f) fbx_simple_property(FileName, std::string, "") fbx_simple_property(EnableNearAttenuation, bool, false) @@ -334,12 +338,7 @@ public: class Model : public Object { public: - Model(uint64_t id, const Element& element, const Document& doc, const std::string& name); - virtual ~Model(); - -public: - enum RotOrder - { + enum RotOrder { RotOrder_EulerXYZ = 0, RotOrder_EulerXZY, RotOrder_EulerYZX, @@ -353,8 +352,7 @@ public: }; - enum TransformInheritance - { + enum TransformInheritance { TransformInheritance_RrSs = 0, TransformInheritance_RSrs, TransformInheritance_Rrs, @@ -362,7 +360,10 @@ public: TransformInheritance_MAX // end-of-enum sentinel }; -public: + Model(uint64_t id, const Element& element, const Document& doc, const std::string& name); + + virtual ~Model(); + fbx_simple_property(QuaternionInterpolate, int, 0) fbx_simple_property(RotationOffset, aiVector3D, aiVector3D()) @@ -439,7 +440,6 @@ public: fbx_simple_property(LODBox, bool, false) fbx_simple_property(Freeze, bool, false) -public: const std::string& Shading() const { return shading; } @@ -458,13 +458,11 @@ public: return materials; } - /** Get geometry links */ const std::vector& GetGeometry() const { return geometry; } - /** Get node attachments */ const std::vector& GetAttributes() const { return attributes; @@ -473,7 +471,6 @@ public: /** convenience method to check if the node has a Null node marker */ bool IsNull() const; - private: void ResolveLinks(const Element& element, const Document& doc); @@ -599,10 +596,10 @@ public: return textures[index]; } - const int textureCount() const { + int textureCount() const { return static_cast(textures.size()); } - const BlendMode GetBlendMode() const + BlendMode GetBlendMode() const { return blendMode; } @@ -650,7 +647,7 @@ public: return content; } - const uint32_t ContentLength() const { + uint32_t ContentLength() const { return contentLength; } @@ -801,7 +798,6 @@ private: typedef std::vector AnimationCurveNodeList; - /** Represents a FBX animation layer (i.e. a list of node animations) */ class AnimationLayer : public Object { @@ -824,10 +820,8 @@ private: const Document& doc; }; - typedef std::vector AnimationLayerList; - /** Represents a FBX animation stack (i.e. a list of animation layers) */ class AnimationStack : public Object { @@ -835,7 +829,6 @@ public: AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc); virtual ~AnimationStack(); -public: fbx_simple_property(LocalStart, int64_t, 0L) fbx_simple_property(LocalStop, int64_t, 0L) fbx_simple_property(ReferenceStart, int64_t, 0L) @@ -875,7 +868,6 @@ private: typedef std::vector WeightArray; typedef std::vector WeightIndexArray; - /** DOM class for skin deformer clusters (aka subdeformers) */ class Cluster : public Deformer { @@ -920,8 +912,6 @@ private: const Model* node; }; - - /** DOM class for skin deformers */ class Skin : public Deformer { @@ -1005,10 +995,8 @@ public: typedef std::map ObjectMap; typedef std::fbx_unordered_map > PropertyTemplateMap; - typedef std::multimap ConnectionMap; - /** DOM class for global document settings, a single instance per document can * be accessed via Document.Globals(). */ class FileGlobalSettings @@ -1070,9 +1058,6 @@ private: const Document& doc; }; - - - /** DOM root for a FBX file */ class Document { @@ -1150,8 +1135,6 @@ private: const ConnectionMap&, const char* const* classnames, size_t count) const; - -private: void ReadHeader(); void ReadObjects(); void ReadPropertyTemplates(); diff --git a/code/FBXDocumentUtil.cpp b/code/FBXDocumentUtil.cpp index 442c60b5d..27921b920 100644 --- a/code/FBXDocumentUtil.cpp +++ b/code/FBXDocumentUtil.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/FBXImportSettings.h b/code/FBXImportSettings.h index df7cdbd37..53fa64ec6 100644 --- a/code/FBXImportSettings.h +++ b/code/FBXImportSettings.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -62,6 +63,7 @@ struct ImportSettings , readWeights(true) , preservePivots(true) , optimizeEmptyAnimationCurves(true) + , searchEmbeddedTextures(false) {} @@ -136,6 +138,10 @@ struct ImportSettings * values matching the corresponding node transformation. * The default value is true. */ bool optimizeEmptyAnimationCurves; + + /** search for embedded loaded textures, where no embedded texture data is provided. + * The default value is false. */ + bool searchEmbeddedTextures; }; diff --git a/code/FBXImporter.cpp b/code/FBXImporter.cpp index d6c80db2f..51e41b8f4 100644 --- a/code/FBXImporter.cpp +++ b/code/FBXImporter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -55,12 +56,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "StreamReader.h" #include "MemoryIOWrapper.h" #include - -#include -#include +#include namespace Assimp { - template<> const std::string LogFunctions::log_prefix = "FBX: "; + template<> const char* LogFunctions::Prefix() + { + static auto prefix = "FBX: "; + return prefix; + } } using namespace Assimp; @@ -132,6 +135,7 @@ void FBXImporter::SetupProperties(const Importer* pImp) settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false); settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true); settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true); + settings.searchEmbeddedTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_SEARCH_EMBEDDED_TEXTURES, false); } // ------------------------------------------------------------------------------------------------ diff --git a/code/FBXImporter.h b/code/FBXImporter.h index 350ecfb67..43be97ffa 100644 --- a/code/FBXImporter.h +++ b/code/FBXImporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/FBXMaterial.cpp b/code/FBXMaterial.cpp index e5e9cd259..a80f243ba 100644 --- a/code/FBXMaterial.cpp +++ b/code/FBXMaterial.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -280,7 +281,7 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std const Scope& sc = GetRequiredScope(element); const Element* const Type = sc["Type"]; - const Element* const FileName = sc["FileName"]; + const Element* const FileName = sc.FindElementCaseInsensitive("FileName"); //some files retain the information as "Filename", others "FileName", who knows const Element* const RelativeFilename = sc["RelativeFilename"]; const Element* const Content = sc["Content"]; @@ -290,35 +291,40 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std if(FileName) { fileName = ParseTokenAsString(GetRequiredToken(*FileName,0)); - } + } if(RelativeFilename) { relativeFileName = ParseTokenAsString(GetRequiredToken(*RelativeFilename,0)); } if(Content) { - const Token& token = GetRequiredToken(*Content, 0); - const char* data = token.begin(); - if(!token.IsBinary()) { - DOMWarning("video content is not binary data, ignoring", &element); - } - else if(static_cast(token.end() - data) < 5) { - DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element); - } - else if(*data != 'R') { - DOMWarning("video content is not raw binary data, ignoring", &element); - } - else { - // read number of elements - uint32_t len = 0; - ::memcpy(&len, data + 1, sizeof(len)); - AI_SWAP4(len); + //this field is ommited when the embedded texture is already loaded, let's ignore if it´s not found + try { + const Token& token = GetRequiredToken(*Content, 0); + const char* data = token.begin(); + if (!token.IsBinary()) { + DOMWarning("video content is not binary data, ignoring", &element); + } + else if (static_cast(token.end() - data) < 5) { + DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element); + } + else if (*data != 'R') { + DOMWarning("video content is not raw binary data, ignoring", &element); + } + else { + // read number of elements + uint32_t len = 0; + ::memcpy(&len, data + 1, sizeof(len)); + AI_SWAP4(len); - contentLength = len; + contentLength = len; - content = new uint8_t[len]; - ::memcpy(content, data + 5, len); - } + content = new uint8_t[len]; + ::memcpy(content, data + 5, len); + } + } catch (runtime_error runtimeError) { + //we don´t need the content data for contents that has already been loaded + } } props = GetPropertyTable(doc,"Video.FbxVideo",element,sc); diff --git a/code/FBXMeshGeometry.cpp b/code/FBXMeshGeometry.cpp index e7a105d45..8d43a2436 100644 --- a/code/FBXMeshGeometry.cpp +++ b/code/FBXMeshGeometry.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -242,7 +243,6 @@ const unsigned int* MeshGeometry::ToOutputVertexIndex( unsigned int in_index, un ai_assert( m_mapping_counts.size() == m_mapping_offsets.size() ); count = m_mapping_counts[ in_index ]; -// ai_assert( count != 0 ); ai_assert( m_mapping_offsets[ in_index ] + count <= m_mappings.size() ); return &m_mappings[ m_mapping_offsets[ in_index ] ]; @@ -356,7 +356,7 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop // avoids losing the material if there are more material layers // coming of which at least one contains actual data (did observe // that with one test file). - const size_t count_neg = std::count_if(temp_materials.begin(),temp_materials.end(),std::bind2nd(std::less(),0)); + const size_t count_neg = std::count_if(temp_materials.begin(),temp_materials.end(),[](int n) { return n < 0; }); if(count_neg == temp_materials.size()) { FBXImporter::LogWarn("ignoring dummy material layer (all entries -1)"); return; diff --git a/code/FBXMeshGeometry.h b/code/FBXMeshGeometry.h index 690a86a01..19f7b0a9c 100644 --- a/code/FBXMeshGeometry.h +++ b/code/FBXMeshGeometry.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/FBXModel.cpp b/code/FBXModel.cpp index bbeb14bfb..3d694d7d8 100644 --- a/code/FBXModel.cpp +++ b/code/FBXModel.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -48,9 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXMeshGeometry.h" #include "FBXDocument.h" #include "FBXImporter.h" -#include "FBXImportSettings.h" #include "FBXDocumentUtil.h" -#include "FBXProperties.h" namespace Assimp { namespace FBX { @@ -78,14 +77,12 @@ Model::Model(uint64_t id, const Element& element, const Document& doc, const std ResolveLinks(element,doc); } - // ------------------------------------------------------------------------------------------------ Model::~Model() { } - // ------------------------------------------------------------------------------------------------ void Model::ResolveLinks(const Element& element, const Document& doc) { @@ -133,7 +130,6 @@ void Model::ResolveLinks(const Element& element, const Document& doc) } } - // ------------------------------------------------------------------------------------------------ bool Model::IsNull() const { diff --git a/code/FBXNodeAttribute.cpp b/code/FBXNodeAttribute.cpp index 405ce7206..545343c09 100644 --- a/code/FBXNodeAttribute.cpp +++ b/code/FBXNodeAttribute.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -47,14 +48,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXParser.h" #include "FBXDocument.h" #include "FBXImporter.h" -#include "FBXImportSettings.h" #include "FBXDocumentUtil.h" -#include "FBXProperties.h" namespace Assimp { namespace FBX { - using namespace Util; +using namespace Util; // ------------------------------------------------------------------------------------------------ NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name) @@ -76,7 +75,7 @@ NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document // ------------------------------------------------------------------------------------------------ NodeAttribute::~NodeAttribute() { - + // empty } @@ -102,33 +101,30 @@ CameraSwitcher::CameraSwitcher(uint64_t id, const Element& element, const Docume } } - // ------------------------------------------------------------------------------------------------ CameraSwitcher::~CameraSwitcher() { - + // empty } - // ------------------------------------------------------------------------------------------------ Camera::Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name) : NodeAttribute(id,element,doc,name) { - + // empty } - // ------------------------------------------------------------------------------------------------ Camera::~Camera() { + // empty } - // ------------------------------------------------------------------------------------------------ Light::Light(uint64_t id, const Element& element, const Document& doc, const std::string& name) : NodeAttribute(id,element,doc,name) { - + // empty } diff --git a/code/FBXParser.cpp b/code/FBXParser.cpp index 8e9d40beb..d4d06567b 100644 --- a/code/FBXParser.cpp +++ b/code/FBXParser.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -51,7 +52,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # include "../contrib/zlib/zlib.h" #endif - #include "FBXTokenizer.h" #include "FBXParser.h" #include "FBXUtil.h" @@ -103,6 +103,7 @@ namespace { T SafeParse(const char* data, const char* end) { // Actual size validation happens during Tokenization so // this is valid as an assertion. + (void)(end); ai_assert(static_cast(end - data) >= sizeof(T)); T result = static_cast(0); ::memcpy(&result, data, sizeof(T)); @@ -224,41 +225,36 @@ Parser::Parser (const TokenList& tokens, bool is_binary) root.reset(new Scope(*this,true)); } - // ------------------------------------------------------------------------------------------------ Parser::~Parser() { + // empty } - // ------------------------------------------------------------------------------------------------ TokenPtr Parser::AdvanceToNextToken() { last = current; if (cursor == tokens.end()) { current = NULL; - } - else { + } else { current = *cursor++; } return current; } - // ------------------------------------------------------------------------------------------------ TokenPtr Parser::CurrentToken() const { return current; } - // ------------------------------------------------------------------------------------------------ TokenPtr Parser::LastToken() const { return last; } - // ------------------------------------------------------------------------------------------------ uint64_t ParseTokenAsID(const Token& t, const char*& err_out) { @@ -286,7 +282,7 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out) unsigned int length = static_cast(t.end() - t.begin()); ai_assert(length > 0); - const char* out; + const char* out = nullptr; const uint64_t id = strtoul10_64(t.begin(),&out,&length); if (out > t.end()) { err_out = "failed to parse ID (text)"; @@ -296,7 +292,6 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out) return id; } - // ------------------------------------------------------------------------------------------------ size_t ParseTokenAsDim(const Token& t, const char*& err_out) { @@ -333,7 +328,7 @@ size_t ParseTokenAsDim(const Token& t, const char*& err_out) return 0; } - const char* out; + const char* out = nullptr; const size_t id = static_cast(strtoul10_64(t.begin() + 1,&out,&length)); if (out > t.end()) { err_out = "failed to parse ID"; @@ -446,7 +441,7 @@ int64_t ParseTokenAsInt64(const Token& t, const char*& err_out) unsigned int length = static_cast(t.end() - t.begin()); ai_assert(length > 0); - const char* out; + const char* out = nullptr; const int64_t id = strtol10_64(t.begin(), &out, &length); if (out > t.end()) { err_out = "failed to parse Int64 (text)"; diff --git a/code/FBXParser.h b/code/FBXParser.h index 6bc34272a..4d3766d70 100644 --- a/code/FBXParser.h +++ b/code/FBXParser.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -48,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "LogAux.h" +#include "fast_atof.h" #include "FBXCompileConfig.h" #include "FBXTokenizer.h" @@ -83,12 +85,9 @@ typedef std::pair Element class Element { public: - Element(const Token& key_token, Parser& parser); ~Element(); -public: - const Scope* Compound() const { return compound.get(); } @@ -102,14 +101,11 @@ public: } private: - const Token& key_token; TokenList tokens; std::unique_ptr compound; }; - - /** FBX data entity that consists of a 'scope', a collection * of not necessarily unique #Element instances. * @@ -123,19 +119,26 @@ private: * @endverbatim */ class Scope { - public: - Scope(Parser& parser, bool topLevel = false); ~Scope(); -public: - const Element* operator[] (const std::string& index) const { ElementMap::const_iterator it = elements.find(index); return it == elements.end() ? NULL : (*it).second; } + const Element* FindElementCaseInsensitive(const std::string& elementName) const { + const char* elementNameCStr = elementName.c_str(); + for (auto element = elements.begin(); element != elements.end(); ++element) + { + if (!ASSIMP_strincmp(element->first.c_str(), elementNameCStr, MAXLEN)) { + return element->second; + } + } + return NULL; + } + ElementCollection GetCollection(const std::string& index) const { return elements.equal_range(index); } @@ -145,28 +148,23 @@ public: } private: - ElementMap elements; }; - /** FBX parsing class, takes a list of input tokens and generates a hierarchy * of nested #Scope instances, representing the fbx DOM.*/ class Parser { public: - /** Parse given a token list. Does not take ownership of the tokens - * the objects must persist during the entire parser lifetime */ Parser (const TokenList& tokens,bool is_binary); ~Parser(); -public: const Scope& GetRootScope() const { return *root.get(); } - bool IsBinary() const { return is_binary; } @@ -220,8 +218,6 @@ void ParseVectorDataArray(std::vector& out, const Element& el); void ParseVectorDataArray(std::vector& out, const Element& e); void ParseVectorDataArray(std::vector& out, const Element& el); - - // extract a required element from a scope, abort if the element cannot be found const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element = NULL); @@ -230,8 +226,6 @@ const Scope& GetRequiredScope(const Element& el); // get token at a particular index const Token& GetRequiredToken(const Element& el, unsigned int index); - - // read a 4x4 matrix from an array of 16 floats aiMatrix4x4 ReadMatrix(const Element& element); diff --git a/code/FBXProperties.cpp b/code/FBXProperties.cpp index 23d072b18..774beac3c 100644 --- a/code/FBXProperties.cpp +++ b/code/FBXProperties.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/FBXProperties.h b/code/FBXProperties.h index 60cdfe2c6..09b8aa94c 100644 --- a/code/FBXProperties.h +++ b/code/FBXProperties.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -44,15 +45,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INCLUDED_AI_FBX_PROPERTIES_H #define INCLUDED_AI_FBX_PROPERTIES_H -#include #include "FBXCompileConfig.h" #include +#include namespace Assimp { namespace FBX { - class Element; - +// Forward declarations +class Element; /** Represents a dynamic property. Type info added by deriving classes, * see #TypedProperty. @@ -60,10 +61,8 @@ namespace FBX { @verbatim P: "ShininessExponent", "double", "Number", "",0.5 @endvebatim - */ -class Property -{ +class Property { protected: Property(); @@ -77,17 +76,14 @@ public: } }; - template -class TypedProperty : public Property -{ +class TypedProperty : public Property { public: explicit TypedProperty(const T& value) - : value(value) - { + : value(value) { + // empty } -public: const T& Value() const { return value; } @@ -98,21 +94,19 @@ private: typedef std::fbx_unordered_map > DirectPropertyMap; -typedef std::fbx_unordered_map PropertyMap; -typedef std::fbx_unordered_map LazyPropertyMap; +typedef std::fbx_unordered_map PropertyMap; +typedef std::fbx_unordered_map LazyPropertyMap; /** * Represents a property table as can be found in the newer FBX files (Properties60, Properties70) */ -class PropertyTable -{ +class PropertyTable { public: // in-memory property table with no source element PropertyTable(); PropertyTable(const Element& element, std::shared_ptr templateProps); ~PropertyTable(); -public: const Property* Get(const std::string& name) const; // PropertyTable's need not be coupled with FBX elements so this can be NULL @@ -133,41 +127,37 @@ private: const Element* const element; }; - // ------------------------------------------------------------------------------------------------ template -inline T PropertyGet(const PropertyTable& in, const std::string& name, - const T& defaultValue) -{ +inline +T PropertyGet(const PropertyTable& in, const std::string& name, const T& defaultValue) { const Property* const prop = in.Get(name); - if(!prop) { + if( nullptr == prop) { return defaultValue; } // strong typing, no need to be lenient const TypedProperty* const tprop = prop->As< TypedProperty >(); - if(!tprop) { + if( nullptr == tprop) { return defaultValue; } return tprop->Value(); } - // ------------------------------------------------------------------------------------------------ template -inline T PropertyGet(const PropertyTable& in, const std::string& name, - bool& result) -{ +inline +T PropertyGet(const PropertyTable& in, const std::string& name, bool& result) { const Property* const prop = in.Get(name); - if(!prop) { + if( nullptr == prop) { result = false; return T(); } // strong typing, no need to be lenient const TypedProperty* const tprop = prop->As< TypedProperty >(); - if(!tprop) { + if( nullptr == tprop) { result = false; return T(); } @@ -176,7 +166,6 @@ inline T PropertyGet(const PropertyTable& in, const std::string& name, return tprop->Value(); } - } //! FBX } //! Assimp diff --git a/code/FBXTokenizer.cpp b/code/FBXTokenizer.cpp index 7ede49f39..881dcf53d 100644 --- a/code/FBXTokenizer.cpp +++ b/code/FBXTokenizer.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/FBXTokenizer.h b/code/FBXTokenizer.h index 66df3992a..e00ff5b79 100644 --- a/code/FBXTokenizer.h +++ b/code/FBXTokenizer.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -44,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INCLUDED_AI_FBX_TOKENIZER_H #define INCLUDED_AI_FBX_TOKENIZER_H -#include #include "FBXCompileConfig.h" #include #include @@ -101,7 +101,6 @@ public: return std::string(begin(),end()); } -public: bool IsBinary() const { return column == BINARY_MARKER; } diff --git a/code/FBXUtil.cpp b/code/FBXUtil.cpp index 601d5e214..4fd91e18f 100644 --- a/code/FBXUtil.cpp +++ b/code/FBXUtil.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -46,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "FBXTokenizer.h" #include "TinyFormatter.h" +#include #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER diff --git a/code/FBXUtil.h b/code/FBXUtil.h index bd41834b0..c1d9459b3 100644 --- a/code/FBXUtil.h +++ b/code/FBXUtil.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -44,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INCLUDED_AI_FBX_UTIL_H #define INCLUDED_AI_FBX_UTIL_H -#include #include "FBXCompileConfig.h" #include "FBXTokenizer.h" diff --git a/code/FIReader.cpp b/code/FIReader.cpp new file mode 100755 index 000000000..0633ea050 --- /dev/null +++ b/code/FIReader.cpp @@ -0,0 +1,1833 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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 FIReader.cpp +/// \brief Reader for Fast Infoset encoded binary XML files. +/// \date 2017 +/// \author Patrick Daehne + +#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER + +#include "FIReader.hpp" +#include "StringUtils.h" + +// Workaround for issue #1361 +// https://github.com/assimp/assimp/issues/1361 +#ifdef __ANDROID__ +# define _GLIBCXX_USE_C99 1 +#endif + +#include "Exceptional.h" +#include +#include +#include "MemoryIOWrapper.h" +#include "irrXMLWrapper.h" +#include "../contrib/utf8cpp/source/utf8.h" +#include "fast_atof.h" +#include +#include +#include +#include +#include + +namespace Assimp { + +static const std::string parseErrorMessage = "Fast Infoset parse error"; + +static const char *xmlDeclarations[] = { + "", + "", + "", + "", + "", + "", + "", + "", + "" +}; + +static size_t parseMagic(const uint8_t *data, const uint8_t *dataEnd) { + if (dataEnd - data < 4) { + return 0; + } + uint32_t magic = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; + switch (magic) { + case 0xe0000001: + return 4; + case 0x3c3f786d: // "= xmlDeclarationLength) && (memcmp(xmlDeclaration, data, xmlDeclarationLength) == 0)) { + data += xmlDeclarationLength; + if (dataEnd - data < 4) { + return 0; + } + magic = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; + return magic == 0xe0000001 ? xmlDeclarationLength + 4 : 0; + } + } + return 0; + } + default: + return 0; + } +} + +static std::string parseUTF8String(const uint8_t *data, size_t len) { + return std::string((char*)data, len); +} + +static std::string parseUTF16String(const uint8_t *data, size_t len) { + if (len & 1) { + throw DeadlyImportError(parseErrorMessage); + } + size_t numShorts = len / 2; + std::vector utf16; + utf16.reserve(numShorts); + for (size_t i = 0; i < numShorts; ++i) { + short v = (data[0] << 8) | data[1]; + utf16.push_back(v); + data += 2; + } + std::string result; + utf8::utf16to8(utf16.begin(), utf16.end(), back_inserter(result)); + return result; +} + +struct FIStringValueImpl: public FIStringValue { + inline FIStringValueImpl(std::string &&value_) { value = std::move(value_); } + virtual const std::string &toString() const /*override*/ { return value; } +}; + +std::shared_ptr FIStringValue::create(std::string &&value) { + return std::make_shared(std::move(value)); +} + +struct FIHexValueImpl: public FIHexValue { + mutable std::string strValue; + mutable bool strValueValid; + inline FIHexValueImpl(std::vector &&value_): strValueValid(false) { value = std::move(value_); } + virtual const std::string &toString() const /*override*/ { + if (!strValueValid) { + strValueValid = true; + std::ostringstream os; + os << std::hex << std::uppercase << std::setfill('0'); + std::for_each(value.begin(), value.end(), [&](uint8_t c) { os << std::setw(2) << static_cast(c); }); + strValue = os.str(); + } + return strValue; + }; +}; + +std::shared_ptr FIHexValue::create(std::vector &&value) { + return std::make_shared(std::move(value)); +} + +struct FIBase64ValueImpl: public FIBase64Value { + mutable std::string strValue; + mutable bool strValueValid; + inline FIBase64ValueImpl(std::vector &&value_): strValueValid(false) { value = std::move(value_); } + virtual const std::string &toString() const /*override*/ { + if (!strValueValid) { + strValueValid = true; + std::ostringstream os; + uint8_t c1 = 0, c2; + int imod3 = 0; + std::vector::size_type valueSize = value.size(); + for (std::vector::size_type i = 0; i < valueSize; ++i) { + c2 = value[i]; + switch (imod3) { + case 0: + os << basis_64[c2 >> 2]; + imod3 = 1; + break; + case 1: + os << basis_64[((c1 & 0x03) << 4) | ((c2 & 0xf0) >> 4)]; + imod3 = 2; + break; + case 2: + os << basis_64[((c1 & 0x0f) << 2) | ((c2 & 0xc0) >> 6)] << basis_64[c2 & 0x3f]; + imod3 = 0; + break; + } + c1 = c2; + } + switch (imod3) { + case 1: + os << basis_64[(c1 & 0x03) << 4] << "=="; + break; + case 2: + os << basis_64[(c1 & 0x0f) << 2] << '='; + break; + } + strValue = os.str(); + } + return strValue; + }; + static const char basis_64[]; +}; + +const char FIBase64ValueImpl::basis_64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +std::shared_ptr FIBase64Value::create(std::vector &&value) { + return std::make_shared(std::move(value)); +} + +struct FIShortValueImpl: public FIShortValue { + mutable std::string strValue; + mutable bool strValueValid; + inline FIShortValueImpl(std::vector &&value_): strValueValid(false) { value = std::move(value_); } + virtual const std::string &toString() const /*override*/ { + if (!strValueValid) { + strValueValid = true; + std::ostringstream os; + int n = 0; + std::for_each(value.begin(), value.end(), [&](int16_t s) { if (++n > 1) os << ' '; os << s; }); + strValue = os.str(); + } + return strValue; + } +}; + +std::shared_ptr FIShortValue::create(std::vector &&value) { + return std::make_shared(std::move(value)); +} + +struct FIIntValueImpl: public FIIntValue { + mutable std::string strValue; + mutable bool strValueValid; + inline FIIntValueImpl(std::vector &&value_): strValueValid(false) { value = std::move(value_); } + virtual const std::string &toString() const /*override*/ { + if (!strValueValid) { + strValueValid = true; + std::ostringstream os; + int n = 0; + std::for_each(value.begin(), value.end(), [&](int32_t i) { if (++n > 1) os << ' '; os << i; }); + strValue = os.str(); + } + return strValue; + }; +}; + +std::shared_ptr FIIntValue::create(std::vector &&value) { + return std::make_shared(std::move(value)); +} + +struct FILongValueImpl: public FILongValue { + mutable std::string strValue; + mutable bool strValueValid; + inline FILongValueImpl(std::vector &&value_): strValueValid(false) { value = std::move(value_); } + virtual const std::string &toString() const /*override*/ { + if (!strValueValid) { + strValueValid = true; + std::ostringstream os; + int n = 0; + std::for_each(value.begin(), value.end(), [&](int64_t l) { if (++n > 1) os << ' '; os << l; }); + strValue = os.str(); + } + return strValue; + }; +}; + +std::shared_ptr FILongValue::create(std::vector &&value) { + return std::make_shared(std::move(value)); +} + +struct FIBoolValueImpl: public FIBoolValue { + mutable std::string strValue; + mutable bool strValueValid; + inline FIBoolValueImpl(std::vector &&value_): strValueValid(false) { value = std::move(value_); } + virtual const std::string &toString() const /*override*/ { + if (!strValueValid) { + strValueValid = true; + std::ostringstream os; + os << std::boolalpha; + int n = 0; + std::for_each(value.begin(), value.end(), [&](bool b) { if (++n > 1) os << ' '; os << b; }); + strValue = os.str(); + } + return strValue; + }; +}; + +std::shared_ptr FIBoolValue::create(std::vector &&value) { + return std::make_shared(std::move(value)); +} + +struct FIFloatValueImpl: public FIFloatValue { + mutable std::string strValue; + mutable bool strValueValid; + inline FIFloatValueImpl(std::vector &&value_): strValueValid(false) { value = std::move(value_); } + virtual const std::string &toString() const /*override*/ { + if (!strValueValid) { + strValueValid = true; + std::ostringstream os; + int n = 0; + std::for_each(value.begin(), value.end(), [&](float f) { if (++n > 1) os << ' '; os << f; }); + strValue = os.str(); + } + return strValue; + } +}; + +std::shared_ptr FIFloatValue::create(std::vector &&value) { + return std::make_shared(std::move(value)); +} + +struct FIDoubleValueImpl: public FIDoubleValue { + mutable std::string strValue; + mutable bool strValueValid; + inline FIDoubleValueImpl(std::vector &&value_): strValueValid(false) { value = std::move(value_); } + virtual const std::string &toString() const /*override*/ { + if (!strValueValid) { + strValueValid = true; + std::ostringstream os; + int n = 0; + std::for_each(value.begin(), value.end(), [&](double d) { if (++n > 1) os << ' '; os << d; }); + strValue = os.str(); + } + return strValue; + } +}; + +std::shared_ptr FIDoubleValue::create(std::vector &&value) { + return std::make_shared(std::move(value)); +} + +struct FIUUIDValueImpl: public FIUUIDValue { + mutable std::string strValue; + mutable bool strValueValid; + inline FIUUIDValueImpl(std::vector &&value_): strValueValid(false) { value = std::move(value_); } + virtual const std::string &toString() const /*override*/ { + if (!strValueValid) { + strValueValid = true; + std::ostringstream os; + os << std::hex << std::uppercase << std::setfill('0'); + std::vector::size_type valueSize = value.size(); + for (std::vector::size_type i = 0; i < valueSize; ++i) { + switch (i & 15) { + case 0: + if (i > 0) { + os << ' '; + } + os << std::setw(2) << static_cast(value[i]); + break; + case 4: + case 6: + case 8: + case 10: + os << '-'; + // intentionally fall through! + case 1: + case 2: + case 3: + case 5: + case 7: + case 9: + case 11: + case 12: + case 13: + case 14: + case 15: + os << std::setw(2) << static_cast(value[i]); + break; + } + } + strValue = os.str(); + } + return strValue; + }; +}; + +std::shared_ptr FIUUIDValue::create(std::vector &&value) { + return std::make_shared(std::move(value)); +} + +struct FICDATAValueImpl: public FICDATAValue { + inline FICDATAValueImpl(std::string &&value_) { value = std::move(value_); } + virtual const std::string &toString() const /*override*/ { return value; } +}; + +std::shared_ptr FICDATAValue::create(std::string &&value) { + return std::make_shared(std::move(value)); +} + +struct FIHexDecoder: public FIDecoder { + virtual std::shared_ptr decode(const uint8_t *data, size_t len) /*override*/ { + return FIHexValue::create(std::vector(data, data + len)); + } +}; + +struct FIBase64Decoder: public FIDecoder { + virtual std::shared_ptr decode(const uint8_t *data, size_t len) /*override*/ { + return FIBase64Value::create(std::vector(data, data + len)); + } +}; + +struct FIShortDecoder: public FIDecoder { + virtual std::shared_ptr decode(const uint8_t *data, size_t len) /*override*/ { + if (len & 1) { + throw DeadlyImportError(parseErrorMessage); + } + std::vector value; + size_t numShorts = len / 2; + value.reserve(numShorts); + for (size_t i = 0; i < numShorts; ++i) { + int16_t v = (data[0] << 8) | data[1]; + value.push_back(v); + data += 2; + } + return FIShortValue::create(std::move(value)); + } +}; + +struct FIIntDecoder: public FIDecoder { + virtual std::shared_ptr decode(const uint8_t *data, size_t len) /*override*/ { + if (len & 3) { + throw DeadlyImportError(parseErrorMessage); + } + std::vector value; + size_t numInts = len / 4; + value.reserve(numInts); + for (size_t i = 0; i < numInts; ++i) { + int32_t v = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; + value.push_back(v); + data += 4; + } + return FIIntValue::create(std::move(value)); + } +}; + +struct FILongDecoder: public FIDecoder { + virtual std::shared_ptr decode(const uint8_t *data, size_t len) /*override*/ { + if (len & 7) { + throw DeadlyImportError(parseErrorMessage); + } + std::vector value; + size_t numLongs = len / 8; + value.reserve(numLongs); + for (size_t i = 0; i < numLongs; ++i) { + int64_t b0 = data[0], b1 = data[1], b2 = data[2], b3 = data[3], b4 = data[4], b5 = data[5], b6 = data[6], b7 = data[7]; + int64_t v = (b0 << 56) | (b1 << 48) | (b2 << 40) | (b3 << 32) | (b4 << 24) | (b5 << 16) | (b6 << 8) | b7; + value.push_back(v); + data += 8; + } + return FILongValue::create(std::move(value)); + } +}; + +struct FIBoolDecoder: public FIDecoder { + virtual std::shared_ptr decode(const uint8_t *data, size_t len) /*override*/ { + if (len < 1) { + throw DeadlyImportError(parseErrorMessage); + } + std::vector value; + uint8_t b = *data++; + size_t unusedBits = b >> 4; + size_t numBools = (len * 8) - 4 - unusedBits; + value.reserve(numBools); + uint8_t mask = 1 << 3; + for (size_t i = 0; i < numBools; ++i) { + if (!mask) { + mask = 1 << 7; + b = *data++; + } + value.push_back((b & mask) != 0); + } + return FIBoolValue::create(std::move(value)); + } +}; + +struct FIFloatDecoder: public FIDecoder { + virtual std::shared_ptr decode(const uint8_t *data, size_t len) /*override*/ { + if (len & 3) { + throw DeadlyImportError(parseErrorMessage); + } + std::vector value; + size_t numFloats = len / 4; + value.reserve(numFloats); + for (size_t i = 0; i < numFloats; ++i) { + int v = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; + float f; + memcpy(&f, &v, 4); + value.push_back(f); + data += 4; + } + return FIFloatValue::create(std::move(value)); + } +}; + +struct FIDoubleDecoder: public FIDecoder { + virtual std::shared_ptr decode(const uint8_t *data, size_t len) /*override*/ { + if (len & 7) { + throw DeadlyImportError(parseErrorMessage); + } + std::vector value; + size_t numDoubles = len / 8; + value.reserve(numDoubles); + for (size_t i = 0; i < numDoubles; ++i) { + long long b0 = data[0], b1 = data[1], b2 = data[2], b3 = data[3], b4 = data[4], b5 = data[5], b6 = data[6], b7 = data[7]; + long long v = (b0 << 56) | (b1 << 48) | (b2 << 40) | (b3 << 32) | (b4 << 24) | (b5 << 16) | (b6 << 8) | b7; + double f; + memcpy(&f, &v, 8); + value.push_back(f); + data += 8; + } + return FIDoubleValue::create(std::move(value)); + } +}; + +struct FIUUIDDecoder: public FIDecoder { + virtual std::shared_ptr decode(const uint8_t *data, size_t len) /*override*/ { + if (len & 15) { + throw DeadlyImportError(parseErrorMessage); + } + return FIUUIDValue::create(std::vector(data, data + len)); + } +}; + +struct FICDATADecoder: public FIDecoder { + virtual std::shared_ptr decode(const uint8_t *data, size_t len) /*override*/ { + return FICDATAValue::create(parseUTF8String(data, len)); + } +}; + +class CFIReaderImpl: public FIReader { +public: + + CFIReaderImpl(std::unique_ptr data_, size_t size): + data(std::move(data_)), dataP(data.get()), dataEnd(data.get() + size), currentNodeType(irr::io::EXN_NONE), + emptyElement(false), headerPending(true), terminatorPending(false) + {} + + virtual ~CFIReaderImpl() {} + + virtual bool read() /*override*/ { + if (headerPending) { + headerPending = false; + parseHeader(); + } + if (terminatorPending) { + terminatorPending = false; + if (elementStack.empty()) { + return false; + } + else { + nodeName = elementStack.top(); + elementStack.pop(); + currentNodeType = nodeName.empty() ? irr::io::EXN_UNKNOWN : irr::io::EXN_ELEMENT_END; + return true; + } + } + if (dataP >= dataEnd) { + return false; + } + uint8_t b = *dataP; + if (b < 0x80) { // Element (C.2.11.2, C.3.7.2) + // C.3 + parseElement(); + return true; + } + else if (b < 0xc0) { // Characters (C.3.7.5) + // C.7 + auto chars = parseNonIdentifyingStringOrIndex3(vocabulary.charactersTable); + nodeName = chars->toString(); + currentNodeType = irr::io::EXN_TEXT; + return true; + } + else if (b < 0xe0) { + if ((b & 0xfc) == 0xc4) { // DTD (C.2.11.5) + // C.9 + ++dataP; + if (b & 0x02) { + /*const std::string &systemID =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable); + } + if (b & 0x01) { + /*const std::string &publicID =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable); + } + elementStack.push(EmptyString); + currentNodeType = irr::io::EXN_UNKNOWN; + return true; + } + else if ((b & 0xfc) == 0xc8) { // Unexpanded entity reference (C.3.7.4) + // C.6 + ++dataP; + /*const std::string &name =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable); + if (b & 0x02) { + /*const std::string &systemID =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable); + } + if (b & 0x01) { + /*const std::string &publicID =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable); + } + currentNodeType = irr::io::EXN_UNKNOWN; + return true; + } + } + else if (b < 0xf0) { + if (b == 0xe1) { // Processing instruction (C.2.11.3, C.3.7.3) + // C.5 + ++dataP; + /*const std::string &target =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable); + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + /*std::shared_ptr data =*/ parseNonIdentifyingStringOrIndex1(vocabulary.otherStringTable); + currentNodeType = irr::io::EXN_UNKNOWN; + return true; + } + else if (b == 0xe2) { // Comment (C.2.11.4, C.3.7.6) + // C.8 + ++dataP; + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + std::shared_ptr comment = parseNonIdentifyingStringOrIndex1(vocabulary.otherStringTable); + nodeName = comment->toString(); + currentNodeType = irr::io::EXN_COMMENT; + return true; + } + } + else { // Terminator (C.2.12, C.3.8) + ++dataP; + if (b == 0xff) { + terminatorPending = true; + } + if (elementStack.empty()) { + return false; + } + else { + nodeName = elementStack.top(); + elementStack.pop(); + currentNodeType = nodeName.empty() ? irr::io::EXN_UNKNOWN : irr::io::EXN_ELEMENT_END; + return true; + } + } + throw DeadlyImportError(parseErrorMessage); + } + + virtual irr::io::EXML_NODE getNodeType() const /*override*/ { + return currentNodeType; + } + + virtual int getAttributeCount() const /*override*/ { + return static_cast(attributes.size()); + } + + virtual const char* getAttributeName(int idx) const /*override*/ { + if (idx < 0 || idx >= (int)attributes.size()) { + return nullptr; + } + return attributes[idx].name.c_str(); + } + + virtual const char* getAttributeValue(int idx) const /*override*/ { + if (idx < 0 || idx >= (int)attributes.size()) { + return nullptr; + } + return attributes[idx].value->toString().c_str(); + } + + virtual const char* getAttributeValue(const char* name) const /*override*/ { + const Attribute* attr = getAttributeByName(name); + if (!attr) { + return nullptr; + } + return attr->value->toString().c_str(); + } + + virtual const char* getAttributeValueSafe(const char* name) const /*override*/ { + const Attribute* attr = getAttributeByName(name); + if (!attr) { + return EmptyString.c_str(); + } + return attr->value->toString().c_str(); + } + + virtual int getAttributeValueAsInt(const char* name) const /*override*/ { + const Attribute* attr = getAttributeByName(name); + if (!attr) { + return 0; + } + std::shared_ptr intValue = std::dynamic_pointer_cast(attr->value); + if (intValue) { + return intValue->value.size() == 1 ? intValue->value.front() : 0; + } + return atoi(attr->value->toString().c_str()); + } + + virtual int getAttributeValueAsInt(int idx) const /*override*/ { + if (idx < 0 || idx >= (int)attributes.size()) { + return 0; + } + std::shared_ptr intValue = std::dynamic_pointer_cast(attributes[idx].value); + if (intValue) { + return intValue->value.size() == 1 ? intValue->value.front() : 0; + } + return atoi(attributes[idx].value->toString().c_str()); + } + + virtual float getAttributeValueAsFloat(const char* name) const /*override*/ { + const Attribute* attr = getAttributeByName(name); + if (!attr) { + return 0; + } + std::shared_ptr floatValue = std::dynamic_pointer_cast(attr->value); + if (floatValue) { + return floatValue->value.size() == 1 ? floatValue->value.front() : 0; + } + + return fast_atof(attr->value->toString().c_str()); + } + + virtual float getAttributeValueAsFloat(int idx) const /*override*/ { + if (idx < 0 || idx >= (int)attributes.size()) { + return 0; + } + std::shared_ptr floatValue = std::dynamic_pointer_cast(attributes[idx].value); + if (floatValue) { + return floatValue->value.size() == 1 ? floatValue->value.front() : 0; + } + return fast_atof(attributes[idx].value->toString().c_str()); + } + + virtual const char* getNodeName() const /*override*/ { + return nodeName.c_str(); + } + + virtual const char* getNodeData() const /*override*/ { + return nodeName.c_str(); + } + + virtual bool isEmptyElement() const /*override*/ { + return emptyElement; + } + + virtual irr::io::ETEXT_FORMAT getSourceFormat() const /*override*/ { + return irr::io::ETF_UTF8; + } + + virtual irr::io::ETEXT_FORMAT getParserFormat() const /*override*/ { + return irr::io::ETF_UTF8; + } + + virtual std::shared_ptr getAttributeEncodedValue(int idx) const /*override*/ { + if (idx < 0 || idx >= (int)attributes.size()) { + return nullptr; + } + return attributes[idx].value; + } + + virtual std::shared_ptr getAttributeEncodedValue(const char* name) const /*override*/ { + const Attribute* attr = getAttributeByName(name); + if (!attr) { + return nullptr; + } + return attr->value; + } + + virtual void registerDecoder(const std::string &algorithmUri, std::unique_ptr decoder) /*override*/ { + decoderMap[algorithmUri] = std::move(decoder); + } + + virtual void registerVocabulary(const std::string &vocabularyUri, const FIVocabulary *vocabulary) /*override*/ { + vocabularyMap[vocabularyUri] = vocabulary; + } + +private: + + struct QName { + std::string prefix; + std::string uri; + std::string name; + inline QName() {} + inline QName(const FIQName &qname): prefix(qname.prefix ? qname.prefix : ""), uri(qname.uri ? qname.uri : ""), name(qname.name) {} + }; + + struct Attribute { + QName qname; + std::string name; + std::shared_ptr value; + }; + + struct Vocabulary { + std::vector restrictedAlphabetTable; + std::vector encodingAlgorithmTable; + std::vector prefixTable; + std::vector namespaceNameTable; + std::vector localNameTable; + std::vector otherNCNameTable; + std::vector otherURITable; + std::vector> attributeValueTable; + std::vector> charactersTable; + std::vector> otherStringTable; + std::vector elementNameTable; + std::vector attributeNameTable; + Vocabulary() { + prefixTable.push_back("xml"); + namespaceNameTable.push_back("http://www.w3.org/XML/1998/namespace"); + } + }; + + const Attribute* getAttributeByName(const char* name) const { + if (!name) { + return 0; + } + std::string n = name; + for (int i=0; i<(int)attributes.size(); ++i) { + if (attributes[i].name == n) { + return &attributes[i]; + } + } + return 0; + } + + size_t parseInt2() { // C.25 + uint8_t b = *dataP++; + if (!(b & 0x40)) { // x0...... (C.25.2) + return b & 0x3f; + } + else if ((b & 0x60) == 0x40) { // x10..... ........ (C.25.3) + if (dataEnd - dataP > 0) { + return (((b & 0x1f) << 8) | *dataP++) + 0x40; + } + } + else if ((b & 0x70) == 0x60) { // x110.... ........ ........ (C.25.4) + if (dataEnd - dataP > 1) { + size_t result = (((b & 0x0f) << 16) | (dataP[0] << 8) | dataP[1]) + 0x2040; + dataP += 2; + return result; + } + } + throw DeadlyImportError(parseErrorMessage); + } + + size_t parseInt3() { // C.27 + uint8_t b = *dataP++; + if (!(b & 0x20)) { // xx0..... (C.27.2) + return b & 0x1f; + } + else if ((b & 0x38) == 0x20) { // xx100... ........ (C.27.3) + if (dataEnd - dataP > 0) { + return (((b & 0x07) << 8) | *dataP++) + 0x20; + } + } + else if ((b & 0x38) == 0x28) { // xx101... ........ ........ (C.27.4) + if (dataEnd - dataP > 1) { + size_t result = (((b & 0x07) << 16) | (dataP[0] << 8) | dataP[1]) + 0x820; + dataP += 2; + return result; + } + } + else if ((b & 0x3f) == 0x30) { // xx110000 0000.... ........ ........ (C.27.5) + if ((dataEnd - dataP > 2) && !(dataP[0] & 0xf0)) { + size_t result = (((dataP[0] & 0x0f) << 16) | (dataP[1] << 8) | dataP[2]) + 0x80820; + dataP += 3; + return result; + } + } + throw DeadlyImportError(parseErrorMessage); + } + + size_t parseInt4() { // C.28 + uint8_t b = *dataP++; + if (!(b & 0x10)) { // xxx0.... (C.28.2) + return b & 0x0f; + } + else if ((b & 0x1c) == 0x10) { // xxx100.. ........ (C.28.3) + if (dataEnd - dataP > 0) { + return (((b & 0x03) << 8) | *dataP++) + 0x10; + } + } + else if ((b & 0x1c) == 0x14) { // xxx101.. ........ ........ (C.28.4) + if (dataEnd - dataP > 1) { + size_t result = (((b & 0x03) << 16) | (dataP[0] << 8) | dataP[1]) + 0x410; + dataP += 2; + return result; + } + } + else if ((b & 0x1f) == 0x18) { // xxx11000 0000.... ........ ........ (C.28.5) + if ((dataEnd - dataP > 2) && !(dataP[0] & 0xf0)) { + size_t result = (((dataP[0] & 0x0f) << 16) | (dataP[1] << 8) | dataP[2]) + 0x40410; + dataP += 3; + return result; + } + } + throw DeadlyImportError(parseErrorMessage); + } + + size_t parseSequenceLen() { // C.21 + if (dataEnd - dataP > 0) { + uint8_t b = *dataP++; + if (b < 0x80) { // 0....... (C.21.2) + return b; + } + else if ((b & 0xf0) == 0x80) { // 1000.... ........ ........ (C.21.3) + if (dataEnd - dataP > 1) { + size_t result = (((b & 0x0f) << 16) | (dataP[0] << 8) | dataP[1]) + 0x80; + dataP += 2; + return result; + } + } + } + throw DeadlyImportError(parseErrorMessage); + } + + std::string parseNonEmptyOctetString2() { // C.22 + // Parse the length of the string + uint8_t b = *dataP++ & 0x7f; + size_t len; + if (!(b & 0x40)) { // x0...... (C.22.3.1) + len = b + 1; + } + else if (b == 0x40) { // x1000000 ........ (C.22.3.2) + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + len = *dataP++ + 0x41; + } + else if (b == 0x60) { // x1100000 ........ ........ ........ ........ (C.22.3.3) + if (dataEnd - dataP < 4) { + throw DeadlyImportError(parseErrorMessage); + } + len = ((dataP[0] << 24) | (dataP[1] << 16) | (dataP[2] << 8) | dataP[3]) + 0x141; + dataP += 4; + } + else { + throw DeadlyImportError(parseErrorMessage); + } + + // Parse the string (C.22.4) + if (dataEnd - dataP < static_cast(len)) { + throw DeadlyImportError(parseErrorMessage); + } + std::string s = parseUTF8String(dataP, len); + dataP += len; + + return s; + } + + size_t parseNonEmptyOctetString5Length() { // C.23 + // Parse the length of the string + size_t b = *dataP++ & 0x0f; + if (!(b & 0x08)) { // xxxx0... (C.23.3.1) + return b + 1; + } + else if (b == 0x08) { // xxxx1000 ........ (C.23.3.2) + if (dataEnd - dataP > 0) { + return *dataP++ + 0x09; + } + } + else if (b == 0x0c) { // xxxx1100 ........ ........ ........ ........ (C.23.3.3) + if (dataEnd - dataP > 3) { + size_t result = ((dataP[0] << 24) | (dataP[1] << 16) | (dataP[2] << 8) | dataP[3]) + 0x109; + dataP += 4; + return result; + } + } + throw DeadlyImportError(parseErrorMessage); + } + + size_t parseNonEmptyOctetString7Length() { // C.24 + // Parse the length of the string + size_t b = *dataP++ & 0x03; + if (!(b & 0x02)) { // xxxxxx0. (C.24.3.1) + return b + 1; + } + else if (b == 0x02) { // xxxxxx10 ........ (C.24.3.2) + if (dataEnd - dataP > 0) { + return *dataP++ + 0x3; + } + } + else if (b == 0x03) { // xxxxxx11 ........ ........ ........ ........ (C.24.3.3) + if (dataEnd - dataP > 3) { + size_t result = ((dataP[0] << 24) | (dataP[1] << 16) | (dataP[2] << 8) | dataP[3]) + 0x103; + dataP += 4; + return result; + } + } + throw DeadlyImportError(parseErrorMessage); + } + + std::shared_ptr parseEncodedData(size_t index, size_t len) { + if (index < 32) { + FIDecoder *decoder = defaultDecoder[index]; + if (!decoder) { + throw DeadlyImportError("Invalid encoding algorithm index " + to_string(index)); + } + return decoder->decode(dataP, len); + } + else { + if (index - 32 >= vocabulary.encodingAlgorithmTable.size()) { + throw DeadlyImportError("Invalid encoding algorithm index " + to_string(index)); + } + std::string uri = vocabulary.encodingAlgorithmTable[index - 32]; + auto it = decoderMap.find(uri); + if (it == decoderMap.end()) { + throw DeadlyImportError("Unsupported encoding algorithm " + uri); + } + else { + return it->second->decode(dataP, len); + } + } + } + + std::shared_ptr parseRestrictedAlphabet(size_t index, size_t len) { + std::string alphabet; + if (index < 16) { + switch (index) { + case 0: // numeric + alphabet = "0123456789-+.e "; + break; + case 1: // date and time + alphabet = "0123456789-:TZ "; + break; + default: + throw DeadlyImportError("Invalid restricted alphabet index " + to_string(index)); + } + } + else { + if (index - 16 >= vocabulary.restrictedAlphabetTable.size()) { + throw DeadlyImportError("Invalid restricted alphabet index " + to_string(index)); + } + alphabet = vocabulary.restrictedAlphabetTable[index - 16]; + } + std::vector alphabetUTF32; + utf8::utf8to32(alphabet.begin(), alphabet.end(), back_inserter(alphabetUTF32)); + std::string::size_type alphabetLength = alphabetUTF32.size(); + if (alphabetLength < 2) { + throw DeadlyImportError("Invalid restricted alphabet length " + to_string(alphabetLength)); + } + std::string::size_type bitsPerCharacter = 1; + while ((1ull << bitsPerCharacter) <= alphabetLength) { + ++bitsPerCharacter; + } + size_t bitsAvail = 0; + uint8_t mask = (1 << bitsPerCharacter) - 1; + uint32_t bits = 0; + std::string s; + for (size_t i = 0; i < len; ++i) { + bits = (bits << 8) | dataP[i]; + bitsAvail += 8; + while (bitsAvail >= bitsPerCharacter) { + bitsAvail -= bitsPerCharacter; + size_t charIndex = (bits >> bitsAvail) & mask; + if (charIndex < alphabetLength) { + s.push_back(alphabetUTF32[charIndex]); + } + else if (charIndex != mask) { + throw DeadlyImportError(parseErrorMessage); + } + } + } + return FIStringValue::create(std::move(s)); + } + + std::shared_ptr parseEncodedCharacterString3() { // C.19 + std::shared_ptr result; + size_t len; + uint8_t b = *dataP; + if (b & 0x20) { + ++dataP; + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + size_t index = ((b & 0x0f) << 4) | ((*dataP & 0xf0) >> 4); // C.29 + len = parseNonEmptyOctetString5Length(); + if (dataEnd - dataP < static_cast(len)) { + throw DeadlyImportError(parseErrorMessage); + } + if (b & 0x10) { + // encoding algorithm (C.19.3.4) + result = parseEncodedData(index, len); + } + else { + // Restricted alphabet (C.19.3.3) + result = parseRestrictedAlphabet(index, len); + } + } + else { + len = parseNonEmptyOctetString5Length(); + if (dataEnd - dataP < static_cast(len)) { + throw DeadlyImportError(parseErrorMessage); + } + if (b & 0x10) { + // UTF-16 (C.19.3.2) + if (len & 1) { + throw DeadlyImportError(parseErrorMessage); + } + result = FIStringValue::create(parseUTF16String(dataP, len)); + } + else { + // UTF-8 (C.19.3.1) + result = FIStringValue::create(parseUTF8String(dataP, len)); + } + } + dataP += len; + return result; + } + + std::shared_ptr parseEncodedCharacterString5() { // C.20 + std::shared_ptr result; + size_t len; + uint8_t b = *dataP; + if (b & 0x08) { + ++dataP; + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + size_t index = ((b & 0x03) << 6) | ((*dataP & 0xfc) >> 2); /* C.29 */ + len = parseNonEmptyOctetString7Length(); + if (dataEnd - dataP < static_cast(len)) { + throw DeadlyImportError(parseErrorMessage); + } + if (b & 0x04) { + // encoding algorithm (C.20.3.4) + result = parseEncodedData(index, len); + } + else { + // Restricted alphabet (C.20.3.3) + result = parseRestrictedAlphabet(index, len); + } + } + else { + len = parseNonEmptyOctetString7Length(); + if (dataEnd - dataP < static_cast(len)) { + throw DeadlyImportError(parseErrorMessage); + } + if (b & 0x04) { + // UTF-16 (C.20.3.2) + if (len & 1) { + throw DeadlyImportError(parseErrorMessage); + } + result = FIStringValue::create(parseUTF16String(dataP, len)); + } + else { + // UTF-8 (C.20.3.1) + result = FIStringValue::create(parseUTF8String(dataP, len)); + } + } + dataP += len; + return result; + } + + const std::string &parseIdentifyingStringOrIndex(std::vector &stringTable) { // C.13 + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + uint8_t b = *dataP; + if (b & 0x80) { + // We have an index (C.13.4) + size_t index = parseInt2(); + if (index >= stringTable.size()) { + throw DeadlyImportError(parseErrorMessage); + } + return stringTable[index]; + } + else { + // We have a string (C.13.3) + stringTable.push_back(parseNonEmptyOctetString2()); + return stringTable.back(); + } + } + + QName parseNameSurrogate() { // C.16 + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + uint8_t b = *dataP++; + if (b & 0xfc) { // Padding '000000' C.2.5.5 + throw DeadlyImportError(parseErrorMessage); + } + QName result; + size_t index; + if (b & 0x02) { // prefix (C.16.3) + if ((dataEnd - dataP < 1) || (*dataP & 0x80)) { + throw DeadlyImportError(parseErrorMessage); + } + index = parseInt2(); + if (index >= vocabulary.prefixTable.size()) { + throw DeadlyImportError(parseErrorMessage); + } + result.prefix = vocabulary.prefixTable[index]; + } + if (b & 0x01) { // namespace-name (C.16.4) + if ((dataEnd - dataP < 1) || (*dataP & 0x80)) { + throw DeadlyImportError(parseErrorMessage); + } + index = parseInt2(); + if (index >= vocabulary.namespaceNameTable.size()) { + throw DeadlyImportError(parseErrorMessage); + } + result.uri = vocabulary.namespaceNameTable[index]; + } + // local-name + if ((dataEnd - dataP < 1) || (*dataP & 0x80)) { + throw DeadlyImportError(parseErrorMessage); + } + index = parseInt2(); + if (index >= vocabulary.localNameTable.size()) { + throw DeadlyImportError(parseErrorMessage); + } + result.name = vocabulary.localNameTable[index]; + return result; + } + + const QName &parseQualifiedNameOrIndex2(std::vector &qNameTable) { // C.17 + uint8_t b = *dataP; + if ((b & 0x7c) == 0x78) { // x11110.. + // We have a literal (C.17.3) + ++dataP; + QName result; + // prefix (C.17.3.1) + result.prefix = b & 0x02 ? parseIdentifyingStringOrIndex(vocabulary.prefixTable) : std::string(); + // namespace-name (C.17.3.1) + result.uri = b & 0x01 ? parseIdentifyingStringOrIndex(vocabulary.namespaceNameTable) : std::string(); + // local-name + result.name = parseIdentifyingStringOrIndex(vocabulary.localNameTable); + qNameTable.push_back(result); + return qNameTable.back(); + } + else { + // We have an index (C.17.4) + size_t index = parseInt2(); + if (index >= qNameTable.size()) { + throw DeadlyImportError(parseErrorMessage); + } + return qNameTable[index]; + } + } + + const QName &parseQualifiedNameOrIndex3(std::vector &qNameTable) { // C.18 + uint8_t b = *dataP; + if ((b & 0x3c) == 0x3c) { // xx1111.. + // We have a literal (C.18.3) + ++dataP; + QName result; + // prefix (C.18.3.1) + result.prefix = b & 0x02 ? parseIdentifyingStringOrIndex(vocabulary.prefixTable) : std::string(); + // namespace-name (C.18.3.1) + result.uri = b & 0x01 ? parseIdentifyingStringOrIndex(vocabulary.namespaceNameTable) : std::string(); + // local-name + result.name = parseIdentifyingStringOrIndex(vocabulary.localNameTable); + qNameTable.push_back(result); + return qNameTable.back(); + } + else { + // We have an index (C.18.4) + size_t index = parseInt3(); + if (index >= qNameTable.size()) { + throw DeadlyImportError(parseErrorMessage); + } + return qNameTable[index]; + } + } + + std::shared_ptr parseNonIdentifyingStringOrIndex1(std::vector> &valueTable) { // C.14 + uint8_t b = *dataP; + if (b == 0xff) { // C.26.2 + // empty string + ++dataP; + return EmptyFIString; + } + else if (b & 0x80) { // C.14.4 + // We have an index + size_t index = parseInt2(); + if (index >= valueTable.size()) { + throw DeadlyImportError(parseErrorMessage); + } + return valueTable[index]; + } + else { // C.14.3 + // We have a literal + std::shared_ptr result = parseEncodedCharacterString3(); + if (b & 0x40) { // C.14.3.1 + valueTable.push_back(result); + } + return result; + } + } + + std::shared_ptr parseNonIdentifyingStringOrIndex3(std::vector> &valueTable) { // C.15 + uint8_t b = *dataP; + if (b & 0x20) { // C.15.4 + // We have an index + size_t index = parseInt4(); + if (index >= valueTable.size()) { + throw DeadlyImportError(parseErrorMessage); + } + return valueTable[index]; + } + else { // C.15.3 + // We have a literal + std::shared_ptr result = parseEncodedCharacterString5(); + if (b & 0x10) { // C.15.3.1 + valueTable.push_back(result); + } + return result; + } + } + + void parseElement() { + // C.3 + + attributes.clear(); + + uint8_t b = *dataP; + bool hasAttributes = (b & 0x40) != 0; // C.3.3 + if ((b & 0x3f) == 0x38) { // C.3.4.1 + // Parse namespaces + ++dataP; + for (;;) { + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + b = *dataP++; + if (b == 0xf0) { // C.3.4.3 + break; + } + if ((b & 0xfc) != 0xcc) { // C.3.4.2 + throw DeadlyImportError(parseErrorMessage); + } + // C.12 + Attribute attr; + attr.qname.prefix = "xmlns"; + attr.qname.name = b & 0x02 ? parseIdentifyingStringOrIndex(vocabulary.prefixTable) : std::string(); + attr.qname.uri = b & 0x01 ? parseIdentifyingStringOrIndex(vocabulary.namespaceNameTable) : std::string(); + attr.name = attr.qname.name.empty() ? "xmlns" : "xmlns:" + attr.qname.name; + attr.value = FIStringValue::create(std::string(attr.qname.uri)); + attributes.push_back(attr); + } + if ((dataEnd - dataP < 1) || (*dataP & 0xc0)) { + throw DeadlyImportError(parseErrorMessage); + } + } + + // Parse Element name (C.3.5) + const QName &elemName = parseQualifiedNameOrIndex3(vocabulary.elementNameTable); + nodeName = elemName.prefix.empty() ? elemName.name : elemName.prefix + ':' + elemName.name; + + if (hasAttributes) { + for (;;) { + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + b = *dataP; + if (b < 0x80) { // C.3.6.1 + // C.4 + Attribute attr; + attr.qname = parseQualifiedNameOrIndex2(vocabulary.attributeNameTable); + attr.name = attr.qname.prefix.empty() ? attr.qname.name : attr.qname.prefix + ':' + attr.qname.name; + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + attr.value = parseNonIdentifyingStringOrIndex1(vocabulary.attributeValueTable); + attributes.push_back(attr); + } + else { + if ((b & 0xf0) != 0xf0) { // C.3.6.2 + throw DeadlyImportError(parseErrorMessage); + } + emptyElement = b == 0xff; // C.3.6.2, C.3.8 + ++dataP; + break; + } + } + } + else { + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + b = *dataP; + switch (b) { + case 0xff: + terminatorPending = true; + // Intentionally fall through + case 0xf0: + emptyElement = true; + ++dataP; + break; + default: + emptyElement = false; + } + } + if (!emptyElement) { + elementStack.push(nodeName); + } + + currentNodeType = irr::io::EXN_ELEMENT; + } + + void parseHeader() { + // Parse header (C.1.3) + size_t magicSize = parseMagic(dataP, dataEnd); + if (!magicSize) { + throw DeadlyImportError(parseErrorMessage); + } + dataP += magicSize; + // C.2.3 + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + uint8_t b = *dataP++; + if (b & 0x40) { + // Parse additional data (C.2.4) + size_t len = parseSequenceLen(); + for (size_t i = 0; i < len; ++i) { + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + /*std::string id =*/ parseNonEmptyOctetString2(); + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + /*std::string data =*/ parseNonEmptyOctetString2(); + } + } + if (b & 0x20) { + // Parse initial vocabulary (C.2.5) + if (dataEnd - dataP < 2) { + throw DeadlyImportError(parseErrorMessage); + } + uint16_t b1 = (dataP[0] << 8) | dataP[1]; + dataP += 2; + if (b1 & 0x1000) { + // External vocabulary (C.2.5.2) + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + std::string uri = parseNonEmptyOctetString2(); + auto it = vocabularyMap.find(uri); + if (it == vocabularyMap.end()) { + throw DeadlyImportError("Unknown vocabulary " + uri); + } + const FIVocabulary *externalVocabulary = it->second; + if (externalVocabulary->restrictedAlphabetTable) { + std::copy(externalVocabulary->restrictedAlphabetTable, externalVocabulary->restrictedAlphabetTable + externalVocabulary->restrictedAlphabetTableSize, std::back_inserter(vocabulary.restrictedAlphabetTable)); + } + if (externalVocabulary->encodingAlgorithmTable) { + std::copy(externalVocabulary->encodingAlgorithmTable, externalVocabulary->encodingAlgorithmTable + externalVocabulary->encodingAlgorithmTableSize, std::back_inserter(vocabulary.encodingAlgorithmTable)); + } + if (externalVocabulary->prefixTable) { + std::copy(externalVocabulary->prefixTable, externalVocabulary->prefixTable + externalVocabulary->prefixTableSize, std::back_inserter(vocabulary.prefixTable)); + } + if (externalVocabulary->namespaceNameTable) { + std::copy(externalVocabulary->namespaceNameTable, externalVocabulary->namespaceNameTable + externalVocabulary->namespaceNameTableSize, std::back_inserter(vocabulary.namespaceNameTable)); + } + if (externalVocabulary->localNameTable) { + std::copy(externalVocabulary->localNameTable, externalVocabulary->localNameTable + externalVocabulary->localNameTableSize, std::back_inserter(vocabulary.localNameTable)); + } + if (externalVocabulary->otherNCNameTable) { + std::copy(externalVocabulary->otherNCNameTable, externalVocabulary->otherNCNameTable + externalVocabulary->otherNCNameTableSize, std::back_inserter(vocabulary.otherNCNameTable)); + } + if (externalVocabulary->otherURITable) { + std::copy(externalVocabulary->otherURITable, externalVocabulary->otherURITable + externalVocabulary->otherURITableSize, std::back_inserter(vocabulary.otherURITable)); + } + if (externalVocabulary->attributeValueTable) { + std::copy(externalVocabulary->attributeValueTable, externalVocabulary->attributeValueTable + externalVocabulary->attributeValueTableSize, std::back_inserter(vocabulary.attributeValueTable)); + } + if (externalVocabulary->charactersTable) { + std::copy(externalVocabulary->charactersTable, externalVocabulary->charactersTable + externalVocabulary->charactersTableSize, std::back_inserter(vocabulary.charactersTable)); + } + if (externalVocabulary->otherStringTable) { + std::copy(externalVocabulary->otherStringTable, externalVocabulary->otherStringTable + externalVocabulary->otherStringTableSize, std::back_inserter(vocabulary.otherStringTable)); + } + if (externalVocabulary->elementNameTable) { + std::copy(externalVocabulary->elementNameTable, externalVocabulary->elementNameTable + externalVocabulary->elementNameTableSize, std::back_inserter(vocabulary.elementNameTable)); + } + if (externalVocabulary->attributeNameTable) { + std::copy(externalVocabulary->attributeNameTable, externalVocabulary->attributeNameTable + externalVocabulary->attributeNameTableSize, std::back_inserter(vocabulary.attributeNameTable)); + } + } + if (b1 & 0x0800) { + // Parse restricted alphabets (C.2.5.3) + for (size_t len = parseSequenceLen(); len > 0; --len) { + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + vocabulary.restrictedAlphabetTable.push_back(parseNonEmptyOctetString2()); + } + } + if (b1 & 0x0400) { + // Parse encoding algorithms (C.2.5.3) + for (size_t len = parseSequenceLen(); len > 0; --len) { + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + vocabulary.encodingAlgorithmTable.push_back(parseNonEmptyOctetString2()); + } + } + if (b1 & 0x0200) { + // Parse prefixes (C.2.5.3) + for (size_t len = parseSequenceLen(); len > 0; --len) { + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + vocabulary.prefixTable.push_back(parseNonEmptyOctetString2()); + } + } + if (b1 & 0x0100) { + // Parse namespace names (C.2.5.3) + for (size_t len = parseSequenceLen(); len > 0; --len) { + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + vocabulary.namespaceNameTable.push_back(parseNonEmptyOctetString2()); + } + } + if (b1 & 0x0080) { + // Parse local names (C.2.5.3) + for (size_t len = parseSequenceLen(); len > 0; --len) { + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + vocabulary.localNameTable.push_back(parseNonEmptyOctetString2()); + } + } + if (b1 & 0x0040) { + // Parse other ncnames (C.2.5.3) + for (size_t len = parseSequenceLen(); len > 0; --len) { + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + vocabulary.otherNCNameTable.push_back(parseNonEmptyOctetString2()); + } + } + if (b1 & 0x0020) { + // Parse other uris (C.2.5.3) + for (size_t len = parseSequenceLen(); len > 0; --len) { + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + vocabulary.otherURITable.push_back(parseNonEmptyOctetString2()); + } + } + if (b1 & 0x0010) { + // Parse attribute values (C.2.5.4) + for (size_t len = parseSequenceLen(); len > 0; --len) { + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + vocabulary.attributeValueTable.push_back(parseEncodedCharacterString3()); + } + } + if (b1 & 0x0008) { + // Parse content character chunks (C.2.5.4) + for (size_t len = parseSequenceLen(); len > 0; --len) { + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + vocabulary.charactersTable.push_back(parseEncodedCharacterString3()); + } + } + if (b1 & 0x0004) { + // Parse other strings (C.2.5.4) + for (size_t len = parseSequenceLen(); len > 0; --len) { + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + vocabulary.otherStringTable.push_back(parseEncodedCharacterString3()); + } + } + if (b1 & 0x0002) { + // Parse element name surrogates (C.2.5.5) + for (size_t len = parseSequenceLen(); len > 0; --len) { + vocabulary.elementNameTable.push_back(parseNameSurrogate()); + } + } + if (b1 & 0x0001) { + // Parse attribute name surrogates (C.2.5.5) + for (size_t len = parseSequenceLen(); len > 0; --len) { + vocabulary.attributeNameTable.push_back(parseNameSurrogate()); + } + } + } + if (b & 0x10) { + // Parse notations (C.2.6) + for (;;) { + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + uint8_t b1 = *dataP++; + if (b1 == 0xf0) { + break; + } + if ((b1 & 0xfc) != 0xc0) { + throw DeadlyImportError(parseErrorMessage); + } + /* C.11 */ + /*const std::string &name =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable); + if (b1 & 0x02) { + /*const std::string &systemId =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable); + } + if (b1 & 0x01) { + /*const std::string &publicId =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable); + } + } + } + if (b & 0x08) { + // Parse unparsed entities (C.2.7) + for (;;) { + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + uint8_t b1 = *dataP++; + if (b1 == 0xf0) { + break; + } + if ((b1 & 0xfe) != 0xd0) { + throw DeadlyImportError(parseErrorMessage); + } + /* C.10 */ + /*const std::string &name =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable); + /*const std::string &systemId =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable); + if (b1 & 0x01) { + /*const std::string &publicId =*/ parseIdentifyingStringOrIndex(vocabulary.otherURITable); + } + /*const std::string ¬ationName =*/ parseIdentifyingStringOrIndex(vocabulary.otherNCNameTable); + } + } + if (b & 0x04) { + // Parse character encoding scheme (C.2.8) + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + /*std::string characterEncodingScheme =*/ parseNonEmptyOctetString2(); + } + if (b & 0x02) { + // Parse standalone flag (C.2.9) + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + uint8_t b1 = *dataP++; + if (b1 & 0xfe) { + throw DeadlyImportError(parseErrorMessage); + } + //bool standalone = b1 & 0x01; + } + if (b & 0x01) { + // Parse version (C.2.10) + if (dataEnd - dataP < 1) { + throw DeadlyImportError(parseErrorMessage); + } + /*std::shared_ptr version =*/ parseNonIdentifyingStringOrIndex1(vocabulary.otherStringTable); + } + } + + std::unique_ptr data; + uint8_t *dataP, *dataEnd; + irr::io::EXML_NODE currentNodeType; + bool emptyElement; + bool headerPending; + bool terminatorPending; + Vocabulary vocabulary; + std::vector attributes; + std::stack elementStack; + std::string nodeName; + std::map> decoderMap; + std::map vocabularyMap; + + static const std::string EmptyString; + static std::shared_ptr EmptyFIString; + + static FIHexDecoder hexDecoder; + static FIBase64Decoder base64Decoder; + static FIShortDecoder shortDecoder; + static FIIntDecoder intDecoder; + static FILongDecoder longDecoder; + static FIBoolDecoder boolDecoder; + static FIFloatDecoder floatDecoder; + static FIDoubleDecoder doubleDecoder; + static FIUUIDDecoder uuidDecoder; + static FICDATADecoder cdataDecoder; + static FIDecoder *defaultDecoder[32]; +}; + +const std::string CFIReaderImpl::EmptyString; +std::shared_ptr CFIReaderImpl::EmptyFIString = FIStringValue::create(std::string()); + +FIHexDecoder CFIReaderImpl::hexDecoder; +FIBase64Decoder CFIReaderImpl::base64Decoder; +FIShortDecoder CFIReaderImpl::shortDecoder; +FIIntDecoder CFIReaderImpl::intDecoder; +FILongDecoder CFIReaderImpl::longDecoder; +FIBoolDecoder CFIReaderImpl::boolDecoder; +FIFloatDecoder CFIReaderImpl::floatDecoder; +FIDoubleDecoder CFIReaderImpl::doubleDecoder; +FIUUIDDecoder CFIReaderImpl::uuidDecoder; +FICDATADecoder CFIReaderImpl::cdataDecoder; + +FIDecoder *CFIReaderImpl::defaultDecoder[32] = { + &hexDecoder, + &base64Decoder, + &shortDecoder, + &intDecoder, + &longDecoder, + &boolDecoder, + &floatDecoder, + &doubleDecoder, + &uuidDecoder, + &cdataDecoder +}; + +class CXMLReaderImpl : public FIReader +{ +public: + + //! Constructor + CXMLReaderImpl(std::unique_ptr> reader_) + : reader(std::move(reader_)) + {} + + virtual ~CXMLReaderImpl() {} + + virtual bool read() /*override*/ { + return reader->read(); + } + + virtual irr::io::EXML_NODE getNodeType() const /*override*/ { + return reader->getNodeType(); + } + + virtual int getAttributeCount() const /*override*/ { + return reader->getAttributeCount(); + } + + virtual const char* getAttributeName(int idx) const /*override*/ { + return reader->getAttributeName(idx); + } + + virtual const char* getAttributeValue(int idx) const /*override*/ { + return reader->getAttributeValue(idx); + } + + virtual const char* getAttributeValue(const char* name) const /*override*/ { + return reader->getAttributeValue(name); + } + + virtual const char* getAttributeValueSafe(const char* name) const /*override*/ { + return reader->getAttributeValueSafe(name); + } + + virtual int getAttributeValueAsInt(const char* name) const /*override*/ { + return reader->getAttributeValueAsInt(name); + } + + virtual int getAttributeValueAsInt(int idx) const /*override*/ { + return reader->getAttributeValueAsInt(idx); + } + + virtual float getAttributeValueAsFloat(const char* name) const /*override*/ { + return reader->getAttributeValueAsFloat(name); + } + + virtual float getAttributeValueAsFloat(int idx) const /*override*/ { + return reader->getAttributeValueAsFloat(idx); + } + + virtual const char* getNodeName() const /*override*/ { + return reader->getNodeName(); + } + + virtual const char* getNodeData() const /*override*/ { + return reader->getNodeData(); + } + + virtual bool isEmptyElement() const /*override*/ { + return reader->isEmptyElement(); + } + + virtual irr::io::ETEXT_FORMAT getSourceFormat() const /*override*/ { + return reader->getSourceFormat(); + } + + virtual irr::io::ETEXT_FORMAT getParserFormat() const /*override*/ { + return reader->getParserFormat(); + } + + virtual std::shared_ptr getAttributeEncodedValue(int /*idx*/) const /*override*/ { + return nullptr; + } + + virtual std::shared_ptr getAttributeEncodedValue(const char* /*name*/) const /*override*/ { + return nullptr; + } + + virtual void registerDecoder(const std::string & /*algorithmUri*/, std::unique_ptr /*decoder*/) /*override*/ {} + + + virtual void registerVocabulary(const std::string &/*vocabularyUri*/, const FIVocabulary * /*vocabulary*/) /*override*/ {} + +private: + + std::unique_ptr> reader; +}; + +static std::unique_ptr readFile(IOStream *stream, size_t &size, bool &isFI) { + size = stream->FileSize(); + std::unique_ptr data = std::unique_ptr(new uint8_t[size]); + if (stream->Read(data.get(), size, 1) != 1) { + size = 0; + data.reset(); + } + isFI = parseMagic(data.get(), data.get() + size) > 0; + return data; +} + +std::unique_ptr FIReader::create(IOStream *stream) +{ + size_t size; + bool isFI; + auto data = readFile(stream, size, isFI); + if (isFI) { + return std::unique_ptr(new CFIReaderImpl(std::move(data), size)); + } + else { + auto memios = std::unique_ptr(new MemoryIOStream(data.release(), size, true)); + auto callback = std::unique_ptr(new CIrrXML_IOStreamReader(memios.get())); + return std::unique_ptr(new CXMLReaderImpl(std::unique_ptr>(createIrrXMLReader(callback.get())))); + } +} + +}// namespace Assimp + +#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER diff --git a/code/FIReader.hpp b/code/FIReader.hpp new file mode 100644 index 000000000..5f4e5bb48 --- /dev/null +++ b/code/FIReader.hpp @@ -0,0 +1,185 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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 FIReader.hpp +/// \brief Reader for Fast Infoset encoded binary XML files. +/// \date 2017 +/// \author Patrick Daehne + +#ifndef INCLUDED_AI_FI_READER_H +#define INCLUDED_AI_FI_READER_H + +#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER + +//#include +#include +#include +#include +#include +#include +//#include +//#include +#include + +namespace Assimp { + +struct FIValue { + virtual const std::string &toString() const = 0; +}; + +struct FIStringValue: public FIValue { + std::string value; + static std::shared_ptr create(std::string &&value); +}; + +struct FIByteValue: public FIValue { + std::vector value; +}; + +struct FIHexValue: public FIByteValue { + static std::shared_ptr create(std::vector &&value); +}; + +struct FIBase64Value: public FIByteValue { + static std::shared_ptr create(std::vector &&value); +}; + +struct FIShortValue: public FIValue { + std::vector value; + static std::shared_ptr create(std::vector &&value); +}; + +struct FIIntValue: public FIValue { + std::vector value; + static std::shared_ptr create(std::vector &&value); +}; + +struct FILongValue: public FIValue { + std::vector value; + static std::shared_ptr create(std::vector &&value); +}; + +struct FIBoolValue: public FIValue { + std::vector value; + static std::shared_ptr create(std::vector &&value); +}; + +struct FIFloatValue: public FIValue { + std::vector value; + static std::shared_ptr create(std::vector &&value); +}; + +struct FIDoubleValue: public FIValue { + std::vector value; + static std::shared_ptr create(std::vector &&value); +}; + +struct FIUUIDValue: public FIByteValue { + static std::shared_ptr create(std::vector &&value); +}; + +struct FICDATAValue: public FIStringValue { + static std::shared_ptr create(std::string &&value); +}; + +struct FIDecoder { + virtual std::shared_ptr decode(const uint8_t *data, size_t len) = 0; +}; + +struct FIQName { + const char *name; + const char *prefix; + const char *uri; +}; + +struct FIVocabulary { + const char **restrictedAlphabetTable; + size_t restrictedAlphabetTableSize; + const char **encodingAlgorithmTable; + size_t encodingAlgorithmTableSize; + const char **prefixTable; + size_t prefixTableSize; + const char **namespaceNameTable; + size_t namespaceNameTableSize; + const char **localNameTable; + size_t localNameTableSize; + const char **otherNCNameTable; + size_t otherNCNameTableSize; + const char **otherURITable; + size_t otherURITableSize; + const std::shared_ptr *attributeValueTable; + size_t attributeValueTableSize; + const std::shared_ptr *charactersTable; + size_t charactersTableSize; + const std::shared_ptr *otherStringTable; + size_t otherStringTableSize; + const FIQName *elementNameTable; + size_t elementNameTableSize; + const FIQName *attributeNameTable; + size_t attributeNameTableSize; +}; + +class IOStream; + +class FIReader: public irr::io::IIrrXMLReader { +public: + virtual ~FIReader(); + virtual std::shared_ptr getAttributeEncodedValue(int idx) const = 0; + + virtual std::shared_ptr getAttributeEncodedValue(const char *name) const = 0; + + virtual void registerDecoder(const std::string &algorithmUri, std::unique_ptr decoder) = 0; + + virtual void registerVocabulary(const std::string &vocabularyUri, const FIVocabulary *vocabulary) = 0; + + static std::unique_ptr create(IOStream *stream); + +};// class IFIReader + +inline +FIReader::~FIReader() { + // empty +} + +}// namespace Assimp + +#endif // #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER + +#endif // INCLUDED_AI_FI_READER_H diff --git a/code/FileLogStream.h b/code/FileLogStream.h index 574a63ed6..e935624a1 100644 --- a/code/FileLogStream.h +++ b/code/FileLogStream.h @@ -1,9 +1,50 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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 FileLofStream.h +*/ #ifndef ASSIMP_FILELOGSTREAM_H_INC #define ASSIMP_FILELOGSTREAM_H_INC #include #include -#include "DefaultIOSystem.h" +#include namespace Assimp { diff --git a/code/FindDegenerates.cpp b/code/FindDegenerates.cpp index 62750bfad..f9c04133a 100644 --- a/code/FindDegenerates.cpp +++ b/code/FindDegenerates.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -55,98 +56,138 @@ using namespace Assimp; // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer FindDegeneratesProcess::FindDegeneratesProcess() -: configRemoveDegenerates (false) -{} +: mConfigRemoveDegenerates( false ) +, mConfigCheckAreaOfTriangle( false ){ + // empty +} // ------------------------------------------------------------------------------------------------ // Destructor, private as well -FindDegeneratesProcess::~FindDegeneratesProcess() -{ +FindDegeneratesProcess::~FindDegeneratesProcess() { // nothing to do here } // ------------------------------------------------------------------------------------------------ // Returns whether the processing step is present in the given flag field. -bool FindDegeneratesProcess::IsActive( unsigned int pFlags) const -{ +bool FindDegeneratesProcess::IsActive( unsigned int pFlags) const { return 0 != (pFlags & aiProcess_FindDegenerates); } // ------------------------------------------------------------------------------------------------ // Setup import configuration -void FindDegeneratesProcess::SetupProperties(const Importer* pImp) -{ +void FindDegeneratesProcess::SetupProperties(const Importer* pImp) { // Get the current value of AI_CONFIG_PP_FD_REMOVE - configRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE,0)); + mConfigRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE,0)); + mConfigCheckAreaOfTriangle = ( 0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_CHECKAREA) ); } // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported data. -void FindDegeneratesProcess::Execute( aiScene* pScene) -{ +void FindDegeneratesProcess::Execute( aiScene* pScene) { DefaultLogger::get()->debug("FindDegeneratesProcess begin"); for (unsigned int i = 0; i < pScene->mNumMeshes;++i){ - ExecuteOnMesh( pScene->mMeshes[i]); + ExecuteOnMesh( pScene->mMeshes[ i ] ); } DefaultLogger::get()->debug("FindDegeneratesProcess finished"); } +static ai_real heron( ai_real a, ai_real b, ai_real c ) { + ai_real s = (a + b + c) / 2; + ai_real area = pow((s * ( s - a ) * ( s - b ) * ( s - c ) ), (ai_real)0.5 ); + return area; +} + +static ai_real distance3D( const aiVector3D &vA, aiVector3D &vB ) { + const ai_real lx = ( vB.x - vA.x ); + const ai_real ly = ( vB.y - vA.y ); + const ai_real lz = ( vB.z - vA.z ); + ai_real a = lx*lx + ly*ly + lz*lz; + ai_real d = pow( a, (ai_real)0.5 ); + + return d; +} + +static ai_real calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh ) { + ai_real area = 0; + + aiVector3D vA( mesh->mVertices[ face.mIndices[ 0 ] ] ); + aiVector3D vB( mesh->mVertices[ face.mIndices[ 1 ] ] ); + aiVector3D vC( mesh->mVertices[ face.mIndices[ 2 ] ] ); + + ai_real a( distance3D( vA, vB ) ); + ai_real b( distance3D( vB, vC ) ); + ai_real c( distance3D( vC, vA ) ); + area = heron( a, b, c ); + + return area; +} + // ------------------------------------------------------------------------------------------------ // Executes the post processing step on the given imported mesh -void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) -{ +void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) { mesh->mPrimitiveTypes = 0; std::vector remove_me; - if (configRemoveDegenerates) - remove_me.resize(mesh->mNumFaces,false); + if (mConfigRemoveDegenerates) { + remove_me.resize( mesh->mNumFaces, false ); + } unsigned int deg = 0, limit; - for (unsigned int a = 0; a < mesh->mNumFaces; ++a) - { + for ( unsigned int a = 0; a < mesh->mNumFaces; ++a ) { aiFace& face = mesh->mFaces[a]; bool first = true; // check whether the face contains degenerated entries - for (unsigned int i = 0; i < face.mNumIndices; ++i) - { + for (unsigned int i = 0; i < face.mNumIndices; ++i) { // Polygons with more than 4 points are allowed to have double points, that is // simulating polygons with holes just with concave polygons. However, // double points may not come directly after another. limit = face.mNumIndices; - if (face.mNumIndices > 4) - limit = std::min(limit,i+2); + if (face.mNumIndices > 4) { + limit = std::min( limit, i+2 ); + } - for (unsigned int t = i+1; t < limit; ++t) - { - if (mesh->mVertices[face.mIndices[i]] == mesh->mVertices[face.mIndices[t]]) - { + for (unsigned int t = i+1; t < limit; ++t) { + if (mesh->mVertices[face.mIndices[ i ] ] == mesh->mVertices[ face.mIndices[ t ] ]) { // we have found a matching vertex position // remove the corresponding index from the array - --face.mNumIndices;--limit; - for (unsigned int m = t; m < face.mNumIndices; ++m) - { - face.mIndices[m] = face.mIndices[m+1]; + --face.mNumIndices; + --limit; + for (unsigned int m = t; m < face.mNumIndices; ++m) { + face.mIndices[ m ] = face.mIndices[ m+1 ]; } --t; // NOTE: we set the removed vertex index to an unique value // to make sure the developer gets notified when his // application attemps to access this data. - face.mIndices[face.mNumIndices] = 0xdeadbeef; + face.mIndices[ face.mNumIndices ] = 0xdeadbeef; - if(first) - { + if(first) { ++deg; first = false; } - if (configRemoveDegenerates) { - remove_me[a] = true; + if ( mConfigRemoveDegenerates ) { + remove_me[ a ] = true; goto evil_jump_outside; // hrhrhrh ... yeah, this rocks baby! } } } + + if ( mConfigCheckAreaOfTriangle ) { + if ( face.mNumIndices == 3 ) { + ai_real area = calculateAreaOfTriangle( face, mesh ); + if ( area < 1e-6 ) { + if ( mConfigRemoveDegenerates ) { + remove_me[ a ] = true; + goto evil_jump_outside; + } + + // todo: check for index which is corrupt. + } + } + } } // We need to update the primitive flags array of the mesh. @@ -170,7 +211,7 @@ evil_jump_outside: } // If AI_CONFIG_PP_FD_REMOVE is true, remove degenerated faces from the import - if (configRemoveDegenerates && deg) { + if (mConfigRemoveDegenerates && deg) { unsigned int n = 0; for (unsigned int a = 0; a < mesh->mNumFaces; ++a) { diff --git a/code/FindDegenerates.h b/code/FindDegenerates.h index 7b945ea3a..cf03a24bc 100644 --- a/code/FindDegenerates.h +++ b/code/FindDegenerates.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -53,15 +54,11 @@ namespace Assimp { // --------------------------------------------------------------------------- /** FindDegeneratesProcess: Searches a mesh for degenerated triangles. */ -class ASSIMP_API FindDegeneratesProcess : public BaseProcess -{ +class ASSIMP_API FindDegeneratesProcess : public BaseProcess { public: - FindDegeneratesProcess(); ~FindDegeneratesProcess(); -public: - // ------------------------------------------------------------------- // Check whether step is active bool IsActive( unsigned int pFlags) const; @@ -78,28 +75,53 @@ public: // Execute step on a given mesh void ExecuteOnMesh( aiMesh* mesh); + // ------------------------------------------------------------------- + /// @brief Enable the instant removal of degenerated primitives + /// @param enabled true for enabled. + void EnableInstantRemoval(bool enabled); // ------------------------------------------------------------------- - /** @brief Enable the instant removal of degenerated primitives - * @param d hm ... difficult to guess what this means, hu!? - */ - void EnableInstantRemoval(bool d) { - configRemoveDegenerates = d; - } + /// @brief Check whether instant removal is currently enabled + /// @return The instant removal state. + bool IsInstantRemoval() const; // ------------------------------------------------------------------- - /** @brief Check whether instant removal is currently enabled - * @return ... - */ - bool IsInstantRemoval() const { - return configRemoveDegenerates; - } + /// @brief Enable the area check for triangles. + /// @param enabled true for enabled. + void EnableAreaCheck( bool enabled ); + + // ------------------------------------------------------------------- + /// @brief Check whether the area check is enabled. + /// @return The area check state. + bool isAreaCheckEnabled() const; private: - //! Configuration option: remove degenerates faces immediately - bool configRemoveDegenerates; + bool mConfigRemoveDegenerates; + //! Configuration option: check for area + bool mConfigCheckAreaOfTriangle; }; + +inline +void FindDegeneratesProcess::EnableInstantRemoval(bool enabled) { + mConfigRemoveDegenerates = enabled; } +inline +bool FindDegeneratesProcess::IsInstantRemoval() const { + return mConfigRemoveDegenerates; +} + +inline +void FindDegeneratesProcess::EnableAreaCheck( bool enabled ) { + mConfigCheckAreaOfTriangle = enabled; +} + +inline +bool FindDegeneratesProcess::isAreaCheckEnabled() const { + return mConfigCheckAreaOfTriangle; +} + +} // Namespace Assimp + #endif // !! AI_FINDDEGENERATESPROCESS_H_INC diff --git a/code/FindInstancesProcess.cpp b/code/FindInstancesProcess.cpp index 479f6561e..ab2d2257b 100644 --- a/code/FindInstancesProcess.cpp +++ b/code/FindInstancesProcess.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/FindInstancesProcess.h b/code/FindInstancesProcess.h index 14876045c..dc4396566 100644 --- a/code/FindInstancesProcess.h +++ b/code/FindInstancesProcess.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/FindInvalidDataProcess.cpp b/code/FindInvalidDataProcess.cpp index bed2eee06..c37d8956c 100644 --- a/code/FindInvalidDataProcess.cpp +++ b/code/FindInvalidDataProcess.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -168,8 +169,8 @@ void FindInvalidDataProcess::Execute( aiScene* pScene) // ------------------------------------------------------------------------------------------------ template -inline const char* ValidateArrayContents(const T* arr, unsigned int size, - const std::vector& dirtyMask, bool mayBeIdentical = false, bool mayBeZero = true) +inline const char* ValidateArrayContents(const T* /*arr*/, unsigned int /*size*/, + const std::vector& /*dirtyMask*/, bool /*mayBeIdentical = false*/, bool /*mayBeZero = true*/) { return NULL; } @@ -338,32 +339,37 @@ void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim) int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh) { bool ret = false; - std::vector dirtyMask(pMesh->mNumVertices,(pMesh->mNumFaces ? true : false)); + std::vector dirtyMask(pMesh->mNumVertices, pMesh->mNumFaces != 0); // Ignore elements that are not referenced by vertices. // (they are, for example, caused by the FindDegenerates step) - for (unsigned int m = 0; m < pMesh->mNumFaces;++m) { + for (unsigned int m = 0; m < pMesh->mNumFaces; ++m) { const aiFace& f = pMesh->mFaces[m]; - for (unsigned int i = 0; i < f.mNumIndices;++i) { + for (unsigned int i = 0; i < f.mNumIndices; ++i) { dirtyMask[f.mIndices[i]] = false; } } // Process vertex positions - if(pMesh->mVertices && ProcessArray(pMesh->mVertices,pMesh->mNumVertices,"positions",dirtyMask)) { + if (pMesh->mVertices && ProcessArray(pMesh->mVertices, pMesh->mNumVertices, "positions", dirtyMask)) { DefaultLogger::get()->error("Deleting mesh: Unable to continue without vertex positions"); + return 2; } // process texture coordinates - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS && pMesh->mTextureCoords[i];++i) { - if (ProcessArray(pMesh->mTextureCoords[i],pMesh->mNumVertices,"uvcoords",dirtyMask)) { + for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS && pMesh->mTextureCoords[i]; ++i) { + if (ProcessArray(pMesh->mTextureCoords[i], pMesh->mNumVertices, "uvcoords", dirtyMask)) { + pMesh->mNumUVComponents[i] = 0; // delete all subsequent texture coordinate sets. - for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) { - delete[] pMesh->mTextureCoords[a]; pMesh->mTextureCoords[a] = NULL; + for (unsigned int a = i + 1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) { + delete[] pMesh->mTextureCoords[a]; + pMesh->mTextureCoords[a] = NULL; + pMesh->mNumUVComponents[a] = 0; } + ret = true; } } diff --git a/code/FindInvalidDataProcess.h b/code/FindInvalidDataProcess.h index 8a1df21fd..cc0ef946d 100644 --- a/code/FindInvalidDataProcess.h +++ b/code/FindInvalidDataProcess.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/FixNormalsStep.cpp b/code/FixNormalsStep.cpp index 0325f8dfb..05d05e873 100644 --- a/code/FixNormalsStep.cpp +++ b/code/FixNormalsStep.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/FixNormalsStep.h b/code/FixNormalsStep.h index 5dea5d868..71309c7e5 100644 --- a/code/FixNormalsStep.h +++ b/code/FixNormalsStep.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -55,14 +56,11 @@ namespace Assimp * vectors of an object are facing inwards. In this case they will be * flipped. */ -class FixInfacingNormalsProcess : public BaseProcess -{ +class FixInfacingNormalsProcess : public BaseProcess { public: - FixInfacingNormalsProcess(); ~FixInfacingNormalsProcess(); -public: // ------------------------------------------------------------------- /** Returns whether the processing step is present in the given flag field. * @param pFlags The processing flags the importer was called with. A bitwise diff --git a/code/GenFaceNormalsProcess.cpp b/code/GenFaceNormalsProcess.cpp index 9218d9db8..82d80db77 100644 --- a/code/GenFaceNormalsProcess.cpp +++ b/code/GenFaceNormalsProcess.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/GenFaceNormalsProcess.h b/code/GenFaceNormalsProcess.h index f56570078..024c74a28 100644 --- a/code/GenFaceNormalsProcess.h +++ b/code/GenFaceNormalsProcess.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/GenVertexNormalsProcess.cpp b/code/GenVertexNormalsProcess.cpp index c205ac5ac..93c0e1351 100644 --- a/code/GenVertexNormalsProcess.cpp +++ b/code/GenVertexNormalsProcess.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/GenVertexNormalsProcess.h b/code/GenVertexNormalsProcess.h index caa327aa3..0471ed6b0 100644 --- a/code/GenVertexNormalsProcess.h +++ b/code/GenVertexNormalsProcess.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/GenericProperty.h b/code/GenericProperty.h index 507bfb693..454f4952b 100644 --- a/code/GenericProperty.h +++ b/code/GenericProperty.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -110,7 +111,7 @@ inline void SetGenericPropertyPtr(std::map< unsigned int, T* >& list, // ------------------------------------------------------------------------------------------------ template -inline const bool HasGenericProperty(const std::map< unsigned int, T >& list, +inline bool HasGenericProperty(const std::map< unsigned int, T >& list, const char* szName) { ai_assert(NULL != szName); diff --git a/code/HMPFileData.h b/code/HMPFileData.h index cff3b6b18..3c060ba1a 100644 --- a/code/HMPFileData.h +++ b/code/HMPFileData.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/HMPLoader.cpp b/code/HMPLoader.cpp index 788286e12..2a669201e 100644 --- a/code/HMPLoader.cpp +++ b/code/HMPLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -51,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include using namespace Assimp; @@ -446,7 +448,8 @@ void HMPImporter::CreateOutputFaceList(unsigned int width,unsigned int height) void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szCursor, const unsigned char** szCursorOut) { - ai_assert(0 != iNumSkins && NULL != szCursor); + ai_assert( 0 != iNumSkins ); + ai_assert( nullptr != szCursor); // read the type of the skin ... // sometimes we need to skip 12 bytes here, I don't know why ... diff --git a/code/HMPLoader.h b/code/HMPLoader.h index 4dd0d9840..546643e8d 100644 --- a/code/HMPLoader.h +++ b/code/HMPLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -44,11 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_HMPLOADER_H_INCLUDED #define AI_HMPLOADER_H_INCLUDED -// public ASSIMP headers -#include -#include -#include - // internal headers #include "BaseImporter.h" #include "MDLLoader.h" diff --git a/code/HalfLifeFileData.h b/code/HalfLifeFileData.h index 54fe83734..3a36d2422 100644 --- a/code/HalfLifeFileData.h +++ b/code/HalfLifeFileData.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -49,7 +50,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_MDLFILEHELPER2_H_INC #define AI_MDLFILEHELPER2_H_INC -#include "MDLFileData.h" #include "./../include/assimp/Compiler/pushpack1.h" namespace Assimp { @@ -66,8 +66,7 @@ namespace MDL { * \brief Data structure for the HL2 main header */ // --------------------------------------------------------------------------- -struct Header_HL2 -{ +struct Header_HL2 { //! magic number: "IDST"/"IDSQ" char ident[4]; @@ -139,7 +138,7 @@ struct Header_HL2 //! Number of animation transitions int32_t numtransitions; int32_t transitionindex; -} PACK_STRUCT; +} /* PACK_STRUCT */; #include "./../include/assimp/Compiler/poppack1.h" diff --git a/code/Hash.h b/code/Hash.h index cd7ca6def..a567adbc3 100644 --- a/code/Hash.h +++ b/code/Hash.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/IFCBoolean.cpp b/code/IFCBoolean.cpp index d3b77d87c..d250fbe36 100644 --- a/code/IFCBoolean.cpp +++ b/code/IFCBoolean.cpp @@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "IFCUtil.h" #include "PolyTools.h" #include "ProcessHelper.h" -#include "Defines.h" +#include #include #include @@ -272,7 +272,6 @@ bool IntersectsBoundaryProfile(const IfcVector3& e0, const IfcVector3& e1, const const IfcVector3& b0 = boundary[i]; const IfcVector3& b1 = boundary[(i + 1) % bcount]; IfcVector3 b = b1 - b0; - IfcFloat b_sqlen_inv = 1.0 / b.SquareLength(); // segment-segment intersection // solve b0 + b*s = e0 + e*t for (s,t) @@ -281,6 +280,7 @@ bool IntersectsBoundaryProfile(const IfcVector3& e0, const IfcVector3& e1, const // no solutions (parallel lines) continue; } + IfcFloat b_sqlen_inv = 1.0 / b.SquareLength(); const IfcFloat x = b0.x - e0.x; const IfcFloat y = b0.y - e0.y; @@ -381,7 +381,6 @@ bool PointInPoly(const IfcVector3& p, const std::vector& boundary) IntersectsBoundaryProfile(p, p + IfcVector3(0.6, -0.6, 0.0), boundary, true, intersected_boundary, true); votes += intersected_boundary.size() % 2; -// ai_assert(votes == 3 || votes == 0); return votes > 1; } diff --git a/code/IFCCurve.cpp b/code/IFCCurve.cpp index 97d9fd574..2aa3ef6a4 100644 --- a/code/IFCCurve.cpp +++ b/code/IFCCurve.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -42,28 +43,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Read profile and curves entities from IFC files */ - - #ifndef ASSIMP_BUILD_NO_IFC_IMPORTER #include "IFCUtil.h" namespace Assimp { - namespace IFC { - namespace { +namespace IFC { +namespace { // -------------------------------------------------------------------------------- // Conic is the base class for Circle and Ellipse // -------------------------------------------------------------------------------- -class Conic : public Curve -{ - +class Conic : public Curve { public: - // -------------------------------------------------- Conic(const IfcConic& entity, ConversionData& conv) - : Curve(entity,conv) - { + : Curve(entity,conv) { IfcMatrix4 trafo; ConvertAxisPlacement(trafo,*entity.Position,conv); @@ -74,8 +69,6 @@ public: p[2] = IfcVector3(trafo.a3,trafo.b3,trafo.c3); } -public: - // -------------------------------------------------- bool IsClosed() const { return true; @@ -83,7 +76,8 @@ public: // -------------------------------------------------- size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const { - ai_assert(InRange(a) && InRange(b)); + ai_assert( InRange( a ) ); + ai_assert( InRange( b ) ); a *= conv.angle_scale; b *= conv.angle_scale; @@ -103,15 +97,11 @@ protected: IfcVector3 location, p[3]; }; - // -------------------------------------------------------------------------------- // Circle // -------------------------------------------------------------------------------- -class Circle : public Conic -{ - +class Circle : public Conic { public: - // -------------------------------------------------- Circle(const IfcCircle& entity, ConversionData& conv) : Conic(entity,conv) @@ -119,8 +109,6 @@ public: { } -public: - // -------------------------------------------------- IfcVector3 Eval(IfcFloat u) const { u = -conv.angle_scale * u; @@ -136,20 +124,15 @@ private: // -------------------------------------------------------------------------------- // Ellipse // -------------------------------------------------------------------------------- -class Ellipse : public Conic -{ - +class Ellipse : public Conic { public: - // -------------------------------------------------- Ellipse(const IfcEllipse& entity, ConversionData& conv) - : Conic(entity,conv) - , entity(entity) - { + : Conic(entity,conv) + , entity(entity) { + // empty } -public: - // -------------------------------------------------- IfcVector3 Eval(IfcFloat u) const { u = -conv.angle_scale * u; @@ -161,25 +144,18 @@ private: const IfcEllipse& entity; }; - // -------------------------------------------------------------------------------- // Line // -------------------------------------------------------------------------------- -class Line : public Curve -{ - +class Line : public Curve { public: - // -------------------------------------------------- Line(const IfcLine& entity, ConversionData& conv) - : Curve(entity,conv) - { + : Curve(entity,conv) { ConvertCartesianPoint(p,entity.Pnt); ConvertVector(v,entity.Dir); } -public: - // -------------------------------------------------- bool IsClosed() const { return false; @@ -192,16 +168,17 @@ public: // -------------------------------------------------- size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const { - ai_assert(InRange(a) && InRange(b)); + ai_assert( InRange( a ) ); + ai_assert( InRange( b ) ); // two points are always sufficient for a line segment return a==b ? 1 : 2; } // -------------------------------------------------- - void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const - { - ai_assert(InRange(a) && InRange(b)); + void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const { + ai_assert( InRange( a ) ); + ai_assert( InRange( b ) ); if (a == b) { out.verts.push_back(Eval(a)); @@ -226,18 +203,14 @@ private: // -------------------------------------------------------------------------------- // CompositeCurve joins multiple smaller, bounded curves // -------------------------------------------------------------------------------- -class CompositeCurve : public BoundedCurve -{ - +class CompositeCurve : public BoundedCurve { typedef std::pair< std::shared_ptr< BoundedCurve >, bool > CurveEntry; public: - // -------------------------------------------------- CompositeCurve(const IfcCompositeCurve& entity, ConversionData& conv) - : BoundedCurve(entity,conv) - , total() - { + : BoundedCurve(entity,conv) + , total() { curves.reserve(entity.Segments.size()); for(const IfcCompositeCurveSegment& curveSegment :entity.Segments) { // according to the specification, this must be a bounded curve @@ -262,8 +235,6 @@ public: } } -public: - // -------------------------------------------------- IfcVector3 Eval(IfcFloat u) const { if (curves.empty()) { @@ -286,7 +257,8 @@ public: // -------------------------------------------------- size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const { - ai_assert(InRange(a) && InRange(b)); + ai_assert( InRange( a ) ); + ai_assert( InRange( b ) ); size_t cnt = 0; IfcFloat acc = 0; @@ -305,9 +277,9 @@ public: } // -------------------------------------------------- - void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const - { - ai_assert(InRange(a) && InRange(b)); + void SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const { + ai_assert( InRange( a ) ); + ai_assert( InRange( b ) ); const size_t cnt = EstimateSampleCount(a,b); out.verts.reserve(out.verts.size() + cnt); @@ -329,19 +301,14 @@ public: private: std::vector< CurveEntry > curves; - IfcFloat total; }; - // -------------------------------------------------------------------------------- // TrimmedCurve can be used to trim an unbounded curve to a bounded range // -------------------------------------------------------------------------------- -class TrimmedCurve : public BoundedCurve -{ - +class TrimmedCurve : public BoundedCurve { public: - // -------------------------------------------------- TrimmedCurve(const IfcTrimmedCurve& entity, ConversionData& conv) : BoundedCurve(entity,conv) @@ -408,8 +375,6 @@ public: ai_assert(maxval >= 0); } -public: - // -------------------------------------------------- IfcVector3 Eval(IfcFloat p) const { ai_assert(InRange(p)); @@ -418,7 +383,8 @@ public: // -------------------------------------------------- size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const { - ai_assert(InRange(a) && InRange(b)); + ai_assert( InRange( a ) ); + ai_assert( InRange( b ) ); return base->EstimateSampleCount(TrimParam(a),TrimParam(b)); } @@ -434,13 +400,11 @@ public: } private: - // -------------------------------------------------- IfcFloat TrimParam(IfcFloat f) const { return agree_sense ? f + range.first : range.second - f; } - private: ParamRange range; IfcFloat maxval; @@ -453,11 +417,8 @@ private: // -------------------------------------------------------------------------------- // PolyLine is a 'curve' defined by linear interpolation over a set of discrete points // -------------------------------------------------------------------------------- -class PolyLine : public BoundedCurve -{ - +class PolyLine : public BoundedCurve { public: - // -------------------------------------------------- PolyLine(const IfcPolyline& entity, ConversionData& conv) : BoundedCurve(entity,conv) @@ -471,8 +432,6 @@ public: } } -public: - // -------------------------------------------------- IfcVector3 Eval(IfcFloat p) const { ai_assert(InRange(p)); @@ -501,13 +460,10 @@ private: std::vector points; }; - } // anon - // ------------------------------------------------------------------------------------------------ -Curve* Curve :: Convert(const IFC::IfcCurve& curve,ConversionData& conv) -{ +Curve* Curve::Convert(const IFC::IfcCurve& curve,ConversionData& conv) { if(curve.ToPtr()) { if(const IfcPolyline* c = curve.ToPtr()) { return new PolyLine(*c,conv); @@ -518,9 +474,6 @@ Curve* Curve :: Convert(const IFC::IfcCurve& curve,ConversionData& conv) if(const IfcCompositeCurve* c = curve.ToPtr()) { return new CompositeCurve(*c,conv); } - //if(const IfcBSplineCurve* c = curve.ToPtr()) { - // return new BSplineCurve(*c,conv); - //} } if(curve.ToPtr()) { @@ -542,13 +495,10 @@ Curve* Curve :: Convert(const IFC::IfcCurve& curve,ConversionData& conv) #ifdef ASSIMP_BUILD_DEBUG // ------------------------------------------------------------------------------------------------ -bool Curve :: InRange(IfcFloat u) const -{ +bool Curve::InRange(IfcFloat u) const { const ParamRange range = GetParametricRange(); if (IsClosed()) { return true; - //ai_assert(range.first != std::numeric_limits::infinity() && range.second != std::numeric_limits::infinity()); - //u = range.first + std::fmod(u-range.first,range.second-range.first); } const IfcFloat epsilon = 1e-5; return u - range.first > -epsilon && range.second - u > -epsilon; @@ -556,24 +506,24 @@ bool Curve :: InRange(IfcFloat u) const #endif // ------------------------------------------------------------------------------------------------ -IfcFloat Curve :: GetParametricRangeDelta() const -{ +IfcFloat Curve::GetParametricRangeDelta() const { const ParamRange& range = GetParametricRange(); return std::abs(range.second - range.first); } // ------------------------------------------------------------------------------------------------ -size_t Curve :: EstimateSampleCount(IfcFloat a, IfcFloat b) const -{ - ai_assert(InRange(a) && InRange(b)); +size_t Curve::EstimateSampleCount(IfcFloat a, IfcFloat b) const { + (void)(a); (void)(b); + ai_assert( InRange( a ) ); + ai_assert( InRange( b ) ); // arbitrary default value, deriving classes should supply better suited values return 16; } // ------------------------------------------------------------------------------------------------ -IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, IfcFloat b, unsigned int samples, IfcFloat threshold, unsigned int recurse = 0, unsigned int max_recurse = 15) -{ +IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, IfcFloat b, + unsigned int samples, IfcFloat threshold, unsigned int recurse = 0, unsigned int max_recurse = 15) { ai_assert(samples>1); const IfcFloat delta = (b-a)/samples, inf = std::numeric_limits::infinity(); @@ -595,7 +545,8 @@ IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, Ifc } } - ai_assert(min_diff[0] != inf && min_diff[1] != inf); + ai_assert( min_diff[ 0 ] != inf ); + ai_assert( min_diff[ 1 ] != inf ); if ( std::fabs(a-min_point[0]) < threshold || recurse >= max_recurse) { return min_point[0]; } @@ -616,15 +567,15 @@ IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, Ifc } // ------------------------------------------------------------------------------------------------ -bool Curve :: ReverseEval(const IfcVector3& val, IfcFloat& paramOut) const +bool Curve::ReverseEval(const IfcVector3& val, IfcFloat& paramOut) const { // note: the following algorithm is not guaranteed to find the 'right' parameter value // in all possible cases, but it will always return at least some value so this function // will never fail in the default implementation. // XXX derive threshold from curve topology - const IfcFloat threshold = 1e-4f; - const unsigned int samples = 16; + static const IfcFloat threshold = 1e-4f; + static const unsigned int samples = 16; const ParamRange& range = GetParametricRange(); paramOut = RecursiveSearch(this,val,range.first,range.second,samples,threshold); @@ -633,9 +584,9 @@ bool Curve :: ReverseEval(const IfcVector3& val, IfcFloat& paramOut) const } // ------------------------------------------------------------------------------------------------ -void Curve :: SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const -{ - ai_assert(InRange(a) && InRange(b)); +void Curve::SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const { + ai_assert( InRange( a ) ); + ai_assert( InRange( b ) ); const size_t cnt = std::max(static_cast(0),EstimateSampleCount(a,b)); out.verts.reserve( out.verts.size() + cnt + 1); @@ -647,16 +598,15 @@ void Curve :: SampleDiscrete(TempMesh& out,IfcFloat a, IfcFloat b) const } // ------------------------------------------------------------------------------------------------ -bool BoundedCurve :: IsClosed() const -{ +bool BoundedCurve::IsClosed() const { return false; } // ------------------------------------------------------------------------------------------------ -void BoundedCurve :: SampleDiscrete(TempMesh& out) const -{ +void BoundedCurve::SampleDiscrete(TempMesh& out) const { const ParamRange& range = GetParametricRange(); - ai_assert(range.first != std::numeric_limits::infinity() && range.second != std::numeric_limits::infinity()); + ai_assert( range.first != std::numeric_limits::infinity() ); + ai_assert( range.second != std::numeric_limits::infinity() ); return SampleDiscrete(out,range.first,range.second); } diff --git a/code/IFCGeometry.cpp b/code/IFCGeometry.cpp index f80fadff9..908f5e065 100644 --- a/code/IFCGeometry.cpp +++ b/code/IFCGeometry.cpp @@ -258,7 +258,7 @@ void ProcessRevolvedAreaSolid(const IfcRevolvedAreaSolid& solid, TempMesh& resul return; } - const unsigned int cnt_segments = std::max(2u,static_cast(16 * std::fabs(max_angle)/AI_MATH_HALF_PI_F)); + const unsigned int cnt_segments = std::max(2u,static_cast(conv.settings.cylindricalTessellation * std::fabs(max_angle)/AI_MATH_HALF_PI_F)); const IfcFloat delta = max_angle/cnt_segments; has_area = has_area && std::fabs(max_angle) < AI_MATH_TWO_PI_F*0.99; @@ -327,7 +327,7 @@ void ProcessSweptDiskSolid(const IfcSweptDiskSolid solid, TempMesh& result, Conv return; } - const unsigned int cnt_segments = 16; + const unsigned int cnt_segments = conv.settings.cylindricalTessellation; const IfcFloat deltaAngle = AI_MATH_TWO_PI/cnt_segments; const size_t samples = curve->EstimateSampleCount(solid.StartParam,solid.EndParam); diff --git a/code/IFCLoader.cpp b/code/IFCLoader.cpp index 1ef51be47..85382d467 100644 --- a/code/IFCLoader.cpp +++ b/code/IFCLoader.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -58,14 +59,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "IFCUtil.h" -#include "StreamReader.h" #include "MemoryIOWrapper.h" #include #include +#include namespace Assimp { - template<> const std::string LogFunctions::log_prefix = "IFC: "; + template<> const char* LogFunctions::Prefix() + { + static auto prefix = "IFC: "; + return prefix; + } } using namespace Assimp; @@ -108,7 +113,7 @@ static const aiImporterDesc desc = { 0, 0, 0, - "ifc ifczip" + "ifc ifczip stp" }; @@ -128,11 +133,9 @@ IFCImporter::~IFCImporter() bool IFCImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { const std::string& extension = GetExtension(pFile); - if (extension == "ifc" || extension == "ifczip") { + if (extension == "ifc" || extension == "ifczip" || extension == "stp" ) { return true; - } - - else if ((!extension.length() || checkSig) && pIOHandler) { + } else if ((!extension.length() || checkSig) && pIOHandler) { // note: this is the common identification for STEP-encoded files, so // it is only unambiguous as long as we don't support any further // file formats with STEP as their encoding. @@ -155,11 +158,10 @@ const aiImporterDesc* IFCImporter::GetInfo () const void IFCImporter::SetupProperties(const Importer* pImp) { settings.skipSpaceRepresentations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS,true); - settings.skipCurveRepresentations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_SKIP_CURVE_REPRESENTATIONS,true); settings.useCustomTriangulation = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_CUSTOM_TRIANGULATION,true); - - settings.conicSamplingAngle = 10.f; - settings.skipAnnotations = true; + settings.conicSamplingAngle = std::min(std::max((float) pImp->GetPropertyFloat(AI_CONFIG_IMPORT_IFC_SMOOTHING_ANGLE, AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE), 5.0f), 120.0f); + settings.cylindricalTessellation = std::min(std::max(pImp->GetPropertyInteger(AI_CONFIG_IMPORT_IFC_CYLINDRICAL_TESSELLATION, AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION), 3), 180); + settings.skipAnnotations = true; } @@ -884,6 +886,7 @@ void ProcessSpatialStructures(ConversionData& conv) } } + std::vector nodes; for(const STEP::LazyObject* lz : *range) { const IfcSpatialStructureElement* const prod = lz->ToPtr(); @@ -892,20 +895,19 @@ void ProcessSpatialStructures(ConversionData& conv) } IFCImporter::LogDebug("looking at spatial structure `" + (prod->Name ? prod->Name.Get() : "unnamed") + "`" + (prod->ObjectType? " which is of type " + prod->ObjectType.Get():"")); - // the primary site is referenced by an IFCRELAGGREGATES element which assigns it to the IFCPRODUCT + // the primary sites are referenced by an IFCRELAGGREGATES element which assigns them to the IFCPRODUCT const STEP::DB::RefMap& refs = conv.db.GetRefs(); - STEP::DB::RefMapRange range = refs.equal_range(conv.proj.GetID()); - for(;range.first != range.second; ++range.first) { - if(const IfcRelAggregates* const aggr = conv.db.GetObject((*range.first).second)->ToPtr()) { + STEP::DB::RefMapRange ref_range = refs.equal_range(conv.proj.GetID()); + for(; ref_range.first != ref_range.second; ++ref_range.first) { + if(const IfcRelAggregates* const aggr = conv.db.GetObject((*ref_range.first).second)->ToPtr()) { for(const IfcObjectDefinition& def : aggr->RelatedObjects) { // comparing pointer values is not sufficient, we would need to cast them to the same type first // as there is multiple inheritance in the game. if (def.GetID() == prod->GetID()) { IFCImporter::LogDebug("selecting this spatial structure as root structure"); - // got it, this is the primary site. - conv.out->mRootNode = ProcessSpatialStructure(NULL,*prod,conv,NULL); - return; + // got it, this is one primary site. + nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL)); } } @@ -913,19 +915,42 @@ void ProcessSpatialStructures(ConversionData& conv) } } + size_t nb_nodes = nodes.size(); - IFCImporter::LogWarn("failed to determine primary site element, taking the first IfcSite"); - for(const STEP::LazyObject* lz : *range) { - const IfcSpatialStructureElement* const prod = lz->ToPtr(); - if(!prod) { - continue; - } + if (nb_nodes == 0) { + IFCImporter::LogWarn("failed to determine primary site element, taking all the IfcSite"); + for (const STEP::LazyObject* lz : *range) { + const IfcSpatialStructureElement* const prod = lz->ToPtr(); + if (!prod) { + continue; + } - conv.out->mRootNode = ProcessSpatialStructure(NULL,*prod,conv,NULL); - return; - } + nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL)); + } - IFCImporter::ThrowException("failed to determine primary site element"); + nb_nodes = nodes.size(); + } + + if (nb_nodes == 1) { + conv.out->mRootNode = nodes[0]; + } + else if (nb_nodes > 1) { + conv.out->mRootNode = new aiNode("Root"); + conv.out->mRootNode->mParent = NULL; + conv.out->mRootNode->mNumChildren = static_cast(nb_nodes); + conv.out->mRootNode->mChildren = new aiNode*[conv.out->mRootNode->mNumChildren]; + + for (size_t i = 0; i < nb_nodes; ++i) { + aiNode* node = nodes[i]; + + node->mParent = conv.out->mRootNode; + + conv.out->mRootNode->mChildren[i] = node; + } + } + else { + IFCImporter::ThrowException("failed to determine primary site element"); + } } // ------------------------------------------------------------------------------------------------ diff --git a/code/IFCLoader.h b/code/IFCLoader.h index e301a329d..4cf116f8e 100644 --- a/code/IFCLoader.h +++ b/code/IFCLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -107,18 +108,18 @@ public: { Settings() : skipSpaceRepresentations() - , skipCurveRepresentations() , useCustomTriangulation() , skipAnnotations() , conicSamplingAngle(10.f) + , cylindricalTessellation(32) {} bool skipSpaceRepresentations; - bool skipCurveRepresentations; bool useCustomTriangulation; bool skipAnnotations; float conicSamplingAngle; + int cylindricalTessellation; }; diff --git a/code/IFCMaterial.cpp b/code/IFCMaterial.cpp index ae2fa3619..aa11c5c22 100644 --- a/code/IFCMaterial.cpp +++ b/code/IFCMaterial.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -42,19 +43,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of conversion routines to convert IFC materials to aiMaterial */ - - #ifndef ASSIMP_BUILD_NO_IFC_IMPORTER + #include "IFCUtil.h" #include #include namespace Assimp { - namespace IFC { +namespace IFC { // ------------------------------------------------------------------------------------------------ -int ConvertShadingMode(const std::string& name) -{ +static int ConvertShadingMode(const std::string& name) { if (name == "BLINN") { return aiShadingMode_Blinn; } @@ -69,8 +68,7 @@ int ConvertShadingMode(const std::string& name) } // ------------------------------------------------------------------------------------------------ -void FillMaterial(aiMaterial* mat,const IFC::IfcSurfaceStyle* surf,ConversionData& conv) -{ +static void FillMaterial(aiMaterial* mat,const IFC::IfcSurfaceStyle* surf,ConversionData& conv) { aiString name; name.Set((surf->Name? surf->Name.Get() : "IfcSurfaceStyle_Unnamed")); mat->AddProperty(&name,AI_MATKEY_NAME); @@ -134,8 +132,7 @@ void FillMaterial(aiMaterial* mat,const IFC::IfcSurfaceStyle* surf,ConversionDat } // ------------------------------------------------------------------------------------------------ -unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionData& conv, bool forceDefaultMat) -{ +unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionData& conv, bool forceDefaultMat) { STEP::DB::RefMapRange range = conv.db.GetRefs().equal_range(id); for(;range.first != range.second; ++range.first) { if(const IFC::IfcStyledItem* const styled = conv.db.GetObject((*range.first).second)->ToPtr()) { @@ -162,31 +159,33 @@ unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionDat unsigned int matindex = static_cast(conv.materials.size() - 1); conv.cached_materials[surf] = matindex; return matindex; + } + } } } } - } - } // no local material defined. If there's global one, use that instead - if( prevMatId != std::numeric_limits::max() ) + if ( prevMatId != std::numeric_limits::max() ) { return prevMatId; + } // we're still here - create an default material if required, or simply fail otherwise - if( !forceDefaultMat ) + if ( !forceDefaultMat ) { return std::numeric_limits::max(); + } aiString name; name.Set(""); // ConvertColorToString( color, name); // look if there's already a default material with this base color - for( size_t a = 0; a < conv.materials.size(); ++a ) - { + for( size_t a = 0; a < conv.materials.size(); ++a ) { aiString mname; conv.materials[a]->Get(AI_MATKEY_NAME, mname); - if( name == mname ) - return (unsigned int)a; + if ( name == mname ) { + return ( unsigned int )a; + } } // we're here, yet - no default material with suitable color available. Generate one @@ -203,4 +202,4 @@ unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionDat } // ! IFC } // ! Assimp -#endif +#endif // ASSIMP_BUILD_NO_IFC_IMPORTER diff --git a/code/IFCOpenings.cpp b/code/IFCOpenings.cpp index c2a7439ee..4d57cd473 100644 --- a/code/IFCOpenings.cpp +++ b/code/IFCOpenings.cpp @@ -901,13 +901,21 @@ size_t CloseWindows(ContourVector& contours, curmesh.verts.reserve(curmesh.verts.size() + (*it).contour.size() * 4); curmesh.vertcnt.reserve(curmesh.vertcnt.size() + (*it).contour.size()); + bool reverseCountourFaces = false; + // compare base poly normal and contour normal to detect if we need to reverse the face winding - IfcVector3 basePolyNormal = TempMesh::ComputePolygonNormal( curmesh.verts.data(), curmesh.vertcnt.front()); - std::vector worldSpaceContourVtx( it->contour.size()); - for( size_t a = 0; a < it->contour.size(); ++a ) - worldSpaceContourVtx[a] = minv * IfcVector3( it->contour[a].x, it->contour[a].y, 0.0); - IfcVector3 contourNormal = TempMesh::ComputePolygonNormal( worldSpaceContourVtx.data(), worldSpaceContourVtx.size()); - bool reverseCountourFaces = (contourNormal * basePolyNormal) > 0.0; + if(curmesh.vertcnt.size() > 0) { + IfcVector3 basePolyNormal = TempMesh::ComputePolygonNormal(curmesh.verts.data(), curmesh.vertcnt.front()); + + std::vector worldSpaceContourVtx(it->contour.size()); + + for(size_t a = 0; a < it->contour.size(); ++a) + worldSpaceContourVtx[a] = minv * IfcVector3(it->contour[a].x, it->contour[a].y, 0.0); + + IfcVector3 contourNormal = TempMesh::ComputePolygonNormal(worldSpaceContourVtx.data(), worldSpaceContourVtx.size()); + + reverseCountourFaces = (contourNormal * basePolyNormal) > 0.0; + } // XXX this algorithm is really a bit inefficient - both in terms // of constant factor and of asymptotic runtime. @@ -1484,14 +1492,14 @@ bool TryAddOpenings_Poly2Tri(const std::vector& openings,const std: vmax -= vmin; // If this happens then the projection must have been wrong. - assert(vmax.Length()); + ai_assert(vmax.Length()); ClipperLib::ExPolygons clipped; ClipperLib::Polygons holes_union; IfcVector3 wall_extrusion; - bool do_connections = false, first = true; + bool first = true; try { @@ -1519,7 +1527,6 @@ bool TryAddOpenings_Poly2Tri(const std::vector& openings,const std: if (first) { first = false; if (dot > 0.f) { - do_connections = true; wall_extrusion = t.extrusionDir; if (is_extruded_side) { wall_extrusion = - wall_extrusion; @@ -1599,44 +1606,6 @@ bool TryAddOpenings_Poly2Tri(const std::vector& openings,const std: old_verts.swap(curmesh.verts); old_vertcnt.swap(curmesh.vertcnt); - - // add connection geometry to close the adjacent 'holes' for the openings - // this should only be done from one side of the wall or the polygons - // would be emitted twice. - if (false && do_connections) { - - std::vector tmpvec; - for(ClipperLib::Polygon& opening : holes_union) { - - assert(ClipperLib::Orientation(opening)); - - tmpvec.clear(); - - for(ClipperLib::IntPoint& point : opening) { - - tmpvec.push_back( minv * IfcVector3( - vmin.x + from_int64(point.X) * vmax.x, - vmin.y + from_int64(point.Y) * vmax.y, - coord)); - } - - for(size_t i = 0, size = tmpvec.size(); i < size; ++i) { - const size_t next = (i+1)%size; - - curmesh.vertcnt.push_back(4); - - const IfcVector3& in_world = tmpvec[i]; - const IfcVector3& next_world = tmpvec[next]; - - // Assumptions: no 'partial' openings, wall thickness roughly the same across the wall - curmesh.verts.push_back(in_world); - curmesh.verts.push_back(in_world+wall_extrusion); - curmesh.verts.push_back(next_world+wall_extrusion); - curmesh.verts.push_back(next_world); - } - } - } - std::vector< std::vector > contours; for(ClipperLib::ExPolygon& clip : clipped) { @@ -1697,7 +1666,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector& openings,const std: static_cast( tri->GetPoint(i)->y ) ); - assert(v.x <= 1.0 && v.x >= 0.0 && v.y <= 1.0 && v.y >= 0.0); + ai_assert(v.x <= 1.0 && v.x >= 0.0 && v.y <= 1.0 && v.y >= 0.0); const IfcVector3 v3 = minv * IfcVector3(vmin.x + v.x * vmax.x, vmin.y + v.y * vmax.y,coord) ; curmesh.verts.push_back(v3); diff --git a/code/IFCProfile.cpp b/code/IFCProfile.cpp index a84f98f58..595159a6b 100644 --- a/code/IFCProfile.cpp +++ b/code/IFCProfile.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -101,7 +102,7 @@ void ProcessOpenProfile(const IfcArbitraryOpenProfileDef& def, TempMesh& meshout } // ------------------------------------------------------------------------------------------------ -void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& /*conv*/) +void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& conv) { if(const IfcRectangleProfileDef* const cprofile = def.ToPtr()) { const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f; @@ -117,7 +118,7 @@ void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& if(def.ToPtr()) { // TODO } - const size_t segments = 32; + const size_t segments = conv.settings.cylindricalTessellation; const IfcFloat delta = AI_MATH_TWO_PI_F/segments, radius = circle->Radius; meshout.verts.reserve(segments); @@ -127,7 +128,7 @@ void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout.verts.push_back( IfcVector3( std::cos(angle)*radius, std::sin(angle)*radius, 0.f )); } - meshout.vertcnt.push_back(segments); + meshout.vertcnt.push_back(static_cast(segments)); } else if( const IfcIShapeProfileDef* const ishape = def.ToPtr()) { // construct simplified IBeam shape diff --git a/code/IFCReaderGen1.cpp b/code/IFCReaderGen1.cpp index d334e8322..bd526d454 100644 --- a/code/IFCReaderGen1.cpp +++ b/code/IFCReaderGen1.cpp @@ -1045,7 +1045,7 @@ void IFC::GetSchema(EXPRESS::ConversionSchema& out) namespace STEP { // ----------------------------------------------------------------------------------------------------------- -template <> size_t GenericFill(const STEP::DB& db, const LIST& params, NotImplemented* in) +template <> size_t GenericFill(const STEP::DB& /*db*/, const LIST& /*params*/, NotImplemented* /*in*/) { return 0; } @@ -1253,7 +1253,7 @@ template <> size_t GenericFill(const DB& db, const LIST& return base; } // ----------------------------------------------------------------------------------------------------------- -template <> size_t GenericFill(const DB& db, const LIST& params, IfcRepresentationItem* in) +template <> size_t GenericFill(const DB& /*db*/, const LIST& /*params*/, IfcRepresentationItem* /*in*/) { size_t base = 0; return base; @@ -1715,7 +1715,7 @@ template <> size_t GenericFill(const DB& db, const LIST& params, I return base; } // ----------------------------------------------------------------------------------------------------------- -template <> size_t GenericFill(const DB& db, const LIST& params, IfcObjectPlacement* in) +template <> size_t GenericFill(const DB& /*db*/, const LIST& /*params*/, IfcObjectPlacement* /*in*/) { size_t base = 0; return base; diff --git a/code/IFCUtil.cpp b/code/IFCUtil.cpp index 7caebbcd4..f5bd56a00 100644 --- a/code/IFCUtil.cpp +++ b/code/IFCUtil.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -49,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "IFCUtil.h" #include "PolyTools.h" #include "ProcessHelper.h" -#include "Defines.h" +#include namespace Assimp { namespace IFC { diff --git a/code/IFCUtil.h b/code/IFCUtil.h index 43d20a434..f90f421d6 100644 --- a/code/IFCUtil.h +++ b/code/IFCUtil.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/IOStreamBuffer.h b/code/IOStreamBuffer.h index 8fb58e548..d7528de7e 100644 --- a/code/IOStreamBuffer.h +++ b/code/IOStreamBuffer.h @@ -4,7 +4,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -44,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "ParsingUtils.h" -#include +#include namespace Assimp { @@ -70,8 +71,8 @@ public: /// @return true if successful. bool close(); - /// @brief Returns the filesize. - /// @return The filesize. + /// @brief Returns the file-size. + /// @return The file-size. size_t size() const; /// @brief Returns the cache size. @@ -97,7 +98,17 @@ public: /// @brief Will read the next line. /// @param buffer The buffer for the next line. /// @return true if successful. - bool getNextLine( std::vector &buffer ); + bool getNextDataLine( std::vector &buffer, T continuationToken ); + + /// @brief Will read the next line ascii or binary end line char. + /// @param buffer The buffer for the next line. + /// @return true if successful. + bool getNextLine(std::vector &buffer); + + /// @brief Will read the next block. + /// @param buffer The buffer for the next block. + /// @return true if successful. + bool getNextBlock( std::vector &buffer ); private: IOStream *m_stream; @@ -228,15 +239,35 @@ size_t IOStreamBuffer::getFilePos() const { template inline -bool IOStreamBuffer::getNextLine( std::vector &buffer ) { +bool IOStreamBuffer::getNextDataLine( std::vector &buffer, T continuationToken ) { buffer.resize( m_cacheSize ); if ( m_cachePos == m_cacheSize || 0 == m_filePos ) { if ( !readNextBlock() ) { return false; } } + + bool continuationFound( false ), endOfDataLine( false ); size_t i = 0; - while ( !IsLineEnd( m_cache[ m_cachePos ] ) ) { + while ( !endOfDataLine ) { + if ( continuationToken == m_cache[ m_cachePos ] ) { + continuationFound = true; + ++m_cachePos; + } + if ( IsLineEnd( m_cache[ m_cachePos ] ) ) { + if ( !continuationFound ) { + // the end of the data line + break; + } else { + // skip line end + while ( m_cache[m_cachePos] != '\n') { + ++m_cachePos; + } + ++m_cachePos; + continuationFound = false; + } + } + buffer[ i ] = m_cache[ m_cachePos ]; m_cachePos++; i++; @@ -246,10 +277,74 @@ bool IOStreamBuffer::getNextLine( std::vector &buffer ) { } } } + buffer[ i ] = '\n'; m_cachePos++; return true; } +static +inline +bool isEndOfCache( size_t pos, size_t cacheSize ) { + return ( pos == cacheSize ); +} + +template +inline +bool IOStreamBuffer::getNextLine(std::vector &buffer) { + buffer.resize(m_cacheSize); + if ( isEndOfCache( m_cachePos, m_cacheSize ) || 0 == m_filePos) { + if (!readNextBlock()) { + return false; + } + } + + if (IsLineEnd(m_cache[m_cachePos])) { + // skip line end + while (m_cache[m_cachePos] != '\n') { + ++m_cachePos; + } + ++m_cachePos; + if ( isEndOfCache( m_cachePos, m_cacheSize ) ) { + if ( !readNextBlock() ) { + return false; + } + } + } + + size_t i = 0; + while (!IsLineEnd(m_cache[ m_cachePos ])) { + buffer[i] = m_cache[ m_cachePos ]; + m_cachePos++; + i++; + if (m_cachePos >= m_cacheSize) { + if (!readNextBlock()) { + return false; + } + } + } + buffer[i] = '\n'; + m_cachePos++; + + return true; +} + +template +inline +bool IOStreamBuffer::getNextBlock( std::vector &buffer) { + //just return the last blockvalue if getNextLine was used before + if ( m_cachePos != 0) { + buffer = std::vector(m_cache.begin() + m_cachePos, m_cache.end()); + m_cachePos = 0; + } + else { + if ( !readNextBlock() ) + return false; + + buffer = std::vector(m_cache.begin(), m_cache.end()); + } + return true; +} + } // !ns Assimp diff --git a/code/IRRLoader.cpp b/code/IRRLoader.cpp index 7145f9b66..c29d5b072 100644 --- a/code/IRRLoader.cpp +++ b/code/IRRLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -52,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "fast_atof.h" #include "GenericProperty.h" -#include "SceneCombiner.h" +#include #include "StandardShapes.h" #include "Importer.h" @@ -65,7 +66,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include - +#include using namespace Assimp; using namespace irr; @@ -393,7 +394,7 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector #include "Importer.h" #include "StringUtils.h" #include diff --git a/code/IRRMeshLoader.cpp b/code/IRRMeshLoader.cpp index 853ead15f..a63a2a134 100644 --- a/code/IRRMeshLoader.cpp +++ b/code/IRRMeshLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -54,9 +55,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include "Macros.h" - using namespace Assimp; using namespace irr; using namespace irr::io; diff --git a/code/IRRMeshLoader.h b/code/IRRMeshLoader.h index 6c208224c..312dbbfe0 100644 --- a/code/IRRMeshLoader.h +++ b/code/IRRMeshLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/IRRShared.cpp b/code/IRRShared.cpp index e38ad1378..bfe408629 100644 --- a/code/IRRShared.cpp +++ b/code/IRRShared.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/Importer.cpp b/code/Importer.cpp index d60dfb6b0..c6c6f0edd 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -45,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include // ------------------------------------------------------------------------------------------------ /* Uncomment this line to prevent Assimp from catching unknown exceptions. @@ -65,8 +67,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BaseImporter.h" #include "BaseProcess.h" -#include "DefaultIOStream.h" -#include "DefaultIOSystem.h" #include "DefaultProgressHandler.h" #include "GenericProperty.h" #include "ProcessHelper.h" @@ -81,6 +81,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include +#include + #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS # include "ValidateDataStructure.h" #endif @@ -271,10 +274,6 @@ aiReturn Importer::UnregisterLoader(BaseImporter* pImp) if (it != pimpl->mImporter.end()) { pimpl->mImporter.erase(it); - - std::set st; - pImp->GetExtensionList(st); - DefaultLogger::get()->info("Unregistering custom importer: "); return AI_SUCCESS; } @@ -828,8 +827,8 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) pimpl->mProgressHandler->UpdatePostProcess( static_cast(pimpl->mPostProcessingSteps.size()), static_cast(pimpl->mPostProcessingSteps.size()) ); // update private scene flags - if( pimpl->mScene ) - ScenePriv(pimpl->mScene)->mPPStepsApplied |= pFlags; + if( pimpl->mScene ) + ScenePriv(pimpl->mScene)->mPPStepsApplied |= pFlags; // clear any data allocated by post-process steps pimpl->mPPShared->Clean(); diff --git a/code/Importer.h b/code/Importer.h index a0df1a6c1..e0fb57f5b 100644 --- a/code/Importer.h +++ b/code/Importer.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -44,8 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_IMPORTER_H #include -#include #include +#include #include struct aiScene; diff --git a/code/ImporterRegistry.cpp b/code/ImporterRegistry.cpp index 95a1867e0..b4d2c3dcf 100644 --- a/code/ImporterRegistry.cpp +++ b/code/ImporterRegistry.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -46,6 +47,9 @@ directly (unless you are adding new loaders), instead use the corresponding preprocessor flag to selectively disable formats. */ +#include +#include "BaseImporter.h" + // ------------------------------------------------------------------------------------------------ // Importers // (include_new_importers_here) @@ -178,6 +182,7 @@ corresponding preprocessor flag to selectively disable formats. #endif #ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER # include "glTFImporter.h" +# include "glTF2Importer.h" #endif #ifndef ASSIMP_BUILD_NO_C4D_IMPORTER # include "C4DImporter.h" @@ -188,6 +193,9 @@ corresponding preprocessor flag to selectively disable formats. #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER # include "X3DImporter.hpp" #endif +#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER +# include "MMDImporter.h" +#endif namespace Assimp { @@ -224,7 +232,9 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out) out.push_back( new MDLImporter()); #endif #if (!defined ASSIMP_BUILD_NO_ASE_IMPORTER) + #if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER) out.push_back( new ASEImporter()); +# endif #endif #if (!defined ASSIMP_BUILD_NO_HMP_IMPORTER) out.push_back( new HMPImporter()); @@ -327,16 +337,20 @@ void GetImporterInstanceList(std::vector< BaseImporter* >& out) #endif #if ( !defined ASSIMP_BUILD_NO_GLTF_IMPORTER ) out.push_back( new glTFImporter() ); + out.push_back( new glTF2Importer() ); #endif #if ( !defined ASSIMP_BUILD_NO_C4D_IMPORTER ) out.push_back( new C4DImporter() ); #endif #if ( !defined ASSIMP_BUILD_NO_3MF_IMPORTER ) - out.push_back(new D3MFImporter() ); + out.push_back( new D3MFImporter() ); #endif #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER out.push_back( new X3DImporter() ); #endif +#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER + out.push_back( new MMDImporter() ); +#endif } /** will delete all registered importers. */ diff --git a/code/ImproveCacheLocality.cpp b/code/ImproveCacheLocality.cpp index 9fd76508b..2ac32aa84 100644 --- a/code/ImproveCacheLocality.cpp +++ b/code/ImproveCacheLocality.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -222,6 +223,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh iMaxRefTris = std::max(iMaxRefTris,*piCur); } } + ai_assert(iMaxRefTris > 0); unsigned int* piCandidates = new unsigned int[iMaxRefTris*3]; unsigned int iCacheMisses = 0; diff --git a/code/ImproveCacheLocality.h b/code/ImproveCacheLocality.h index d43f37f50..d91388c41 100644 --- a/code/ImproveCacheLocality.h +++ b/code/ImproveCacheLocality.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/JoinVerticesProcess.cpp b/code/JoinVerticesProcess.cpp index 9cd34e1d0..17b0ab07f 100644 --- a/code/JoinVerticesProcess.cpp +++ b/code/JoinVerticesProcess.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/JoinVerticesProcess.h b/code/JoinVerticesProcess.h index b1a9aa910..a3204782a 100644 --- a/code/JoinVerticesProcess.h +++ b/code/JoinVerticesProcess.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/LWOAnimation.cpp b/code/LWOAnimation.cpp index 10bc54b16..4b5338f7a 100644 --- a/code/LWOAnimation.cpp +++ b/code/LWOAnimation.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -53,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // internal headers #include "LWOFileData.h" +#include using namespace Assimp; using namespace Assimp::LWO; @@ -162,7 +164,7 @@ void AnimResolver::UpdateAnimRangeSetup() { const double start_time = delta - std::fmod(my_first-first,delta); std::vector::iterator n = std::find_if((*it).keys.begin(),(*it).keys.end(), - std::bind1st(std::greater(),start_time)),m; + [start_time](double t) { return start_time > t; }),m; size_t ofs = 0; if (n != (*it).keys.end()) { @@ -444,8 +446,6 @@ void AnimResolver::GetKeys(std::vector& out, // Iterate through all three arrays at once - it's tricky, but // rather interesting to implement. - double lasttime = std::min(envl_x->keys[0].time,std::min(envl_y->keys[0].time,envl_z->keys[0].time)); - cur_x = envl_x->keys.begin(); cur_y = envl_y->keys.begin(); cur_z = envl_z->keys.begin(); @@ -501,7 +501,7 @@ void AnimResolver::GetKeys(std::vector& out, InterpolateTrack(out,fill,(end_y ? (*cur_x) : (*cur_y)).time); } } - lasttime = fill.mTime; + double lasttime = fill.mTime; out.push_back(fill); if (lasttime >= (*cur_x).time) { diff --git a/code/LWOAnimation.h b/code/LWOAnimation.h index 257abecdd..f0c578ad9 100644 --- a/code/LWOAnimation.h +++ b/code/LWOAnimation.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -47,11 +48,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_LWO_ANIMATION_INCLUDED #define AI_LWO_ANIMATION_INCLUDED -#include +// #include #include struct aiNodeAnim; +struct aiVectorKey; namespace Assimp { namespace LWO { @@ -165,7 +167,6 @@ struct Envelope //! Keyframes for this envelope std::vector keys; - // temporary data for AnimResolver size_t old_first,old_last; }; @@ -197,8 +198,7 @@ public: * @param Output tick rate, per second * @note The input envelopes are possibly modified. */ - AnimResolver(std::list& envelopes, - double tick); + AnimResolver(std::list& envelopes, double tick); public: diff --git a/code/LWOBLoader.cpp b/code/LWOBLoader.cpp index 639675294..6a07f81a7 100644 --- a/code/LWOBLoader.cpp +++ b/code/LWOBLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/LWOFileData.h b/code/LWOFileData.h index d67cf7ec8..7fa9a216d 100644 --- a/code/LWOFileData.h +++ b/code/LWOFileData.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/LWOLoader.cpp b/code/LWOLoader.cpp index 4a45efb91..5ec07800d 100644 --- a/code/LWOLoader.cpp +++ b/code/LWOLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -54,10 +55,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ProcessHelper.h" #include "ConvertToLHProcess.h" #include +#include #include #include #include - +#include using namespace Assimp; @@ -65,7 +67,7 @@ static const aiImporterDesc desc = { "LightWave/Modo Object Importer", "", "", - "http://www.newtek.com/lightwave.html\nhttp://www.luxology.com/modo/", + "https://www.lightwave3d.com/lightwave_sdk/", aiImporterFlags_SupportTextFlavour, 0, 0, diff --git a/code/LWOLoader.h b/code/LWOLoader.h index 09d66cf24..b92e5aab4 100644 --- a/code/LWOLoader.h +++ b/code/LWOLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -49,6 +50,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "LWOFileData.h" #include "BaseImporter.h" +#include + struct aiTexture; struct aiNode; struct aiMaterial; diff --git a/code/LWOMaterial.cpp b/code/LWOMaterial.cpp index 555cc8787..621a2edc6 100644 --- a/code/LWOMaterial.cpp +++ b/code/LWOMaterial.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -454,7 +455,7 @@ void LWOImporter::FindUVChannels(LWO::Surface& surf, ++extra; out[next++] = i; } - // B�h ... seems not to be used at all. Push to end if enough space is available. + // Bah ... seems not to be used at all. Push to end if enough space is available. else { out[extra++] = i; ++num_extra; @@ -482,7 +483,7 @@ void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorte const LWO::VColorChannel& vc = layer.mVColorChannels[i]; if (surf.mVCMap == vc.name) { - // The vertex color map is explicitely requested by the surface so we need to take special care of it + // The vertex color map is explicitly requested by the surface so we need to take special care of it for (unsigned int a = 0; a < std::min(next,AI_MAX_NUMBER_OF_COLOR_SETS-1u); ++a) { out[a+1] = out[a]; } diff --git a/code/LWSLoader.cpp b/code/LWSLoader.cpp index 6ca3cf589..2017cdb9d 100644 --- a/code/LWSLoader.cpp +++ b/code/LWSLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -50,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ParsingUtils.h" #include "fast_atof.h" -#include "SceneCombiner.h" +#include #include "GenericProperty.h" #include "SkeletonMeshBuilder.h" #include "ConvertToLHProcess.h" @@ -58,9 +59,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include - using namespace Assimp; static const aiImporterDesc desc = { @@ -470,7 +471,7 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector 3 && in[1] == ':'&& in[2] != '\\' && in[2] != '/') { diff --git a/code/LWSLoader.h b/code/LWSLoader.h index 9547b67bb..e36d27b77 100644 --- a/code/LWSLoader.h +++ b/code/LWSLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -45,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_LWSLOADER_H_INCLUDED #include "LWOFileData.h" -#include "SceneCombiner.h" +#include #include "BaseImporter.h" struct aiImporterDesc; diff --git a/code/LimitBoneWeightsProcess.cpp b/code/LimitBoneWeightsProcess.cpp index e35fe1462..0bb4a4be3 100644 --- a/code/LimitBoneWeightsProcess.cpp +++ b/code/LimitBoneWeightsProcess.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/LimitBoneWeightsProcess.h b/code/LimitBoneWeightsProcess.h index f6907cf26..3826dbe58 100644 --- a/code/LimitBoneWeightsProcess.h +++ b/code/LimitBoneWeightsProcess.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/LineSplitter.h b/code/LineSplitter.h index 0fa47380e..003b42d52 100644 --- a/code/LineSplitter.h +++ b/code/LineSplitter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -68,27 +69,23 @@ for(LineSplitter splitter(stream);splitter;++splitter) { std::cout << "Current line is: " << splitter.get_index() << std::endl; } -@endcode */ +@endcode +*/ // ------------------------------------------------------------------------------------------------ -class LineSplitter -{ +class LineSplitter { public: - typedef size_t line_idx; -public: - // ----------------------------------------- /** construct from existing stream reader note: trim is *always* assumed true if skyp_empty_lines==true */ LineSplitter(StreamReaderLE& stream, bool skip_empty_lines = true, bool trim = true) - : idx( 0 ) - , stream(stream) - , swallow() - , skip_empty_lines(skip_empty_lines) - , trim(trim) - { + : idx( 0 ) + , stream(stream) + , swallow() + , skip_empty_lines(skip_empty_lines) + , trim(trim) { cur.reserve(1024); operator++(); diff --git a/code/LogAux.h b/code/LogAux.h index f754903c6..f2bc14d54 100644 --- a/code/LogAux.h +++ b/code/LogAux.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -59,34 +60,34 @@ public: // ------------------------------------------------------------------------------------------------ static void ThrowException(const std::string& msg) { - throw DeadlyImportError(log_prefix+msg); + throw DeadlyImportError(Prefix()+msg); } // ------------------------------------------------------------------------------------------------ static void LogWarn(const Formatter::format& message) { if (!DefaultLogger::isNullLogger()) { - DefaultLogger::get()->warn(log_prefix+(std::string)message); + DefaultLogger::get()->warn(Prefix()+(std::string)message); } } // ------------------------------------------------------------------------------------------------ static void LogError(const Formatter::format& message) { if (!DefaultLogger::isNullLogger()) { - DefaultLogger::get()->error(log_prefix+(std::string)message); + DefaultLogger::get()->error(Prefix()+(std::string)message); } } // ------------------------------------------------------------------------------------------------ static void LogInfo(const Formatter::format& message) { if (!DefaultLogger::isNullLogger()) { - DefaultLogger::get()->info(log_prefix+(std::string)message); + DefaultLogger::get()->info(Prefix()+(std::string)message); } } // ------------------------------------------------------------------------------------------------ static void LogDebug(const Formatter::format& message) { if (!DefaultLogger::isNullLogger()) { - DefaultLogger::get()->debug(log_prefix+(std::string)message); + DefaultLogger::get()->debug(Prefix()+(std::string)message); } } @@ -124,8 +125,7 @@ public: #endif private: - - static const std::string log_prefix; + static const char* Prefix(); }; diff --git a/code/MD2FileData.h b/code/MD2FileData.h index f7a494335..f65193264 100644 --- a/code/MD2FileData.h +++ b/code/MD2FileData.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -46,8 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_MD2FILEHELPER_H_INC #include -#include -#include #include #include diff --git a/code/MD2Loader.cpp b/code/MD2Loader.cpp index b4c124774..f0a5432bf 100644 --- a/code/MD2Loader.cpp +++ b/code/MD2Loader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -50,6 +51,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include + #include using namespace Assimp; @@ -271,11 +274,9 @@ void MD2Importer::InternReadFile( const std::string& pFile, aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh(); pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - // navigate to the begin of the frame data - BE_NCONST MD2::Frame* pcFrame = (BE_NCONST MD2::Frame*) ((uint8_t*) - m_pcHeader + m_pcHeader->offsetFrames); - - pcFrame += configFrameID; + // navigate to the begin of the current frame data + BE_NCONST MD2::Frame* pcFrame = (BE_NCONST MD2::Frame*) ((uint8_t*) + m_pcHeader + m_pcHeader->offsetFrames + (m_pcHeader->frameSize * configFrameID)); // navigate to the begin of the triangle data MD2::Triangle* pcTriangles = (MD2::Triangle*) ((uint8_t*) diff --git a/code/MD2Loader.h b/code/MD2Loader.h index 126c16359..a7566dc64 100644 --- a/code/MD2Loader.h +++ b/code/MD2Loader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/MD2NormalTable.h b/code/MD2NormalTable.h index 5b1344bd6..98fbc1d7a 100644 --- a/code/MD2NormalTable.h +++ b/code/MD2NormalTable.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/MD3FileData.h b/code/MD3FileData.h index 3a59d0d1d..19740c30e 100644 --- a/code/MD3FileData.h +++ b/code/MD3FileData.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -141,14 +142,14 @@ struct Frame //! name of frame char name[ AI_MD3_MAXFRAME ]; -} PACK_STRUCT; +} /* PACK_STRUCT */; // ------------------------------------------------------------------------------- -/** @brief Data structure for the tag header +/** + * @brief Data structure for the tag header */ -struct Tag -{ +struct Tag { //! name of the tag char NAME[ AI_MD3_MAXQPATH ]; @@ -156,14 +157,13 @@ struct Tag aiVector3D origin; ai_real orientation[3][3]; -} PACK_STRUCT; +} /* PACK_STRUCT */; // ------------------------------------------------------------------------------- /** @brief Data structure for the surface header */ -struct Surface -{ +struct Surface { //! magic number int32_t IDENT; @@ -185,7 +185,6 @@ struct Surface //! number of triangles in the surface uint32_t NUM_TRIANGLES; - //! offset to the triangle data uint32_t OFS_TRIANGLES; @@ -200,19 +199,18 @@ struct Surface //! offset to the end of the Surface object int32_t OFS_END; -} PACK_STRUCT; +} /*PACK_STRUCT*/; // ------------------------------------------------------------------------------- /** @brief Data structure for a shader defined in there */ -struct Shader -{ +struct Shader { //! filename of the shader char NAME[ AI_MD3_MAXQPATH ]; //! index of the shader uint32_t SHADER_INDEX; -} PACK_STRUCT; +} /*PACK_STRUCT*/; // ------------------------------------------------------------------------------- @@ -222,7 +220,7 @@ struct Triangle { //! triangle indices uint32_t INDEXES[3]; -} PACK_STRUCT; +} /*PACK_STRUCT*/; // ------------------------------------------------------------------------------- @@ -232,7 +230,7 @@ struct TexCoord { //! UV coordinates ai_real U,V; -} PACK_STRUCT; +} /*PACK_STRUCT*/; // ------------------------------------------------------------------------------- @@ -245,7 +243,7 @@ struct Vertex //! encoded normal vector uint16_t NORMAL; -} PACK_STRUCT; +} /*PACK_STRUCT*/; #include "./../include/assimp/Compiler/poppack1.h" diff --git a/code/MD3Loader.cpp b/code/MD3Loader.cpp index 0736e84b9..11a6e56dd 100644 --- a/code/MD3Loader.cpp +++ b/code/MD3Loader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -52,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_MD3_IMPORTER #include "MD3Loader.h" -#include "SceneCombiner.h" +#include #include "GenericProperty.h" #include "RemoveComments.h" #include "ParsingUtils.h" @@ -62,10 +63,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include - - using namespace Assimp; static const aiImporterDesc desc = { @@ -1018,11 +1018,11 @@ void MD3Importer::InternReadFile( const std::string& pFile, // Convert the normal vector to uncompressed float3 format aiVector3D& nor = pcMesh->mNormals[iCurrent]; - LatLngNormalToVec3(pcVertices[pcTriangles->INDEXES[c]].NORMAL,(ai_real*)&nor); + LatLngNormalToVec3(pcVertices[index].NORMAL,(ai_real*)&nor); // Read texture coordinates - pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[ pcTriangles->INDEXES[c]].U; - pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-pcUVs[ pcTriangles->INDEXES[c]].V; + pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[index].U; + pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-pcUVs[index].V; } // Flip face order if necessary if (!shader || shader->cull == Q3Shader::CULL_CW) { diff --git a/code/MD3Loader.h b/code/MD3Loader.h index 6b8143a97..ff5b56a52 100644 --- a/code/MD3Loader.h +++ b/code/MD3Loader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/MD5Loader.cpp b/code/MD5Loader.cpp index 0703e92de..172c98a30 100644 --- a/code/MD5Loader.cpp +++ b/code/MD5Loader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -56,6 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include using namespace Assimp; diff --git a/code/MD5Loader.h b/code/MD5Loader.h index a68655f55..13a01451d 100644 --- a/code/MD5Loader.h +++ b/code/MD5Loader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/MD5Parser.cpp b/code/MD5Parser.cpp index 9379deab1..8076e5bc4 100644 --- a/code/MD5Parser.cpp +++ b/code/MD5Parser.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/MD5Parser.h b/code/MD5Parser.h index 78ade8430..bafcaf962 100644 --- a/code/MD5Parser.h +++ b/code/MD5Parser.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/MDCFileData.h b/code/MDCFileData.h index c98828c28..9ea3d8f5e 100644 --- a/code/MDCFileData.h +++ b/code/MDCFileData.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -156,7 +157,7 @@ struct Frame //! Name of the frame char name [ 16 ] ; -} PACK_STRUCT; +} /*PACK_STRUCT*/; // --------------------------------------------------------------------------- /** \brief Data structure for a MDC triangle diff --git a/code/MDCLoader.cpp b/code/MDCLoader.cpp index d97215864..21aca53ff 100644 --- a/code/MDCLoader.cpp +++ b/code/MDCLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -52,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include diff --git a/code/MDCLoader.h b/code/MDCLoader.h index fcfbc642d..5f3b365fd 100644 --- a/code/MDCLoader.h +++ b/code/MDCLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/MDLDefaultColorMap.h b/code/MDLDefaultColorMap.h index 6db696af0..800c717c5 100644 --- a/code/MDLDefaultColorMap.h +++ b/code/MDLDefaultColorMap.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/MDLFileData.h b/code/MDLFileData.h index 536bf082a..3ef58ca5a 100644 --- a/code/MDLFileData.h +++ b/code/MDLFileData.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -52,10 +53,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_MDLFILEHELPER_H_INC #define AI_MDLFILEHELPER_H_INC +#include +#include +#include #include "ByteSwapper.h" -#include "./../include/assimp/anim.h" -#include "./../include/assimp/mesh.h" -#include "./../include/assimp/Compiler/pushpack1.h" #include #include @@ -89,7 +90,6 @@ namespace MDL { #define AI_MDL_MAGIC_NUMBER_BE_GS7 AI_MAKE_MAGIC("MDL7") #define AI_MDL_MAGIC_NUMBER_LE_GS7 AI_MAKE_MAGIC("7LDM") - // common limitations for Quake1 meshes. The loader does not check them, // (however it warns) but models should not exceed these limits. #if (!defined AI_MDL_VERSION) @@ -118,8 +118,7 @@ namespace MDL { /** \struct Header * \brief Data structure for the MDL main header */ -struct Header -{ +struct Header { //! magic number: "IDPO" uint32_t ident; @@ -127,16 +126,16 @@ struct Header int32_t version; //! scale factors for each axis - aiVector3D scale; + ai_real scale[3]; //! translation factors for each axis - aiVector3D translate; + ai_real translate[3]; //! bounding radius of the mesh float boundingradius; //! Position of the viewer's exe. Ignored - aiVector3D vEyePos; + ai_real vEyePos[3]; //! Number of textures int32_t num_skins; @@ -172,8 +171,7 @@ struct Header /** \struct Header_MDL7 * \brief Data structure for the MDL 7 main header */ -struct Header_MDL7 -{ +struct Header_MDL7 { //! magic number: "MDL7" char ident[4]; @@ -232,8 +230,7 @@ struct Header_MDL7 /** \struct Bone_MDL7 * \brief Data structure for a bone in a MDL7 file */ -struct Bone_MDL7 -{ +struct Bone_MDL7 { //! Index of the parent bone of *this* bone. 0xffff means: //! "hey, I have no parent, I'm an orphan" uint16_t parent_index; @@ -267,8 +264,7 @@ struct Bone_MDL7 /** \struct Group_MDL7 * \brief Group in a MDL7 file */ -struct Group_MDL7 -{ +struct Group_MDL7 { //! = '1' -> triangle based Mesh unsigned char typ; @@ -309,8 +305,7 @@ struct Group_MDL7 /** \struct Deformer_MDL7 * \brief Deformer in a MDL7 file */ -struct Deformer_MDL7 -{ +struct Deformer_MDL7 { int8_t deformer_version; // 0 int8_t deformer_typ; // 0 - bones int8_t _unused_[2]; @@ -324,27 +319,23 @@ struct Deformer_MDL7 /** \struct DeformerElement_MDL7 * \brief Deformer element in a MDL7 file */ -struct DeformerElement_MDL7 -{ +struct DeformerElement_MDL7 { //! bei deformer_typ==0 (==bones) element_index == bone index int32_t element_index; char element_name[AI_MDL7_MAX_BONENAMESIZE]; int32_t weights; } PACK_STRUCT; - // ------------------------------------------------------------------------------------- /** \struct DeformerWeight_MDL7 * \brief Deformer weight in a MDL7 file */ -struct DeformerWeight_MDL7 -{ +struct DeformerWeight_MDL7 { //! for deformer_typ==0 (==bones) index == vertex index int32_t index; float weight; } PACK_STRUCT; - // don't know why this was in the original headers ... typedef int32_t MD7_MATERIAL_ASCDEFSIZE; @@ -352,8 +343,7 @@ typedef int32_t MD7_MATERIAL_ASCDEFSIZE; /** \struct ColorValue_MDL7 * \brief Data structure for a color value in a MDL7 file */ -struct ColorValue_MDL7 -{ +struct ColorValue_MDL7 { float r,g,b,a; } PACK_STRUCT; @@ -361,8 +351,7 @@ struct ColorValue_MDL7 /** \struct Material_MDL7 * \brief Data structure for a Material in a MDL7 file */ -struct Material_MDL7 -{ +struct Material_MDL7 { //! Diffuse base color of the material ColorValue_MDL7 Diffuse; @@ -379,13 +368,11 @@ struct Material_MDL7 float Power; } PACK_STRUCT; - // ------------------------------------------------------------------------------------- /** \struct Skin * \brief Skin data structure #1 - used by Quake1, MDL2, MDL3 and MDL4 */ -struct Skin -{ +struct Skin { //! 0 = single (Skin), 1 = group (GroupSkin) //! For MDL3-5: Defines the type of the skin and there //! fore the size of the data to skip: @@ -409,8 +396,7 @@ struct Skin * \brief Skin data structure #2 - used by MDL5, MDL6 and MDL7 * \see Skin */ -struct Skin_MDL5 -{ +struct Skin_MDL5 { int32_t size, width, height; uint8_t *data; } PACK_STRUCT; @@ -424,8 +410,7 @@ struct Skin_MDL5 /** \struct Skin_MDL7 * \brief Skin data structure #3 - used by MDL7 and HMP7 */ -struct Skin_MDL7 -{ +struct Skin_MDL7 { uint8_t typ; int8_t _unused_[3]; int32_t width; @@ -437,8 +422,7 @@ struct Skin_MDL7 /** \struct RGB565 * \brief Data structure for a RGB565 pixel in a texture */ -struct RGB565 -{ +struct RGB565 { uint16_t r : 5; uint16_t g : 6; uint16_t b : 5; @@ -448,20 +432,18 @@ struct RGB565 /** \struct ARGB4 * \brief Data structure for a ARGB4444 pixel in a texture */ -struct ARGB4 -{ +struct ARGB4 { uint16_t a : 4; uint16_t r : 4; uint16_t g : 4; uint16_t b : 4; -} PACK_STRUCT; +} /*PACK_STRUCT*/; // ------------------------------------------------------------------------------------- /** \struct GroupSkin * \brief Skin data structure #2 (group of pictures) */ -struct GroupSkin -{ +struct GroupSkin { //! 0 = single (Skin), 1 = group (GroupSkin) int32_t group; @@ -479,8 +461,7 @@ struct GroupSkin /** \struct TexCoord * \brief Texture coordinate data structure used by the Quake1 MDL format */ -struct TexCoord -{ +struct TexCoord { //! Is the vertex on the noundary between front and back piece? int32_t onseam; @@ -495,8 +476,7 @@ struct TexCoord /** \struct TexCoord_MDL3 * \brief Data structure for an UV coordinate in the 3DGS MDL3 format */ -struct TexCoord_MDL3 -{ +struct TexCoord_MDL3 { //! position, horizontally in range 0..skinwidth-1 int16_t u; @@ -508,8 +488,7 @@ struct TexCoord_MDL3 /** \struct TexCoord_MDL7 * \brief Data structure for an UV coordinate in the 3DGS MDL7 format */ -struct TexCoord_MDL7 -{ +struct TexCoord_MDL7 { //! position, horizontally in range 0..1 float u; @@ -626,7 +605,6 @@ struct Vertex_MDL7 }; } PACK_STRUCT; - // ------------------------------------------------------------------------------------- /** \struct BoneTransform_MDL7 * \brief bone transformation matrix structure used in MDL7 files @@ -647,7 +625,6 @@ struct BoneTransform_MDL7 #define AI_MDL7_MAX_FRAMENAMESIZE 16 - // ------------------------------------------------------------------------------------- /** \struct Frame_MDL7 * \brief Frame data structure used by MDL7 files @@ -737,8 +714,7 @@ struct GroupFrame /** \struct IntFace_MDL7 * \brief Internal data structure to temporarily represent a face */ -struct IntFace_MDL7 -{ +struct IntFace_MDL7 { // provide a constructor for our own convenience IntFace_MDL7() { diff --git a/code/MDLLoader.cpp b/code/MDLLoader.cpp index f82e7abfe..2025d79b3 100644 --- a/code/MDLLoader.cpp +++ b/code/MDLLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -58,10 +59,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include - using namespace Assimp; static const aiImporterDesc desc = { @@ -1131,7 +1132,9 @@ bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInf const unsigned char* szCurrent, const unsigned char** szCurrentOut) { - ai_assert(NULL != szCurrent && NULL != szCurrentOut); + ai_assert( nullptr != szCurrent ); + ai_assert( nullptr != szCurrentOut); + const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)mBuffer; // if we have no bones we can simply skip all frames, diff --git a/code/MDLLoader.h b/code/MDLLoader.h index 62e451cbe..8709426e6 100644 --- a/code/MDLLoader.h +++ b/code/MDLLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/MDLMaterialLoader.cpp b/code/MDLMaterialLoader.cpp index 3425d7b09..9086925aa 100644 --- a/code/MDLMaterialLoader.cpp +++ b/code/MDLMaterialLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -52,8 +53,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include "qnan.h" -#include "Defines.h" using namespace Assimp; @@ -545,10 +546,6 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7( } else if (iMasked || !iType || (iType && iWidth && iHeight)) { - // ***** STANDARD COLOR TEXTURE ***** - if(pcNew!= nullptr) - delete pcNew; - pcNew = new aiTexture(); if (!iHeight || !iWidth) { @@ -668,7 +665,9 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7( if (0.0f != pcMatIn->Power) { iShadingMode = (int)aiShadingMode_Phong; - pcMatOut->AddProperty(&pcMatIn->Power,1,AI_MATKEY_SHININESS); + // pcMatIn is packed, we can't form pointers to its members + float power = pcMatIn->Power; + pcMatOut->AddProperty(&power,1,AI_MATKEY_SHININESS); } pcMatOut->AddProperty(&iShadingMode,1,AI_MATKEY_SHADING_MODEL); } diff --git a/code/MMDCpp14.h b/code/MMDCpp14.h new file mode 100644 index 000000000..f6f81f827 --- /dev/null +++ b/code/MMDCpp14.h @@ -0,0 +1,82 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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. + +---------------------------------------------------------------------- +*/ +#pragma once + +#ifndef MMD_CPP14_H +#define MMD_CPP14_H + +#include +#include +#include +#include + +namespace mmd { + template struct _Unique_if { + typedef std::unique_ptr _Single_object; + }; + + template struct _Unique_if { + typedef std::unique_ptr _Unknown_bound; + }; + + template struct _Unique_if { + typedef void _Known_bound; + }; + + template + typename _Unique_if::_Single_object + make_unique(Args&&... args) { + return std::unique_ptr(new T(std::forward(args)...)); + } + + template + typename _Unique_if::_Unknown_bound + make_unique(size_t n) { + typedef typename std::remove_extent::type U; + return std::unique_ptr(new U[n]()); + } + + template + typename _Unique_if::_Known_bound + make_unique(Args&&...) = delete; +} + +#endif diff --git a/code/MMDImporter.cpp b/code/MMDImporter.cpp new file mode 100644 index 000000000..01f009519 --- /dev/null +++ b/code/MMDImporter.cpp @@ -0,0 +1,370 @@ +/* +--------------------------------------------------------------------------- +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. +--------------------------------------------------------------------------- +*/ + +#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER + +#include "MMDImporter.h" +#include "MMDPmdParser.h" +#include "MMDPmxParser.h" +#include "MMDVmdParser.h" +#include "ConvertToLHProcess.h" +#include +#include +#include +#include +#include +#include +#include + +static const aiImporterDesc desc = {"MMD Importer", + "", + "", + "surfaces supported?", + aiImporterFlags_SupportTextFlavour, + 0, + 0, + 0, + 0, + "pmx"}; + +namespace Assimp { + +using namespace std; + +// ------------------------------------------------------------------------------------------------ +// Default constructor +MMDImporter::MMDImporter() + : m_Buffer(), + // m_pRootObject( NULL ), + m_strAbsPath("") { + DefaultIOSystem io; + m_strAbsPath = io.getOsSeparator(); +} + +// ------------------------------------------------------------------------------------------------ +// Destructor. +MMDImporter::~MMDImporter() { + // delete m_pRootObject; + // m_pRootObject = NULL; +} + +// ------------------------------------------------------------------------------------------------ +// Returns true, if file is an pmx file. +bool MMDImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, + bool checkSig) const { + if (!checkSig) // Check File Extension + { + return SimpleExtensionCheck(pFile, "pmx"); + } else // Check file Header + { + static const char *pTokens[] = {"PMX "}; + return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, + 1); + } +} + +// ------------------------------------------------------------------------------------------------ +const aiImporterDesc *MMDImporter::GetInfo() const { return &desc; } + +// ------------------------------------------------------------------------------------------------ +// MMD import implementation +void MMDImporter::InternReadFile(const std::string &file, aiScene *pScene, + IOSystem * /*pIOHandler*/) { + // Read file by istream + std::filebuf fb; + if (!fb.open(file, std::ios::in | std::ios::binary)) { + throw DeadlyImportError("Failed to open file " + file + "."); + } + + std::istream fileStream(&fb); + + // Get the file-size and validate it, throwing an exception when fails + fileStream.seekg(0, fileStream.end); + size_t fileSize = static_cast(fileStream.tellg()); + fileStream.seekg(0, fileStream.beg); + + if (fileSize < sizeof(pmx::PmxModel)) { + throw DeadlyImportError(file + " is too small."); + } + + pmx::PmxModel model; + model.Read(&fileStream); + + CreateDataFromImport(&model, pScene); +} + +// ------------------------------------------------------------------------------------------------ +void MMDImporter::CreateDataFromImport(const pmx::PmxModel *pModel, + aiScene *pScene) { + if (pModel == NULL) { + return; + } + + aiNode *pNode = new aiNode; + if (!pModel->model_name.empty()) { + pNode->mName.Set(pModel->model_name); + } else { + ai_assert(false); + } + + pScene->mRootNode = pNode; + + pNode = new aiNode; + pScene->mRootNode->addChildren(1, &pNode); + pNode->mName.Set(string(pModel->model_name) + string("_mesh")); + + // split mesh by materials + pNode->mNumMeshes = pModel->material_count; + pNode->mMeshes = new unsigned int[pNode->mNumMeshes]; + for (unsigned int index = 0; index < pNode->mNumMeshes; index++) { + pNode->mMeshes[index] = index; + } + + pScene->mNumMeshes = pModel->material_count; + pScene->mMeshes = new aiMesh *[pScene->mNumMeshes]; + for (unsigned int i = 0, indexStart = 0; i < pScene->mNumMeshes; i++) { + const int indexCount = pModel->materials[i].index_count; + + pScene->mMeshes[i] = CreateMesh(pModel, indexStart, indexCount); + pScene->mMeshes[i]->mName = pModel->materials[i].material_name; + pScene->mMeshes[i]->mMaterialIndex = i; + indexStart += indexCount; + } + + // create node hierarchy for bone position + aiNode **ppNode = new aiNode *[pModel->bone_count]; + for (auto i = 0; i < pModel->bone_count; i++) { + ppNode[i] = new aiNode(pModel->bones[i].bone_name); + } + + for (auto i = 0; i < pModel->bone_count; i++) { + const pmx::PmxBone &bone = pModel->bones[i]; + + if (bone.parent_index < 0) { + pScene->mRootNode->addChildren(1, ppNode + i); + } else { + ppNode[bone.parent_index]->addChildren(1, ppNode + i); + + aiVector3D v3 = aiVector3D( + bone.position[0] - pModel->bones[bone.parent_index].position[0], + bone.position[1] - pModel->bones[bone.parent_index].position[1], + bone.position[2] - pModel->bones[bone.parent_index].position[2]); + aiMatrix4x4::Translation(v3, ppNode[i]->mTransformation); + } + } + + // create materials + pScene->mNumMaterials = pModel->material_count; + pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials]; + for (unsigned int i = 0; i < pScene->mNumMaterials; i++) { + pScene->mMaterials[i] = CreateMaterial(&pModel->materials[i], pModel); + } + + // Convert everything to OpenGL space + MakeLeftHandedProcess convertProcess; + convertProcess.Execute(pScene); + + FlipUVsProcess uvFlipper; + uvFlipper.Execute(pScene); + + FlipWindingOrderProcess windingFlipper; + windingFlipper.Execute(pScene); +} + +// ------------------------------------------------------------------------------------------------ +aiMesh *MMDImporter::CreateMesh(const pmx::PmxModel *pModel, + const int indexStart, const int indexCount) { + aiMesh *pMesh = new aiMesh; + + pMesh->mNumVertices = indexCount; + + pMesh->mNumFaces = indexCount / 3; + pMesh->mFaces = new aiFace[pMesh->mNumFaces]; + + const int numIndices = 3; // trianglular face + for (unsigned int index = 0; index < pMesh->mNumFaces; index++) { + pMesh->mFaces[index].mNumIndices = numIndices; + unsigned int *indices = new unsigned int[numIndices]; + indices[0] = numIndices * index; + indices[1] = numIndices * index + 1; + indices[2] = numIndices * index + 2; + pMesh->mFaces[index].mIndices = indices; + } + + pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; + pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; + pMesh->mTextureCoords[0] = new aiVector3D[pMesh->mNumVertices]; + pMesh->mNumUVComponents[0] = 2; + + // additional UVs + for (int i = 1; i <= pModel->setting.uv; i++) { + pMesh->mTextureCoords[i] = new aiVector3D[pMesh->mNumVertices]; + pMesh->mNumUVComponents[i] = 4; + } + + map> bone_vertex_map; + + // fill in contents and create bones + for (int index = 0; index < indexCount; index++) { + const pmx::PmxVertex *v = + &pModel->vertices[pModel->indices[indexStart + index]]; + const float *position = v->position; + pMesh->mVertices[index].Set(position[0], position[1], position[2]); + const float *normal = v->normal; + + pMesh->mNormals[index].Set(normal[0], normal[1], normal[2]); + pMesh->mTextureCoords[0][index].x = v->uv[0]; + pMesh->mTextureCoords[0][index].y = v->uv[1]; + + for (int i = 1; i <= pModel->setting.uv; i++) { + // TODO: wrong here? use quaternion transform? + pMesh->mTextureCoords[i][index].x = v->uva[i][0]; + pMesh->mTextureCoords[i][index].y = v->uva[i][1]; + } + + // handle bone map + const auto vsBDEF1_ptr = + dynamic_cast(v->skinning.get()); + const auto vsBDEF2_ptr = + dynamic_cast(v->skinning.get()); + const auto vsBDEF4_ptr = + dynamic_cast(v->skinning.get()); + const auto vsSDEF_ptr = + dynamic_cast(v->skinning.get()); + switch (v->skinning_type) { + case pmx::PmxVertexSkinningType::BDEF1: + bone_vertex_map[vsBDEF1_ptr->bone_index].push_back( + aiVertexWeight(index, 1.0)); + break; + case pmx::PmxVertexSkinningType::BDEF2: + bone_vertex_map[vsBDEF2_ptr->bone_index1].push_back( + aiVertexWeight(index, vsBDEF2_ptr->bone_weight)); + bone_vertex_map[vsBDEF2_ptr->bone_index2].push_back( + aiVertexWeight(index, 1.0f - vsBDEF2_ptr->bone_weight)); + break; + case pmx::PmxVertexSkinningType::BDEF4: + bone_vertex_map[vsBDEF4_ptr->bone_index1].push_back( + aiVertexWeight(index, vsBDEF4_ptr->bone_weight1)); + bone_vertex_map[vsBDEF4_ptr->bone_index2].push_back( + aiVertexWeight(index, vsBDEF4_ptr->bone_weight2)); + bone_vertex_map[vsBDEF4_ptr->bone_index3].push_back( + aiVertexWeight(index, vsBDEF4_ptr->bone_weight3)); + bone_vertex_map[vsBDEF4_ptr->bone_index4].push_back( + aiVertexWeight(index, vsBDEF4_ptr->bone_weight4)); + break; + case pmx::PmxVertexSkinningType::SDEF: // TODO: how to use sdef_c, sdef_r0, + // sdef_r1? + bone_vertex_map[vsSDEF_ptr->bone_index1].push_back( + aiVertexWeight(index, vsSDEF_ptr->bone_weight)); + bone_vertex_map[vsSDEF_ptr->bone_index2].push_back( + aiVertexWeight(index, 1.0f - vsSDEF_ptr->bone_weight)); + break; + case pmx::PmxVertexSkinningType::QDEF: + const auto vsQDEF_ptr = + dynamic_cast(v->skinning.get()); + bone_vertex_map[vsQDEF_ptr->bone_index1].push_back( + aiVertexWeight(index, vsQDEF_ptr->bone_weight1)); + bone_vertex_map[vsQDEF_ptr->bone_index2].push_back( + aiVertexWeight(index, vsQDEF_ptr->bone_weight2)); + bone_vertex_map[vsQDEF_ptr->bone_index3].push_back( + aiVertexWeight(index, vsQDEF_ptr->bone_weight3)); + bone_vertex_map[vsQDEF_ptr->bone_index4].push_back( + aiVertexWeight(index, vsQDEF_ptr->bone_weight4)); + break; + } + } + + // make all bones for each mesh + // assign bone weights to skinned bones (otherwise just initialize) + auto bone_ptr_ptr = new aiBone *[pModel->bone_count]; + pMesh->mNumBones = pModel->bone_count; + pMesh->mBones = bone_ptr_ptr; + for (auto ii = 0; ii < pModel->bone_count; ++ii) { + auto pBone = new aiBone; + const auto &pmxBone = pModel->bones[ii]; + pBone->mName = pmxBone.bone_name; + aiVector3D pos(pmxBone.position[0], pmxBone.position[1], pmxBone.position[2]); + aiMatrix4x4::Translation(-pos, pBone->mOffsetMatrix); + auto it = bone_vertex_map.find(ii); + if (it != bone_vertex_map.end()) { + pBone->mNumWeights = static_cast(it->second.size()); + pBone->mWeights = it->second.data(); + it->second.swap(*(new vector)); + } + bone_ptr_ptr[ii] = pBone; + } + + return pMesh; +} + +// ------------------------------------------------------------------------------------------------ +aiMaterial *MMDImporter::CreateMaterial(const pmx::PmxMaterial *pMat, + const pmx::PmxModel *pModel) { + aiMaterial *mat = new aiMaterial(); + aiString name(pMat->material_english_name); + mat->AddProperty(&name, AI_MATKEY_NAME); + + aiColor3D diffuse(pMat->diffuse[0], pMat->diffuse[1], pMat->diffuse[2]); + mat->AddProperty(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE); + aiColor3D specular(pMat->specular[0], pMat->specular[1], pMat->specular[2]); + mat->AddProperty(&specular, 1, AI_MATKEY_COLOR_SPECULAR); + aiColor3D ambient(pMat->ambient[0], pMat->ambient[1], pMat->ambient[2]); + mat->AddProperty(&ambient, 1, AI_MATKEY_COLOR_AMBIENT); + + float opacity = pMat->diffuse[3]; + mat->AddProperty(&opacity, 1, AI_MATKEY_OPACITY); + float shininess = pMat->specularlity; + mat->AddProperty(&shininess, 1, AI_MATKEY_SHININESS_STRENGTH); + + aiString texture_path(pModel->textures[pMat->diffuse_texture_index]); + mat->AddProperty(&texture_path, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); + int mapping_uvwsrc = 0; + mat->AddProperty(&mapping_uvwsrc, 1, + AI_MATKEY_UVWSRC(aiTextureType_DIFFUSE, 0)); + + return mat; +} + +// ------------------------------------------------------------------------------------------------ + +} // Namespace Assimp + +#endif // !! ASSIMP_BUILD_NO_MMD_IMPORTER diff --git a/code/MMDImporter.h b/code/MMDImporter.h new file mode 100644 index 000000000..e660abaaa --- /dev/null +++ b/code/MMDImporter.h @@ -0,0 +1,96 @@ +/* +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. + +---------------------------------------------------------------------- +*/ +#ifndef MMD_FILE_IMPORTER_H_INC +#define MMD_FILE_IMPORTER_H_INC + +#include "BaseImporter.h" +#include "MMDPmxParser.h" +#include +#include + +struct aiMesh; + +namespace Assimp { + +// ------------------------------------------------------------------------------------------------ +/// \class MMDImporter +/// \brief Imports MMD a pmx/pmd/vmd file +// ------------------------------------------------------------------------------------------------ +class MMDImporter : public BaseImporter { +public: + /// \brief Default constructor + MMDImporter(); + + /// \brief Destructor + ~MMDImporter(); + +public: + /// \brief Returns whether the class can handle the format of the given file. + /// \remark See BaseImporter::CanRead() for details. + bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const; + +private: + //! \brief Appends the supported extension. + const aiImporterDesc* GetInfo () const; + + //! \brief File import implementation. + void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); + + //! \brief Create the data from imported content. + void CreateDataFromImport(const pmx::PmxModel* pModel, aiScene* pScene); + + //! \brief Create the mesh + aiMesh* CreateMesh(const pmx::PmxModel* pModel, const int indexStart, const int indexCount); + + //! \brief Create the material + aiMaterial* CreateMaterial(const pmx::PmxMaterial* pMat, const pmx::PmxModel* pModel); + +private: + //! Data buffer + std::vector m_Buffer; + //! Absolute pathname of model in file system + std::string m_strAbsPath; +}; + +// ------------------------------------------------------------------------------------------------ + +} // Namespace Assimp + +#endif \ No newline at end of file diff --git a/code/MMDPmdParser.h b/code/MMDPmdParser.h new file mode 100644 index 000000000..586f20a5f --- /dev/null +++ b/code/MMDPmdParser.h @@ -0,0 +1,596 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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. + +---------------------------------------------------------------------- +*/ +#pragma once + +#include +#include +#include +#include +#include +#include "MMDCpp14.h" + +namespace pmd +{ + class PmdHeader + { + public: + std::string name; + std::string name_english; + std::string comment; + std::string comment_english; + + bool Read(std::ifstream* stream) + { + char buffer[256]; + stream->read(buffer, 20); + name = std::string(buffer); + stream->read(buffer, 256); + comment = std::string(buffer); + return true; + } + + bool ReadExtension(std::ifstream* stream) + { + char buffer[256]; + stream->read(buffer, 20); + name_english = std::string(buffer); + stream->read(buffer, 256); + comment_english = std::string(buffer); + return true; + } + }; + + class PmdVertex + { + public: + float position[3]; + + float normal[3]; + + float uv[2]; + + uint16_t bone_index[2]; + + uint8_t bone_weight; + + bool edge_invisible; + + bool Read(std::ifstream* stream) + { + stream->read((char*) position, sizeof(float) * 3); + stream->read((char*) normal, sizeof(float) * 3); + stream->read((char*) uv, sizeof(float) * 2); + stream->read((char*) bone_index, sizeof(uint16_t) * 2); + stream->read((char*) &bone_weight, sizeof(uint8_t)); + stream->read((char*) &edge_invisible, sizeof(uint8_t)); + return true; + } + }; + + class PmdMaterial + { + public: + float diffuse[4]; + float power; + float specular[3]; + float ambient[3]; + uint8_t toon_index; + uint8_t edge_flag; + uint32_t index_count; + std::string texture_filename; + std::string sphere_filename; + + bool Read(std::ifstream* stream) + { + char buffer[20]; + stream->read((char*) &diffuse, sizeof(float) * 4); + stream->read((char*) &power, sizeof(float)); + stream->read((char*) &specular, sizeof(float) * 3); + stream->read((char*) &ambient, sizeof(float) * 3); + stream->read((char*) &toon_index, sizeof(uint8_t)); + stream->read((char*) &edge_flag, sizeof(uint8_t)); + stream->read((char*) &index_count, sizeof(uint32_t)); + stream->read((char*) &buffer, sizeof(char) * 20); + char* pstar = strchr(buffer, '*'); + if (NULL == pstar) + { + texture_filename = std::string(buffer); + sphere_filename.clear(); + } + else { + *pstar = 0; + texture_filename = std::string(buffer); + sphere_filename = std::string(pstar+1); + } + return true; + } + }; + + enum class BoneType : uint8_t + { + Rotation, + RotationAndMove, + IkEffector, + Unknown, + IkEffectable, + RotationEffectable, + IkTarget, + Invisible, + Twist, + RotationMovement + }; + + class PmdBone + { + public: + std::string name; + std::string name_english; + uint16_t parent_bone_index; + uint16_t tail_pos_bone_index; + BoneType bone_type; + uint16_t ik_parent_bone_index; + float bone_head_pos[3]; + + void Read(std::istream *stream) + { + char buffer[20]; + stream->read(buffer, 20); + name = std::string(buffer); + stream->read((char*) &parent_bone_index, sizeof(uint16_t)); + stream->read((char*) &tail_pos_bone_index, sizeof(uint16_t)); + stream->read((char*) &bone_type, sizeof(uint8_t)); + stream->read((char*) &ik_parent_bone_index, sizeof(uint16_t)); + stream->read((char*) &bone_head_pos, sizeof(float) * 3); + } + + void ReadExpantion(std::istream *stream) + { + char buffer[20]; + stream->read(buffer, 20); + name_english = std::string(buffer); + } + }; + + class PmdIk + { + public: + uint16_t ik_bone_index; + uint16_t target_bone_index; + uint16_t interations; + float angle_limit; + std::vector ik_child_bone_index; + + void Read(std::istream *stream) + { + stream->read((char *) &ik_bone_index, sizeof(uint16_t)); + stream->read((char *) &target_bone_index, sizeof(uint16_t)); + uint8_t ik_chain_length; + stream->read((char*) &ik_chain_length, sizeof(uint8_t)); + stream->read((char *) &interations, sizeof(uint16_t)); + stream->read((char *) &angle_limit, sizeof(float)); + ik_child_bone_index.resize(ik_chain_length); + for (int i = 0; i < ik_chain_length; i++) + { + stream->read((char *) &ik_child_bone_index[i], sizeof(uint16_t)); + } + } + }; + + class PmdFaceVertex + { + public: + int vertex_index; + float position[3]; + + void Read(std::istream *stream) + { + stream->read((char *) &vertex_index, sizeof(int)); + stream->read((char *) position, sizeof(float) * 3); + } + }; + + enum class FaceCategory : uint8_t + { + Base, + Eyebrow, + Eye, + Mouth, + Other + }; + + class PmdFace + { + public: + std::string name; + FaceCategory type; + std::vector vertices; + std::string name_english; + + void Read(std::istream *stream) + { + char buffer[20]; + stream->read(buffer, 20); + name = std::string(buffer); + int vertex_count; + stream->read((char*) &vertex_count, sizeof(int)); + stream->read((char*) &type, sizeof(uint8_t)); + vertices.resize(vertex_count); + for (int i = 0; i < vertex_count; i++) + { + vertices[i].Read(stream); + } + } + + void ReadExpantion(std::istream *stream) + { + char buffer[20]; + stream->read(buffer, 20); + name_english = std::string(buffer); + } + }; + + class PmdBoneDispName + { + public: + std::string bone_disp_name; + std::string bone_disp_name_english; + + void Read(std::istream *stream) + { + char buffer[50]; + stream->read(buffer, 50); + bone_disp_name = std::string(buffer); + bone_disp_name_english.clear(); + } + void ReadExpantion(std::istream *stream) + { + char buffer[50]; + stream->read(buffer, 50); + bone_disp_name_english = std::string(buffer); + } + }; + + class PmdBoneDisp + { + public: + uint16_t bone_index; + uint8_t bone_disp_index; + + void Read(std::istream *stream) + { + stream->read((char*) &bone_index, sizeof(uint16_t)); + stream->read((char*) &bone_disp_index, sizeof(uint8_t)); + } + }; + + enum class RigidBodyShape : uint8_t + { + Sphere = 0, + Box = 1, + Cpusel = 2 + }; + + enum class RigidBodyType : uint8_t + { + BoneConnected = 0, + Physics = 1, + ConnectedPhysics = 2 + }; + + class PmdRigidBody + { + public: + std::string name; + uint16_t related_bone_index; + uint8_t group_index; + uint16_t mask; + RigidBodyShape shape; + float size[3]; + float position[3]; + float orientation[3]; + float weight; + float linear_damping; + float anglar_damping; + float restitution; + float friction; + RigidBodyType rigid_type; + + void Read(std::istream *stream) + { + char buffer[20]; + stream->read(buffer, sizeof(char) * 20); + name = (std::string(buffer)); + stream->read((char*) &related_bone_index, sizeof(uint16_t)); + stream->read((char*) &group_index, sizeof(uint8_t)); + stream->read((char*) &mask, sizeof(uint16_t)); + stream->read((char*) &shape, sizeof(uint8_t)); + stream->read((char*) size, sizeof(float) * 3); + stream->read((char*) position, sizeof(float) * 3); + stream->read((char*) orientation, sizeof(float) * 3); + stream->read((char*) &weight, sizeof(float)); + stream->read((char*) &linear_damping, sizeof(float)); + stream->read((char*) &anglar_damping, sizeof(float)); + stream->read((char*) &restitution, sizeof(float)); + stream->read((char*) &friction, sizeof(float)); + stream->read((char*) &rigid_type, sizeof(char)); + } + }; + + class PmdConstraint + { + public: + std::string name; + uint32_t rigid_body_index_a; + uint32_t rigid_body_index_b; + float position[3]; + float orientation[3]; + float linear_lower_limit[3]; + float linear_upper_limit[3]; + float angular_lower_limit[3]; + float angular_upper_limit[3]; + float linear_stiffness[3]; + float angular_stiffness[3]; + + void Read(std::istream *stream) + { + char buffer[20]; + stream->read(buffer, 20); + name = std::string(buffer); + stream->read((char *) &rigid_body_index_a, sizeof(uint32_t)); + stream->read((char *) &rigid_body_index_b, sizeof(uint32_t)); + stream->read((char *) position, sizeof(float) * 3); + stream->read((char *) orientation, sizeof(float) * 3); + stream->read((char *) linear_lower_limit, sizeof(float) * 3); + stream->read((char *) linear_upper_limit, sizeof(float) * 3); + stream->read((char *) angular_lower_limit, sizeof(float) * 3); + stream->read((char *) angular_upper_limit, sizeof(float) * 3); + stream->read((char *) linear_stiffness, sizeof(float) * 3); + stream->read((char *) angular_stiffness, sizeof(float) * 3); + } + }; + + class PmdModel + { + public: + float version; + PmdHeader header; + std::vector vertices; + std::vector indices; + std::vector materials; + std::vector bones; + std::vector iks; + std::vector faces; + std::vector faces_indices; + std::vector bone_disp_name; + std::vector bone_disp; + std::vector toon_filenames; + std::vector rigid_bodies; + std::vector constraints; + + static std::unique_ptr LoadFromFile(const char *filename) + { + std::ifstream stream(filename, std::ios::binary); + if (stream.fail()) + { + std::cerr << "could not open \"" << filename << "\"" << std::endl; + return nullptr; + } + auto result = LoadFromStream(&stream); + stream.close(); + return result; + } + + static std::unique_ptr LoadFromStream(std::ifstream *stream) + { + auto result = mmd::make_unique(); + char buffer[100]; + + // magic + char magic[3]; + stream->read(magic, 3); + if (magic[0] != 'P' || magic[1] != 'm' || magic[2] != 'd') + { + std::cerr << "invalid file" << std::endl; + return nullptr; + } + + // version + stream->read((char*) &(result->version), sizeof(float)); + if (result ->version != 1.0f) + { + std::cerr << "invalid version" << std::endl; + return nullptr; + } + + // header + result->header.Read(stream); + + // vertices + uint32_t vertex_num; + stream->read((char*) &vertex_num, sizeof(uint32_t)); + result->vertices.resize(vertex_num); + for (uint32_t i = 0; i < vertex_num; i++) + { + result->vertices[i].Read(stream); + } + + // indices + uint32_t index_num; + stream->read((char*) &index_num, sizeof(uint32_t)); + result->indices.resize(index_num); + for (uint32_t i = 0; i < index_num; i++) + { + stream->read((char*) &result->indices[i], sizeof(uint16_t)); + } + + // materials + uint32_t material_num; + stream->read((char*) &material_num, sizeof(uint32_t)); + result->materials.resize(material_num); + for (uint32_t i = 0; i < material_num; i++) + { + result->materials[i].Read(stream); + } + + // bones + uint16_t bone_num; + stream->read((char*) &bone_num, sizeof(uint16_t)); + result->bones.resize(bone_num); + for (uint32_t i = 0; i < bone_num; i++) + { + result->bones[i].Read(stream); + } + + // iks + uint16_t ik_num; + stream->read((char*) &ik_num, sizeof(uint16_t)); + result->iks.resize(ik_num); + for (uint32_t i = 0; i < ik_num; i++) + { + result->iks[i].Read(stream); + } + + // faces + uint16_t face_num; + stream->read((char*) &face_num, sizeof(uint16_t)); + result->faces.resize(face_num); + for (uint32_t i = 0; i < face_num; i++) + { + result->faces[i].Read(stream); + } + + // face frames + uint8_t face_frame_num; + stream->read((char*) &face_frame_num, sizeof(uint8_t)); + result->faces_indices.resize(face_frame_num); + for (uint32_t i = 0; i < face_frame_num; i++) + { + stream->read((char*) &result->faces_indices[i], sizeof(uint16_t)); + } + + // bone names + uint8_t bone_disp_num; + stream->read((char*) &bone_disp_num, sizeof(uint8_t)); + result->bone_disp_name.resize(bone_disp_num); + for (uint32_t i = 0; i < bone_disp_num; i++) + { + result->bone_disp_name[i].Read(stream); + } + + // bone frame + uint32_t bone_frame_num; + stream->read((char*) &bone_frame_num, sizeof(uint32_t)); + result->bone_disp.resize(bone_frame_num); + for (uint32_t i = 0; i < bone_frame_num; i++) + { + result->bone_disp[i].Read(stream); + } + + // english name + bool english; + stream->read((char*) &english, sizeof(char)); + if (english) + { + result->header.ReadExtension(stream); + for (uint32_t i = 0; i < bone_num; i++) + { + result->bones[i].ReadExpantion(stream); + } + for (uint32_t i = 0; i < face_num; i++) + { + if (result->faces[i].type == pmd::FaceCategory::Base) + { + continue; + } + result->faces[i].ReadExpantion(stream); + } + for (uint32_t i = 0; i < result->bone_disp_name.size(); i++) + { + result->bone_disp_name[i].ReadExpantion(stream); + } + } + + // toon textures + if (stream->peek() == std::ios::traits_type::eof()) + { + result->toon_filenames.clear(); + } + else { + result->toon_filenames.resize(10); + for (uint32_t i = 0; i < 10; i++) + { + stream->read(buffer, 100); + result->toon_filenames[i] = std::string(buffer); + } + } + + // physics + if (stream->peek() == std::ios::traits_type::eof()) + { + result->rigid_bodies.clear(); + result->constraints.clear(); + } + else { + uint32_t rigid_body_num; + stream->read((char*) &rigid_body_num, sizeof(uint32_t)); + result->rigid_bodies.resize(rigid_body_num); + for (uint32_t i = 0; i < rigid_body_num; i++) + { + result->rigid_bodies[i].Read(stream); + } + uint32_t constraint_num; + stream->read((char*) &constraint_num, sizeof(uint32_t)); + result->constraints.resize(constraint_num); + for (uint32_t i = 0; i < constraint_num; i++) + { + result->constraints[i].Read(stream); + } + } + + if (stream->peek() != std::ios::traits_type::eof()) + { + std::cerr << "there is unknown data" << std::endl; + } + + return result; + } + }; +} diff --git a/code/MMDPmxParser.cpp b/code/MMDPmxParser.cpp new file mode 100644 index 000000000..970cbc31e --- /dev/null +++ b/code/MMDPmxParser.cpp @@ -0,0 +1,637 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +#include +#include "MMDPmxParser.h" +#include "../contrib/utf8cpp/source/utf8.h" +#include "Exceptional.h" + +namespace pmx +{ + int ReadIndex(std::istream *stream, int size) + { + switch (size) + { + case 1: + uint8_t tmp8; + stream->read((char*) &tmp8, sizeof(uint8_t)); + if (255 == tmp8) + { + return -1; + } + else { + return (int) tmp8; + } + case 2: + uint16_t tmp16; + stream->read((char*) &tmp16, sizeof(uint16_t)); + if (65535 == tmp16) + { + return -1; + } + else { + return (int) tmp16; + } + case 4: + int tmp32; + stream->read((char*) &tmp32, sizeof(int)); + return tmp32; + default: + return -1; + } + } + + std::string ReadString(std::istream *stream, uint8_t encoding) + { + int size; + stream->read((char*) &size, sizeof(int)); + std::vector buffer; + if (size == 0) + { + return std::string(""); + } + buffer.reserve(size); + stream->read((char*) buffer.data(), size); + if (encoding == 0) + { + // UTF16 to UTF8 + std::string result; + + const char* sourceStart = buffer.data(); + const unsigned int targetSize = size * 3; // enough to encode + char* targetStart = new char[targetSize](); + const char* targetReserved = targetStart; + utf8::utf16to8( sourceStart, sourceStart + size, targetStart ); + + result.assign(targetReserved, targetStart - targetReserved); + delete[] targetReserved; + return result; + } + else + { + // the name is already UTF8 + return std::string((const char*)buffer.data(), size); + } + } + + void PmxSetting::Read(std::istream *stream) + { + uint8_t count; + stream->read((char*) &count, sizeof(uint8_t)); + if (count < 8) + { + throw; + } + stream->read((char*) &encoding, sizeof(uint8_t)); + stream->read((char*) &uv, sizeof(uint8_t)); + stream->read((char*) &vertex_index_size, sizeof(uint8_t)); + stream->read((char*) &texture_index_size, sizeof(uint8_t)); + stream->read((char*) &material_index_size, sizeof(uint8_t)); + stream->read((char*) &bone_index_size, sizeof(uint8_t)); + stream->read((char*) &morph_index_size, sizeof(uint8_t)); + stream->read((char*) &rigidbody_index_size, sizeof(uint8_t)); + uint8_t temp; + for (int i = 8; i < count; i++) + { + stream->read((char*)&temp, sizeof(uint8_t)); + } + } + + void PmxVertexSkinningBDEF1::Read(std::istream *stream, PmxSetting *setting) + { + this->bone_index = ReadIndex(stream, setting->bone_index_size); + } + + void PmxVertexSkinningBDEF2::Read(std::istream *stream, PmxSetting *setting) + { + this->bone_index1 = ReadIndex(stream, setting->bone_index_size); + this->bone_index2 = ReadIndex(stream, setting->bone_index_size); + stream->read((char*) &this->bone_weight, sizeof(float)); + } + + void PmxVertexSkinningBDEF4::Read(std::istream *stream, PmxSetting *setting) + { + this->bone_index1 = ReadIndex(stream, setting->bone_index_size); + this->bone_index2 = ReadIndex(stream, setting->bone_index_size); + this->bone_index3 = ReadIndex(stream, setting->bone_index_size); + this->bone_index4 = ReadIndex(stream, setting->bone_index_size); + stream->read((char*) &this->bone_weight1, sizeof(float)); + stream->read((char*) &this->bone_weight2, sizeof(float)); + stream->read((char*) &this->bone_weight3, sizeof(float)); + stream->read((char*) &this->bone_weight4, sizeof(float)); + } + + void PmxVertexSkinningSDEF::Read(std::istream *stream, PmxSetting *setting) + { + this->bone_index1 = ReadIndex(stream, setting->bone_index_size); + this->bone_index2 = ReadIndex(stream, setting->bone_index_size); + stream->read((char*) &this->bone_weight, sizeof(float)); + stream->read((char*) this->sdef_c, sizeof(float) * 3); + stream->read((char*) this->sdef_r0, sizeof(float) * 3); + stream->read((char*) this->sdef_r1, sizeof(float) * 3); + } + + void PmxVertexSkinningQDEF::Read(std::istream *stream, PmxSetting *setting) + { + this->bone_index1 = ReadIndex(stream, setting->bone_index_size); + this->bone_index2 = ReadIndex(stream, setting->bone_index_size); + this->bone_index3 = ReadIndex(stream, setting->bone_index_size); + this->bone_index4 = ReadIndex(stream, setting->bone_index_size); + stream->read((char*) &this->bone_weight1, sizeof(float)); + stream->read((char*) &this->bone_weight2, sizeof(float)); + stream->read((char*) &this->bone_weight3, sizeof(float)); + stream->read((char*) &this->bone_weight4, sizeof(float)); + } + + void PmxVertex::Read(std::istream *stream, PmxSetting *setting) + { + stream->read((char*) this->position, sizeof(float) * 3); + stream->read((char*) this->normal, sizeof(float) * 3); + stream->read((char*) this->uv, sizeof(float) * 2); + for (int i = 0; i < setting->uv; ++i) + { + stream->read((char*) this->uva[i], sizeof(float) * 4); + } + stream->read((char*) &this->skinning_type, sizeof(PmxVertexSkinningType)); + switch (this->skinning_type) + { + case PmxVertexSkinningType::BDEF1: + this->skinning = mmd::make_unique(); + break; + case PmxVertexSkinningType::BDEF2: + this->skinning = mmd::make_unique(); + break; + case PmxVertexSkinningType::BDEF4: + this->skinning = mmd::make_unique(); + break; + case PmxVertexSkinningType::SDEF: + this->skinning = mmd::make_unique(); + break; + case PmxVertexSkinningType::QDEF: + this->skinning = mmd::make_unique(); + break; + default: + throw "invalid skinning type"; + } + this->skinning->Read(stream, setting); + stream->read((char*) &this->edge, sizeof(float)); + } + + void PmxMaterial::Read(std::istream *stream, PmxSetting *setting) + { + this->material_name = ReadString(stream, setting->encoding); + this->material_english_name = ReadString(stream, setting->encoding); + stream->read((char*) this->diffuse, sizeof(float) * 4); + stream->read((char*) this->specular, sizeof(float) * 3); + stream->read((char*) &this->specularlity, sizeof(float)); + stream->read((char*) this->ambient, sizeof(float) * 3); + stream->read((char*) &this->flag, sizeof(uint8_t)); + stream->read((char*) this->edge_color, sizeof(float) * 4); + stream->read((char*) &this->edge_size, sizeof(float)); + this->diffuse_texture_index = ReadIndex(stream, setting->texture_index_size); + this->sphere_texture_index = ReadIndex(stream, setting->texture_index_size); + stream->read((char*) &this->sphere_op_mode, sizeof(uint8_t)); + stream->read((char*) &this->common_toon_flag, sizeof(uint8_t)); + if (this->common_toon_flag) + { + stream->read((char*) &this->toon_texture_index, sizeof(uint8_t)); + } + else { + this->toon_texture_index = ReadIndex(stream, setting->texture_index_size); + } + this->memo = ReadString(stream, setting->encoding); + stream->read((char*) &this->index_count, sizeof(int)); + } + + void PmxIkLink::Read(std::istream *stream, PmxSetting *setting) + { + this->link_target = ReadIndex(stream, setting->bone_index_size); + stream->read((char*) &this->angle_lock, sizeof(uint8_t)); + if (angle_lock == 1) + { + stream->read((char*) this->max_radian, sizeof(float) * 3); + stream->read((char*) this->min_radian, sizeof(float) * 3); + } + } + + void PmxBone::Read(std::istream *stream, PmxSetting *setting) + { + this->bone_name = ReadString(stream, setting->encoding); + this->bone_english_name = ReadString(stream, setting->encoding); + stream->read((char*) this->position, sizeof(float) * 3); + this->parent_index = ReadIndex(stream, setting->bone_index_size); + stream->read((char*) &this->level, sizeof(int)); + stream->read((char*) &this->bone_flag, sizeof(uint16_t)); + if (this->bone_flag & 0x0001) { + this->target_index = ReadIndex(stream, setting->bone_index_size); + } + else { + stream->read((char*)this->offset, sizeof(float) * 3); + } + if (this->bone_flag & (0x0100 | 0x0200)) { + this->grant_parent_index = ReadIndex(stream, setting->bone_index_size); + stream->read((char*) &this->grant_weight, sizeof(float)); + } + if (this->bone_flag & 0x0400) { + stream->read((char*)this->lock_axis_orientation, sizeof(float) * 3); + } + if (this->bone_flag & 0x0800) { + stream->read((char*)this->local_axis_x_orientation, sizeof(float) * 3); + stream->read((char*)this->local_axis_y_orientation, sizeof(float) * 3); + } + if (this->bone_flag & 0x2000) { + stream->read((char*) &this->key, sizeof(int)); + } + if (this->bone_flag & 0x0020) { + this->ik_target_bone_index = ReadIndex(stream, setting->bone_index_size); + stream->read((char*) &ik_loop, sizeof(int)); + stream->read((char*) &ik_loop_angle_limit, sizeof(float)); + stream->read((char*) &ik_link_count, sizeof(int)); + this->ik_links = mmd::make_unique(ik_link_count); + for (int i = 0; i < ik_link_count; i++) { + ik_links[i].Read(stream, setting); + } + } + } + + void PmxMorphVertexOffset::Read(std::istream *stream, PmxSetting *setting) + { + this->vertex_index = ReadIndex(stream, setting->vertex_index_size); + stream->read((char*)this->position_offset, sizeof(float) * 3); + } + + void PmxMorphUVOffset::Read(std::istream *stream, PmxSetting *setting) + { + this->vertex_index = ReadIndex(stream, setting->vertex_index_size); + stream->read((char*)this->uv_offset, sizeof(float) * 4); + } + + void PmxMorphBoneOffset::Read(std::istream *stream, PmxSetting *setting) + { + this->bone_index = ReadIndex(stream, setting->bone_index_size); + stream->read((char*)this->translation, sizeof(float) * 3); + stream->read((char*)this->rotation, sizeof(float) * 4); + } + + void PmxMorphMaterialOffset::Read(std::istream *stream, PmxSetting *setting) + { + this->material_index = ReadIndex(stream, setting->material_index_size); + stream->read((char*) &this->offset_operation, sizeof(uint8_t)); + stream->read((char*)this->diffuse, sizeof(float) * 4); + stream->read((char*)this->specular, sizeof(float) * 3); + stream->read((char*) &this->specularity, sizeof(float)); + stream->read((char*)this->ambient, sizeof(float) * 3); + stream->read((char*)this->edge_color, sizeof(float) * 4); + stream->read((char*) &this->edge_size, sizeof(float)); + stream->read((char*)this->texture_argb, sizeof(float) * 4); + stream->read((char*)this->sphere_texture_argb, sizeof(float) * 4); + stream->read((char*)this->toon_texture_argb, sizeof(float) * 4); + } + + void PmxMorphGroupOffset::Read(std::istream *stream, PmxSetting *setting) + { + this->morph_index = ReadIndex(stream, setting->morph_index_size); + stream->read((char*) &this->morph_weight, sizeof(float)); + } + + void PmxMorphFlipOffset::Read(std::istream *stream, PmxSetting *setting) + { + this->morph_index = ReadIndex(stream, setting->morph_index_size); + stream->read((char*) &this->morph_value, sizeof(float)); + } + + void PmxMorphImplusOffset::Read(std::istream *stream, PmxSetting *setting) + { + this->rigid_body_index = ReadIndex(stream, setting->rigidbody_index_size); + stream->read((char*) &this->is_local, sizeof(uint8_t)); + stream->read((char*)this->velocity, sizeof(float) * 3); + stream->read((char*)this->angular_torque, sizeof(float) * 3); + } + + void PmxMorph::Read(std::istream *stream, PmxSetting *setting) + { + this->morph_name = ReadString(stream, setting->encoding); + this->morph_english_name = ReadString(stream, setting->encoding); + stream->read((char*) &category, sizeof(MorphCategory)); + stream->read((char*) &morph_type, sizeof(MorphType)); + stream->read((char*) &this->offset_count, sizeof(int)); + switch (this->morph_type) + { + case MorphType::Group: + group_offsets = mmd::make_unique(this->offset_count); + for (int i = 0; i < offset_count; i++) + { + group_offsets[i].Read(stream, setting); + } + break; + case MorphType::Vertex: + vertex_offsets = mmd::make_unique(this->offset_count); + for (int i = 0; i < offset_count; i++) + { + vertex_offsets[i].Read(stream, setting); + } + break; + case MorphType::Bone: + bone_offsets = mmd::make_unique(this->offset_count); + for (int i = 0; i < offset_count; i++) + { + bone_offsets[i].Read(stream, setting); + } + break; + case MorphType::Matrial: + material_offsets = mmd::make_unique(this->offset_count); + for (int i = 0; i < offset_count; i++) + { + material_offsets[i].Read(stream, setting); + } + break; + case MorphType::UV: + case MorphType::AdditionalUV1: + case MorphType::AdditionalUV2: + case MorphType::AdditionalUV3: + case MorphType::AdditionalUV4: + uv_offsets = mmd::make_unique(this->offset_count); + for (int i = 0; i < offset_count; i++) + { + uv_offsets[i].Read(stream, setting); + } + break; + default: + throw; + } + } + + void PmxFrameElement::Read(std::istream *stream, PmxSetting *setting) + { + stream->read((char*) &this->element_target, sizeof(uint8_t)); + if (this->element_target == 0x00) + { + this->index = ReadIndex(stream, setting->bone_index_size); + } + else { + this->index = ReadIndex(stream, setting->morph_index_size); + } + } + + void PmxFrame::Read(std::istream *stream, PmxSetting *setting) + { + this->frame_name = ReadString(stream, setting->encoding); + this->frame_english_name = ReadString(stream, setting->encoding); + stream->read((char*) &this->frame_flag, sizeof(uint8_t)); + stream->read((char*) &this->element_count, sizeof(int)); + this->elements = mmd::make_unique(this->element_count); + for (int i = 0; i < this->element_count; i++) + { + this->elements[i].Read(stream, setting); + } + } + + void PmxRigidBody::Read(std::istream *stream, PmxSetting *setting) + { + this->girid_body_name = ReadString(stream, setting->encoding); + this->girid_body_english_name = ReadString(stream, setting->encoding); + this->target_bone = ReadIndex(stream, setting->bone_index_size); + stream->read((char*) &this->group, sizeof(uint8_t)); + stream->read((char*) &this->mask, sizeof(uint16_t)); + stream->read((char*) &this->shape, sizeof(uint8_t)); + stream->read((char*) this->size, sizeof(float) * 3); + stream->read((char*) this->position, sizeof(float) * 3); + stream->read((char*) this->orientation, sizeof(float) * 3); + stream->read((char*) &this->mass, sizeof(float)); + stream->read((char*) &this->move_attenuation, sizeof(float)); + stream->read((char*) &this->rotation_attenuation, sizeof(float)); + stream->read((char*) &this->repulsion, sizeof(float)); + stream->read((char*) &this->friction, sizeof(float)); + stream->read((char*) &this->physics_calc_type, sizeof(uint8_t)); + } + + void PmxJointParam::Read(std::istream *stream, PmxSetting *setting) + { + this->rigid_body1 = ReadIndex(stream, setting->rigidbody_index_size); + this->rigid_body2 = ReadIndex(stream, setting->rigidbody_index_size); + stream->read((char*) this->position, sizeof(float) * 3); + stream->read((char*) this->orientaiton, sizeof(float) * 3); + stream->read((char*) this->move_limitation_min, sizeof(float) * 3); + stream->read((char*) this->move_limitation_max, sizeof(float) * 3); + stream->read((char*) this->rotation_limitation_min, sizeof(float) * 3); + stream->read((char*) this->rotation_limitation_max, sizeof(float) * 3); + stream->read((char*) this->spring_move_coefficient, sizeof(float) * 3); + stream->read((char*) this->spring_rotation_coefficient, sizeof(float) * 3); + } + + void PmxJoint::Read(std::istream *stream, PmxSetting *setting) + { + this->joint_name = ReadString(stream, setting->encoding); + this->joint_english_name = ReadString(stream, setting->encoding); + stream->read((char*) &this->joint_type, sizeof(uint8_t)); + this->param.Read(stream, setting); + } + + void PmxAncherRigidBody::Read(std::istream *stream, PmxSetting *setting) + { + this->related_rigid_body = ReadIndex(stream, setting->rigidbody_index_size); + this->related_vertex = ReadIndex(stream, setting->vertex_index_size); + stream->read((char*) &this->is_near, sizeof(uint8_t)); + } + + void PmxSoftBody::Read(std::istream * /*stream*/, PmxSetting * /*setting*/) + { + // 未実装 + std::cerr << "Not Implemented Exception" << std::endl; + throw; + } + + void PmxModel::Init() + { + this->version = 0.0f; + this->model_name.clear(); + this->model_english_name.clear(); + this->model_comment.clear(); + this->model_english_comment.clear(); + this->vertex_count = 0; + this->vertices = nullptr; + this->index_count = 0; + this->indices = nullptr; + this->texture_count = 0; + this->textures = nullptr; + this->material_count = 0; + this->materials = nullptr; + this->bone_count = 0; + this->bones = nullptr; + this->morph_count = 0; + this->morphs = nullptr; + this->frame_count = 0; + this->frames = nullptr; + this->rigid_body_count = 0; + this->rigid_bodies = nullptr; + this->joint_count = 0; + this->joints = nullptr; + this->soft_body_count = 0; + this->soft_bodies = nullptr; + } + + void PmxModel::Read(std::istream *stream) + { + // マジック + char magic[4]; + stream->read((char*) magic, sizeof(char) * 4); + if (magic[0] != 0x50 || magic[1] != 0x4d || magic[2] != 0x58 || magic[3] != 0x20) + { + std::cerr << "invalid magic number." << std::endl; + throw; + } + // バージョン + stream->read((char*) &version, sizeof(float)); + if (version != 2.0f && version != 2.1f) + { + std::cerr << "this is not ver2.0 or ver2.1 but " << version << "." << std::endl; + throw; + } + // ファイル設定 + this->setting.Read(stream); + + // モデル情報 + this->model_name = ReadString(stream, setting.encoding); + this->model_english_name = ReadString(stream, setting.encoding); + this->model_comment = ReadString(stream, setting.encoding); + this->model_english_comment = ReadString(stream, setting.encoding); + + // 頂点 + stream->read((char*) &vertex_count, sizeof(int)); + this->vertices = mmd::make_unique(vertex_count); + for (int i = 0; i < vertex_count; i++) + { + vertices[i].Read(stream, &setting); + } + + // 面 + stream->read((char*) &index_count, sizeof(int)); + this->indices = mmd::make_unique(index_count); + for (int i = 0; i < index_count; i++) + { + this->indices[i] = ReadIndex(stream, setting.vertex_index_size); + } + + // テクスチャ + stream->read((char*) &texture_count, sizeof(int)); + this->textures = mmd::make_unique(texture_count); + for (int i = 0; i < texture_count; i++) + { + this->textures[i] = ReadString(stream, setting.encoding); + } + + // マテリアル + stream->read((char*) &material_count, sizeof(int)); + this->materials = mmd::make_unique(material_count); + for (int i = 0; i < material_count; i++) + { + this->materials[i].Read(stream, &setting); + } + + // ボーン + stream->read((char*) &this->bone_count, sizeof(int)); + this->bones = mmd::make_unique(this->bone_count); + for (int i = 0; i < this->bone_count; i++) + { + this->bones[i].Read(stream, &setting); + } + + // モーフ + stream->read((char*) &this->morph_count, sizeof(int)); + this->morphs = mmd::make_unique(this->morph_count); + for (int i = 0; i < this->morph_count; i++) + { + this->morphs[i].Read(stream, &setting); + } + + // 表示枠 + stream->read((char*) &this->frame_count, sizeof(int)); + this->frames = mmd::make_unique(this->frame_count); + for (int i = 0; i < this->frame_count; i++) + { + this->frames[i].Read(stream, &setting); + } + + // 剛体 + stream->read((char*) &this->rigid_body_count, sizeof(int)); + this->rigid_bodies = mmd::make_unique(this->rigid_body_count); + for (int i = 0; i < this->rigid_body_count; i++) + { + this->rigid_bodies[i].Read(stream, &setting); + } + + // ジョイント + stream->read((char*) &this->joint_count, sizeof(int)); + this->joints = mmd::make_unique(this->joint_count); + for (int i = 0; i < this->joint_count; i++) + { + this->joints[i].Read(stream, &setting); + } + + //if (this->version == 2.1f) + //{ + // stream->read((char*) &this->soft_body_count, sizeof(int)); + // this->soft_bodies = mmd::make_unique(this->soft_body_count); + // for (int i = 0; i < this->soft_body_count; i++) + // { + // this->soft_bodies[i].Read(stream, &setting); + // } + //} + } + + //std::unique_ptr ReadFromFile(const char *filename) + //{ + // auto stream = std::ifstream(filename, std::ios_base::binary); + // auto pmx = PmxModel::ReadFromStream(&stream); + // if (!stream.eof()) + // { + // std::cerr << "don't reach the end of file." << std::endl; + // } + // stream.close(); + // return pmx; + //} + + //std::unique_ptr ReadFromStream(std::istream *stream) + //{ + // auto pmx = mmd::make_unique(); + // pmx->Read(stream); + // return pmx; + //} +} diff --git a/code/MMDPmxParser.h b/code/MMDPmxParser.h new file mode 100644 index 000000000..989cffed6 --- /dev/null +++ b/code/MMDPmxParser.h @@ -0,0 +1,780 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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. + +---------------------------------------------------------------------- +*/ +#pragma once + +#include +#include +#include +#include +#include +#include "MMDCpp14.h" + +namespace pmx +{ + class PmxSetting + { + public: + PmxSetting() + : encoding(0) + , uv(0) + , vertex_index_size(0) + , texture_index_size(0) + , material_index_size(0) + , bone_index_size(0) + , morph_index_size(0) + , rigidbody_index_size(0) + {} + + uint8_t encoding; + uint8_t uv; + uint8_t vertex_index_size; + uint8_t texture_index_size; + uint8_t material_index_size; + uint8_t bone_index_size; + uint8_t morph_index_size; + uint8_t rigidbody_index_size; + void Read(std::istream *stream); + }; + + enum class PmxVertexSkinningType : uint8_t + { + BDEF1 = 0, + BDEF2 = 1, + BDEF4 = 2, + SDEF = 3, + QDEF = 4, + }; + + class PmxVertexSkinning + { + public: + virtual void Read(std::istream *stream, PmxSetting *setting) = 0; + }; + + class PmxVertexSkinningBDEF1 : public PmxVertexSkinning + { + public: + PmxVertexSkinningBDEF1() + : bone_index(0) + {} + + int bone_index; + void Read(std::istream *stresam, PmxSetting *setting); + }; + + class PmxVertexSkinningBDEF2 : public PmxVertexSkinning + { + public: + PmxVertexSkinningBDEF2() + : bone_index1(0) + , bone_index2(0) + , bone_weight(0.0f) + {} + + int bone_index1; + int bone_index2; + float bone_weight; + void Read(std::istream *stresam, PmxSetting *setting); + }; + + class PmxVertexSkinningBDEF4 : public PmxVertexSkinning + { + public: + PmxVertexSkinningBDEF4() + : bone_index1(0) + , bone_index2(0) + , bone_index3(0) + , bone_index4(0) + , bone_weight1(0.0f) + , bone_weight2(0.0f) + , bone_weight3(0.0f) + , bone_weight4(0.0f) + {} + + int bone_index1; + int bone_index2; + int bone_index3; + int bone_index4; + float bone_weight1; + float bone_weight2; + float bone_weight3; + float bone_weight4; + void Read(std::istream *stresam, PmxSetting *setting); + }; + + class PmxVertexSkinningSDEF : public PmxVertexSkinning + { + public: + PmxVertexSkinningSDEF() + : bone_index1(0) + , bone_index2(0) + , bone_weight(0.0f) + { + for (int i = 0; i < 3; ++i) { + sdef_c[i] = 0.0f; + sdef_r0[i] = 0.0f; + sdef_r1[i] = 0.0f; + } + } + + int bone_index1; + int bone_index2; + float bone_weight; + float sdef_c[3]; + float sdef_r0[3]; + float sdef_r1[3]; + void Read(std::istream *stresam, PmxSetting *setting); + }; + + class PmxVertexSkinningQDEF : public PmxVertexSkinning + { + public: + PmxVertexSkinningQDEF() + : bone_index1(0) + , bone_index2(0) + , bone_index3(0) + , bone_index4(0) + , bone_weight1(0.0f) + , bone_weight2(0.0f) + , bone_weight3(0.0f) + , bone_weight4(0.0f) + {} + + int bone_index1; + int bone_index2; + int bone_index3; + int bone_index4; + float bone_weight1; + float bone_weight2; + float bone_weight3; + float bone_weight4; + void Read(std::istream *stresam, PmxSetting *setting); + }; + + class PmxVertex + { + public: + PmxVertex() + : edge(0.0f) + { + uv[0] = uv[1] = 0.0f; + for (int i = 0; i < 3; ++i) { + position[i] = 0.0f; + normal[i] = 0.0f; + } + for (int i = 0; i < 4; ++i) { + for (int k = 0; k < 4; ++k) { + uva[i][k] = 0.0f; + } + } + } + + float position[3]; + float normal[3]; + float uv[2]; + float uva[4][4]; + PmxVertexSkinningType skinning_type; + std::unique_ptr skinning; + float edge; + void Read(std::istream *stream, PmxSetting *setting); + }; + + class PmxMaterial + { + public: + PmxMaterial() + : specularlity(0.0f) + , flag(0) + , edge_size(0.0f) + , diffuse_texture_index(0) + , sphere_texture_index(0) + , sphere_op_mode(0) + , common_toon_flag(0) + , toon_texture_index(0) + , index_count(0) + { + for (int i = 0; i < 3; ++i) { + specular[i] = 0.0f; + ambient[i] = 0.0f; + edge_color[i] = 0.0f; + } + for (int i = 0; i < 4; ++i) { + diffuse[i] = 0.0f; + } + } + + std::string material_name; + std::string material_english_name; + float diffuse[4]; + float specular[3]; + float specularlity; + float ambient[3]; + uint8_t flag; + float edge_color[4]; + float edge_size; + int diffuse_texture_index; + int sphere_texture_index; + uint8_t sphere_op_mode; + uint8_t common_toon_flag; + int toon_texture_index; + std::string memo; + int index_count; + void Read(std::istream *stream, PmxSetting *setting); + }; + + class PmxIkLink + { + public: + PmxIkLink() + : link_target(0) + , angle_lock(0) + { + for (int i = 0; i < 3; ++i) { + max_radian[i] = 0.0f; + min_radian[i] = 0.0f; + } + } + + int link_target; + uint8_t angle_lock; + float max_radian[3]; + float min_radian[3]; + void Read(std::istream *stream, PmxSetting *settingn); + }; + + class PmxBone + { + public: + PmxBone() + : parent_index(0) + , level(0) + , bone_flag(0) + , target_index(0) + , grant_parent_index(0) + , grant_weight(0.0f) + , key(0) + , ik_target_bone_index(0) + , ik_loop(0) + , ik_loop_angle_limit(0.0f) + , ik_link_count(0) + { + for (int i = 0; i < 3; ++i) { + position[i] = 0.0f; + offset[i] = 0.0f; + lock_axis_orientation[i] = 0.0f; + local_axis_x_orientation[i] = 0.0f; + local_axis_y_orientation[i] = 0.0f; + } + } + + std::string bone_name; + std::string bone_english_name; + float position[3]; + int parent_index; + int level; + uint16_t bone_flag; + float offset[3]; + int target_index; + int grant_parent_index; + float grant_weight; + float lock_axis_orientation[3]; + float local_axis_x_orientation[3]; + float local_axis_y_orientation[3]; + int key; + int ik_target_bone_index; + int ik_loop; + float ik_loop_angle_limit; + int ik_link_count; + std::unique_ptr ik_links; + void Read(std::istream *stream, PmxSetting *setting); + }; + + enum class MorphType : uint8_t + { + Group = 0, + Vertex = 1, + Bone = 2, + UV = 3, + AdditionalUV1 = 4, + AdditionalUV2 = 5, + AdditionalUV3 = 6, + AdditionalUV4 = 7, + Matrial = 8, + Flip = 9, + Implus = 10, + }; + + enum class MorphCategory : uint8_t + { + ReservedCategory = 0, + Eyebrow = 1, + Eye = 2, + Mouth = 3, + Other = 4, + }; + + class PmxMorphOffset + { + public: + void virtual Read(std::istream *stream, PmxSetting *setting) = 0; + }; + + class PmxMorphVertexOffset : public PmxMorphOffset + { + public: + PmxMorphVertexOffset() + : vertex_index(0) + { + for (int i = 0; i < 3; ++i) { + position_offset[i] = 0.0f; + } + } + int vertex_index; + float position_offset[3]; + void Read(std::istream *stream, PmxSetting *setting); //override; + }; + + class PmxMorphUVOffset : public PmxMorphOffset + { + public: + PmxMorphUVOffset() + : vertex_index(0) + { + for (int i = 0; i < 4; ++i) { + uv_offset[i] = 0.0f; + } + } + int vertex_index; + float uv_offset[4]; + void Read(std::istream *stream, PmxSetting *setting); //override; + }; + + class PmxMorphBoneOffset : public PmxMorphOffset + { + public: + PmxMorphBoneOffset() + : bone_index(0) + { + for (int i = 0; i < 3; ++i) { + translation[i] = 0.0f; + } + for (int i = 0; i < 4; ++i) { + rotation[i] = 0.0f; + } + } + int bone_index; + float translation[3]; + float rotation[4]; + void Read(std::istream *stream, PmxSetting *setting); //override; + }; + + class PmxMorphMaterialOffset : public PmxMorphOffset + { + public: + PmxMorphMaterialOffset() + : specularity(0.0f) + , edge_size(0.0f) + { + for (int i = 0; i < 3; ++i) { + specular[i] = 0.0f; + ambient[i] = 0.0f; + } + for (int i = 0; i < 4; ++i) { + diffuse[i] = 0.0f; + edge_color[i] = 0.0f; + texture_argb[i] = 0.0f; + sphere_texture_argb[i] = 0.0f; + toon_texture_argb[i] = 0.0f; + } + } + int material_index; + uint8_t offset_operation; + float diffuse[4]; + float specular[3]; + float specularity; + float ambient[3]; + float edge_color[4]; + float edge_size; + float texture_argb[4]; + float sphere_texture_argb[4]; + float toon_texture_argb[4]; + void Read(std::istream *stream, PmxSetting *setting); //override; + }; + + class PmxMorphGroupOffset : public PmxMorphOffset + { + public: + PmxMorphGroupOffset() + : morph_index(0) + , morph_weight(0.0f) + {} + int morph_index; + float morph_weight; + void Read(std::istream *stream, PmxSetting *setting); //override; + }; + + class PmxMorphFlipOffset : public PmxMorphOffset + { + public: + PmxMorphFlipOffset() + : morph_index(0) + , morph_value(0.0f) + {} + int morph_index; + float morph_value; + void Read(std::istream *stream, PmxSetting *setting); //override; + }; + + class PmxMorphImplusOffset : public PmxMorphOffset + { + public: + PmxMorphImplusOffset() + : rigid_body_index(0) + , is_local(0) + { + for (int i = 0; i < 3; ++i) { + velocity[i] = 0.0f; + angular_torque[i] = 0.0f; + } + } + int rigid_body_index; + uint8_t is_local; + float velocity[3]; + float angular_torque[3]; + void Read(std::istream *stream, PmxSetting *setting); //override; + }; + + class PmxMorph + { + public: + PmxMorph() + : offset_count(0) + { + } + std::string morph_name; + std::string morph_english_name; + MorphCategory category; + MorphType morph_type; + int offset_count; + std::unique_ptr vertex_offsets; + std::unique_ptr uv_offsets; + std::unique_ptr bone_offsets; + std::unique_ptr material_offsets; + std::unique_ptr group_offsets; + std::unique_ptr flip_offsets; + std::unique_ptr implus_offsets; + void Read(std::istream *stream, PmxSetting *setting); + }; + + class PmxFrameElement + { + public: + PmxFrameElement() + : element_target(0) + , index(0) + { + } + uint8_t element_target; + int index; + void Read(std::istream *stream, PmxSetting *setting); + }; + + class PmxFrame + { + public: + PmxFrame() + : frame_flag(0) + , element_count(0) + { + } + std::string frame_name; + std::string frame_english_name; + uint8_t frame_flag; + int element_count; + std::unique_ptr elements; + void Read(std::istream *stream, PmxSetting *setting); + }; + + class PmxRigidBody + { + public: + PmxRigidBody() + : target_bone(0) + , group(0) + , mask(0) + , shape(0) + , mass(0.0f) + , move_attenuation(0.0f) + , rotation_attenuation(0.0f) + , repulsion(0.0f) + , friction(0.0f) + , physics_calc_type(0) + { + for (int i = 0; i < 3; ++i) { + size[i] = 0.0f; + position[i] = 0.0f; + orientation[i] = 0.0f; + } + } + std::string girid_body_name; + std::string girid_body_english_name; + int target_bone; + uint8_t group; + uint16_t mask; + uint8_t shape; + float size[3]; + float position[3]; + float orientation[3]; + float mass; + float move_attenuation; + float rotation_attenuation; + float repulsion; + float friction; + uint8_t physics_calc_type; + void Read(std::istream *stream, PmxSetting *setting); + }; + + enum class PmxJointType : uint8_t + { + Generic6DofSpring = 0, + Generic6Dof = 1, + Point2Point = 2, + ConeTwist = 3, + Slider = 5, + Hinge = 6 + }; + + class PmxJointParam + { + public: + PmxJointParam() + : rigid_body1(0) + , rigid_body2(0) + { + for (int i = 0; i < 3; ++i) { + position[i] = 0.0f; + orientaiton[i] = 0.0f; + move_limitation_min[i] = 0.0f; + move_limitation_max[i] = 0.0f; + rotation_limitation_min[i] = 0.0f; + rotation_limitation_max[i] = 0.0f; + spring_move_coefficient[i] = 0.0f; + spring_rotation_coefficient[i] = 0.0f; + } + } + int rigid_body1; + int rigid_body2; + float position[3]; + float orientaiton[3]; + float move_limitation_min[3]; + float move_limitation_max[3]; + float rotation_limitation_min[3]; + float rotation_limitation_max[3]; + float spring_move_coefficient[3]; + float spring_rotation_coefficient[3]; + void Read(std::istream *stream, PmxSetting *setting); + }; + + class PmxJoint + { + public: + std::string joint_name; + std::string joint_english_name; + PmxJointType joint_type; + PmxJointParam param; + void Read(std::istream *stream, PmxSetting *setting); + }; + + enum PmxSoftBodyFlag : uint8_t + { + BLink = 0x01, + Cluster = 0x02, + Link = 0x04 + }; + + class PmxAncherRigidBody + { + public: + PmxAncherRigidBody() + : related_rigid_body(0) + , related_vertex(0) + , is_near(false) + {} + int related_rigid_body; + int related_vertex; + bool is_near; + void Read(std::istream *stream, PmxSetting *setting); + }; + + class PmxSoftBody + { + public: + PmxSoftBody() + : shape(0) + , target_material(0) + , group(0) + , mask(0) + , blink_distance(0) + , cluster_count(0) + , mass(0.0) + , collisioni_margin(0.0) + , aero_model(0) + , VCF(0.0f) + , DP(0.0f) + , DG(0.0f) + , LF(0.0f) + , PR(0.0f) + , VC(0.0f) + , DF(0.0f) + , MT(0.0f) + , CHR(0.0f) + , KHR(0.0f) + , SHR(0.0f) + , AHR(0.0f) + , SRHR_CL(0.0f) + , SKHR_CL(0.0f) + , SSHR_CL(0.0f) + , SR_SPLT_CL(0.0f) + , SK_SPLT_CL(0.0f) + , SS_SPLT_CL(0.0f) + , V_IT(0) + , P_IT(0) + , D_IT(0) + , C_IT(0) + , LST(0.0f) + , AST(0.0f) + , VST(0.0f) + , anchor_count(0) + , pin_vertex_count(0) + {} + std::string soft_body_name; + std::string soft_body_english_name; + uint8_t shape; + int target_material; + uint8_t group; + uint16_t mask; + PmxSoftBodyFlag flag; + int blink_distance; + int cluster_count; + float mass; + float collisioni_margin; + int aero_model; + float VCF; + float DP; + float DG; + float LF; + float PR; + float VC; + float DF; + float MT; + float CHR; + float KHR; + float SHR; + float AHR; + float SRHR_CL; + float SKHR_CL; + float SSHR_CL; + float SR_SPLT_CL; + float SK_SPLT_CL; + float SS_SPLT_CL; + int V_IT; + int P_IT; + int D_IT; + int C_IT; + float LST; + float AST; + float VST; + int anchor_count; + std::unique_ptr anchers; + int pin_vertex_count; + std::unique_ptr pin_vertices; + void Read(std::istream *stream, PmxSetting *setting); + }; + + class PmxModel + { + public: + PmxModel() + : version(0.0f) + , vertex_count(0) + , index_count(0) + , texture_count(0) + , material_count(0) + , bone_count(0) + , morph_count(0) + , frame_count(0) + , rigid_body_count(0) + , joint_count(0) + , soft_body_count(0) + {} + + float version; + PmxSetting setting; + std::string model_name; + std::string model_english_name; + std::string model_comment; + std::string model_english_comment; + int vertex_count; + std::unique_ptr vertices; + int index_count; + std::unique_ptr indices; + int texture_count; + std::unique_ptr< std::string []> textures; + int material_count; + std::unique_ptr materials; + int bone_count; + std::unique_ptr bones; + int morph_count; + std::unique_ptr morphs; + int frame_count; + std::unique_ptr frames; + int rigid_body_count; + std::unique_ptr rigid_bodies; + int joint_count; + std::unique_ptr joints; + int soft_body_count; + std::unique_ptr soft_bodies; + void Init(); + void Read(std::istream *stream); + //static std::unique_ptr ReadFromFile(const char *filename); + //static std::unique_ptr ReadFromStream(std::istream *stream); + }; +} diff --git a/code/MMDVmdParser.h b/code/MMDVmdParser.h new file mode 100644 index 000000000..43e7a923a --- /dev/null +++ b/code/MMDVmdParser.h @@ -0,0 +1,375 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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. + +---------------------------------------------------------------------- +*/ +#pragma once + +#include +#include +#include +#include +#include +#include +#include "MMDCpp14.h" + +namespace vmd +{ + class VmdBoneFrame + { + public: + std::string name; + int frame; + float position[3]; + float orientation[4]; + char interpolation[4][4][4]; + + void Read(std::istream* stream) + { + char buffer[15]; + stream->read((char*) buffer, sizeof(char)*15); + name = std::string(buffer); + stream->read((char*) &frame, sizeof(int)); + stream->read((char*) position, sizeof(float)*3); + stream->read((char*) orientation, sizeof(float)*4); + stream->read((char*) interpolation, sizeof(char) * 4 * 4 * 4); + } + + void Write(std::ostream* stream) + { + stream->write((char*)name.c_str(), sizeof(char) * 15); + stream->write((char*)&frame, sizeof(int)); + stream->write((char*)position, sizeof(float) * 3); + stream->write((char*)orientation, sizeof(float) * 4); + stream->write((char*)interpolation, sizeof(char) * 4 * 4 * 4); + } + }; + + class VmdFaceFrame + { + public: + std::string face_name; + float weight; + uint32_t frame; + + void Read(std::istream* stream) + { + char buffer[15]; + stream->read((char*) &buffer, sizeof(char) * 15); + face_name = std::string(buffer); + stream->read((char*) &frame, sizeof(int)); + stream->read((char*) &weight, sizeof(float)); + } + + void Write(std::ostream* stream) + { + stream->write((char*)face_name.c_str(), sizeof(char) * 15); + stream->write((char*)&frame, sizeof(int)); + stream->write((char*)&weight, sizeof(float)); + } + }; + + class VmdCameraFrame + { + public: + int frame; + float distance; + float position[3]; + float orientation[3]; + char interpolation[6][4]; + float angle; + char unknown[3]; + + void Read(std::istream *stream) + { + stream->read((char*) &frame, sizeof(int)); + stream->read((char*) &distance, sizeof(float)); + stream->read((char*) position, sizeof(float) * 3); + stream->read((char*) orientation, sizeof(float) * 3); + stream->read((char*) interpolation, sizeof(char) * 24); + stream->read((char*) &angle, sizeof(float)); + stream->read((char*) unknown, sizeof(char) * 3); + } + + void Write(std::ostream *stream) + { + stream->write((char*)&frame, sizeof(int)); + stream->write((char*)&distance, sizeof(float)); + stream->write((char*)position, sizeof(float) * 3); + stream->write((char*)orientation, sizeof(float) * 3); + stream->write((char*)interpolation, sizeof(char) * 24); + stream->write((char*)&angle, sizeof(float)); + stream->write((char*)unknown, sizeof(char) * 3); + } + }; + + class VmdLightFrame + { + public: + int frame; + float color[3]; + float position[3]; + + void Read(std::istream* stream) + { + stream->read((char*) &frame, sizeof(int)); + stream->read((char*) color, sizeof(float) * 3); + stream->read((char*) position, sizeof(float) * 3); + } + + void Write(std::ostream* stream) + { + stream->write((char*)&frame, sizeof(int)); + stream->write((char*)color, sizeof(float) * 3); + stream->write((char*)position, sizeof(float) * 3); + } + }; + + class VmdIkEnable + { + public: + std::string ik_name; + bool enable; + }; + + class VmdIkFrame + { + public: + int frame; + bool display; + std::vector ik_enable; + + void Read(std::istream *stream) + { + char buffer[20]; + stream->read((char*) &frame, sizeof(int)); + stream->read((char*) &display, sizeof(uint8_t)); + int ik_count; + stream->read((char*) &ik_count, sizeof(int)); + ik_enable.resize(ik_count); + for (int i = 0; i < ik_count; i++) + { + stream->read(buffer, 20); + ik_enable[i].ik_name = std::string(buffer); + stream->read((char*) &ik_enable[i].enable, sizeof(uint8_t)); + } + } + + void Write(std::ostream *stream) + { + stream->write((char*)&frame, sizeof(int)); + stream->write((char*)&display, sizeof(uint8_t)); + int ik_count = static_cast(ik_enable.size()); + stream->write((char*)&ik_count, sizeof(int)); + for (int i = 0; i < ik_count; i++) + { + const VmdIkEnable& ik_enable = this->ik_enable.at(i); + stream->write(ik_enable.ik_name.c_str(), 20); + stream->write((char*)&ik_enable.enable, sizeof(uint8_t)); + } + } + }; + + class VmdMotion + { + public: + std::string model_name; + int version; + std::vector bone_frames; + std::vector face_frames; + std::vector camera_frames; + std::vector light_frames; + std::vector ik_frames; + + static std::unique_ptr LoadFromFile(char const *filename) + { + std::ifstream stream(filename, std::ios::binary); + auto result = LoadFromStream(&stream); + stream.close(); + return result; + } + + static std::unique_ptr LoadFromStream(std::ifstream *stream) + { + + char buffer[30]; + auto result = mmd::make_unique(); + + // magic and version + stream->read((char*) buffer, 30); + if (strncmp(buffer, "Vocaloid Motion Data", 20)) + { + std::cerr << "invalid vmd file." << std::endl; + return nullptr; + } + result->version = std::atoi(buffer + 20); + + // name + stream->read(buffer, 20); + result->model_name = std::string(buffer); + + // bone frames + int bone_frame_num; + stream->read((char*) &bone_frame_num, sizeof(int)); + result->bone_frames.resize(bone_frame_num); + for (int i = 0; i < bone_frame_num; i++) + { + result->bone_frames[i].Read(stream); + } + + // face frames + int face_frame_num; + stream->read((char*) &face_frame_num, sizeof(int)); + result->face_frames.resize(face_frame_num); + for (int i = 0; i < face_frame_num; i++) + { + result->face_frames[i].Read(stream); + } + + // camera frames + int camera_frame_num; + stream->read((char*) &camera_frame_num, sizeof(int)); + result->camera_frames.resize(camera_frame_num); + for (int i = 0; i < camera_frame_num; i++) + { + result->camera_frames[i].Read(stream); + } + + // light frames + int light_frame_num; + stream->read((char*) &light_frame_num, sizeof(int)); + result->light_frames.resize(light_frame_num); + for (int i = 0; i < light_frame_num; i++) + { + result->light_frames[i].Read(stream); + } + + // unknown2 + stream->read(buffer, 4); + + // ik frames + if (stream->peek() != std::ios::traits_type::eof()) + { + int ik_num; + stream->read((char*) &ik_num, sizeof(int)); + result->ik_frames.resize(ik_num); + for (int i = 0; i < ik_num; i++) + { + result->ik_frames[i].Read(stream); + } + } + + if (stream->peek() != std::ios::traits_type::eof()) + { + std::cerr << "vmd stream has unknown data." << std::endl; + } + + return result; + } + + bool SaveToFile(const std::u16string& /*filename*/) + { + // TODO: How to adapt u16string to string? + /* + std::ofstream stream(filename.c_str(), std::ios::binary); + auto result = SaveToStream(&stream); + stream.close(); + return result; + */ + return false; + } + + bool SaveToStream(std::ofstream *stream) + { + std::string magic = "Vocaloid Motion Data 0002\0"; + magic.resize(30); + + // magic and version + stream->write(magic.c_str(), 30); + + // name + stream->write(model_name.c_str(), 20); + + // bone frames + const int bone_frame_num = static_cast(bone_frames.size()); + stream->write(reinterpret_cast(&bone_frame_num), sizeof(int)); + for (int i = 0; i < bone_frame_num; i++) + { + bone_frames[i].Write(stream); + } + + // face frames + const int face_frame_num = static_cast(face_frames.size()); + stream->write(reinterpret_cast(&face_frame_num), sizeof(int)); + for (int i = 0; i < face_frame_num; i++) + { + face_frames[i].Write(stream); + } + + // camera frames + const int camera_frame_num = static_cast(camera_frames.size()); + stream->write(reinterpret_cast(&camera_frame_num), sizeof(int)); + for (int i = 0; i < camera_frame_num; i++) + { + camera_frames[i].Write(stream); + } + + // light frames + const int light_frame_num = static_cast(light_frames.size()); + stream->write(reinterpret_cast(&light_frame_num), sizeof(int)); + for (int i = 0; i < light_frame_num; i++) + { + light_frames[i].Write(stream); + } + + // self shadow datas + const int self_shadow_num = 0; + stream->write(reinterpret_cast(&self_shadow_num), sizeof(int)); + + // ik frames + const int ik_num = static_cast(ik_frames.size()); + stream->write(reinterpret_cast(&ik_num), sizeof(int)); + for (int i = 0; i < ik_num; i++) + { + ik_frames[i].Write(stream); + } + + return true; + } + }; +} diff --git a/code/MS3DLoader.cpp b/code/MS3DLoader.cpp index c50ccc46e..64ec1e076 100644 --- a/code/MS3DLoader.cpp +++ b/code/MS3DLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -53,7 +54,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include - +#include +#include using namespace Assimp; diff --git a/code/MS3DLoader.h b/code/MS3DLoader.h index 22d12e3cf..b4b19b3ad 100644 --- a/code/MS3DLoader.h +++ b/code/MS3DLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/MakeVerboseFormat.cpp b/code/MakeVerboseFormat.cpp index be68bf3d6..720d44519 100644 --- a/code/MakeVerboseFormat.cpp +++ b/code/MakeVerboseFormat.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -192,14 +193,14 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh) p = 0; while (pcMesh->HasTextureCoords(p)) { - delete pcMesh->mTextureCoords[p]; + delete[] pcMesh->mTextureCoords[p]; pcMesh->mTextureCoords[p] = apvTextureCoords[p]; ++p; } p = 0; while (pcMesh->HasVertexColors(p)) { - delete pcMesh->mColors[p]; + delete[] pcMesh->mColors[p]; pcMesh->mColors[p] = apvColorSets[p]; ++p; } diff --git a/code/MakeVerboseFormat.h b/code/MakeVerboseFormat.h index 1b32cf19e..9832a3f65 100644 --- a/code/MakeVerboseFormat.h +++ b/code/MakeVerboseFormat.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/MaterialSystem.cpp b/code/MaterialSystem.cpp index 5fcf28a4f..55f1a4ff5 100644 --- a/code/MaterialSystem.cpp +++ b/code/MaterialSystem.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -455,6 +456,9 @@ aiReturn aiMaterial::AddBinaryProperty (const void* pInput, ai_assert (pKey != NULL); ai_assert (0 != pSizeInBytes); + if ( 0 == pSizeInBytes ) { + + } // first search the list whether there is already an entry with this key unsigned int iOutIndex = UINT_MAX; for (unsigned int i = 0; i < mNumProperties;++i) { diff --git a/code/MaterialSystem.h b/code/MaterialSystem.h index 6726e0518..b083a5bb8 100644 --- a/code/MaterialSystem.h +++ b/code/MaterialSystem.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/MemoryIOWrapper.h b/code/MemoryIOWrapper.h index d6aaafae0..9bd245337 100644 --- a/code/MemoryIOWrapper.h +++ b/code/MemoryIOWrapper.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/NDOLoader.cpp b/code/NDOLoader.cpp index cf3d6edf6..2586bac3e 100644 --- a/code/NDOLoader.cpp +++ b/code/NDOLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -49,7 +50,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include "StreamReader.h" +#include using namespace Assimp; diff --git a/code/NFFLoader.cpp b/code/NFFLoader.cpp index 8cc1624d5..a51c500f1 100644 --- a/code/NFFLoader.cpp +++ b/code/NFFLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -54,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include @@ -241,8 +243,6 @@ void NFFImporter::InternReadFile( const std::string& pFile, if( !file.get()) throw DeadlyImportError( "Failed to open NFF file " + pFile + "."); - unsigned int m = (unsigned int)file->FileSize(); - // allocate storage and copy the contents of the file to a memory buffer // (terminate it with zero) std::vector mBuffer2; @@ -467,7 +467,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, for (unsigned int a = 0; a < numIdx;++a) { SkipSpaces(sz,&sz); - m = ::strtoul10(sz,&sz); + unsigned int m = ::strtoul10(sz,&sz); if (m >= (unsigned int)tempPositions.size()) { DefaultLogger::get()->error("NFF2: Vertex index overflow"); @@ -633,7 +633,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, for (std::vector::const_iterator it = tempIdx.begin(), end = tempIdx.end(); it != end;++it) { - m = *it; + unsigned int m = *it; // copy colors -vertex color specifications override polygon color specifications if (hasColor) @@ -733,7 +733,7 @@ void NFFImporter::InternReadFile( const std::string& pFile, sz = &line[1];out = currentMesh; } SkipSpaces(sz,&sz); - m = strtoul10(sz); + unsigned int m = strtoul10(sz); // ---- flip the face order out->vertices.resize(out->vertices.size()+m); @@ -1079,7 +1079,9 @@ void NFFImporter::InternReadFile( const std::string& pFile, // generate the camera if (hasCam) { - aiNode* nd = *ppcChildren = new aiNode(); + ai_assert(ppcChildren); + aiNode* nd = new aiNode(); + *ppcChildren = nd; nd->mName.Set(""); nd->mParent = root; @@ -1103,13 +1105,15 @@ void NFFImporter::InternReadFile( const std::string& pFile, // generate light sources if (!lights.empty()) { + ai_assert(ppcChildren); pScene->mNumLights = (unsigned int)lights.size(); pScene->mLights = new aiLight*[pScene->mNumLights]; for (unsigned int i = 0; i < pScene->mNumLights;++i,++ppcChildren) { const Light& l = lights[i]; - aiNode* nd = *ppcChildren = new aiNode(); + aiNode* nd = new aiNode(); + *ppcChildren = nd; nd->mParent = root; nd->mName.length = ::ai_snprintf(nd->mName.data,1024,"",i); @@ -1126,7 +1130,8 @@ void NFFImporter::InternReadFile( const std::string& pFile, if (!pScene->mNumMeshes)throw DeadlyImportError("NFF: No meshes loaded"); pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = pScene->mNumMeshes]; - for (it = meshes.begin(), m = 0; it != end;++it) + unsigned int m = 0; + for (it = meshes.begin(); it != end;++it) { if ((*it).faces.empty())continue; diff --git a/code/NFFLoader.h b/code/NFFLoader.h index 2b5232645..0640d4405 100644 --- a/code/NFFLoader.h +++ b/code/NFFLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/OFFLoader.cpp b/code/OFFLoader.cpp index cb2226bf6..5038176e2 100644 --- a/code/OFFLoader.cpp +++ b/code/OFFLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -54,7 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include - +#include using namespace Assimp; @@ -93,7 +94,7 @@ bool OFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool { if (!pIOHandler)return true; const char* tokens[] = {"off"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); + return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1,3); } return false; } diff --git a/code/OFFLoader.h b/code/OFFLoader.h index f01dc6244..29a4927bd 100644 --- a/code/OFFLoader.h +++ b/code/OFFLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/ObjExporter.cpp b/code/ObjExporter.cpp index aada4efd7..a8bf9935a 100644 --- a/code/ObjExporter.cpp +++ b/code/ObjExporter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -38,8 +39,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ - - #ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER @@ -53,17 +52,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include - using namespace Assimp; -namespace Assimp { + +namespace Assimp { // ------------------------------------------------------------------------------------------------ // Worker function for exporting a scene to Wavefront OBJ. Prototyped and registered in Exporter.cpp -void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) -{ +void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { // invoke the exporter ObjExporter exporter(pFile, pScene); + if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) { + throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); + } + // we're still here - export successfully completed. Write both the main OBJ file and the material script { std::unique_ptr outfile (pIOSystem->Open(pFile,"wt")); @@ -81,16 +83,46 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene } } +// ------------------------------------------------------------------------------------------------ +// Worker function for exporting a scene to Wavefront OBJ without the material file. Prototyped and registered in Exporter.cpp +void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) { + // invoke the exporter + ObjExporter exporter(pFile, pScene, true); + + if (exporter.mOutput.fail() || exporter.mOutputMat.fail()) { + throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); + } + + // we're still here - export successfully completed. Write both the main OBJ file and the material script + { + std::unique_ptr outfile (pIOSystem->Open(pFile,"wt")); + if(outfile == NULL) { + throw DeadlyExportError("could not open output .obj file: " + std::string(pFile)); + } + outfile->Write( exporter.mOutput.str().c_str(), static_cast(exporter.mOutput.tellp()),1); + } + + +} + } // end of namespace Assimp static const std::string MaterialExt = ".mtl"; // ------------------------------------------------------------------------------------------------ -ObjExporter :: ObjExporter(const char* _filename, const aiScene* pScene) +ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMtl) : filename(_filename) , pScene(pScene) -, endl("\n") -{ +, vp() +, vn() +, vt() +, vc() +, mVpMap() +, mVnMap() +, mVtMap() +, mVcMap() +, mMeshes() +, endl("\n") { // make sure that all formatting happens using the standard, C locale and not the user's current locale const std::locale& l = std::locale("C"); mOutput.imbue(l); @@ -98,8 +130,14 @@ ObjExporter :: ObjExporter(const char* _filename, const aiScene* pScene) mOutputMat.imbue(l); mOutputMat.precision(16); - WriteGeometryFile(); - WriteMaterialFile(); + WriteGeometryFile(noMtl); + if (!noMtl) + WriteMaterialFile(); +} + +// ------------------------------------------------------------------------------------------------ +ObjExporter::~ObjExporter() { + } // ------------------------------------------------------------------------------------------------ @@ -116,22 +154,31 @@ std::string ObjExporter :: GetMaterialLibName() } // ------------------------------------------------------------------------------------------------ -std::string ObjExporter :: GetMaterialLibFileName() -{ +std::string ObjExporter::GetMaterialLibFileName() { + // Remove existing .obj file extension so that the final material file name will be fileName.mtl and not fileName.obj.mtl + size_t lastdot = filename.find_last_of('.'); + if (lastdot != std::string::npos) + return filename.substr(0, lastdot) + MaterialExt; + return filename + MaterialExt; } // ------------------------------------------------------------------------------------------------ -void ObjExporter :: WriteHeader(std::ostringstream& out) -{ +void ObjExporter::WriteHeader(std::ostringstream& out) { out << "# File produced by Open Asset Import Library (http://www.assimp.sf.net)" << endl; - out << "# (assimp v" << aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.' << aiGetVersionRevision() << ")" << endl << endl; + out << "# (assimp v" << aiGetVersionMajor() << '.' << aiGetVersionMinor() << '.' + << aiGetVersionRevision() << ")" << endl << endl; } // ------------------------------------------------------------------------------------------------ -std::string ObjExporter :: GetMaterialName(unsigned int index) +std::string ObjExporter::GetMaterialName(unsigned int index) { const aiMaterial* const mat = pScene->mMaterials[index]; + if ( nullptr == mat ) { + static const std::string EmptyStr; + return EmptyStr; + } + aiString s; if(AI_SUCCESS == mat->Get(AI_MATKEY_NAME,s)) { return std::string(s.data,s.length); @@ -166,11 +213,17 @@ void ObjExporter::WriteMaterialFile() if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_EMISSIVE,c)) { mOutputMat << "Ke " << c.r << " " << c.g << " " << c.b << endl; } + if(AI_SUCCESS == mat->Get(AI_MATKEY_COLOR_TRANSPARENT,c)) { + mOutputMat << "Tf " << c.r << " " << c.g << " " << c.b << endl; + } ai_real o; if(AI_SUCCESS == mat->Get(AI_MATKEY_OPACITY,o)) { mOutputMat << "d " << o << endl; } + if(AI_SUCCESS == mat->Get(AI_MATKEY_REFRACTI,o)) { + mOutputMat << "Ni " << o << endl; + } if(AI_SUCCESS == mat->Get(AI_MATKEY_SHININESS,o) && o) { mOutputMat << "Ns " << o << endl; @@ -205,26 +258,37 @@ void ObjExporter::WriteMaterialFile() } } -// ------------------------------------------------------------------------------------------------ -void ObjExporter :: WriteGeometryFile() -{ +void ObjExporter::WriteGeometryFile(bool noMtl) { WriteHeader(mOutput); - mOutput << "mtllib " << GetMaterialLibName() << endl << endl; + if (!noMtl) + mOutput << "mtllib " << GetMaterialLibName() << endl << endl; // collect mesh geometry aiMatrix4x4 mBase; AddNode(pScene->mRootNode, mBase); - // write vertex positions - vpMap.getVectors(vp); - mOutput << "# " << vp.size() << " vertex positions" << endl; - for(const aiVector3D& v : vp) { - mOutput << "v " << v.x << " " << v.y << " " << v.z << endl; + // write vertex positions with colors, if any + mVpMap.getVectors( vp ); + mVcMap.getColors( vc ); + if ( vc.empty() ) { + mOutput << "# " << vp.size() << " vertex positions" << endl; + for ( const aiVector3D& v : vp ) { + mOutput << "v " << v.x << " " << v.y << " " << v.z << endl; + } + } else { + mOutput << "# " << vp.size() << " vertex positions and colors" << endl; + size_t colIdx = 0; + for ( const aiVector3D& v : vp ) { + if ( colIdx < vc.size() ) { + mOutput << "v " << v.x << " " << v.y << " " << v.z << " " << vc[ colIdx ].r << " " << vc[ colIdx ].g << " " << vc[ colIdx ].b << endl; + } + ++colIdx; + } } mOutput << endl; // write uv coordinates - vtMap.getVectors(vt); + mVtMap.getVectors(vt); mOutput << "# " << vt.size() << " UV coordinates" << endl; for(const aiVector3D& v : vt) { mOutput << "vt " << v.x << " " << v.y << " " << v.z << endl; @@ -232,7 +296,7 @@ void ObjExporter :: WriteGeometryFile() mOutput << endl; // write vertex normals - vnMap.getVectors(vn); + mVnMap.getVectors(vn); mOutput << "# " << vn.size() << " vertex normals" << endl; for(const aiVector3D& v : vn) { mOutput << "vn " << v.x << " " << v.y << " " << v.z << endl; @@ -240,12 +304,13 @@ void ObjExporter :: WriteGeometryFile() mOutput << endl; // now write all mesh instances - for(const MeshInstance& m : meshes) { + for(const MeshInstance& m : mMeshes) { mOutput << "# Mesh \'" << m.name << "\' with " << m.faces.size() << " faces" << endl; if (!m.name.empty()) { mOutput << "g " << m.name << endl; } - mOutput << "usemtl " << m.matname << endl; + if (!noMtl) + mOutput << "usemtl " << m.matname << endl; for(const Face& f : m.faces) { mOutput << f.kind << ' '; @@ -272,8 +337,7 @@ void ObjExporter :: WriteGeometryFile() } // ------------------------------------------------------------------------------------------------ -int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec) -{ +int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec) { vecIndexMap::dataType::iterator vertIt = vecMap.find(vec); // vertex already exists, so reference it if(vertIt != vecMap.end()){ @@ -286,8 +350,7 @@ int ObjExporter::vecIndexMap::getIndex(const aiVector3D& vec) } // ------------------------------------------------------------------------------------------------ -void ObjExporter::vecIndexMap::getVectors( std::vector& vecs ) -{ +void ObjExporter::vecIndexMap::getVectors( std::vector& vecs ) { vecs.resize(vecMap.size()); for(vecIndexMap::dataType::iterator it = vecMap.begin(); it != vecMap.end(); ++it){ vecs[it->second-1] = it->first; @@ -295,12 +358,33 @@ void ObjExporter::vecIndexMap::getVectors( std::vector& vecs ) } // ------------------------------------------------------------------------------------------------ -void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) -{ - meshes.push_back(MeshInstance()); - MeshInstance& mesh = meshes.back(); +int ObjExporter::colIndexMap::getIndex( const aiColor4D& col ) { + colIndexMap::dataType::iterator vertIt = colMap.find( col ); + // vertex already exists, so reference it + if ( vertIt != colMap.end() ) { + return vertIt->second; + } + colMap[ col ] = mNextIndex; + int ret = mNextIndex; + mNextIndex++; - mesh.name = std::string(name.data,name.length) + (m->mName.length ? "_" + std::string(m->mName.data,m->mName.length) : ""); + return ret; +} + +// ------------------------------------------------------------------------------------------------ +void ObjExporter::colIndexMap::getColors( std::vector &colors ) { + colors.resize( colMap.size() ); + for ( colIndexMap::dataType::iterator it = colMap.begin(); it != colMap.end(); ++it ) { + colors[ it->second - 1 ] = it->first; + } +} + +// ------------------------------------------------------------------------------------------------ +void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) { + mMeshes.push_back(MeshInstance()); + MeshInstance& mesh = mMeshes.back(); + + mesh.name = std::string( name.data, name.length ); mesh.matname = GetMaterialName(m->mMaterialIndex); mesh.faces.resize(m->mNumFaces); @@ -325,20 +409,25 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4 const unsigned int idx = f.mIndices[a]; aiVector3D vert = mat * m->mVertices[idx]; - face.indices[a].vp = vpMap.getIndex(vert); + face.indices[a].vp = mVpMap.getIndex(vert); if (m->mNormals) { aiVector3D norm = aiMatrix3x3(mat) * m->mNormals[idx]; - face.indices[a].vn = vnMap.getIndex(norm); - } - else{ + face.indices[a].vn = mVnMap.getIndex(norm); + } else { face.indices[a].vn = 0; } - if (m->mTextureCoords[0]) { - face.indices[a].vt = vtMap.getIndex(m->mTextureCoords[0][idx]); + if ( nullptr != m->mColors[ 0 ] ) { + aiColor4D col4 = m->mColors[ 0 ][ idx ]; + face.indices[ a ].vc = mVcMap.getIndex( col4 ); + } else { + face.indices[ a ].vc = 0; } - else{ + + if ( m->mTextureCoords[ 0 ] ) { + face.indices[a].vt = mVtMap.getIndex(m->mTextureCoords[0][idx]); + } else { face.indices[a].vt = 0; } } diff --git a/code/ObjExporter.h b/code/ObjExporter.h index 9d817f067..391f8416d 100644 --- a/code/ObjExporter.h +++ b/code/ObjExporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -53,40 +54,35 @@ struct aiScene; struct aiNode; struct aiMesh; -namespace Assimp -{ +namespace Assimp { // ------------------------------------------------------------------------------------------------ /** Helper class to export a given scene to an OBJ file. */ // ------------------------------------------------------------------------------------------------ -class ObjExporter -{ +class ObjExporter { public: /// Constructor for a specific scene to export - ObjExporter(const char* filename, const aiScene* pScene); - -public: - + ObjExporter(const char* filename, const aiScene* pScene, bool noMtl=false); + ~ObjExporter(); std::string GetMaterialLibName(); std::string GetMaterialLibFileName(); - -public: - - /// public stringstreams to write all output into + + /// public string-streams to write all output into std::ostringstream mOutput, mOutputMat; private: - // intermediate data structures - struct FaceVertex - { + struct FaceVertex { FaceVertex() - : vp(),vn(),vt() - { + : vp() + , vn() + , vt() + , vc() { + // empty } // one-based, 0 means: 'does not exist' - unsigned int vp,vn,vt; + unsigned int vp, vn, vt, vc; }; struct Face { @@ -95,33 +91,25 @@ private: }; struct MeshInstance { - std::string name, matname; std::vector faces; }; void WriteHeader(std::ostringstream& out); - void WriteMaterialFile(); - void WriteGeometryFile(); - + void WriteGeometryFile(bool noMtl=false); std::string GetMaterialName(unsigned int index); - void AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat); void AddNode(const aiNode* nd, const aiMatrix4x4& mParent); private: - - const std::string filename; + std::string filename; const aiScene* const pScene; - std::vector vp, vn, vt; + std::vector vc; - - struct aiVectorCompare - { - bool operator() (const aiVector3D& a, const aiVector3D& b) const - { + struct aiVectorCompare { + bool operator() (const aiVector3D& a, const aiVector3D& b) const { if(a.x < b.x) return true; if(a.x > b.x) return false; if(a.y < b.y) return true; @@ -131,22 +119,53 @@ private: } }; - class vecIndexMap - { + struct aiColor4Compare { + bool operator() ( const aiColor4D& a, const aiColor4D& b ) const { + if ( a.r < b.r ) return true; + if ( a.r > b.r ) return false; + if ( a.g < b.g ) return true; + if ( a.g > b.g ) return false; + if ( a.b < b.b ) return true; + if ( a.b > b.b ) return false; + if ( a.a < b.a ) return true; + if ( a.a > b.a ) return false; + return false; + } + }; + + class vecIndexMap { int mNextIndex; typedef std::map dataType; dataType vecMap; + public: - - vecIndexMap():mNextIndex(1) - {} + vecIndexMap() + : mNextIndex(1) { + // empty + } int getIndex(const aiVector3D& vec); void getVectors( std::vector& vecs ); }; - vecIndexMap vpMap, vnMap, vtMap; - std::vector meshes; + class colIndexMap { + int mNextIndex; + typedef std::map dataType; + dataType colMap; + + public: + colIndexMap() + : mNextIndex( 1 ) { + // empty + } + + int getIndex( const aiColor4D& col ); + void getColors( std::vector &colors ); + }; + + vecIndexMap mVpMap, mVnMap, mVtMap; + colIndexMap mVcMap; + std::vector mMeshes; // this endl() doesn't flush() the stream const std::string endl; diff --git a/code/ObjFileData.h b/code/ObjFileData.h index c72175d4d..2658f8a2a 100644 --- a/code/ObjFileData.h +++ b/code/ObjFileData.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -178,6 +179,8 @@ struct Material { int illumination_model; //! Index of refraction ai_real ior; + //! Transparency color + aiColor3D transparent; //! Constructor Material() @@ -185,7 +188,8 @@ struct Material { , alpha (ai_real( 1.0 ) ) , shineness ( ai_real( 0.0) ) , illumination_model (1) - , ior ( ai_real( 1.0 ) ) { + , ior ( ai_real( 1.0 ) ) + , transparent( ai_real( 1.0), ai_real (1.0), ai_real(1.0)) { // empty for (size_t i = 0; i < TextureTypeCount; ++i) { clamp[ i ] = false; diff --git a/code/ObjFileImporter.cpp b/code/ObjFileImporter.cpp index a30c640a6..9f3bdef97 100644 --- a/code/ObjFileImporter.cpp +++ b/code/ObjFileImporter.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -41,16 +42,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER -#include "DefaultIOSystem.h" #include "ObjFileImporter.h" #include "ObjFileParser.h" #include "ObjFileData.h" #include "IOStreamBuffer.h" #include +#include #include #include #include #include +#include static const aiImporterDesc desc = { "Wavefront Object Importer", @@ -607,14 +609,18 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc mat->AddProperty( &pCurrentMaterial->emissive, 1, AI_MATKEY_COLOR_EMISSIVE ); mat->AddProperty( &pCurrentMaterial->shineness, 1, AI_MATKEY_SHININESS ); mat->AddProperty( &pCurrentMaterial->alpha, 1, AI_MATKEY_OPACITY ); + mat->AddProperty( &pCurrentMaterial->transparent,1,AI_MATKEY_COLOR_TRANSPARENT); // Adding refraction index mat->AddProperty( &pCurrentMaterial->ior, 1, AI_MATKEY_REFRACTI ); // Adding textures + const int uvwIndex = 0; + if ( 0 != pCurrentMaterial->texture.length ) { mat->AddProperty( &pCurrentMaterial->texture, AI_MATKEY_TEXTURE_DIFFUSE(0)); + mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_DIFFUSE(0) ); if (pCurrentMaterial->clamp[ObjFile::Material::TextureDiffuseType]) { addTextureMappingModeProperty(mat, aiTextureType_DIFFUSE); @@ -624,6 +630,7 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc if ( 0 != pCurrentMaterial->textureAmbient.length ) { mat->AddProperty( &pCurrentMaterial->textureAmbient, AI_MATKEY_TEXTURE_AMBIENT(0)); + mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_AMBIENT(0) ); if (pCurrentMaterial->clamp[ObjFile::Material::TextureAmbientType]) { addTextureMappingModeProperty(mat, aiTextureType_AMBIENT); @@ -631,11 +638,15 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc } if ( 0 != pCurrentMaterial->textureEmissive.length ) + { mat->AddProperty( &pCurrentMaterial->textureEmissive, AI_MATKEY_TEXTURE_EMISSIVE(0)); + mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_EMISSIVE(0) ); + } if ( 0 != pCurrentMaterial->textureSpecular.length ) { mat->AddProperty( &pCurrentMaterial->textureSpecular, AI_MATKEY_TEXTURE_SPECULAR(0)); + mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_SPECULAR(0) ); if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularType]) { addTextureMappingModeProperty(mat, aiTextureType_SPECULAR); @@ -645,6 +656,7 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc if ( 0 != pCurrentMaterial->textureBump.length ) { mat->AddProperty( &pCurrentMaterial->textureBump, AI_MATKEY_TEXTURE_HEIGHT(0)); + mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_HEIGHT(0) ); if (pCurrentMaterial->clamp[ObjFile::Material::TextureBumpType]) { addTextureMappingModeProperty(mat, aiTextureType_HEIGHT); @@ -654,6 +666,7 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc if ( 0 != pCurrentMaterial->textureNormal.length ) { mat->AddProperty( &pCurrentMaterial->textureNormal, AI_MATKEY_TEXTURE_NORMALS(0)); + mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_NORMALS(0) ); if (pCurrentMaterial->clamp[ObjFile::Material::TextureNormalType]) { addTextureMappingModeProperty(mat, aiTextureType_NORMALS); @@ -670,6 +683,7 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc for( unsigned i = 0; i < count; i++ ) { mat->AddProperty(&pCurrentMaterial->textureReflection[i], AI_MATKEY_TEXTURE_REFLECTION(i)); + mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_REFLECTION(i) ); if(pCurrentMaterial->clamp[type]) addTextureMappingModeProperty(mat, aiTextureType_REFLECTION, 1, i); @@ -679,6 +693,7 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc if ( 0 != pCurrentMaterial->textureDisp.length ) { mat->AddProperty( &pCurrentMaterial->textureDisp, AI_MATKEY_TEXTURE_DISPLACEMENT(0) ); + mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_DISPLACEMENT(0) ); if (pCurrentMaterial->clamp[ObjFile::Material::TextureDispType]) { addTextureMappingModeProperty(mat, aiTextureType_DISPLACEMENT); @@ -688,6 +703,7 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc if ( 0 != pCurrentMaterial->textureOpacity.length ) { mat->AddProperty( &pCurrentMaterial->textureOpacity, AI_MATKEY_TEXTURE_OPACITY(0)); + mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_OPACITY(0) ); if (pCurrentMaterial->clamp[ObjFile::Material::TextureOpacityType]) { addTextureMappingModeProperty(mat, aiTextureType_OPACITY); @@ -697,6 +713,7 @@ void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pSc if ( 0 != pCurrentMaterial->textureSpecularity.length ) { mat->AddProperty( &pCurrentMaterial->textureSpecularity, AI_MATKEY_TEXTURE_SHININESS(0)); + mat->AddProperty( &uvwIndex, 1, AI_MATKEY_UVWSRC_SHININESS(0) ); if (pCurrentMaterial->clamp[ObjFile::Material::TextureSpecularityType]) { addTextureMappingModeProperty(mat, aiTextureType_SHININESS); diff --git a/code/ObjFileImporter.h b/code/ObjFileImporter.h index bd3f42f27..302cf951a 100644 --- a/code/ObjFileImporter.h +++ b/code/ObjFileImporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/ObjFileMtlImporter.cpp b/code/ObjFileMtlImporter.cpp index 0a62a0c2c..6ef655f8a 100644 --- a/code/ObjFileMtlImporter.cpp +++ b/code/ObjFileMtlImporter.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -54,20 +55,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { -// Material specific token -static const std::string DiffuseTexture = "map_Kd"; -static const std::string AmbientTexture = "map_Ka"; -static const std::string SpecularTexture = "map_Ks"; -static const std::string OpacityTexture = "map_d"; -static const std::string EmissiveTexture = "map_emissive"; -static const std::string EmissiveTexture_1 = "map_Ke"; -static const std::string BumpTexture1 = "map_bump"; -static const std::string BumpTexture2 = "map_Bump"; -static const std::string BumpTexture3 = "bump"; -static const std::string NormalTexture = "map_Kn"; -static const std::string ReflectionTexture = "refl"; -static const std::string DisplacementTexture = "disp"; -static const std::string SpecularityTexture = "map_ns"; +// Material specific token (case insensitive compare) +static const std::string DiffuseTexture = "map_Kd"; +static const std::string AmbientTexture = "map_Ka"; +static const std::string SpecularTexture = "map_Ks"; +static const std::string OpacityTexture = "map_d"; +static const std::string EmissiveTexture1 = "map_emissive"; +static const std::string EmissiveTexture2 = "map_Ke"; +static const std::string BumpTexture1 = "map_bump"; +static const std::string BumpTexture2 = "bump"; +static const std::string NormalTexture = "map_Kn"; +static const std::string ReflectionTexture = "refl"; +static const std::string DisplacementTexture1 = "map_disp"; +static const std::string DisplacementTexture2 = "disp"; +static const std::string SpecularityTexture = "map_ns"; // texture option specific token static const std::string BlendUOption = "-blendu"; @@ -163,7 +164,17 @@ void ObjFileMtlImporter::load() m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); } break; - + case 'T': + { + ++m_DataIt; + if (*m_DataIt == 'f') // Material transmission + { + ++m_DataIt; + getColorRGBA( &m_pModel->m_pCurrentMaterial->transparent); + } + m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); + } + break; case 'd': { if( *(m_DataIt+1) == 'i' && *( m_DataIt + 2 ) == 's' && *( m_DataIt + 3 ) == 'p' ) { @@ -292,6 +303,9 @@ void ObjFileMtlImporter::createMaterial() // New Material created m_pModel->m_pCurrentMaterial = new ObjFile::Material(); m_pModel->m_pCurrentMaterial->MaterialName.Set( name ); + if (m_pModel->m_pCurrentMesh) { + m_pModel->m_pCurrentMesh->m_uiMaterialIndex = static_cast(m_pModel->m_MaterialLib.size() - 1); + } m_pModel->m_MaterialLib.push_back( name ); m_pModel->m_MaterialMap[ name ] = m_pModel->m_pCurrentMaterial; } else { @@ -315,7 +329,7 @@ void ObjFileMtlImporter::getTexture() { // Ambient texture out = & m_pModel->m_pCurrentMaterial->textureAmbient; clampIndex = ObjFile::Material::TextureAmbientType; - } else if (!ASSIMP_strincmp( pPtr, SpecularTexture.c_str(), static_cast(SpecularTexture.size()) ) ) { + } else if ( !ASSIMP_strincmp( pPtr, SpecularTexture.c_str(), static_cast(SpecularTexture.size()) ) ) { // Specular texture out = & m_pModel->m_pCurrentMaterial->textureSpecular; clampIndex = ObjFile::Material::TextureSpecularType; @@ -323,33 +337,30 @@ void ObjFileMtlImporter::getTexture() { // Opacity texture out = & m_pModel->m_pCurrentMaterial->textureOpacity; clampIndex = ObjFile::Material::TextureOpacityType; - } else if (!ASSIMP_strincmp( pPtr, EmissiveTexture.c_str(), static_cast(EmissiveTexture.size()) ) ) { + } else if ( !ASSIMP_strincmp( pPtr, EmissiveTexture1.c_str(), static_cast(EmissiveTexture1.size()) ) || + !ASSIMP_strincmp( pPtr, EmissiveTexture2.c_str(), static_cast(EmissiveTexture2.size()) ) ) { // Emissive texture out = & m_pModel->m_pCurrentMaterial->textureEmissive; clampIndex = ObjFile::Material::TextureEmissiveType; - } else if ( !ASSIMP_strincmp( pPtr, EmissiveTexture_1.c_str(), static_cast(EmissiveTexture_1.size()) ) ) { - // Emissive texture - out = &m_pModel->m_pCurrentMaterial->textureEmissive; - clampIndex = ObjFile::Material::TextureEmissiveType; } else if ( !ASSIMP_strincmp( pPtr, BumpTexture1.c_str(), static_cast(BumpTexture1.size()) ) || - !ASSIMP_strincmp( pPtr, BumpTexture2.c_str(), static_cast(BumpTexture2.size()) ) || - !ASSIMP_strincmp( pPtr, BumpTexture3.c_str(), static_cast(BumpTexture3.size()) ) ) { + !ASSIMP_strincmp( pPtr, BumpTexture2.c_str(), static_cast(BumpTexture2.size()) ) ) { // Bump texture out = & m_pModel->m_pCurrentMaterial->textureBump; clampIndex = ObjFile::Material::TextureBumpType; - } else if (!ASSIMP_strincmp( pPtr,NormalTexture.c_str(), static_cast(NormalTexture.size()) ) ) { + } else if ( !ASSIMP_strincmp( pPtr,NormalTexture.c_str(), static_cast(NormalTexture.size()) ) ) { // Normal map out = & m_pModel->m_pCurrentMaterial->textureNormal; clampIndex = ObjFile::Material::TextureNormalType; - } else if(!ASSIMP_strincmp( pPtr, ReflectionTexture.c_str(), static_cast(ReflectionTexture.size()) ) ) { + } else if( !ASSIMP_strincmp( pPtr, ReflectionTexture.c_str(), static_cast(ReflectionTexture.size()) ) ) { // Reflection texture(s) //Do nothing here return; - } else if (!ASSIMP_strincmp( pPtr, DisplacementTexture.c_str(), static_cast(DisplacementTexture.size()) ) ) { + } else if ( !ASSIMP_strincmp( pPtr, DisplacementTexture1.c_str(), static_cast(DisplacementTexture1.size()) ) || + !ASSIMP_strincmp( pPtr, DisplacementTexture2.c_str(), static_cast(DisplacementTexture2.size()) ) ) { // Displacement texture out = &m_pModel->m_pCurrentMaterial->textureDisp; clampIndex = ObjFile::Material::TextureDispType; - } else if (!ASSIMP_strincmp( pPtr, SpecularityTexture.c_str(), static_cast(SpecularityTexture.size()) ) ) { + } else if ( !ASSIMP_strincmp( pPtr, SpecularityTexture.c_str(), static_cast(SpecularityTexture.size()) ) ) { // Specularity scaling (glossiness) out = & m_pModel->m_pCurrentMaterial->textureSpecularity; clampIndex = ObjFile::Material::TextureSpecularityType; diff --git a/code/ObjFileMtlImporter.h b/code/ObjFileMtlImporter.h index 54e4b7cef..c9bcc9a9f 100644 --- a/code/ObjFileMtlImporter.h +++ b/code/ObjFileMtlImporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -112,4 +113,4 @@ private: } // Namespace Assimp -#endif +#endif // OBJFILEMTLIMPORTER_H_INC diff --git a/code/ObjFileParser.cpp b/code/ObjFileParser.cpp index df9fe6be9..d89d52977 100644 --- a/code/ObjFileParser.cpp +++ b/code/ObjFileParser.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -45,8 +46,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ObjTools.h" #include "ObjFileData.h" #include "ParsingUtils.h" -#include "DefaultIOSystem.h" #include "BaseImporter.h" +#include #include #include #include @@ -56,9 +57,18 @@ namespace Assimp { const std::string ObjFileParser::DEFAULT_MATERIAL = AI_DEFAULT_MATERIAL_NAME; -// ------------------------------------------------------------------- -// Constructor with loaded data and directories. -ObjFileParser::ObjFileParser( IOStreamBuffer &streamBuffer, const std::string &modelName, +ObjFileParser::ObjFileParser() +: m_DataIt() +, m_DataItEnd() +, m_pModel( NULL ) +, m_uiLine( 0 ) +, m_pIO( nullptr ) +, m_progress( nullptr ) +, m_originalObjFileName() { + // empty +} + +ObjFileParser::ObjFileParser( IOStreamBuffer &streamBuffer, const std::string &modelName, IOSystem *io, ProgressHandler* progress, const std::string &originalObjFileName) : m_DataIt(), @@ -85,21 +95,20 @@ ObjFileParser::ObjFileParser( IOStreamBuffer &streamBuffer, const std::str parseFile( streamBuffer ); } -// ------------------------------------------------------------------- -// Destructor ObjFileParser::~ObjFileParser() { delete m_pModel; m_pModel = NULL; } -// ------------------------------------------------------------------- -// Returns a pointer to the model instance. +void ObjFileParser::setBuffer( std::vector &buffer ) { + m_DataIt = buffer.begin(); + m_DataItEnd = buffer.end(); +} + ObjFile::Model *ObjFileParser::GetModel() const { return m_pModel; } -// ------------------------------------------------------------------- -// File parsing method. void ObjFileParser::parseFile( IOStreamBuffer &streamBuffer ) { // only update every 100KB or it'll be too slow //const unsigned int updateProgressEveryBytes = 100 * 1024; @@ -111,11 +120,11 @@ void ObjFileParser::parseFile( IOStreamBuffer &streamBuffer ) { size_t lastFilePos( 0 ); std::vector buffer; - while ( streamBuffer.getNextLine( buffer ) ) { + while ( streamBuffer.getNextDataLine( buffer, '\\' ) ) { m_DataIt = buffer.begin(); m_DataItEnd = buffer.end(); - // Handle progress reporting + // Handle progress reporting const size_t filePos( streamBuffer.getFilePos() ); if ( lastFilePos < filePos ) { processed += static_cast(filePos); @@ -130,7 +139,7 @@ void ObjFileParser::parseFile( IOStreamBuffer &streamBuffer ) { { ++m_DataIt; if (*m_DataIt == ' ' || *m_DataIt == '\t') { - size_t numComponents = getNumComponentsInLine(); + size_t numComponents = getNumComponentsInDataDefinition(); if (numComponents == 3) { // read in vertex definition getVector3(m_pModel->m_Vertices); @@ -170,7 +179,18 @@ void ObjFileParser::parseFile( IOStreamBuffer &streamBuffer ) { case 'u': // Parse a material desc. setter { - getMaterialDesc(); + std::string name; + + getNameNoSpace(m_DataIt, m_DataItEnd, name); + + size_t nextSpace = name.find(" "); + if (nextSpace != std::string::npos) + name = name.substr(0, nextSpace); + + if(name == "usemtl") + { + getMaterialDesc(); + } } break; @@ -214,7 +234,6 @@ void ObjFileParser::parseFile( IOStreamBuffer &streamBuffer ) { default: { pf_skip_line: - m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); } break; @@ -222,11 +241,14 @@ pf_skip_line: } } -// ------------------------------------------------------------------- -// Copy the next word in a temporary buffer void ObjFileParser::copyNextWord(char *pBuffer, size_t length) { size_t index = 0; m_DataIt = getNextWord(m_DataIt, m_DataItEnd); + if ( *m_DataIt == '\\' ) { + m_DataIt++; + m_DataIt++; + m_DataIt = getNextWord( m_DataIt, m_DataItEnd ); + } while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) { pBuffer[index] = *m_DataIt; index++; @@ -240,21 +262,44 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t length) { pBuffer[index] = '\0'; } -size_t ObjFileParser::getNumComponentsInLine() { +static bool isDataDefinitionEnd( const char *tmp ) { + if ( *tmp == '\\' ) { + tmp++; + if ( IsLineEnd( *tmp ) ) { + tmp++; + return true; + } + } + return false; +} + +size_t ObjFileParser::getNumComponentsInDataDefinition() { size_t numComponents( 0 ); const char* tmp( &m_DataIt[0] ); - while( !IsLineEnd( *tmp ) ) { + bool end_of_definition = false; + while ( !end_of_definition ) { + if ( isDataDefinitionEnd( tmp ) ) { + tmp += 2; + } else if ( IsLineEnd( *tmp ) ) { + end_of_definition = true; + } if ( !SkipSpaces( &tmp ) ) { break; } + const bool isNum( IsNumeric( *tmp ) ); SkipToken( tmp ); - ++numComponents; + if ( isNum ) { + ++numComponents; + } + if ( !SkipSpaces( &tmp ) ) { + break; + } } return numComponents; } void ObjFileParser::getVector( std::vector &point3d_array ) { - size_t numComponents = getNumComponentsInLine(); + size_t numComponents = getNumComponentsInDataDefinition(); ai_real x, y, z; if( 2 == numComponents ) { copyNextWord( m_buffer, Buffersize ); @@ -279,8 +324,6 @@ void ObjFileParser::getVector( std::vector &point3d_array ) { m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); } -// ------------------------------------------------------------------- -// Get values for a new 3D vector instance void ObjFileParser::getVector3( std::vector &point3d_array ) { ai_real x, y, z; copyNextWord(m_buffer, Buffersize); @@ -316,8 +359,6 @@ void ObjFileParser::getHomogeneousVector3( std::vector &point3d_arra m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); } -// ------------------------------------------------------------------- -// Get values for two 3D vectors on the same line void ObjFileParser::getTwoVectors3( std::vector &point3d_array_a, std::vector &point3d_array_b ) { ai_real x, y, z; copyNextWord(m_buffer, Buffersize); @@ -345,8 +386,6 @@ void ObjFileParser::getTwoVectors3( std::vector &point3d_array_a, st m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); } -// ------------------------------------------------------------------- -// Get values for a new 2D vector instance void ObjFileParser::getVector2( std::vector &point2d_array ) { ai_real x, y; copyNextWord(m_buffer, Buffersize); @@ -362,13 +401,7 @@ void ObjFileParser::getVector2( std::vector &point2d_array ) { static const std::string DefaultObjName = "defaultobject"; -// ------------------------------------------------------------------- -// Get values for a new face instance void ObjFileParser::getFace( aiPrimitiveType type ) { - //copyNextLine(m_buffer, Buffersize); - //char *pPtr = m_DataIt; - //char *pPtr = m_buffer; - //char *pEnd = &pPtr[Buffersize]; m_DataIt = getNextToken( m_DataIt, m_DataItEnd ); if ( m_DataIt == m_DataItEnd || *m_DataIt == '\0' ) { return; @@ -442,7 +475,14 @@ void ObjFileParser::getFace( aiPrimitiveType type ) { } else { reportErrorTokenInFace(); } + } else { + //On error, std::atoi will return 0 which is not a valid value + delete face; + delete m_pModel; + m_pModel = nullptr; + throw DeadlyImportError("OBJ: Invalid face indice"); } + } m_DataIt += iStep; } @@ -483,8 +523,6 @@ void ObjFileParser::getFace( aiPrimitiveType type ) { m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); } -// ------------------------------------------------------------------- -// Get values for a new material description void ObjFileParser::getMaterialDesc() { // Get next data for material data m_DataIt = getNextToken(m_DataIt, m_DataItEnd); @@ -516,10 +554,15 @@ void ObjFileParser::getMaterialDesc() { // Search for material std::map::iterator it = m_pModel->m_MaterialMap.find(strName); if (it == m_pModel->m_MaterialMap.end()) { - // Not found, use default material - m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial; - DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", skipping"); - strName = m_pModel->m_pDefaultMaterial->MaterialName.C_Str(); + // Not found, so we don't know anything about the material except for its name. + // This may be the case if the material library is missing. We don't want to lose all + // materials if that happens, so create a new named material instead of discarding it + // completely. + DefaultLogger::get()->error("OBJ: failed to locate material " + strName + ", creating new material"); + m_pModel->m_pCurrentMaterial = new ObjFile::Material(); + m_pModel->m_pCurrentMaterial->MaterialName.Set(strName); + m_pModel->m_MaterialLib.push_back(strName); + m_pModel->m_MaterialMap[strName] = m_pModel->m_pCurrentMaterial; } else { // Found, using detected material m_pModel->m_pCurrentMaterial = (*it).second; @@ -539,14 +582,7 @@ void ObjFileParser::getMaterialDesc() { // ------------------------------------------------------------------- // Get a comment, values will be skipped void ObjFileParser::getComment() { - while (m_DataIt != m_DataItEnd) { - if ( '\n' == (*m_DataIt)) { - ++m_DataIt; - break; - } else { - ++m_DataIt; - } - } + m_DataIt = skipLine( m_DataIt, m_DataItEnd, m_uiLine ); } // ------------------------------------------------------------------- @@ -568,7 +604,10 @@ void ObjFileParser::getMaterialLib() { std::string absName; // Check if directive is valid. - if(!strMatName.length()) throw DeadlyImportError("File name of the material is absent."); + if ( 0 == strMatName.length() ) { + DefaultLogger::get()->warn( "OBJ: no name for material library specified." ); + return; + } if ( m_pIO->StackSize() > 0 ) { std::string path = m_pIO->CurrentDirectory(); diff --git a/code/ObjFileParser.h b/code/ObjFileParser.h index 55be305bb..fa5b3ca31 100644 --- a/code/ObjFileParser.h +++ b/code/ObjFileParser.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -64,7 +65,7 @@ class ProgressHandler; /// \class ObjFileParser /// \brief Parser for a obj waveform file -class ObjFileParser { +class ASSIMP_API ObjFileParser { public: static const size_t Buffersize = 4096; typedef std::vector DataArray; @@ -72,20 +73,26 @@ public: typedef std::vector::const_iterator ConstDataArrayIt; public: - /// \brief Constructor with data array. - ObjFileParser( IOStreamBuffer &streamBuffer, const std::string &strModelName, IOSystem* io, ProgressHandler* progress, const std::string &originalObjFileName); - /// \brief Destructor + /// @brief The default constructor. + ObjFileParser(); + /// @brief Constructor with data array. + ObjFileParser( IOStreamBuffer &streamBuffer, const std::string &modelName, IOSystem* io, ProgressHandler* progress, const std::string &originalObjFileName); + /// @brief Destructor ~ObjFileParser(); - /// \brief Model getter. + /// @brief If you want to load in-core data. + void setBuffer( std::vector &buffer ); + /// @brief Model getter. ObjFile::Model *GetModel() const; -private: +protected: /// Parse the loaded file void parseFile( IOStreamBuffer &streamBuffer ); /// Method to copy the new delimited word in the current line. void copyNextWord(char *pBuffer, size_t length); /// Method to copy the new line. // void copyNextLine(char *pBuffer, size_t length); + /// Get the number of components in a line. + size_t getNumComponentsInDataDefinition(); /// Stores the vector void getVector( std::vector &point3d_array ); /// Stores the following 3d vector. @@ -124,8 +131,6 @@ private: bool needsNewMesh( const std::string &rMaterialName ); /// Error report in token void reportErrorTokenInFace(); - /// Get the number of components in a line. - size_t getNumComponentsInLine(); private: // Copy and assignment constructor should be private @@ -149,9 +154,8 @@ private: IOSystem *m_pIO; //! Pointer to progress handler ProgressHandler* m_progress; - /// Path to the current model - // name of the obj file where the buffer comes from - const std::string& m_originalObjFileName; + /// Path to the current model, name of the obj file where the buffer comes from + const std::string m_originalObjFileName; }; } // Namespace Assimp diff --git a/code/ObjTools.h b/code/ObjTools.h index 26c9256ce..7236cedc0 100644 --- a/code/ObjTools.h +++ b/code/ObjTools.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -78,8 +79,10 @@ inline Char_T getNextWord( Char_T pBuffer, Char_T pEnd ) { while ( !isEndOfBuffer( pBuffer, pEnd ) ) { - if( !IsSpaceOrNewLine( *pBuffer ) || IsLineEnd( *pBuffer ) ) - break; + if ( !IsSpaceOrNewLine( *pBuffer ) || IsLineEnd( *pBuffer ) ) { + //if ( *pBuffer != '\\' ) + break; + } pBuffer++; } return pBuffer; @@ -113,14 +116,16 @@ inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine ) { while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) ) { ++it; } - if ( it != end ) - { + + if ( it != end ) { ++it; ++uiLine; } // fix .. from time to time there are spaces at the beginning of a material line - while ( it != end && (*it == '\t' || *it == ' ') ) + while ( it != end && ( *it == '\t' || *it == ' ' ) ) { ++it; + } + return it; } @@ -140,15 +145,13 @@ inline char_t getName( char_t it, char_t end, std::string &name ) } char *pStart = &( *it ); - while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it ) && !IsSpaceOrNewLine( *it ) ) { + while( !isEndOfBuffer( it, end ) && !IsLineEnd( *it )) { ++it; } - /*while( isEndOfBuffer( it, end ) || IsLineEnd( *it ) || IsSpaceOrNewLine( *it ) ) { + while(IsSpace( *it ) ) { --it; } - ++it; - */ // Get name // if there is no name, and the previous char is a separator, come back to start while (&(*it) < pStart) { diff --git a/code/OgreBinarySerializer.cpp b/code/OgreBinarySerializer.cpp index 59bd0d92d..95aec221f 100644 --- a/code/OgreBinarySerializer.cpp +++ b/code/OgreBinarySerializer.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/OgreBinarySerializer.h b/code/OgreBinarySerializer.h index 067e36a63..c48e33dd6 100644 --- a/code/OgreBinarySerializer.h +++ b/code/OgreBinarySerializer.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/OgreImporter.cpp b/code/OgreImporter.cpp index 504f6a96f..4dc802574 100644 --- a/code/OgreImporter.cpp +++ b/code/OgreImporter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -40,12 +41,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER - - #include "OgreImporter.h" #include "OgreBinarySerializer.h" #include "OgreXmlSerializer.h" #include +#include #include static const aiImporterDesc desc = { diff --git a/code/OgreImporter.h b/code/OgreImporter.h index 8b2179502..2b3009096 100644 --- a/code/OgreImporter.h +++ b/code/OgreImporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/OgreMaterial.cpp b/code/OgreMaterial.cpp index bdcd0285a..1abca2cf1 100644 --- a/code/OgreMaterial.cpp +++ b/code/OgreMaterial.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -257,7 +258,7 @@ aiMaterial* OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste ReadTechnique(Trim(techniqueName), ss, material); } - // Read informations from a custom material + // Read information from a custom material /** @todo This "set $x y" does not seem to be a official Ogre material system feature. Materials can inherit other materials and override texture units by using the (unique) parent texture unit name in your cloned material. diff --git a/code/OgreParsingUtils.h b/code/OgreParsingUtils.h index def3cf733..b0c31e5be 100644 --- a/code/OgreParsingUtils.h +++ b/code/OgreParsingUtils.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -90,11 +91,11 @@ static inline std::string &TrimLeft(std::string &s, bool newlines = true) { if (!newlines) { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpace)))); + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpace(c); })); } else { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine)))); + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine(c); })); } return s; } @@ -104,11 +105,11 @@ static inline std::string &TrimRight(std::string &s, bool newlines = true) { if (!newlines) { - s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(Assimp::IsSpace))).base(),s.end()); + s.erase(std::find_if(s.rbegin(), s.rend(), [](char c) { return !Assimp::IsSpace(c); }).base(),s.end()); } else { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(Assimp::IsSpaceOrNewLine)))); + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine(c); })); } return s; } diff --git a/code/OgreStructs.cpp b/code/OgreStructs.cpp index d9cd547d6..09597950a 100644 --- a/code/OgreStructs.cpp +++ b/code/OgreStructs.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/OgreStructs.h b/code/OgreStructs.h index c4e86a805..04383bc4e 100644 --- a/code/OgreStructs.h +++ b/code/OgreStructs.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/OgreXmlSerializer.cpp b/code/OgreXmlSerializer.cpp index 16767252d..b5d20cdf6 100644 --- a/code/OgreXmlSerializer.cpp +++ b/code/OgreXmlSerializer.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/OgreXmlSerializer.h b/code/OgreXmlSerializer.h index 47b4cafc0..01b9a7b23 100644 --- a/code/OgreXmlSerializer.h +++ b/code/OgreXmlSerializer.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/OpenGEXExporter.cpp b/code/OpenGEXExporter.cpp index cf06c9f39..0f2b1c35b 100644 --- a/code/OpenGEXExporter.cpp +++ b/code/OpenGEXExporter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -50,7 +51,7 @@ OpenGEXExporter::OpenGEXExporter() { OpenGEXExporter::~OpenGEXExporter() { } -bool OpenGEXExporter::exportScene( const char *filename, const aiScene* pScene ) { +bool OpenGEXExporter::exportScene( const char * /*filename*/, const aiScene* /*pScene*/ ) { return true; } diff --git a/code/OpenGEXExporter.h b/code/OpenGEXExporter.h index f9757f41c..9df9d853e 100644 --- a/code/OpenGEXExporter.h +++ b/code/OpenGEXExporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/OpenGEXImporter.cpp b/code/OpenGEXImporter.cpp index a605e0f41..025356c1d 100644 --- a/code/OpenGEXImporter.cpp +++ b/code/OpenGEXImporter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -40,7 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_OPENGEX_IMPORTER #include "OpenGEXImporter.h" -#include "DefaultIOSystem.h" +#include #include #include "MakeVerboseFormat.h" #include "StringComparison.h" @@ -48,11 +49,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include -static const std::string OpenGexExt = "ogex"; - static const aiImporterDesc desc = { "Open Game Engine Exchange", "", @@ -63,7 +63,7 @@ static const aiImporterDesc desc = { 0, 0, 0, - OpenGexExt.c_str() + "ogex" }; namespace Grammar { @@ -196,7 +196,6 @@ namespace Grammar { return NoneType; } - } // Namespace Grammar namespace Assimp { @@ -262,6 +261,7 @@ OpenGEXImporter::OpenGEXImporter() , m_nodeChildMap() , m_meshCache() , m_mesh2refMap() +, m_material2refMap() , m_ctx( nullptr ) , m_metrics() , m_currentNode( nullptr ) @@ -288,7 +288,7 @@ OpenGEXImporter::~OpenGEXImporter() { bool OpenGEXImporter::CanRead( const std::string &file, IOSystem *pIOHandler, bool checkSig ) const { bool canRead( false ); if( !checkSig ) { - canRead = SimpleExtensionCheck( file, OpenGexExt.c_str() ); + canRead = SimpleExtensionCheck( file, "ogex" ); } else { static const char *token[] = { "Metric", "GeometryNode", "VertexArray (attrib", "IndexArray" }; canRead = BaseImporter::SearchFileHeaderForToken( pIOHandler, file, token, 4 ); @@ -307,6 +307,7 @@ void OpenGEXImporter::InternReadFile( const std::string &filename, aiScene *pSce std::vector buffer; TextFileToBuffer( file, buffer ); + pIOHandler->Close( file ); OpenDDLParser myParser; myParser.setBuffer( &buffer[ 0 ], buffer.size() ); @@ -321,6 +322,7 @@ void OpenGEXImporter::InternReadFile( const std::string &filename, aiScene *pSce copyMeshes( pScene ); copyCameras( pScene ); copyLights( pScene ); + copyMaterials( pScene ); resolveReferences(); createNodeTree( pScene ); } @@ -429,7 +431,7 @@ void OpenGEXImporter::handleNodes( DDLNode *node, aiScene *pScene ) { } //------------------------------------------------------------------------------------------------ -void OpenGEXImporter::handleMetricNode( DDLNode *node, aiScene *pScene ) { +void OpenGEXImporter::handleMetricNode( DDLNode *node, aiScene * /*pScene*/ ) { if( nullptr == node || nullptr == m_ctx ) { return; } @@ -465,7 +467,7 @@ void OpenGEXImporter::handleMetricNode( DDLNode *node, aiScene *pScene ) { } //------------------------------------------------------------------------------------------------ -void OpenGEXImporter::handleNameNode( DDLNode *node, aiScene *pScene ) { +void OpenGEXImporter::handleNameNode( DDLNode *node, aiScene * /*pScene*/ ) { if( nullptr == m_currentNode ) { throw DeadlyImportError( "No current node for name." ); return; @@ -483,7 +485,10 @@ void OpenGEXImporter::handleNameNode( DDLNode *node, aiScene *pScene ) { || m_tokenType == Grammar::CameraNodeToken ) { m_currentNode->mName.Set( name.c_str() ); } else if( m_tokenType == Grammar::MaterialToken ) { - + aiString aiName; + aiName.Set( name ); + m_currentMaterial->AddProperty( &aiName, AI_MATKEY_NAME ); + m_material2refMap[ name ] = m_materialCache.size() - 1; } } } @@ -507,7 +512,7 @@ static void getRefNames( DDLNode *node, std::vector &names ) { } //------------------------------------------------------------------------------------------------ -void OpenGEXImporter::handleObjectRefNode( DDLNode *node, aiScene *pScene ) { +void OpenGEXImporter::handleObjectRefNode( DDLNode *node, aiScene * /*pScene*/ ) { if( nullptr == m_currentNode ) { throw DeadlyImportError( "No parent node for name." ); return; @@ -521,13 +526,17 @@ void OpenGEXImporter::handleObjectRefNode( DDLNode *node, aiScene *pScene ) { m_currentNode->mNumMeshes = static_cast(objRefNames.size()); m_currentNode->mMeshes = new unsigned int[ objRefNames.size() ]; if ( !objRefNames.empty() ) { - m_unresolvedRefStack.push_back( new RefInfo( m_currentNode, RefInfo::MeshRef, objRefNames ) ); + m_unresolvedRefStack.push_back( std::unique_ptr( new RefInfo( m_currentNode, RefInfo::MeshRef, objRefNames ) ) ); } + } else if ( m_tokenType == Grammar::LightNodeToken ) { + // TODO! + } else if ( m_tokenType == Grammar::CameraNodeToken ) { + // TODO! } } //------------------------------------------------------------------------------------------------ -void OpenGEXImporter::handleMaterialRefNode( ODDLParser::DDLNode *node, aiScene *pScene ) { +void OpenGEXImporter::handleMaterialRefNode( ODDLParser::DDLNode *node, aiScene * /*pScene*/ ) { if( nullptr == m_currentNode ) { throw DeadlyImportError( "No parent node for name." ); return; @@ -536,7 +545,7 @@ void OpenGEXImporter::handleMaterialRefNode( ODDLParser::DDLNode *node, aiScene std::vector matRefNames; getRefNames( node, matRefNames ); if( !matRefNames.empty() ) { - m_unresolvedRefStack.push_back( new RefInfo( m_currentNode, RefInfo::MaterialRef, matRefNames ) ); + m_unresolvedRefStack.push_back( std::unique_ptr( new RefInfo( m_currentNode, RefInfo::MaterialRef, matRefNames ) ) ); } } @@ -602,6 +611,13 @@ void OpenGEXImporter::handleCameraObject( ODDLParser::DDLNode *node, aiScene *pS //------------------------------------------------------------------------------------------------ void OpenGEXImporter::handleLightObject( ODDLParser::DDLNode *node, aiScene *pScene ) { + aiLight *light( new aiLight ); + m_lightCache.push_back( light ); + std::string objName = node->getName(); + if ( !objName.empty() ) { + light->mName.Set( objName ); + } + m_currentLight = light; Property *prop( node->findPropertyByName( "type" ) ); if ( nullptr != prop ) { @@ -636,6 +652,8 @@ static void setMatrix( aiNode *node, DataArrayList *transformData ) { i++; } + ai_assert(i == 16); + node->mTransformation.a1 = m[ 0 ]; node->mTransformation.a2 = m[ 4 ]; node->mTransformation.a3 = m[ 8 ]; @@ -658,7 +676,7 @@ static void setMatrix( aiNode *node, DataArrayList *transformData ) { } //------------------------------------------------------------------------------------------------ -void OpenGEXImporter::handleTransformNode( ODDLParser::DDLNode *node, aiScene *pScene ) { +void OpenGEXImporter::handleTransformNode( ODDLParser::DDLNode *node, aiScene * /*pScene*/ ) { if( nullptr == m_currentNode ) { throw DeadlyImportError( "No parent node for name." ); return; @@ -803,7 +821,7 @@ static void copyColor4DArray( size_t numItems, DataArrayList *vaList, aiColor4D } //------------------------------------------------------------------------------------------------ -void OpenGEXImporter::handleVertexArrayNode( ODDLParser::DDLNode *node, aiScene *pScene ) { +void OpenGEXImporter::handleVertexArrayNode( ODDLParser::DDLNode *node, aiScene * /*pScene*/ ) { if( nullptr == node ) { throw DeadlyImportError( "No parent node for name." ); return; @@ -846,7 +864,7 @@ void OpenGEXImporter::handleVertexArrayNode( ODDLParser::DDLNode *node, aiScene } //------------------------------------------------------------------------------------------------ -void OpenGEXImporter::handleIndexArrayNode( ODDLParser::DDLNode *node, aiScene *pScene ) { +void OpenGEXImporter::handleIndexArrayNode( ODDLParser::DDLNode *node, aiScene * /*pScene*/ ) { if( nullptr == node ) { throw DeadlyImportError( "No parent node for name." ); return; @@ -917,7 +935,7 @@ void OpenGEXImporter::handleIndexArrayNode( ODDLParser::DDLNode *node, aiScene * } //------------------------------------------------------------------------------------------------ -static void getColorRGB( aiColor3D *pColor, DataArrayList *colList ) { +static void getColorRGB3( aiColor3D *pColor, DataArrayList *colList ) { if( nullptr == pColor || nullptr == colList ) { return; } @@ -931,6 +949,23 @@ static void getColorRGB( aiColor3D *pColor, DataArrayList *colList ) { pColor->b = val->getFloat(); } +//------------------------------------------------------------------------------------------------ +static void getColorRGB4( aiColor4D *pColor, DataArrayList *colList ) { + if ( nullptr == pColor || nullptr == colList ) { + return; + } + + ai_assert( 4 == colList->m_numItems ); + Value *val( colList->m_dataList ); + pColor->r = val->getFloat(); + val = val->getNext(); + pColor->g = val->getFloat(); + val = val->getNext(); + pColor->b = val->getFloat(); + val = val->getNext(); + pColor->a = val->getFloat(); +} + //------------------------------------------------------------------------------------------------ enum ColorType { NoneColor = 0, @@ -968,7 +1003,7 @@ void OpenGEXImporter::handleMaterialNode( ODDLParser::DDLNode *node, aiScene *pS } //------------------------------------------------------------------------------------------------ -void OpenGEXImporter::handleColorNode( ODDLParser::DDLNode *node, aiScene *pScene ) { +void OpenGEXImporter::handleColorNode( ODDLParser::DDLNode *node, aiScene * /*pScene*/ ) { if( nullptr == node ) { return; } @@ -981,7 +1016,17 @@ void OpenGEXImporter::handleColorNode( ODDLParser::DDLNode *node, aiScene *pScen return; } aiColor3D col; - getColorRGB( &col, colList ); + if ( 3 == colList->m_numItems ) { + aiColor3D col3; + getColorRGB3( &col3, colList ); + col = col3; + } else { + aiColor4D col4; + getColorRGB4( &col4, colList ); + col.r = col4.r; + col.g = col4.g; + col.b = col4.b; + } const ColorType colType( getColorType( prop->m_key ) ); if( DiffuseColor == colType ) { m_currentMaterial->AddProperty( &col, 1, AI_MATKEY_COLOR_DIFFUSE ); @@ -997,7 +1042,7 @@ void OpenGEXImporter::handleColorNode( ODDLParser::DDLNode *node, aiScene *pScen } //------------------------------------------------------------------------------------------------ -void OpenGEXImporter::handleTextureNode( ODDLParser::DDLNode *node, aiScene *pScene ) { +void OpenGEXImporter::handleTextureNode( ODDLParser::DDLNode *node, aiScene * /*pScene*/ ) { if( nullptr == node ) { return; } @@ -1013,7 +1058,6 @@ void OpenGEXImporter::handleTextureNode( ODDLParser::DDLNode *node, aiScene *pSc m_currentMaterial->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) ); } else if( prop->m_value->getString() == Grammar::SpecularPowerTextureToken ) { m_currentMaterial->AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR( 0 ) ); - } else if( prop->m_value->getString() == Grammar::EmissionTextureToken ) { m_currentMaterial->AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE( 0 ) ); } else if( prop->m_value->getString() == Grammar::OpacyTextureToken ) { @@ -1032,7 +1076,7 @@ void OpenGEXImporter::handleTextureNode( ODDLParser::DDLNode *node, aiScene *pSc } //------------------------------------------------------------------------------------------------ -void OpenGEXImporter::handleParamNode( ODDLParser::DDLNode *node, aiScene *pScene ) { +void OpenGEXImporter::handleParamNode( ODDLParser::DDLNode *node, aiScene * /*pScene*/ ) { if ( nullptr == node ) { return; } @@ -1061,7 +1105,7 @@ void OpenGEXImporter::handleParamNode( ODDLParser::DDLNode *node, aiScene *pScen } //------------------------------------------------------------------------------------------------ -void OpenGEXImporter::handleAttenNode( ODDLParser::DDLNode *node, aiScene *pScene ) { +void OpenGEXImporter::handleAttenNode( ODDLParser::DDLNode *node, aiScene * /*pScene*/ ) { if ( nullptr == node ) { return; } @@ -1117,6 +1161,19 @@ void OpenGEXImporter::copyLights( aiScene *pScene ) { std::copy( m_lightCache.begin(), m_lightCache.end(), pScene->mLights ); } +//------------------------------------------------------------------------------------------------ +void OpenGEXImporter::copyMaterials( aiScene *pScene ) { + ai_assert( nullptr != pScene ); + + if ( m_materialCache.empty() ) { + return; + } + + pScene->mNumMaterials = static_cast(m_materialCache.size()); + pScene->mMaterials = new aiMaterial*[ pScene->mNumMaterials ]; + std::copy( m_materialCache.begin(), m_materialCache.end(), pScene->mMaterials ); +} + //------------------------------------------------------------------------------------------------ void OpenGEXImporter::resolveReferences() { if( m_unresolvedRefStack.empty() ) { @@ -1124,12 +1181,12 @@ void OpenGEXImporter::resolveReferences() { } RefInfo *currentRefInfo( nullptr ); - for( std::vector::iterator it = m_unresolvedRefStack.begin(); it != m_unresolvedRefStack.end(); ++it ) { - currentRefInfo = *it; + for( auto it = m_unresolvedRefStack.begin(); it != m_unresolvedRefStack.end(); ++it ) { + currentRefInfo = it->get(); if( nullptr != currentRefInfo ) { aiNode *node( currentRefInfo->m_node ); if( RefInfo::MeshRef == currentRefInfo->m_type ) { - for( size_t i = 0; i < currentRefInfo->m_Names.size(); i++ ) { + for( size_t i = 0; i < currentRefInfo->m_Names.size(); ++i ) { const std::string &name( currentRefInfo->m_Names[ i ] ); ReferenceMap::const_iterator it( m_mesh2refMap.find( name ) ); if( m_mesh2refMap.end() != it ) { @@ -1138,7 +1195,22 @@ void OpenGEXImporter::resolveReferences() { } } } else if( RefInfo::MaterialRef == currentRefInfo->m_type ) { - // ToDo! + for ( size_t i = 0; i < currentRefInfo->m_Names.size(); ++i ) { + const std::string name( currentRefInfo->m_Names[ i ] ); + ReferenceMap::const_iterator it( m_material2refMap.find( name ) ); + if ( m_material2refMap.end() != it ) { + if ( nullptr != m_currentMesh ) { + unsigned int matIdx = static_cast< unsigned int >( m_material2refMap[ name ] ); + if ( m_currentMesh->mMaterialIndex != 0 ) { + DefaultLogger::get()->warn( "Override of material reference in current mesh by material reference." ); + } + m_currentMesh->mMaterialIndex = matIdx; + } else { + DefaultLogger::get()->warn( "Cannot resolve material reference, because no current mesh is there." ); + + } + } + } } else { throw DeadlyImportError( "Unknown reference info to resolve." ); } @@ -1176,9 +1248,9 @@ void OpenGEXImporter::pushNode( aiNode *node, aiScene *pScene ) { if( m_nodeChildMap.end() == it ) { info = new ChildInfo; m_root = info; - m_nodeChildMap[ node->mParent ] = info; + m_nodeChildMap[ node->mParent ] = std::unique_ptr(info); } else { - info = it->second; + info = it->second.get(); } info->m_children.push_back( node ); } else { @@ -1188,9 +1260,9 @@ void OpenGEXImporter::pushNode( aiNode *node, aiScene *pScene ) { NodeChildMap::iterator it( m_nodeChildMap.find( node->mParent ) ); if( m_nodeChildMap.end() == it ) { info = new ChildInfo; - m_nodeChildMap[ node->mParent ] = info; + m_nodeChildMap[ node->mParent ] = std::unique_ptr(info); } else { - info = it->second; + info = it->second.get(); } info->m_children.push_back( node ); } diff --git a/code/OpenGEXImporter.h b/code/OpenGEXImporter.h index 103b27903..c0cde579c 100644 --- a/code/OpenGEXImporter.h +++ b/code/OpenGEXImporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -47,6 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include +#include namespace ODDLParser { class DDLNode; @@ -130,7 +133,7 @@ protected: void copyMeshes( aiScene *pScene ); void copyCameras( aiScene *pScene ); void copyLights( aiScene *pScene ); - + void copyMaterials( aiScene *pScene ); void resolveReferences(); void pushNode( aiNode *node, aiScene *pScene ); aiNode *popNode(); @@ -178,12 +181,13 @@ private: std::list m_children; }; ChildInfo *m_root; - typedef std::map NodeChildMap; + typedef std::map > NodeChildMap; NodeChildMap m_nodeChildMap; std::vector m_meshCache; typedef std::map ReferenceMap; std::map m_mesh2refMap; + std::map m_material2refMap; ODDLParser::Context *m_ctx; MetricInfo m_metrics[ MetricInfo::Max ]; @@ -198,7 +202,7 @@ private: std::vector m_cameraCache; std::vector m_lightCache; std::vector m_nodeStack; - std::vector m_unresolvedRefStack; + std::vector > m_unresolvedRefStack; }; } // Namespace OpenGEX diff --git a/code/OpenGEXStructs.h b/code/OpenGEXStructs.h index 910b03f60..6144a10c5 100644 --- a/code/OpenGEXStructs.h +++ b/code/OpenGEXStructs.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/OptimizeGraph.cpp b/code/OptimizeGraph.cpp index 4d033ee31..11a6fcf65 100644 --- a/code/OptimizeGraph.cpp +++ b/code/OptimizeGraph.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -48,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "OptimizeGraph.h" #include "ProcessHelper.h" -#include "SceneCombiner.h" +#include #include "Exceptional.h" #include @@ -232,10 +233,12 @@ void OptimizeGraphProcess::CollectNewChildren(aiNode* nd, std::list& no nd->mNumChildren = static_cast(child_nodes.size()); - aiNode** tmp = nd->mChildren; - for (std::list::iterator it = child_nodes.begin(); it != child_nodes.end(); ++it) { - aiNode* node = *tmp++ = *it; - node->mParent = nd; + if (nd->mChildren) { + aiNode** tmp = nd->mChildren; + for (std::list::iterator it = child_nodes.begin(); it != child_nodes.end(); ++it) { + aiNode* node = *tmp++ = *it; + node->mParent = nd; + } } nodes_out += static_cast(child_nodes.size()); diff --git a/code/OptimizeGraph.h b/code/OptimizeGraph.h index 7b3a1d0de..22d53afff 100644 --- a/code/OptimizeGraph.h +++ b/code/OptimizeGraph.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/OptimizeMeshes.cpp b/code/OptimizeMeshes.cpp index 2bb9c5717..f8183fc75 100644 --- a/code/OptimizeMeshes.cpp +++ b/code/OptimizeMeshes.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -49,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "OptimizeMeshes.h" #include "ProcessHelper.h" -#include "SceneCombiner.h" +#include #include "Exceptional.h" using namespace Assimp; @@ -180,11 +181,8 @@ void OptimizeMeshesProcess::ProcessNode( aiNode* pNode) verts += mScene->mMeshes[am]->mNumVertices; faces += mScene->mMeshes[am]->mNumFaces; + pNode->mMeshes[a] = pNode->mMeshes[pNode->mNumMeshes - 1]; --pNode->mNumMeshes; - for( unsigned int n = a; n < pNode->mNumMeshes; ++n ) { - pNode->mMeshes[ n ] = pNode->mMeshes[ n + 1 ]; - } - --a; } } diff --git a/code/OptimizeMeshes.h b/code/OptimizeMeshes.h index fc8b6a10b..bcefe9247 100644 --- a/code/OptimizeMeshes.h +++ b/code/OptimizeMeshes.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/ParsingUtils.h b/code/ParsingUtils.h index 2371ee606..7da664374 100644 --- a/code/ParsingUtils.h +++ b/code/ParsingUtils.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/PlyExporter.cpp b/code/PlyExporter.cpp index 1d14c9219..b20c2b328 100644 --- a/code/PlyExporter.cpp +++ b/code/PlyExporter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -64,11 +65,15 @@ template<> const char* type_of(double&) { return "double"; } // ------------------------------------------------------------------------------------------------ // Worker function for exporting a scene to PLY. Prototyped and registered in Exporter.cpp -void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) +void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { // invoke the exporter PlyExporter exporter(pFile, pScene); + if (exporter.mOutput.fail()) { + throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); + } + // we're still here - export successfully completed. Write the file. std::unique_ptr outfile (pIOSystem->Open(pFile,"wt")); if(outfile == NULL) { @@ -78,7 +83,7 @@ void ExportScenePly(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene outfile->Write( exporter.mOutput.str().c_str(), static_cast(exporter.mOutput.tellp()),1); } -void ExportScenePlyBinary(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) +void ExportScenePlyBinary(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { // invoke the exporter PlyExporter exporter(pFile, pScene, true); diff --git a/code/PlyExporter.h b/code/PlyExporter.h index be4fa466f..d1d4eafbb 100644 --- a/code/PlyExporter.h +++ b/code/PlyExporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -50,14 +51,12 @@ struct aiScene; struct aiNode; struct aiMesh; -namespace Assimp -{ +namespace Assimp { // ------------------------------------------------------------------------------------------------ /** Helper class to export a given scene to a Stanford Ply file. */ // ------------------------------------------------------------------------------------------------ -class PlyExporter -{ +class PlyExporter { public: /// The class constructor for a specific scene to export PlyExporter(const char* filename, const aiScene* pScene, bool binary = false); diff --git a/code/PlyLoader.cpp b/code/PlyLoader.cpp index dc002531f..c6e862bf1 100644 --- a/code/PlyLoader.cpp +++ b/code/PlyLoader.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team All rights reserved. @@ -12,18 +12,18 @@ 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. +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. +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. +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 @@ -47,25 +47,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // internal headers #include "PlyLoader.h" +#include "IOStreamBuffer.h" #include "Macros.h" #include #include #include - +#include using namespace Assimp; static const aiImporterDesc desc = { - "Stanford Polygon Library (PLY) Importer", - "", - "", - "", - aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportTextFlavour, - 0, - 0, - 0, - 0, - "ply" + "Stanford Polygon Library (PLY) Importer", + "", + "", + "", + aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportTextFlavour, + 0, + 0, + 0, + 0, + "ply" }; @@ -73,1040 +74,941 @@ static const aiImporterDesc desc = { // Internal stuff namespace { - // ------------------------------------------------------------------------------------------------ - // Checks that property index is within range - template - const T &GetProperty(const std::vector &props, int idx) - { - if( static_cast< size_t >( idx ) >= props.size() ) { - throw DeadlyImportError( "Invalid .ply file: Property index is out of range." ); - } - - return props[idx]; + // ------------------------------------------------------------------------------------------------ + // Checks that property index is within range + template + const T &GetProperty(const std::vector &props, int idx) + { + if (static_cast(idx) >= props.size()) { + throw DeadlyImportError("Invalid .ply file: Property index is out of range."); } + + return props[idx]; + } } // ------------------------------------------------------------------------------------------------ // Constructor to be privately used by Importer PLYImporter::PLYImporter() - : mBuffer(), - pcDOM() -{} + : mBuffer() + , pcDOM() + , mGeneratedMesh(NULL){ + // empty +} // ------------------------------------------------------------------------------------------------ // Destructor, private as well -PLYImporter::~PLYImporter() -{} +PLYImporter::~PLYImporter() { + // empty +} // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool PLYImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const +bool PLYImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { - const std::string extension = GetExtension(pFile); + const std::string extension = GetExtension(pFile); - if (extension == "ply") - return true; - else if (!extension.length() || checkSig) - { - if (!pIOHandler)return true; - const char* tokens[] = {"ply"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); - } - return false; + if (extension == "ply") + return true; + else if (!extension.length() || checkSig) + { + if (!pIOHandler)return true; + const char* tokens[] = { "ply" }; + return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); + } + return false; } // ------------------------------------------------------------------------------------------------ -const aiImporterDesc* PLYImporter::GetInfo () const +const aiImporterDesc* PLYImporter::GetInfo() const { - return &desc; + return &desc; } // ------------------------------------------------------------------------------------------------ -static bool isBigEndian( const char* szMe ) { - ai_assert( NULL != szMe ); +static bool isBigEndian(const char* szMe) { + ai_assert(NULL != szMe); - // binary_little_endian - // binary_big_endian - bool isBigEndian( false ); + // binary_little_endian + // binary_big_endian + bool isBigEndian(false); #if (defined AI_BUILD_BIG_ENDIAN) - if ( 'l' == *szMe || 'L' == *szMe ) { - isBigEndian = true; -} + if ( 'l' == *szMe || 'L' == *szMe ) { + isBigEndian = true; + } #else - if ( 'b' == *szMe || 'B' == *szMe ) { - isBigEndian = true; - } + if ('b' == *szMe || 'B' == *szMe) { + isBigEndian = true; + } #endif // ! AI_BUILD_BIG_ENDIAN - return isBigEndian; + return isBigEndian; } // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. -void PLYImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) +void PLYImporter::InternReadFile(const std::string& pFile, + aiScene* pScene, IOSystem* pIOHandler) { - std::unique_ptr file( pIOHandler->Open( pFile)); + static const std::string mode = "rb"; + std::unique_ptr fileStream(pIOHandler->Open(pFile, mode)); + if (!fileStream.get()) { + throw DeadlyImportError("Failed to open file " + pFile + "."); + } - // Check whether we can read from the file - if( file.get() == NULL) { - throw DeadlyImportError( "Failed to open PLY file " + pFile + "."); + // Get the file-size + size_t fileSize = fileStream->FileSize(); + if ( 0 == fileSize ) { + throw DeadlyImportError("File " + pFile + " is empty."); + } + + IOStreamBuffer streamedBuffer(1024 * 1024); + streamedBuffer.open(fileStream.get()); + + // the beginning of the file must be PLY - magic, magic + std::vector headerCheck; + streamedBuffer.getNextLine(headerCheck); + + if ((headerCheck.size() < 3) || + (headerCheck[0] != 'P' && headerCheck[0] != 'p') || + (headerCheck[1] != 'L' && headerCheck[1] != 'l') || + (headerCheck[2] != 'Y' && headerCheck[2] != 'y') ) + { + streamedBuffer.close(); + throw DeadlyImportError("Invalid .ply file: Magic number \'ply\' is no there"); + } + + std::vector mBuffer2; + streamedBuffer.getNextLine(mBuffer2); + mBuffer = (unsigned char*)&mBuffer2[0]; + + char* szMe = (char*)&this->mBuffer[0]; + SkipSpacesAndLineEnd(szMe, (const char**)&szMe); + + // determine the format of the file data and construct the aimesh + PLY::DOM sPlyDom; + this->pcDOM = &sPlyDom; + + if (TokenMatch(szMe, "format", 6)) { + if (TokenMatch(szMe, "ascii", 5)) { + SkipLine(szMe, (const char**)&szMe); + if (!PLY::DOM::ParseInstance(streamedBuffer, &sPlyDom, this)) + { + if (mGeneratedMesh != NULL) + delete(mGeneratedMesh); + + streamedBuffer.close(); + throw DeadlyImportError("Invalid .ply file: Unable to build DOM (#1)"); + } } + else if (!::strncmp(szMe, "binary_", 7)) + { + szMe += 7; + const bool bIsBE(isBigEndian(szMe)); - // allocate storage and copy the contents of the file to a memory buffer - std::vector mBuffer2; - TextFileToBuffer(file.get(),mBuffer2); - mBuffer = (unsigned char*)&mBuffer2[0]; + // skip the line, parse the rest of the header and build the DOM + if (!PLY::DOM::ParseInstanceBinary(streamedBuffer, &sPlyDom, this, bIsBE)) + { + if (mGeneratedMesh != NULL) + delete(mGeneratedMesh); - // the beginning of the file must be PLY - magic, magic - if ((mBuffer[0] != 'P' && mBuffer[0] != 'p') || - (mBuffer[1] != 'L' && mBuffer[1] != 'l') || - (mBuffer[2] != 'Y' && mBuffer[2] != 'y')) { - throw DeadlyImportError( "Invalid .ply file: Magic number \'ply\' is no there"); - } - - char* szMe = (char*)&this->mBuffer[3]; - SkipSpacesAndLineEnd(szMe,(const char**)&szMe); - - // determine the format of the file data - PLY::DOM sPlyDom; - if (TokenMatch(szMe,"format",6)) { - if (TokenMatch(szMe,"ascii",5)) { - SkipLine(szMe,(const char**)&szMe); - if(!PLY::DOM::ParseInstance(szMe,&sPlyDom)) - throw DeadlyImportError( "Invalid .ply file: Unable to build DOM (#1)"); - } else if (!::strncmp(szMe,"binary_",7)) - { - szMe += 7; - const bool bIsBE( isBigEndian( szMe ) ); - - // skip the line, parse the rest of the header and build the DOM - SkipLine(szMe,(const char**)&szMe); - if ( !PLY::DOM::ParseInstanceBinary( szMe, &sPlyDom, bIsBE ) ) { - throw DeadlyImportError( "Invalid .ply file: Unable to build DOM (#2)" ); - } - } else { - throw DeadlyImportError( "Invalid .ply file: Unknown file format" ); - } + streamedBuffer.close(); + throw DeadlyImportError("Invalid .ply file: Unable to build DOM (#2)"); + } } else { - AI_DEBUG_INVALIDATE_PTR(this->mBuffer); - throw DeadlyImportError( "Invalid .ply file: Missing format specification"); + if (mGeneratedMesh != NULL) + delete(mGeneratedMesh); + + streamedBuffer.close(); + throw DeadlyImportError("Invalid .ply file: Unknown file format"); } - this->pcDOM = &sPlyDom; + } + else + { + AI_DEBUG_INVALIDATE_PTR(this->mBuffer); + if (mGeneratedMesh != NULL) + delete(mGeneratedMesh); - // now load a list of vertices. This must be successfully in order to procedure - std::vector avPositions; - this->LoadVertices(&avPositions,false); + streamedBuffer.close(); + throw DeadlyImportError("Invalid .ply file: Missing format specification"); + } - if ( avPositions.empty() ) { - throw DeadlyImportError( "Invalid .ply file: No vertices found. " - "Unable to parse the data format of the PLY file." ); - } + //free the file buffer + streamedBuffer.close(); - // now load a list of normals. - std::vector avNormals; - LoadVertices(&avNormals,true); + if (mGeneratedMesh == NULL) + { + throw DeadlyImportError("Invalid .ply file: Unable to extract mesh data "); + } - // load the face list - std::vector avFaces; - LoadFaces(&avFaces); - - // if no face list is existing we assume that the vertex - // list is containing a list of triangles - if (avFaces.empty()) + // if no face list is existing we assume that the vertex + // list is containing a list of points + bool pointsOnly = mGeneratedMesh->mFaces == NULL ? true : false; + if (pointsOnly) + { + if (mGeneratedMesh->mNumVertices < 3) { - if (avPositions.size() < 3) - { - throw DeadlyImportError( "Invalid .ply file: Not enough " - "vertices to build a proper face list. "); - } + if (mGeneratedMesh != NULL) + delete(mGeneratedMesh); - const unsigned int iNum = (unsigned int)avPositions.size() / 3; - for (unsigned int i = 0; i< iNum;++i) - { - PLY::Face sFace; - sFace.mIndices.push_back((iNum*3)); - sFace.mIndices.push_back((iNum*3)+1); - sFace.mIndices.push_back((iNum*3)+2); - avFaces.push_back(sFace); - } + streamedBuffer.close(); + throw DeadlyImportError("Invalid .ply file: Not enough " + "vertices to build a proper face list. "); } - // now load a list of all materials - std::vector avMaterials; - LoadMaterial(&avMaterials); + const unsigned int iNum = (unsigned int)mGeneratedMesh->mNumVertices / 3; + mGeneratedMesh->mNumFaces = iNum; + mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces]; - // now load a list of all vertex color channels - std::vector avColors; - avColors.reserve(avPositions.size()); - LoadVertexColor(&avColors); - - // now try to load texture coordinates - std::vector avTexCoords; - avTexCoords.reserve(avPositions.size()); - LoadTextureCoordinates(&avTexCoords); - - // now replace the default material in all faces and validate all material indices - ReplaceDefaultMaterial(&avFaces,&avMaterials); - - // now convert this to a list of aiMesh instances - std::vector avMeshes; - avMeshes.reserve(avMaterials.size()+1); - ConvertMeshes(&avFaces,&avPositions,&avNormals, - &avColors,&avTexCoords,&avMaterials,&avMeshes); - - if ( avMeshes.empty() ) { - throw DeadlyImportError( "Invalid .ply file: Unable to extract mesh data " ); + for (unsigned int i = 0; i < iNum; ++i) + { + mGeneratedMesh->mFaces[i].mNumIndices = 3; + mGeneratedMesh->mFaces[i].mIndices = new unsigned int[3]; + mGeneratedMesh->mFaces[i].mIndices[0] = (i * 3); + mGeneratedMesh->mFaces[i].mIndices[1] = (i * 3) + 1; + mGeneratedMesh->mFaces[i].mIndices[2] = (i * 3) + 2; } + } - // now generate the output scene object. Fill the material list - pScene->mNumMaterials = (unsigned int)avMaterials.size(); - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; - for ( unsigned int i = 0; i < pScene->mNumMaterials; ++i ) { - pScene->mMaterials[ i ] = avMaterials[ i ]; - } + // now load a list of all materials + std::vector avMaterials; + std::string defaultTexture; + LoadMaterial(&avMaterials, defaultTexture, pointsOnly); - // fill the mesh list - pScene->mNumMeshes = (unsigned int)avMeshes.size(); - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - for ( unsigned int i = 0; i < pScene->mNumMeshes; ++i ) { - pScene->mMeshes[ i ] = avMeshes[ i ]; - } + // now generate the output scene object. Fill the material list + pScene->mNumMaterials = (unsigned int)avMaterials.size(); + pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; + for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) { + pScene->mMaterials[i] = avMaterials[i]; + } - // generate a simple node structure - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; - pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; + // fill the mesh list + pScene->mNumMeshes = 1; + pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; + pScene->mMeshes[0] = mGeneratedMesh; - for ( unsigned int i = 0; i < pScene->mRootNode->mNumMeshes; ++i ) { - pScene->mRootNode->mMeshes[ i ] = i; - } + // generate a simple node structure + pScene->mRootNode = new aiNode(); + pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; + pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; + + for (unsigned int i = 0; i < pScene->mRootNode->mNumMeshes; ++i) { + pScene->mRootNode->mMeshes[i] = i; + } } -// ------------------------------------------------------------------------------------------------ -// Split meshes by material IDs -void PLYImporter::ConvertMeshes(std::vector* avFaces, - const std::vector* avPositions, - const std::vector* avNormals, - const std::vector* avColors, - const std::vector* avTexCoords, - const std::vector* avMaterials, - std::vector* avOut) -{ - ai_assert(NULL != avFaces); - ai_assert(NULL != avPositions); - ai_assert(NULL != avMaterials); +void PLYImporter::LoadVertex(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos) { + ai_assert(NULL != pcElement); + ai_assert(NULL != instElement); - // split by materials - std::vector* aiSplit = new std::vector[avMaterials->size()]; + ai_uint aiPositions[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + PLY::EDataType aiTypes[3] = { EDT_Char, EDT_Char, EDT_Char }; - unsigned int iNum = 0; - for (std::vector::const_iterator i = avFaces->begin();i != avFaces->end();++i,++iNum) - aiSplit[(*i).iMaterialIndex].push_back(iNum); + ai_uint aiNormal[3] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + PLY::EDataType aiNormalTypes[3] = { EDT_Char, EDT_Char, EDT_Char }; - // now generate sub-meshes - for (unsigned int p = 0; p < avMaterials->size();++p) - { - if (aiSplit[p].size() != 0) - { - // allocate the mesh object - aiMesh* p_pcOut = new aiMesh(); - p_pcOut->mMaterialIndex = p; + unsigned int aiColors[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + PLY::EDataType aiColorsTypes[4] = { EDT_Char, EDT_Char, EDT_Char, EDT_Char }; - p_pcOut->mNumFaces = (unsigned int)aiSplit[p].size(); - p_pcOut->mFaces = new aiFace[aiSplit[p].size()]; + unsigned int aiTexcoord[2] = { 0xFFFFFFFF, 0xFFFFFFFF }; + PLY::EDataType aiTexcoordTypes[2] = { EDT_Char, EDT_Char }; - // at first we need to determine the size of the output vector array - unsigned int iNum = 0; - for (unsigned int i = 0; i < aiSplit[p].size();++i) - { - iNum += (unsigned int)(*avFaces)[aiSplit[p][i]].mIndices.size(); - } - p_pcOut->mNumVertices = iNum; - if( 0 == iNum ) { // nothing to do - delete[] aiSplit; // cleanup - delete p_pcOut; - return; - } - p_pcOut->mVertices = new aiVector3D[iNum]; - - if (!avColors->empty()) - p_pcOut->mColors[0] = new aiColor4D[iNum]; - if (!avTexCoords->empty()) - { - p_pcOut->mNumUVComponents[0] = 2; - p_pcOut->mTextureCoords[0] = new aiVector3D[iNum]; - } - if (!avNormals->empty()) - p_pcOut->mNormals = new aiVector3D[iNum]; - - // add all faces - iNum = 0; - unsigned int iVertex = 0; - for (std::vector::const_iterator i = aiSplit[p].begin(); - i != aiSplit[p].end();++i,++iNum) - { - p_pcOut->mFaces[iNum].mNumIndices = (unsigned int)(*avFaces)[*i].mIndices.size(); - p_pcOut->mFaces[iNum].mIndices = new unsigned int[p_pcOut->mFaces[iNum].mNumIndices]; - - // build an unique set of vertices/colors for this face - for (unsigned int q = 0; q < p_pcOut->mFaces[iNum].mNumIndices;++q) - { - p_pcOut->mFaces[iNum].mIndices[q] = iVertex; - const size_t idx = ( *avFaces )[ *i ].mIndices[ q ]; - if( idx >= ( *avPositions ).size() ) { - // out of border - continue; - } - p_pcOut->mVertices[ iVertex ] = ( *avPositions )[ idx ]; - - if (!avColors->empty()) - p_pcOut->mColors[ 0 ][ iVertex ] = ( *avColors )[ idx ]; - - if (!avTexCoords->empty()) - { - const aiVector2D& vec = ( *avTexCoords )[ idx ]; - p_pcOut->mTextureCoords[0][iVertex].x = vec.x; - p_pcOut->mTextureCoords[0][iVertex].y = vec.y; - } - - if (!avNormals->empty()) - p_pcOut->mNormals[ iVertex ] = ( *avNormals )[ idx ]; - iVertex++; - } - - } - // add the mesh to the output list - avOut->push_back(p_pcOut); + // now check whether which normal components are available + unsigned int _a( 0 ), cnt( 0 ); + for ( std::vector::const_iterator a = pcElement->alProperties.begin(); + a != pcElement->alProperties.end(); ++a, ++_a) { + if ((*a).bIsList) { + continue; } - } - delete[] aiSplit; // cleanup -} -// ------------------------------------------------------------------------------------------------ -// Generate a default material if none was specified and apply it to all vanilla faces -void PLYImporter::ReplaceDefaultMaterial(std::vector* avFaces, - std::vector* avMaterials) -{ - bool bNeedDefaultMat = false; - - for (std::vector::iterator i = avFaces->begin();i != avFaces->end();++i) { - if (0xFFFFFFFF == (*i).iMaterialIndex) { - bNeedDefaultMat = true; - (*i).iMaterialIndex = (unsigned int)avMaterials->size(); - } - else if ((*i).iMaterialIndex >= avMaterials->size() ) { - // clamp the index - (*i).iMaterialIndex = (unsigned int)avMaterials->size()-1; + // Positions + if (PLY::EST_XCoord == (*a).Semantic) { + ++cnt; + aiPositions[0] = _a; + aiTypes[0] = (*a).eType; + } else if (PLY::EST_YCoord == (*a).Semantic) { + ++cnt; + aiPositions[1] = _a; + aiTypes[1] = (*a).eType; + } else if (PLY::EST_ZCoord == (*a).Semantic) { + ++cnt; + aiPositions[2] = _a; + aiTypes[2] = (*a).eType; + } else if (PLY::EST_XNormal == (*a).Semantic) { + // Normals + ++cnt; + aiNormal[0] = _a; + aiNormalTypes[0] = (*a).eType; + } else if (PLY::EST_YNormal == (*a).Semantic) { + ++cnt; + aiNormal[1] = _a; + aiNormalTypes[1] = (*a).eType; + } else if (PLY::EST_ZNormal == (*a).Semantic) { + ++cnt; + aiNormal[2] = _a; + aiNormalTypes[2] = (*a).eType; + } else if (PLY::EST_Red == (*a).Semantic) { + // Colors + ++cnt; + aiColors[0] = _a; + aiColorsTypes[0] = (*a).eType; + } else if (PLY::EST_Green == (*a).Semantic) { + ++cnt; + aiColors[1] = _a; + aiColorsTypes[1] = (*a).eType; + } else if (PLY::EST_Blue == (*a).Semantic) { + ++cnt; + aiColors[2] = _a; + aiColorsTypes[2] = (*a).eType; + } else if (PLY::EST_Alpha == (*a).Semantic) { + ++cnt; + aiColors[3] = _a; + aiColorsTypes[3] = (*a).eType; + } else if (PLY::EST_UTextureCoord == (*a).Semantic) { + // Texture coordinates + ++cnt; + aiTexcoord[0] = _a; + aiTexcoordTypes[0] = (*a).eType; + } else if (PLY::EST_VTextureCoord == (*a).Semantic) { + ++cnt; + aiTexcoord[1] = _a; + aiTexcoordTypes[1] = (*a).eType; } } - if (bNeedDefaultMat) { - // generate a default material - aiMaterial* pcHelper = new aiMaterial(); - - // fill in a default material - int iMode = (int)aiShadingMode_Gouraud; - pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); - - aiColor3D clr; - clr.b = clr.g = clr.r = 0.6f; - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_SPECULAR); - - clr.b = clr.g = clr.r = 0.05f; - pcHelper->AddProperty(&clr, 1,AI_MATKEY_COLOR_AMBIENT); - - // The face order is absolutely undefined for PLY, so we have to - // use two-sided rendering to be sure it's ok. - const int two_sided = 1; - pcHelper->AddProperty(&two_sided,1,AI_MATKEY_TWOSIDED); - - avMaterials->push_back(pcHelper); - } -} - -// ------------------------------------------------------------------------------------------------ -void PLYImporter::LoadTextureCoordinates(std::vector* pvOut) -{ - ai_assert(NULL != pvOut); - - unsigned int aiPositions[2] = {0xFFFFFFFF,0xFFFFFFFF}; - PLY::EDataType aiTypes[2] = {EDT_Char,EDT_Char}; - PLY::ElementInstanceList* pcList = NULL; - unsigned int cnt = 0; - - // serach in the DOM for a vertex entry - unsigned int _i = 0; - for (std::vector::const_iterator i = pcDOM->alElements.begin(); - i != pcDOM->alElements.end();++i,++_i) - { - if (PLY::EEST_Vertex == (*i).eSemantic) - { - pcList = &this->pcDOM->alElementData[_i]; - - // now check whether which normal components are available - unsigned int _a = 0; - for (std::vector::const_iterator a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) - { - if ((*a).bIsList)continue; - if (PLY::EST_UTextureCoord == (*a).Semantic) - { - cnt++; - aiPositions[0] = _a; - aiTypes[0] = (*a).eType; - } - else if (PLY::EST_VTextureCoord == (*a).Semantic) - { - cnt++; - aiPositions[1] = _a; - aiTypes[1] = (*a).eType; - } - } - } - } - // check whether we have a valid source for the texture coordinates data - if (NULL != pcList && 0 != cnt) - { - pvOut->reserve(pcList->alInstances.size()); - for (std::vector::const_iterator i = pcList->alInstances.begin(); - i != pcList->alInstances.end();++i) - { - // convert the vertices to sp floats - aiVector2D vOut; - - if (0xFFFFFFFF != aiPositions[0]) - { - vOut.x = PLY::PropertyInstance::ConvertTo( - GetProperty((*i).alProperties, aiPositions[0]).avList.front(),aiTypes[0]); - } - - if (0xFFFFFFFF != aiPositions[1]) - { - vOut.y = PLY::PropertyInstance::ConvertTo( - GetProperty((*i).alProperties, aiPositions[1]).avList.front(),aiTypes[1]); - } - // and add them to our nice list - pvOut->push_back(vOut); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Try to extract vertices from the PLY DOM -void PLYImporter::LoadVertices(std::vector* pvOut, bool p_bNormals) -{ - ai_assert(NULL != pvOut); - - ai_uint aiPositions[3] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}; - PLY::EDataType aiTypes[3] = {EDT_Char,EDT_Char,EDT_Char}; - PLY::ElementInstanceList* pcList = NULL; - unsigned int cnt = 0; - - // search in the DOM for a vertex entry - unsigned int _i = 0; - for (std::vector::const_iterator i = pcDOM->alElements.begin(); - i != pcDOM->alElements.end();++i,++_i) - { - if (PLY::EEST_Vertex == (*i).eSemantic) - { - pcList = &pcDOM->alElementData[_i]; - - // load normal vectors? - if (p_bNormals) - { - // now check whether which normal components are available - unsigned int _a = 0; - for (std::vector::const_iterator a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) - { - if ((*a).bIsList)continue; - if (PLY::EST_XNormal == (*a).Semantic) - { - cnt++; - aiPositions[0] = _a; - aiTypes[0] = (*a).eType; - } - else if (PLY::EST_YNormal == (*a).Semantic) - { - cnt++; - aiPositions[1] = _a; - aiTypes[1] = (*a).eType; - } - else if (PLY::EST_ZNormal == (*a).Semantic) - { - cnt++; - aiPositions[2] = _a; - aiTypes[2] = (*a).eType; - } - } - } - // load vertex coordinates - else - { - // now check whether which coordinate sets are available - unsigned int _a = 0; - for (std::vector::const_iterator a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) - { - if ((*a).bIsList)continue; - if (PLY::EST_XCoord == (*a).Semantic) - { - cnt++; - aiPositions[0] = _a; - aiTypes[0] = (*a).eType; - } - else if (PLY::EST_YCoord == (*a).Semantic) - { - cnt++; - aiPositions[1] = _a; - aiTypes[1] = (*a).eType; - } - else if (PLY::EST_ZCoord == (*a).Semantic) - { - cnt++; - aiPositions[2] = _a; - aiTypes[2] = (*a).eType; - } - if (3 == cnt)break; - } - } - break; - } - } // check whether we have a valid source for the vertex data - if (NULL != pcList && 0 != cnt) - { - pvOut->reserve(pcList->alInstances.size()); - for (std::vector::const_iterator - i = pcList->alInstances.begin(); - i != pcList->alInstances.end();++i) - { - // convert the vertices to sp floats - aiVector3D vOut; + if (0 != cnt) { + // Position + aiVector3D vOut; + if (0xFFFFFFFF != aiPositions[0]) { + vOut.x = PLY::PropertyInstance::ConvertTo( + GetProperty(instElement->alProperties, aiPositions[0]).avList.front(), aiTypes[0]); + } - if (0xFFFFFFFF != aiPositions[0]) - { - vOut.x = PLY::PropertyInstance::ConvertTo( - GetProperty((*i).alProperties, aiPositions[0]).avList.front(),aiTypes[0]); + if (0xFFFFFFFF != aiPositions[1]) { + vOut.y = PLY::PropertyInstance::ConvertTo( + GetProperty(instElement->alProperties, aiPositions[1]).avList.front(), aiTypes[1]); + } + + if (0xFFFFFFFF != aiPositions[2]) { + vOut.z = PLY::PropertyInstance::ConvertTo( + GetProperty(instElement->alProperties, aiPositions[2]).avList.front(), aiTypes[2]); + } + + // Normals + aiVector3D nOut; + bool haveNormal = false; + if (0xFFFFFFFF != aiNormal[0]) { + nOut.x = PLY::PropertyInstance::ConvertTo( + GetProperty(instElement->alProperties, aiNormal[0]).avList.front(), aiNormalTypes[0]); + haveNormal = true; + } + + if (0xFFFFFFFF != aiNormal[1]) { + nOut.y = PLY::PropertyInstance::ConvertTo( + GetProperty(instElement->alProperties, aiNormal[1]).avList.front(), aiNormalTypes[1]); + haveNormal = true; + } + + if (0xFFFFFFFF != aiNormal[2]) { + nOut.z = PLY::PropertyInstance::ConvertTo( + GetProperty(instElement->alProperties, aiNormal[2]).avList.front(), aiNormalTypes[2]); + haveNormal = true; + } + + //Colors + aiColor4D cOut; + bool haveColor = false; + if (0xFFFFFFFF != aiColors[0]) { + cOut.r = NormalizeColorValue(GetProperty(instElement->alProperties, + aiColors[0]).avList.front(), aiColorsTypes[0]); + haveColor = true; + } + + if (0xFFFFFFFF != aiColors[1]) { + cOut.g = NormalizeColorValue(GetProperty(instElement->alProperties, + aiColors[1]).avList.front(), aiColorsTypes[1]); + haveColor = true; + } + + if (0xFFFFFFFF != aiColors[2]) { + cOut.b = NormalizeColorValue(GetProperty(instElement->alProperties, + aiColors[2]).avList.front(), aiColorsTypes[2]); + haveColor = true; + } + + // assume 1.0 for the alpha channel ifit is not set + if (0xFFFFFFFF == aiColors[3]) { + cOut.a = 1.0; + } else { + cOut.a = NormalizeColorValue(GetProperty(instElement->alProperties, + aiColors[3]).avList.front(), aiColorsTypes[3]); + + haveColor = true; + } + + //Texture coordinates + aiVector3D tOut; + tOut.z = 0; + bool haveTextureCoords = false; + if (0xFFFFFFFF != aiTexcoord[0]) { + tOut.x = PLY::PropertyInstance::ConvertTo( + GetProperty(instElement->alProperties, aiTexcoord[0]).avList.front(), aiTexcoordTypes[0]); + haveTextureCoords = true; + } + + if (0xFFFFFFFF != aiTexcoord[1]) { + tOut.y = PLY::PropertyInstance::ConvertTo( + GetProperty(instElement->alProperties, aiTexcoord[1]).avList.front(), aiTexcoordTypes[1]); + haveTextureCoords = true; + } + + //create aiMesh if needed + if ( nullptr == mGeneratedMesh ) { + mGeneratedMesh = new aiMesh(); + mGeneratedMesh->mMaterialIndex = 0; + } + + if (nullptr == mGeneratedMesh->mVertices) { + mGeneratedMesh->mNumVertices = pcElement->NumOccur; + mGeneratedMesh->mVertices = new aiVector3D[mGeneratedMesh->mNumVertices]; + } + + mGeneratedMesh->mVertices[pos] = vOut; + + if (haveNormal) { + if (nullptr == mGeneratedMesh->mNormals) + mGeneratedMesh->mNormals = new aiVector3D[mGeneratedMesh->mNumVertices]; + mGeneratedMesh->mNormals[pos] = nOut; + } + + if (haveColor) { + if (nullptr == mGeneratedMesh->mColors[0]) + mGeneratedMesh->mColors[0] = new aiColor4D[mGeneratedMesh->mNumVertices]; + mGeneratedMesh->mColors[0][pos] = cOut; + } + + if (haveTextureCoords) { + if (nullptr == mGeneratedMesh->mTextureCoords[0]) { + mGeneratedMesh->mNumUVComponents[0] = 2; + mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices]; } - - if (0xFFFFFFFF != aiPositions[1]) - { - vOut.y = PLY::PropertyInstance::ConvertTo( - GetProperty((*i).alProperties, aiPositions[1]).avList.front(),aiTypes[1]); - } - - if (0xFFFFFFFF != aiPositions[2]) - { - vOut.z = PLY::PropertyInstance::ConvertTo( - GetProperty((*i).alProperties, aiPositions[2]).avList.front(),aiTypes[2]); - } - - // and add them to our nice list - pvOut->push_back(vOut); + mGeneratedMesh->mTextureCoords[0][pos] = tOut; } } } + // ------------------------------------------------------------------------------------------------ // Convert a color component to [0...1] -ai_real PLYImporter::NormalizeColorValue (PLY::PropertyInstance::ValueUnion val, - PLY::EDataType eType) +ai_real PLYImporter::NormalizeColorValue(PLY::PropertyInstance::ValueUnion val, + PLY::EDataType eType) { - switch (eType) - { - case EDT_Float: - return val.fFloat; - case EDT_Double: - return (ai_real)val.fDouble; + switch (eType) + { + case EDT_Float: + return val.fFloat; + case EDT_Double: + return (ai_real)val.fDouble; - case EDT_UChar: - return (ai_real)val.iUInt / (ai_real)0xFF; - case EDT_Char: - return (ai_real)(val.iInt+(0xFF/2)) / (ai_real)0xFF; - case EDT_UShort: - return (ai_real)val.iUInt / (ai_real)0xFFFF; - case EDT_Short: - return (ai_real)(val.iInt+(0xFFFF/2)) / (ai_real)0xFFFF; - case EDT_UInt: - return (ai_real)val.iUInt / (ai_real)0xFFFF; - case EDT_Int: - return ((ai_real)val.iInt / (ai_real)0xFF) + 0.5f; - default: ; - }; - return 0.0f; -} - -// ------------------------------------------------------------------------------------------------ -// Try to extract proper vertex colors from the PLY DOM -void PLYImporter::LoadVertexColor(std::vector* pvOut) -{ - ai_assert(NULL != pvOut); - - unsigned int aiPositions[4] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}; - PLY::EDataType aiTypes[4] = {EDT_Char, EDT_Char, EDT_Char, EDT_Char}; // silencing gcc - unsigned int cnt = 0; - PLY::ElementInstanceList* pcList = NULL; - - // serach in the DOM for a vertex entry - unsigned int _i = 0; - for (std::vector::const_iterator i = pcDOM->alElements.begin(); - i != pcDOM->alElements.end();++i,++_i) - { - if (PLY::EEST_Vertex == (*i).eSemantic) - { - pcList = &this->pcDOM->alElementData[_i]; - - // now check whether which coordinate sets are available - unsigned int _a = 0; - for (std::vector::const_iterator - a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) - { - if ((*a).bIsList)continue; - if (PLY::EST_Red == (*a).Semantic) - { - cnt++; - aiPositions[0] = _a; - aiTypes[0] = (*a).eType; - } - else if (PLY::EST_Green == (*a).Semantic) - { - cnt++; - aiPositions[1] = _a; - aiTypes[1] = (*a).eType; - } - else if (PLY::EST_Blue == (*a).Semantic) - { - cnt++; - aiPositions[2] = _a; - aiTypes[2] = (*a).eType; - } - else if (PLY::EST_Alpha == (*a).Semantic) - { - cnt++; - aiPositions[3] = _a; - aiTypes[3] = (*a).eType; - } - if (4 == cnt)break; - } - break; - } - } - // check whether we have a valid source for the vertex data - if (NULL != pcList && 0 != cnt) - { - pvOut->reserve(pcList->alInstances.size()); - for (std::vector::const_iterator i = pcList->alInstances.begin(); - i != pcList->alInstances.end();++i) - { - // convert the vertices to sp floats - aiColor4D vOut; - - if (0xFFFFFFFF != aiPositions[0]) - { - vOut.r = NormalizeColorValue(GetProperty((*i).alProperties, - aiPositions[0]).avList.front(),aiTypes[0]); - } - - if (0xFFFFFFFF != aiPositions[1]) - { - vOut.g = NormalizeColorValue(GetProperty((*i).alProperties, - aiPositions[1]).avList.front(),aiTypes[1]); - } - - if (0xFFFFFFFF != aiPositions[2]) - { - vOut.b = NormalizeColorValue(GetProperty((*i).alProperties, - aiPositions[2]).avList.front(),aiTypes[2]); - } - - // assume 1.0 for the alpha channel ifit is not set - if (0xFFFFFFFF == aiPositions[3])vOut.a = 1.0; - else - { - vOut.a = NormalizeColorValue(GetProperty((*i).alProperties, - aiPositions[3]).avList.front(),aiTypes[3]); - } - - // and add them to our nice list - pvOut->push_back(vOut); - } - } + case EDT_UChar: + return (ai_real)val.iUInt / (ai_real)0xFF; + case EDT_Char: + return (ai_real)(val.iInt + (0xFF / 2)) / (ai_real)0xFF; + case EDT_UShort: + return (ai_real)val.iUInt / (ai_real)0xFFFF; + case EDT_Short: + return (ai_real)(val.iInt + (0xFFFF / 2)) / (ai_real)0xFFFF; + case EDT_UInt: + return (ai_real)val.iUInt / (ai_real)0xFFFF; + case EDT_Int: + return ((ai_real)val.iInt / (ai_real)0xFF) + 0.5f; + default:; + }; + return 0.0f; } // ------------------------------------------------------------------------------------------------ // Try to extract proper faces from the PLY DOM -void PLYImporter::LoadFaces(std::vector* pvOut) +void PLYImporter::LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos) { - ai_assert(NULL != pvOut); + ai_assert(NULL != pcElement); + ai_assert(NULL != instElement); - PLY::ElementInstanceList* pcList = NULL; - bool bOne = false; + if (mGeneratedMesh == NULL) + throw DeadlyImportError("Invalid .ply file: Vertices should be declared before faces"); - // index of the vertex index list - unsigned int iProperty = 0xFFFFFFFF; - PLY::EDataType eType = EDT_Char; - bool bIsTristrip = false; + bool bOne = false; - // index of the material index property - unsigned int iMaterialIndex = 0xFFFFFFFF; - PLY::EDataType eType2 = EDT_Char; + // index of the vertex index list + unsigned int iProperty = 0xFFFFFFFF; + PLY::EDataType eType = EDT_Char; + bool bIsTriStrip = false; - // serach in the DOM for a face entry - unsigned int _i = 0; - for (std::vector::const_iterator i = pcDOM->alElements.begin(); - i != pcDOM->alElements.end();++i,++_i) + // index of the material index property + //unsigned int iMaterialIndex = 0xFFFFFFFF; + //PLY::EDataType eType2 = EDT_Char; + + // texture coordinates + unsigned int iTextureCoord = 0xFFFFFFFF; + PLY::EDataType eType3 = EDT_Char; + + // face = unique number of vertex indices + if (PLY::EEST_Face == pcElement->eSemantic) + { + unsigned int _a = 0; + for (std::vector::const_iterator a = pcElement->alProperties.begin(); + a != pcElement->alProperties.end(); ++a, ++_a) { - // face = unique number of vertex indices - if (PLY::EEST_Face == (*i).eSemantic) - { - pcList = &pcDOM->alElementData[_i]; - unsigned int _a = 0; - for (std::vector::const_iterator a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) - { - if (PLY::EST_VertexIndex == (*a).Semantic) - { - // must be a dynamic list! - if (!(*a).bIsList)continue; - iProperty = _a; - bOne = true; - eType = (*a).eType; - } - else if (PLY::EST_MaterialIndex == (*a).Semantic) - { - if ((*a).bIsList)continue; - iMaterialIndex = _a; - bOne = true; - eType2 = (*a).eType; - } - } - break; - } - // triangle strip - // TODO: triangle strip and material index support??? - else if (PLY::EEST_TriStrip == (*i).eSemantic) - { - // find a list property in this ... - pcList = &this->pcDOM->alElementData[_i]; - unsigned int _a = 0; - for (std::vector::const_iterator a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) - { - // must be a dynamic list! - if (!(*a).bIsList)continue; - iProperty = _a; - bOne = true; - bIsTristrip = true; - eType = (*a).eType; - break; - } - break; - } + if (PLY::EST_VertexIndex == (*a).Semantic) + { + // must be a dynamic list! + if (!(*a).bIsList) + continue; + + iProperty = _a; + bOne = true; + eType = (*a).eType; + } + /*else if (PLY::EST_MaterialIndex == (*a).Semantic) + { + if ((*a).bIsList) + continue; + iMaterialIndex = _a; + bOne = true; + eType2 = (*a).eType; + }*/ + else if (PLY::EST_TextureCoordinates == (*a).Semantic) + { + // must be a dynamic list! + if (!(*a).bIsList) + continue; + iTextureCoord = _a; + bOne = true; + eType3 = (*a).eType; + } } - // check whether we have at least one per-face information set - if (pcList && bOne) + } + // triangle strip + // TODO: triangle strip and material index support??? + else if (PLY::EEST_TriStrip == pcElement->eSemantic) + { + unsigned int _a = 0; + for (std::vector::const_iterator a = pcElement->alProperties.begin(); + a != pcElement->alProperties.end(); ++a, ++_a) { - if (!bIsTristrip) - { - pvOut->reserve(pcList->alInstances.size()); - for (std::vector::const_iterator i = pcList->alInstances.begin(); - i != pcList->alInstances.end();++i) - { - PLY::Face sFace; - - // parse the list of vertex indices - if (0xFFFFFFFF != iProperty) - { - const unsigned int iNum = (unsigned int)GetProperty((*i).alProperties, iProperty).avList.size(); - sFace.mIndices.resize(iNum); - - std::vector::const_iterator p = - GetProperty((*i).alProperties, iProperty).avList.begin(); - - for (unsigned int a = 0; a < iNum;++a,++p) - { - sFace.mIndices[a] = PLY::PropertyInstance::ConvertTo(*p,eType); - } - } - - // parse the material index - if (0xFFFFFFFF != iMaterialIndex) - { - sFace.iMaterialIndex = PLY::PropertyInstance::ConvertTo( - GetProperty((*i).alProperties, iMaterialIndex).avList.front(),eType2); - } - pvOut->push_back(sFace); - } - } - else // triangle strips - { - // normally we have only one triangle strip instance where - // a value of -1 indicates a restart of the strip - bool flip = false; - for (std::vector::const_iterator i = pcList->alInstances.begin();i != pcList->alInstances.end();++i) { - const std::vector& quak = GetProperty((*i).alProperties, iProperty).avList; - pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u)); - - int aiTable[2] = {-1,-1}; - for (std::vector::const_iterator a = quak.begin();a != quak.end();++a) { - const int p = PLY::PropertyInstance::ConvertTo(*a,eType); - - if (-1 == p) { - // restart the strip ... - aiTable[0] = aiTable[1] = -1; - flip = false; - continue; - } - if (-1 == aiTable[0]) { - aiTable[0] = p; - continue; - } - if (-1 == aiTable[1]) { - aiTable[1] = p; - continue; - } - - pvOut->push_back(PLY::Face()); - PLY::Face& sFace = pvOut->back(); - sFace.mIndices[0] = aiTable[0]; - sFace.mIndices[1] = aiTable[1]; - sFace.mIndices[2] = p; - if ((flip = !flip)) { - std::swap(sFace.mIndices[0],sFace.mIndices[1]); - } - - aiTable[0] = aiTable[1]; - aiTable[1] = p; - } - } - } + // must be a dynamic list! + if (!(*a).bIsList) + continue; + iProperty = _a; + bOne = true; + bIsTriStrip = true; + eType = (*a).eType; + break; } + } + + // check whether we have at least one per-face information set + if (bOne) + { + if (mGeneratedMesh->mFaces == NULL) + { + mGeneratedMesh->mNumFaces = pcElement->NumOccur; + mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces]; + } + + if (!bIsTriStrip) + { + // parse the list of vertex indices + if (0xFFFFFFFF != iProperty) + { + const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iProperty).avList.size(); + mGeneratedMesh->mFaces[pos].mNumIndices = iNum; + mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[iNum]; + + std::vector::const_iterator p = + GetProperty(instElement->alProperties, iProperty).avList.begin(); + + for (unsigned int a = 0; a < iNum; ++a, ++p) + { + mGeneratedMesh->mFaces[pos].mIndices[a] = PLY::PropertyInstance::ConvertTo(*p, eType); + } + } + + // parse the material index + // cannot be handled without processing the whole file first + /*if (0xFFFFFFFF != iMaterialIndex) + { + mGeneratedMesh->mFaces[pos]. = PLY::PropertyInstance::ConvertTo( + GetProperty(instElement->alProperties, iMaterialIndex).avList.front(), eType2); + }*/ + + if (0xFFFFFFFF != iTextureCoord) + { + const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size(); + + //should be 6 coords + std::vector::const_iterator p = + GetProperty(instElement->alProperties, iTextureCoord).avList.begin(); + + if ((iNum / 3) == 2) // X Y coord + { + for (unsigned int a = 0; a < iNum; ++a, ++p) + { + unsigned int vindex = mGeneratedMesh->mFaces[pos].mIndices[a / 2]; + if (vindex < mGeneratedMesh->mNumVertices) + { + if (mGeneratedMesh->mTextureCoords[0] == NULL) + { + mGeneratedMesh->mNumUVComponents[0] = 2; + mGeneratedMesh->mTextureCoords[0] = new aiVector3D[mGeneratedMesh->mNumVertices]; + } + + if (a % 2 == 0) + mGeneratedMesh->mTextureCoords[0][vindex].x = PLY::PropertyInstance::ConvertTo(*p, eType3); + else + mGeneratedMesh->mTextureCoords[0][vindex].y = PLY::PropertyInstance::ConvertTo(*p, eType3); + + mGeneratedMesh->mTextureCoords[0][vindex].z = 0; + } + } + } + } + } + else // triangle strips + { + // normally we have only one triangle strip instance where + // a value of -1 indicates a restart of the strip + bool flip = false; + const std::vector& quak = GetProperty(instElement->alProperties, iProperty).avList; + //pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u)); //Limits memory consumption + + int aiTable[2] = { -1, -1 }; + for (std::vector::const_iterator a = quak.begin(); a != quak.end(); ++a) { + const int p = PLY::PropertyInstance::ConvertTo(*a, eType); + + if (-1 == p) { + // restart the strip ... + aiTable[0] = aiTable[1] = -1; + flip = false; + continue; + } + if (-1 == aiTable[0]) { + aiTable[0] = p; + continue; + } + if (-1 == aiTable[1]) { + aiTable[1] = p; + continue; + } + + if (mGeneratedMesh->mFaces == NULL) + { + mGeneratedMesh->mNumFaces = pcElement->NumOccur; + mGeneratedMesh->mFaces = new aiFace[mGeneratedMesh->mNumFaces]; + } + + mGeneratedMesh->mFaces[pos].mNumIndices = 3; + mGeneratedMesh->mFaces[pos].mIndices = new unsigned int[3]; + mGeneratedMesh->mFaces[pos].mIndices[0] = aiTable[0]; + mGeneratedMesh->mFaces[pos].mIndices[1] = aiTable[1]; + mGeneratedMesh->mFaces[pos].mIndices[2] = p; + + if ((flip = !flip)) { + std::swap(mGeneratedMesh->mFaces[pos].mIndices[0], mGeneratedMesh->mFaces[pos].mIndices[1]); + } + + aiTable[0] = aiTable[1]; + aiTable[1] = p; + } + } + } } // ------------------------------------------------------------------------------------------------ // Get a RGBA color in [0...1] range void PLYImporter::GetMaterialColor(const std::vector& avList, - unsigned int aiPositions[4], - PLY::EDataType aiTypes[4], - aiColor4D* clrOut) + unsigned int aiPositions[4], + PLY::EDataType aiTypes[4], + aiColor4D* clrOut) { - ai_assert(NULL != clrOut); + ai_assert(NULL != clrOut); - if (0xFFFFFFFF == aiPositions[0])clrOut->r = 0.0f; - else - { - clrOut->r = NormalizeColorValue(GetProperty(avList, - aiPositions[0]).avList.front(),aiTypes[0]); - } + if (0xFFFFFFFF == aiPositions[0])clrOut->r = 0.0f; + else + { + clrOut->r = NormalizeColorValue(GetProperty(avList, + aiPositions[0]).avList.front(), aiTypes[0]); + } - if (0xFFFFFFFF == aiPositions[1])clrOut->g = 0.0f; - else - { - clrOut->g = NormalizeColorValue(GetProperty(avList, - aiPositions[1]).avList.front(),aiTypes[1]); - } + if (0xFFFFFFFF == aiPositions[1])clrOut->g = 0.0f; + else + { + clrOut->g = NormalizeColorValue(GetProperty(avList, + aiPositions[1]).avList.front(), aiTypes[1]); + } - if (0xFFFFFFFF == aiPositions[2])clrOut->b = 0.0f; - else - { - clrOut->b = NormalizeColorValue(GetProperty(avList, - aiPositions[2]).avList.front(),aiTypes[2]); - } + if (0xFFFFFFFF == aiPositions[2])clrOut->b = 0.0f; + else + { + clrOut->b = NormalizeColorValue(GetProperty(avList, + aiPositions[2]).avList.front(), aiTypes[2]); + } - // assume 1.0 for the alpha channel ifit is not set - if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f; - else - { - clrOut->a = NormalizeColorValue(GetProperty(avList, - aiPositions[3]).avList.front(),aiTypes[3]); - } + // assume 1.0 for the alpha channel ifit is not set + if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f; + else + { + clrOut->a = NormalizeColorValue(GetProperty(avList, + aiPositions[3]).avList.front(), aiTypes[3]); + } } // ------------------------------------------------------------------------------------------------ // Extract a material from the PLY DOM -void PLYImporter::LoadMaterial(std::vector* pvOut) +void PLYImporter::LoadMaterial(std::vector* pvOut, std::string &defaultTexture, const bool pointsOnly) { - ai_assert(NULL != pvOut); + ai_assert(NULL != pvOut); - // diffuse[4], specular[4], ambient[4] - // rgba order - unsigned int aaiPositions[3][4] = { + // diffuse[4], specular[4], ambient[4] + // rgba order + unsigned int aaiPositions[3][4] = { - {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}, - {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}, - {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}, - }; + { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }, + { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }, + { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }, + }; - PLY::EDataType aaiTypes[3][4] = { - {EDT_Char,EDT_Char,EDT_Char,EDT_Char}, - {EDT_Char,EDT_Char,EDT_Char,EDT_Char}, - {EDT_Char,EDT_Char,EDT_Char,EDT_Char} - }; - PLY::ElementInstanceList* pcList = NULL; + PLY::EDataType aaiTypes[3][4] = { + { EDT_Char, EDT_Char, EDT_Char, EDT_Char }, + { EDT_Char, EDT_Char, EDT_Char, EDT_Char }, + { EDT_Char, EDT_Char, EDT_Char, EDT_Char } + }; + PLY::ElementInstanceList* pcList = NULL; - unsigned int iPhong = 0xFFFFFFFF; - PLY::EDataType ePhong = EDT_Char; + unsigned int iPhong = 0xFFFFFFFF; + PLY::EDataType ePhong = EDT_Char; - unsigned int iOpacity = 0xFFFFFFFF; - PLY::EDataType eOpacity = EDT_Char; + unsigned int iOpacity = 0xFFFFFFFF; + PLY::EDataType eOpacity = EDT_Char; - // serach in the DOM for a vertex entry - unsigned int _i = 0; - for (std::vector::const_iterator i = this->pcDOM->alElements.begin(); - i != this->pcDOM->alElements.end();++i,++_i) + // search in the DOM for a vertex entry + unsigned int _i = 0; + for (std::vector::const_iterator i = this->pcDOM->alElements.begin(); + i != this->pcDOM->alElements.end(); ++i, ++_i) + { + if (PLY::EEST_Material == (*i).eSemantic) { - if (PLY::EEST_Material == (*i).eSemantic) + pcList = &this->pcDOM->alElementData[_i]; + + // now check whether which coordinate sets are available + unsigned int _a = 0; + for (std::vector::const_iterator + a = (*i).alProperties.begin(); + a != (*i).alProperties.end(); ++a, ++_a) + { + if ((*a).bIsList)continue; + + // pohng specularity ----------------------------------- + if (PLY::EST_PhongPower == (*a).Semantic) { - pcList = &this->pcDOM->alElementData[_i]; - - // now check whether which coordinate sets are available - unsigned int _a = 0; - for (std::vector::const_iterator - a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) - { - if ((*a).bIsList)continue; - - // pohng specularity ----------------------------------- - if (PLY::EST_PhongPower == (*a).Semantic) - { - iPhong = _a; - ePhong = (*a).eType; - } - - // general opacity ----------------------------------- - if (PLY::EST_Opacity == (*a).Semantic) - { - iOpacity = _a; - eOpacity = (*a).eType; - } - - // diffuse color channels ----------------------------------- - if (PLY::EST_DiffuseRed == (*a).Semantic) - { - aaiPositions[0][0] = _a; - aaiTypes[0][0] = (*a).eType; - } - else if (PLY::EST_DiffuseGreen == (*a).Semantic) - { - aaiPositions[0][1] = _a; - aaiTypes[0][1] = (*a).eType; - } - else if (PLY::EST_DiffuseBlue == (*a).Semantic) - { - aaiPositions[0][2] = _a; - aaiTypes[0][2] = (*a).eType; - } - else if (PLY::EST_DiffuseAlpha == (*a).Semantic) - { - aaiPositions[0][3] = _a; - aaiTypes[0][3] = (*a).eType; - } - // specular color channels ----------------------------------- - else if (PLY::EST_SpecularRed == (*a).Semantic) - { - aaiPositions[1][0] = _a; - aaiTypes[1][0] = (*a).eType; - } - else if (PLY::EST_SpecularGreen == (*a).Semantic) - { - aaiPositions[1][1] = _a; - aaiTypes[1][1] = (*a).eType; - } - else if (PLY::EST_SpecularBlue == (*a).Semantic) - { - aaiPositions[1][2] = _a; - aaiTypes[1][2] = (*a).eType; - } - else if (PLY::EST_SpecularAlpha == (*a).Semantic) - { - aaiPositions[1][3] = _a; - aaiTypes[1][3] = (*a).eType; - } - // ambient color channels ----------------------------------- - else if (PLY::EST_AmbientRed == (*a).Semantic) - { - aaiPositions[2][0] = _a; - aaiTypes[2][0] = (*a).eType; - } - else if (PLY::EST_AmbientGreen == (*a).Semantic) - { - aaiPositions[2][1] = _a; - aaiTypes[2][1] = (*a).eType; - } - else if (PLY::EST_AmbientBlue == (*a).Semantic) - { - aaiPositions[2][2] = _a; - aaiTypes[2][2] = (*a).eType; - } - else if (PLY::EST_AmbientAlpha == (*a).Semantic) - { - aaiPositions[2][3] = _a; - aaiTypes[2][3] = (*a).eType; - } - } - break; + iPhong = _a; + ePhong = (*a).eType; } - } - // check whether we have a valid source for the material data - if (NULL != pcList) { - for (std::vector::const_iterator i = pcList->alInstances.begin();i != pcList->alInstances.end();++i) { - aiColor4D clrOut; - aiMaterial* pcHelper = new aiMaterial(); - // build the diffuse material color - GetMaterialColor((*i).alProperties,aaiPositions[0],aaiTypes[0],&clrOut); - pcHelper->AddProperty(&clrOut,1,AI_MATKEY_COLOR_DIFFUSE); - - // build the specular material color - GetMaterialColor((*i).alProperties,aaiPositions[1],aaiTypes[1],&clrOut); - pcHelper->AddProperty(&clrOut,1,AI_MATKEY_COLOR_SPECULAR); - - // build the ambient material color - GetMaterialColor((*i).alProperties,aaiPositions[2],aaiTypes[2],&clrOut); - pcHelper->AddProperty(&clrOut,1,AI_MATKEY_COLOR_AMBIENT); - - // handle phong power and shading mode - int iMode; - if (0xFFFFFFFF != iPhong) { - ai_real fSpec = PLY::PropertyInstance::ConvertTo(GetProperty((*i).alProperties, iPhong).avList.front(),ePhong); - - // if shininess is 0 (and the pow() calculation would therefore always - // become 1, not depending on the angle), use gouraud lighting - if (fSpec) { - // scale this with 15 ... hopefully this is correct - fSpec *= 15; - pcHelper->AddProperty(&fSpec, 1, AI_MATKEY_SHININESS); - - iMode = (int)aiShadingMode_Phong; - } - else iMode = (int)aiShadingMode_Gouraud; - } - else iMode = (int)aiShadingMode_Gouraud; - pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); - - // handle opacity - if (0xFFFFFFFF != iOpacity) { - ai_real fOpacity = PLY::PropertyInstance::ConvertTo(GetProperty((*i).alProperties, iPhong).avList.front(),eOpacity); - pcHelper->AddProperty(&fOpacity, 1, AI_MATKEY_OPACITY); - } - - // The face order is absolutely undefined for PLY, so we have to - // use two-sided rendering to be sure it's ok. - const int two_sided = 1; - pcHelper->AddProperty(&two_sided,1,AI_MATKEY_TWOSIDED); - - // add the newly created material instance to the list - pvOut->push_back(pcHelper); + // general opacity ----------------------------------- + if (PLY::EST_Opacity == (*a).Semantic) + { + iOpacity = _a; + eOpacity = (*a).eType; } + + // diffuse color channels ----------------------------------- + if (PLY::EST_DiffuseRed == (*a).Semantic) + { + aaiPositions[0][0] = _a; + aaiTypes[0][0] = (*a).eType; + } + else if (PLY::EST_DiffuseGreen == (*a).Semantic) + { + aaiPositions[0][1] = _a; + aaiTypes[0][1] = (*a).eType; + } + else if (PLY::EST_DiffuseBlue == (*a).Semantic) + { + aaiPositions[0][2] = _a; + aaiTypes[0][2] = (*a).eType; + } + else if (PLY::EST_DiffuseAlpha == (*a).Semantic) + { + aaiPositions[0][3] = _a; + aaiTypes[0][3] = (*a).eType; + } + // specular color channels ----------------------------------- + else if (PLY::EST_SpecularRed == (*a).Semantic) + { + aaiPositions[1][0] = _a; + aaiTypes[1][0] = (*a).eType; + } + else if (PLY::EST_SpecularGreen == (*a).Semantic) + { + aaiPositions[1][1] = _a; + aaiTypes[1][1] = (*a).eType; + } + else if (PLY::EST_SpecularBlue == (*a).Semantic) + { + aaiPositions[1][2] = _a; + aaiTypes[1][2] = (*a).eType; + } + else if (PLY::EST_SpecularAlpha == (*a).Semantic) + { + aaiPositions[1][3] = _a; + aaiTypes[1][3] = (*a).eType; + } + // ambient color channels ----------------------------------- + else if (PLY::EST_AmbientRed == (*a).Semantic) + { + aaiPositions[2][0] = _a; + aaiTypes[2][0] = (*a).eType; + } + else if (PLY::EST_AmbientGreen == (*a).Semantic) + { + aaiPositions[2][1] = _a; + aaiTypes[2][1] = (*a).eType; + } + else if (PLY::EST_AmbientBlue == (*a).Semantic) + { + aaiPositions[2][2] = _a; + aaiTypes[2][2] = (*a).eType; + } + else if (PLY::EST_AmbientAlpha == (*a).Semantic) + { + aaiPositions[2][3] = _a; + aaiTypes[2][3] = (*a).eType; + } + } + break; } + else if (PLY::EEST_TextureFile == (*i).eSemantic) + { + defaultTexture = (*i).szName; + } + } + // check whether we have a valid source for the material data + if (NULL != pcList) { + for (std::vector::const_iterator i = pcList->alInstances.begin(); i != pcList->alInstances.end(); ++i) { + aiColor4D clrOut; + aiMaterial* pcHelper = new aiMaterial(); + + // build the diffuse material color + GetMaterialColor((*i).alProperties, aaiPositions[0], aaiTypes[0], &clrOut); + pcHelper->AddProperty(&clrOut, 1, AI_MATKEY_COLOR_DIFFUSE); + + // build the specular material color + GetMaterialColor((*i).alProperties, aaiPositions[1], aaiTypes[1], &clrOut); + pcHelper->AddProperty(&clrOut, 1, AI_MATKEY_COLOR_SPECULAR); + + // build the ambient material color + GetMaterialColor((*i).alProperties, aaiPositions[2], aaiTypes[2], &clrOut); + pcHelper->AddProperty(&clrOut, 1, AI_MATKEY_COLOR_AMBIENT); + + // handle phong power and shading mode + int iMode = (int)aiShadingMode_Gouraud; + if (0xFFFFFFFF != iPhong) { + ai_real fSpec = PLY::PropertyInstance::ConvertTo(GetProperty((*i).alProperties, iPhong).avList.front(), ePhong); + + // if shininess is 0 (and the pow() calculation would therefore always + // become 1, not depending on the angle), use gouraud lighting + if (fSpec) { + // scale this with 15 ... hopefully this is correct + fSpec *= 15; + pcHelper->AddProperty(&fSpec, 1, AI_MATKEY_SHININESS); + + iMode = (int)aiShadingMode_Phong; + } + } + pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); + + // handle opacity + if (0xFFFFFFFF != iOpacity) { + ai_real fOpacity = PLY::PropertyInstance::ConvertTo(GetProperty((*i).alProperties, iPhong).avList.front(), eOpacity); + pcHelper->AddProperty(&fOpacity, 1, AI_MATKEY_OPACITY); + } + + // The face order is absolutely undefined for PLY, so we have to + // use two-sided rendering to be sure it's ok. + const int two_sided = 1; + pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED); + + //default texture + if (!defaultTexture.empty()) + { + const aiString name(defaultTexture.c_str()); + pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0); + } + + if (!pointsOnly) + { + const int two_sided = 1; + pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED); + } + + //set to wireframe, so when using this material info we can switch to points rendering + if (pointsOnly) + { + const int wireframe = 1; + pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME); + } + + // add the newly created material instance to the list + pvOut->push_back(pcHelper); + } + } + else + { + // generate a default material + aiMaterial* pcHelper = new aiMaterial(); + + // fill in a default material + int iMode = (int)aiShadingMode_Gouraud; + pcHelper->AddProperty(&iMode, 1, AI_MATKEY_SHADING_MODEL); + + //generate white material most 3D engine just multiply ambient / diffuse color with actual ambient / light color + aiColor3D clr; + clr.b = clr.g = clr.r = 1.0f; + pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE); + pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_SPECULAR); + + clr.b = clr.g = clr.r = 1.0f; + pcHelper->AddProperty(&clr, 1, AI_MATKEY_COLOR_AMBIENT); + + // The face order is absolutely undefined for PLY, so we have to + // use two-sided rendering to be sure it's ok. + if (!pointsOnly) + { + const int two_sided = 1; + pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED); + } + + //default texture + if (!defaultTexture.empty()) + { + const aiString name(defaultTexture.c_str()); + pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0); + } + + //set to wireframe, so when using this material info we can switch to points rendering + if (pointsOnly) + { + const int wireframe = 1; + pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME); + } + + pvOut->push_back(pcHelper); + } } #endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER diff --git a/code/PlyLoader.h b/code/PlyLoader.h index 3297524a9..eb64a9036 100644 --- a/code/PlyLoader.h +++ b/code/PlyLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -53,7 +54,7 @@ struct aiNode; struct aiMaterial; struct aiMesh; -namespace Assimp { +namespace Assimp { using namespace PLY; @@ -67,7 +68,6 @@ public: PLYImporter(); ~PLYImporter(); - public: // ------------------------------------------------------------------- @@ -77,6 +77,16 @@ public: bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const; + // ------------------------------------------------------------------- + /** Extract a vertex from the DOM + */ + void LoadVertex(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos); + + // ------------------------------------------------------------------- + /** Extract a face from the DOM + */ + void LoadFace(const PLY::Element* pcElement, const PLY::ElementInstance* instElement, unsigned int pos); + protected: // ------------------------------------------------------------------- @@ -93,53 +103,10 @@ protected: IOSystem* pIOHandler); protected: - - - // ------------------------------------------------------------------- - /** Extract vertices from the DOM - */ - void LoadVertices(std::vector* pvOut, - bool p_bNormals = false); - - // ------------------------------------------------------------------- - /** Extract vertex color channels from the DOM - */ - void LoadVertexColor(std::vector* pvOut); - - // ------------------------------------------------------------------- - /** Extract texture coordinate channels from the DOM - */ - void LoadTextureCoordinates(std::vector* pvOut); - - // ------------------------------------------------------------------- - /** Extract a face list from the DOM - */ - void LoadFaces(std::vector* pvOut); - // ------------------------------------------------------------------- /** Extract a material list from the DOM */ - void LoadMaterial(std::vector* pvOut); - - - // ------------------------------------------------------------------- - /** Validate material indices, replace default material identifiers - */ - void ReplaceDefaultMaterial(std::vector* avFaces, - std::vector* avMaterials); - - - // ------------------------------------------------------------------- - /** Convert all meshes into our ourer representation - */ - void ConvertMeshes(std::vector* avFaces, - const std::vector* avPositions, - const std::vector* avNormals, - const std::vector* avColors, - const std::vector* avTexCoords, - const std::vector* avMaterials, - std::vector* avOut); - + void LoadMaterial(std::vector* pvOut, std::string &defaultTexture, const bool pointsOnly); // ------------------------------------------------------------------- /** Static helper to parse a color from four single channels in @@ -150,7 +117,6 @@ protected: PLY::EDataType aiTypes[4], aiColor4D* clrOut); - // ------------------------------------------------------------------- /** Static helper to parse a color channel value. The input value * is normalized to 0-1. @@ -159,12 +125,14 @@ protected: PLY::PropertyInstance::ValueUnion val, PLY::EDataType eType); - /** Buffer to hold the loaded file */ unsigned char* mBuffer; /** Document object model representation extracted from the file */ PLY::DOM* pcDOM; + + /** Mesh generated by loader */ + aiMesh* mGeneratedMesh; }; } // end of namespace Assimp diff --git a/code/PlyParser.cpp b/code/PlyParser.cpp index edc13ce10..6321821d2 100644 --- a/code/PlyParser.cpp +++ b/code/PlyParser.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team All rights reserved. @@ -12,18 +12,18 @@ 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. +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. +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. +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 @@ -44,888 +44,1078 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_PLY_IMPORTER -#include "PlyLoader.h" #include "fast_atof.h" #include #include "ByteSwapper.h" - +#include "PlyLoader.h" using namespace Assimp; // ------------------------------------------------------------------------------------------------ -PLY::EDataType PLY::Property::ParseDataType(const char* pCur,const char** pCurOut) -{ - ai_assert(NULL != pCur && NULL != pCurOut); - PLY::EDataType eOut = PLY::EDT_INVALID; +PLY::EDataType PLY::Property::ParseDataType(std::vector &buffer) { + ai_assert(!buffer.empty()); - if (TokenMatch(pCur,"char",4) || - TokenMatch(pCur,"int8",4)) - { - eOut = PLY::EDT_Char; - } - else if (TokenMatch(pCur,"uchar",5) || - TokenMatch(pCur,"uint8",5)) - { - eOut = PLY::EDT_UChar; - } - else if (TokenMatch(pCur,"short",5) || - TokenMatch(pCur,"int16",5)) - { - eOut = PLY::EDT_Short; - } - else if (TokenMatch(pCur,"ushort",6) || - TokenMatch(pCur,"uint16",6)) - { - eOut = PLY::EDT_UShort; - } - else if (TokenMatch(pCur,"int32",5) || TokenMatch(pCur,"int",3)) - { - eOut = PLY::EDT_Int; - } - else if (TokenMatch(pCur,"uint32",6) || TokenMatch(pCur,"uint",4)) - { - eOut = PLY::EDT_UInt; - } - else if (TokenMatch(pCur,"float",5) || TokenMatch(pCur,"float32",7)) - { - eOut = PLY::EDT_Float; - } - else if (TokenMatch(pCur,"double64",8) || TokenMatch(pCur,"double",6) || - TokenMatch(pCur,"float64",7)) - { - eOut = PLY::EDT_Double; - } - if (PLY::EDT_INVALID == eOut) - { - DefaultLogger::get()->info("Found unknown data type in PLY file. This is OK"); - } - *pCurOut = pCur; - return eOut; + PLY::EDataType eOut = PLY::EDT_INVALID; + + if (PLY::DOM::TokenMatch(buffer, "char", 4) || + PLY::DOM::TokenMatch(buffer, "int8", 4)) + { + eOut = PLY::EDT_Char; + } + else if (PLY::DOM::TokenMatch(buffer, "uchar", 5) || + PLY::DOM::TokenMatch(buffer, "uint8", 5)) + { + eOut = PLY::EDT_UChar; + } + else if (PLY::DOM::TokenMatch(buffer, "short", 5) || + PLY::DOM::TokenMatch(buffer, "int16", 5)) + { + eOut = PLY::EDT_Short; + } + else if (PLY::DOM::TokenMatch(buffer, "ushort", 6) || + PLY::DOM::TokenMatch(buffer, "uint16", 6)) + { + eOut = PLY::EDT_UShort; + } + else if (PLY::DOM::TokenMatch(buffer, "int32", 5) || PLY::DOM::TokenMatch(buffer, "int", 3)) + { + eOut = PLY::EDT_Int; + } + else if (PLY::DOM::TokenMatch(buffer, "uint32", 6) || PLY::DOM::TokenMatch(buffer, "uint", 4)) + { + eOut = PLY::EDT_UInt; + } + else if (PLY::DOM::TokenMatch(buffer, "float", 5) || PLY::DOM::TokenMatch(buffer, "float32", 7)) + { + eOut = PLY::EDT_Float; + } + else if (PLY::DOM::TokenMatch(buffer, "double64", 8) || PLY::DOM::TokenMatch(buffer, "double", 6) || + PLY::DOM::TokenMatch(buffer, "float64", 7)) + { + eOut = PLY::EDT_Double; + } + if (PLY::EDT_INVALID == eOut) + { + DefaultLogger::get()->info("Found unknown data type in PLY file. This is OK"); + } + + return eOut; } // ------------------------------------------------------------------------------------------------ -PLY::ESemantic PLY::Property::ParseSemantic(const char* pCur,const char** pCurOut) -{ - ai_assert(NULL != pCur && NULL != pCurOut); +PLY::ESemantic PLY::Property::ParseSemantic(std::vector &buffer) { + ai_assert(!buffer.empty()); - PLY::ESemantic eOut = PLY::EST_INVALID; - if (TokenMatch(pCur,"red",3)) - { - eOut = PLY::EST_Red; - } - else if (TokenMatch(pCur,"green",5)) - { - eOut = PLY::EST_Green; - } - else if (TokenMatch(pCur,"blue",4)) - { - eOut = PLY::EST_Blue; - } - else if (TokenMatch(pCur,"alpha",5)) - { - eOut = PLY::EST_Alpha; - } - else if (TokenMatch(pCur,"vertex_index",12) || TokenMatch(pCur,"vertex_indices",14)) - { - eOut = PLY::EST_VertexIndex; - } - else if (TokenMatch(pCur,"material_index",14)) - { - eOut = PLY::EST_MaterialIndex; - } - else if (TokenMatch(pCur,"ambient_red",11)) - { - eOut = PLY::EST_AmbientRed; - } - else if (TokenMatch(pCur,"ambient_green",13)) - { - eOut = PLY::EST_AmbientGreen; - } - else if (TokenMatch(pCur,"ambient_blue",12)) - { - eOut = PLY::EST_AmbientBlue; - } - else if (TokenMatch(pCur,"ambient_alpha",13)) - { - eOut = PLY::EST_AmbientAlpha; - } - else if (TokenMatch(pCur,"diffuse_red",11)) - { - eOut = PLY::EST_DiffuseRed; - } - else if (TokenMatch(pCur,"diffuse_green",13)) - { - eOut = PLY::EST_DiffuseGreen; - } - else if (TokenMatch(pCur,"diffuse_blue",12)) - { - eOut = PLY::EST_DiffuseBlue; - } - else if (TokenMatch(pCur,"diffuse_alpha",13)) - { - eOut = PLY::EST_DiffuseAlpha; - } - else if (TokenMatch(pCur,"specular_red",12)) - { - eOut = PLY::EST_SpecularRed; - } - else if (TokenMatch(pCur,"specular_green",14)) - { - eOut = PLY::EST_SpecularGreen; - } - else if (TokenMatch(pCur,"specular_blue",13)) - { - eOut = PLY::EST_SpecularBlue; - } - else if (TokenMatch(pCur,"specular_alpha",14)) - { - eOut = PLY::EST_SpecularAlpha; - } - else if (TokenMatch(pCur,"opacity",7)) - { - eOut = PLY::EST_Opacity; - } - else if (TokenMatch(pCur,"specular_power",14)) - { - eOut = PLY::EST_PhongPower; - } - else if (TokenMatch(pCur,"r",1)) - { - eOut = PLY::EST_Red; - } - else if (TokenMatch(pCur,"g",1)) - { - eOut = PLY::EST_Green; - } - else if (TokenMatch(pCur,"b",1)) - { - eOut = PLY::EST_Blue; - } - // NOTE: Blender3D exports texture coordinates as s,t tuples - else if (TokenMatch(pCur,"u",1) || TokenMatch(pCur,"s",1) || TokenMatch(pCur,"tx",2)) - { - eOut = PLY::EST_UTextureCoord; - } - else if (TokenMatch(pCur,"v",1) || TokenMatch(pCur,"t",1) || TokenMatch(pCur,"ty",2)) - { - eOut = PLY::EST_VTextureCoord; - } - else if (TokenMatch(pCur,"x",1)) - { - eOut = PLY::EST_XCoord; - } - else if (TokenMatch(pCur,"y",1)) - { - eOut = PLY::EST_YCoord; - } - else if (TokenMatch(pCur,"z",1)) - { - eOut = PLY::EST_ZCoord; - } - else if (TokenMatch(pCur,"nx",2)) - { - eOut = PLY::EST_XNormal; - } - else if (TokenMatch(pCur,"ny",2)) - { - eOut = PLY::EST_YNormal; - } - else if (TokenMatch(pCur,"nz",2)) - { - eOut = PLY::EST_ZNormal; - } - else - { - DefaultLogger::get()->info("Found unknown property semantic in file. This is ok"); - SkipLine(&pCur); - } - *pCurOut = pCur; - return eOut; + PLY::ESemantic eOut = PLY::EST_INVALID; + if (PLY::DOM::TokenMatch(buffer, "red", 3)) { + eOut = PLY::EST_Red; + } + else if (PLY::DOM::TokenMatch(buffer, "green", 5)) { + eOut = PLY::EST_Green; + } + else if (PLY::DOM::TokenMatch(buffer, "blue", 4)) { + eOut = PLY::EST_Blue; + } + else if (PLY::DOM::TokenMatch(buffer, "alpha", 5)) { + eOut = PLY::EST_Alpha; + } + else if (PLY::DOM::TokenMatch(buffer, "vertex_index", 12) || PLY::DOM::TokenMatch(buffer, "vertex_indices", 14)) { + eOut = PLY::EST_VertexIndex; + } + else if (PLY::DOM::TokenMatch(buffer, "texcoord", 8)) // Manage uv coords on faces + { + eOut = PLY::EST_TextureCoordinates; + } + else if (PLY::DOM::TokenMatch(buffer, "material_index", 14)) + { + eOut = PLY::EST_MaterialIndex; + } + else if (PLY::DOM::TokenMatch(buffer, "ambient_red", 11)) + { + eOut = PLY::EST_AmbientRed; + } + else if (PLY::DOM::TokenMatch(buffer, "ambient_green", 13)) + { + eOut = PLY::EST_AmbientGreen; + } + else if (PLY::DOM::TokenMatch(buffer, "ambient_blue", 12)) + { + eOut = PLY::EST_AmbientBlue; + } + else if (PLY::DOM::TokenMatch(buffer, "ambient_alpha", 13)) + { + eOut = PLY::EST_AmbientAlpha; + } + else if (PLY::DOM::TokenMatch(buffer, "diffuse_red", 11)) + { + eOut = PLY::EST_DiffuseRed; + } + else if (PLY::DOM::TokenMatch(buffer, "diffuse_green", 13)) + { + eOut = PLY::EST_DiffuseGreen; + } + else if (PLY::DOM::TokenMatch(buffer, "diffuse_blue", 12)) + { + eOut = PLY::EST_DiffuseBlue; + } + else if (PLY::DOM::TokenMatch(buffer, "diffuse_alpha", 13)) + { + eOut = PLY::EST_DiffuseAlpha; + } + else if (PLY::DOM::TokenMatch(buffer, "specular_red", 12)) + { + eOut = PLY::EST_SpecularRed; + } + else if (PLY::DOM::TokenMatch(buffer, "specular_green", 14)) + { + eOut = PLY::EST_SpecularGreen; + } + else if (PLY::DOM::TokenMatch(buffer, "specular_blue", 13)) + { + eOut = PLY::EST_SpecularBlue; + } + else if (PLY::DOM::TokenMatch(buffer, "specular_alpha", 14)) + { + eOut = PLY::EST_SpecularAlpha; + } + else if (PLY::DOM::TokenMatch(buffer, "opacity", 7)) + { + eOut = PLY::EST_Opacity; + } + else if (PLY::DOM::TokenMatch(buffer, "specular_power", 14)) + { + eOut = PLY::EST_PhongPower; + } + else if (PLY::DOM::TokenMatch(buffer, "r", 1)) + { + eOut = PLY::EST_Red; + } + else if (PLY::DOM::TokenMatch(buffer, "g", 1)) + { + eOut = PLY::EST_Green; + } + else if (PLY::DOM::TokenMatch(buffer, "b", 1)) + { + eOut = PLY::EST_Blue; + } + + // NOTE: Blender3D exports texture coordinates as s,t tuples + else if (PLY::DOM::TokenMatch(buffer, "u", 1) || PLY::DOM::TokenMatch(buffer, "s", 1) || PLY::DOM::TokenMatch(buffer, "tx", 2) || PLY::DOM::TokenMatch(buffer, "texture_u", 9)) + { + eOut = PLY::EST_UTextureCoord; + } + else if (PLY::DOM::TokenMatch(buffer, "v", 1) || PLY::DOM::TokenMatch(buffer, "t", 1) || PLY::DOM::TokenMatch(buffer, "ty", 2) || PLY::DOM::TokenMatch(buffer, "texture_v", 9)) + { + eOut = PLY::EST_VTextureCoord; + } + else if (PLY::DOM::TokenMatch(buffer, "x", 1)) + { + eOut = PLY::EST_XCoord; + } + else if (PLY::DOM::TokenMatch(buffer, "y", 1)) { + eOut = PLY::EST_YCoord; + } + else if (PLY::DOM::TokenMatch(buffer, "z", 1)) { + eOut = PLY::EST_ZCoord; + } + else if (PLY::DOM::TokenMatch(buffer, "nx", 2)) { + eOut = PLY::EST_XNormal; + } + else if (PLY::DOM::TokenMatch(buffer, "ny", 2)) { + eOut = PLY::EST_YNormal; + } + else if (PLY::DOM::TokenMatch(buffer, "nz", 2)) { + eOut = PLY::EST_ZNormal; + } + else { + DefaultLogger::get()->info("Found unknown property semantic in file. This is ok"); + PLY::DOM::SkipLine(buffer); + } + return eOut; } // ------------------------------------------------------------------------------------------------ -bool PLY::Property::ParseProperty (const char* pCur, - const char** pCurOut, - PLY::Property* pOut) +bool PLY::Property::ParseProperty(std::vector &buffer, PLY::Property* pOut) { - ai_assert(NULL != pCur && NULL != pCurOut); + ai_assert(!buffer.empty()); - // Forms supported: - // "property float x" - // "property list uchar int vertex_index" - *pCurOut = pCur; + // Forms supported: + // "property float x" + // "property list uchar int vertex_index" - // skip leading spaces - if (!SkipSpaces(pCur,&pCur))return false; + // skip leading spaces + if (!PLY::DOM::SkipSpaces(buffer)) { + return false; + } - // skip the "property" string at the beginning - if (!TokenMatch(pCur,"property",8)) + // skip the "property" string at the beginning + if (!PLY::DOM::TokenMatch(buffer, "property", 8)) + { + // seems not to be a valid property entry + return false; + } + // get next word + if (!PLY::DOM::SkipSpaces(buffer)) { + return false; + } + if (PLY::DOM::TokenMatch(buffer, "list", 4)) + { + pOut->bIsList = true; + + // seems to be a list. + if (EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(buffer))) { - // seems not to be a valid property entry - return false; + // unable to parse list size data type + PLY::DOM::SkipLine(buffer); + return false; } - // get next word - if (!SkipSpaces(pCur,&pCur))return false; - if (TokenMatch(pCur,"list",4)) + if (!PLY::DOM::SkipSpaces(buffer))return false; + if (EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(buffer))) { - pOut->bIsList = true; - - // seems to be a list. - if(EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(pCur, &pCur))) - { - // unable to parse list size data type - SkipLine(pCur,&pCur); - *pCurOut = pCur; - return false; - } - if (!SkipSpaces(pCur,&pCur))return false; - if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(pCur, &pCur))) - { - // unable to parse list data type - SkipLine(pCur,&pCur); - *pCurOut = pCur; - return false; - } + // unable to parse list data type + PLY::DOM::SkipLine(buffer); + return false; } - else + } + else + { + if (EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(buffer))) { - if(EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(pCur, &pCur))) - { - // unable to parse data type. Skip the property - SkipLine(pCur,&pCur); - *pCurOut = pCur; - return false; - } + // unable to parse data type. Skip the property + PLY::DOM::SkipLine(buffer); + return false; } + } - if (!SkipSpaces(pCur,&pCur))return false; - const char* szCur = pCur; - pOut->Semantic = PLY::Property::ParseSemantic(pCur, &pCur); + if (!PLY::DOM::SkipSpaces(buffer)) + return false; - if (PLY::EST_INVALID == pOut->Semantic) - { - // store the name of the semantic - uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; + pOut->Semantic = PLY::Property::ParseSemantic(buffer); - DefaultLogger::get()->info("Found unknown semantic in PLY file. This is OK"); - pOut->szName = std::string(szCur,iDiff); - } + if (PLY::EST_INVALID == pOut->Semantic) + { + DefaultLogger::get()->info("Found unknown semantic in PLY file. This is OK"); + std::string(&buffer[0], &buffer[0] + strlen(&buffer[0])); + } - SkipSpacesAndLineEnd(pCur,&pCur); - *pCurOut = pCur; - return true; + PLY::DOM::SkipSpacesAndLineEnd(buffer); + return true; } // ------------------------------------------------------------------------------------------------ -PLY::EElementSemantic PLY::Element::ParseSemantic(const char* pCur, - const char** pCurOut) +PLY::EElementSemantic PLY::Element::ParseSemantic(std::vector &buffer) { - ai_assert(NULL != pCur && NULL != pCurOut); - PLY::EElementSemantic eOut = PLY::EEST_INVALID; - if (TokenMatch(pCur,"vertex",6)) - { - eOut = PLY::EEST_Vertex; - } - else if (TokenMatch(pCur,"face",4)) - { - eOut = PLY::EEST_Face; - } + ai_assert(!buffer.empty()); + + PLY::EElementSemantic eOut = PLY::EEST_INVALID; + if (PLY::DOM::TokenMatch(buffer, "vertex", 6)) + { + eOut = PLY::EEST_Vertex; + } + else if (PLY::DOM::TokenMatch(buffer, "face", 4)) + { + eOut = PLY::EEST_Face; + } + else if (PLY::DOM::TokenMatch(buffer, "tristrips", 9)) + { + eOut = PLY::EEST_TriStrip; + } #if 0 - // TODO: maybe implement this? - else if (TokenMatch(pCur,"range_grid",10)) - { - eOut = PLY::EEST_Face; - } + // TODO: maybe implement this? + else if (PLY::DOM::TokenMatch(buffer,"range_grid",10)) + { + eOut = PLY::EEST_Face; + } #endif - else if (TokenMatch(pCur,"tristrips",9)) - { - eOut = PLY::EEST_TriStrip; - } - else if (TokenMatch(pCur,"edge",4)) - { - eOut = PLY::EEST_Edge; - } - else if (TokenMatch(pCur,"material",8)) - { - eOut = PLY::EEST_Material; - } - *pCurOut = pCur; - return eOut; + else if (PLY::DOM::TokenMatch(buffer, "edge", 4)) + { + eOut = PLY::EEST_Edge; + } + else if (PLY::DOM::TokenMatch(buffer, "material", 8)) + { + eOut = PLY::EEST_Material; + } + else if (PLY::DOM::TokenMatch(buffer, "TextureFile", 11)) + { + eOut = PLY::EEST_TextureFile; + } + + return eOut; } // ------------------------------------------------------------------------------------------------ -bool PLY::Element::ParseElement (const char* pCur, - const char** pCurOut, - PLY::Element* pOut) +bool PLY::Element::ParseElement(IOStreamBuffer &streamBuffer, std::vector &buffer, PLY::Element* pOut) { - ai_assert(NULL != pCur && NULL != pCurOut && NULL != pOut); + ai_assert(NULL != pOut); + // Example format: "element vertex 8" - // Example format: "element vertex 8" - *pCurOut = pCur; + // skip leading spaces + if (!PLY::DOM::SkipSpaces(buffer)) + { + return false; + } - // skip leading spaces - if (!SkipSpaces(&pCur))return false; + // skip the "element" string at the beginning + if (!PLY::DOM::TokenMatch(buffer, "element", 7) && !PLY::DOM::TokenMatch(buffer, "comment", 7)) + { + // seems not to be a valid property entry + return false; + } + // get next word + if (!PLY::DOM::SkipSpaces(buffer)) + return false; - // skip the "element" string at the beginning - if (!TokenMatch(pCur,"element",7)) - { - // seems not to be a valid property entry - return false; - } - // get next word - if (!SkipSpaces(&pCur))return false; + // parse the semantic of the element + pOut->eSemantic = PLY::Element::ParseSemantic(buffer); + if (PLY::EEST_INVALID == pOut->eSemantic) + { + // if the exact semantic can't be determined, just store + // the original string identifier + pOut->szName = std::string(&buffer[0], &buffer[0] + strlen(&buffer[0])); + } - // parse the semantic of the element - const char* szCur = pCur; - pOut->eSemantic = PLY::Element::ParseSemantic(pCur,&pCur); - if (PLY::EEST_INVALID == pOut->eSemantic) - { - // if the exact semantic can't be determined, just store - // the original string identifier - uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; - pOut->szName = std::string(szCur,iDiff); - } + if (!PLY::DOM::SkipSpaces(buffer)) + return false; - if (!SkipSpaces(&pCur))return false; - - //parse the number of occurrences of this element - pOut->NumOccur = strtoul10(pCur,&pCur); + if (PLY::EEST_TextureFile == pOut->eSemantic) + { + char* endPos = &buffer[0] + (strlen(&buffer[0]) - 1); + pOut->szName = std::string(&buffer[0], endPos); // go to the next line - SkipSpacesAndLineEnd(pCur,&pCur); + PLY::DOM::SkipSpacesAndLineEnd(buffer); - // now parse all properties of the element - while(true) - { - // skip all comments - PLY::DOM::SkipComments(pCur,&pCur); - - PLY::Property prop; - if(!PLY::Property::ParseProperty(pCur,&pCur,&prop))break; - pOut->alProperties.push_back(prop); - } - *pCurOut = pCur; return true; + } + + //parse the number of occurrences of this element + const char* pCur = (char*)&buffer[0]; + pOut->NumOccur = strtoul10(pCur, &pCur); + + // go to the next line + PLY::DOM::SkipSpacesAndLineEnd(buffer); + + // now parse all properties of the element + while (true) + { + streamBuffer.getNextLine(buffer); + pCur = (char*)&buffer[0]; + + // skip all comments + PLY::DOM::SkipComments(buffer); + + PLY::Property prop; + if (!PLY::Property::ParseProperty(buffer, &prop)) + break; + + pOut->alProperties.push_back(prop); + } + + return true; } // ------------------------------------------------------------------------------------------------ -bool PLY::DOM::SkipComments (const char* pCur, - const char** pCurOut) +bool PLY::DOM::SkipSpaces(std::vector &buffer) { - ai_assert(NULL != pCur && NULL != pCurOut); - *pCurOut = pCur; + const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0]; + bool ret = false; + if (pCur) + { + const char* szCur = pCur; + ret = Assimp::SkipSpaces(pCur, &pCur); - // skip spaces - if (!SkipSpaces(pCur,&pCur))return false; + uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; + buffer.erase(buffer.begin(), buffer.begin() + iDiff); + return ret; + } - if (TokenMatch(pCur,"comment",7)) - { - if ( !IsLineEnd(pCur[-1]) ) - { - SkipLine(pCur,&pCur); - } - SkipComments(pCur,&pCur); - *pCurOut = pCur; - return true; - } - *pCurOut = pCur; + return ret; +} + +bool PLY::DOM::SkipLine(std::vector &buffer) +{ + const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0]; + bool ret = false; + if (pCur) + { + const char* szCur = pCur; + ret = Assimp::SkipLine(pCur, &pCur); + + uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; + buffer.erase(buffer.begin(), buffer.begin() + iDiff); + return ret; + } + + return ret; +} + +bool PLY::DOM::TokenMatch(std::vector &buffer, const char* token, unsigned int len) +{ + const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0]; + bool ret = false; + if (pCur) + { + const char* szCur = pCur; + ret = Assimp::TokenMatch(pCur, token, len); + + uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; + buffer.erase(buffer.begin(), buffer.begin() + iDiff); + return ret; + } + + return ret; +} + +bool PLY::DOM::SkipSpacesAndLineEnd(std::vector &buffer) +{ + const char* pCur = buffer.empty() ? NULL : (char*)&buffer[0]; + bool ret = false; + if (pCur) + { + const char* szCur = pCur; + ret = Assimp::SkipSpacesAndLineEnd(pCur, &pCur); + + uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; + buffer.erase(buffer.begin(), buffer.begin() + iDiff); + return ret; + } + + return ret; +} + +bool PLY::DOM::SkipComments(std::vector &buffer) +{ + ai_assert(!buffer.empty()); + + std::vector nbuffer = buffer; + // skip spaces + if (!SkipSpaces(nbuffer)) { return false; -} + } -// ------------------------------------------------------------------------------------------------ -bool PLY::DOM::ParseHeader (const char* pCur,const char** pCurOut,bool isBinary) -{ - ai_assert(NULL != pCur && NULL != pCurOut); - DefaultLogger::get()->debug("PLY::DOM::ParseHeader() begin"); + if (TokenMatch(nbuffer, "comment", 7)) + { + if (!SkipSpaces(nbuffer)) + SkipLine(nbuffer); - // after ply and format line - *pCurOut = pCur; - - // parse all elements - while ((*pCur) != '\0') + if (!TokenMatch(nbuffer, "TextureFile", 11)) { - // skip all comments - PLY::DOM::SkipComments(pCur,&pCur); - - PLY::Element out; - if(PLY::Element::ParseElement(pCur,&pCur,&out)) - { - // add the element to the list of elements - alElements.push_back(out); - } - else if (TokenMatch(pCur,"end_header",10)) - { - // we have reached the end of the header - break; - } - else - { - // ignore unknown header elements - SkipLine(&pCur); - } + SkipLine(nbuffer); + buffer = nbuffer; + return true; } - if(!isBinary) - { // it would occur an error, if binary data start with values as space or line end. - SkipSpacesAndLineEnd(pCur,&pCur); - } - *pCurOut = pCur; - DefaultLogger::get()->debug("PLY::DOM::ParseHeader() succeeded"); return true; + } + + return false; } // ------------------------------------------------------------------------------------------------ -bool PLY::DOM::ParseElementInstanceLists ( - const char* pCur, - const char** pCurOut) -{ - ai_assert(NULL != pCur && NULL != pCurOut); +bool PLY::DOM::ParseHeader(IOStreamBuffer &streamBuffer, std::vector &buffer, bool isBinary) { + DefaultLogger::get()->debug("PLY::DOM::ParseHeader() begin"); - DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() begin"); - *pCurOut = pCur; + // parse all elements + while (!buffer.empty()) + { + // skip all comments + PLY::DOM::SkipComments(buffer); - alElementData.resize(alElements.size()); - - std::vector::const_iterator i = alElements.begin(); - std::vector::iterator a = alElementData.begin(); - - // parse all element instances - for (;i != alElements.end();++i,++a) + PLY::Element out; + if (PLY::Element::ParseElement(streamBuffer, buffer, &out)) { - (*a).alInstances.resize((*i).NumOccur); - PLY::ElementInstanceList::ParseInstanceList(pCur,&pCur,&(*i),&(*a)); + // add the element to the list of elements + alElements.push_back(out); } + else if (TokenMatch(buffer, "end_header", 10)) + { + // we have reached the end of the header + break; + } + else + { + // ignore unknown header elements + streamBuffer.getNextLine(buffer); + } + } - DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() succeeded"); - *pCurOut = pCur; - return true; + if (!isBinary) // it would occur an error, if binary data start with values as space or line end. + SkipSpacesAndLineEnd(buffer); + + DefaultLogger::get()->debug("PLY::DOM::ParseHeader() succeeded"); + return true; } // ------------------------------------------------------------------------------------------------ -bool PLY::DOM::ParseElementInstanceListsBinary ( - const char* pCur, - const char** pCurOut, +bool PLY::DOM::ParseElementInstanceLists(IOStreamBuffer &streamBuffer, std::vector &buffer, PLYImporter* loader) +{ + DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() begin"); + alElementData.resize(alElements.size()); + + std::vector::const_iterator i = alElements.begin(); + std::vector::iterator a = alElementData.begin(); + + // parse all element instances + //construct vertices and faces + for (; i != alElements.end(); ++i, ++a) + { + if ((*i).eSemantic == EEST_Vertex || (*i).eSemantic == EEST_Face || (*i).eSemantic == EEST_TriStrip) + { + PLY::ElementInstanceList::ParseInstanceList(streamBuffer, buffer, &(*i), NULL, loader); + } + else + { + (*a).alInstances.resize((*i).NumOccur); + PLY::ElementInstanceList::ParseInstanceList(streamBuffer, buffer, &(*i), &(*a), NULL); + } + } + + DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() succeeded"); + return true; +} + +// ------------------------------------------------------------------------------------------------ +bool PLY::DOM::ParseElementInstanceListsBinary(IOStreamBuffer &streamBuffer, std::vector &buffer, + const char* &pCur, + unsigned int &bufferSize, + PLYImporter* loader, bool p_bBE) { - ai_assert(NULL != pCur && NULL != pCurOut); + DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() begin"); + alElementData.resize(alElements.size()); - DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() begin"); - *pCurOut = pCur; + std::vector::const_iterator i = alElements.begin(); + std::vector::iterator a = alElementData.begin(); - alElementData.resize(alElements.size()); - - std::vector::const_iterator i = alElements.begin(); - std::vector::iterator a = alElementData.begin(); - - // parse all element instances - for (;i != alElements.end();++i,++a) + // parse all element instances + for (; i != alElements.end(); ++i, ++a) + { + if ((*i).eSemantic == EEST_Vertex || (*i).eSemantic == EEST_Face || (*i).eSemantic == EEST_TriStrip) { - (*a).alInstances.resize((*i).NumOccur); - PLY::ElementInstanceList::ParseInstanceListBinary(pCur,&pCur,&(*i),&(*a),p_bBE); - } - - DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() succeeded"); - *pCurOut = pCur; - return true; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::DOM::ParseInstanceBinary (const char* pCur,DOM* p_pcOut,bool p_bBE) -{ - ai_assert(NULL != pCur && NULL != p_pcOut); - - DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() begin"); - - if(!p_pcOut->ParseHeader(pCur,&pCur,true)) - { - DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure"); - return false; - } - if(!p_pcOut->ParseElementInstanceListsBinary(pCur,&pCur,p_bBE)) - { - DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure"); - return false; - } - DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() succeeded"); - return true; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::DOM::ParseInstance (const char* pCur,DOM* p_pcOut) -{ - ai_assert(NULL != pCur); - ai_assert(NULL != p_pcOut); - - DefaultLogger::get()->debug("PLY::DOM::ParseInstance() begin"); - - - if(!p_pcOut->ParseHeader(pCur,&pCur,false)) - { - DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure"); - return false; - } - if(!p_pcOut->ParseElementInstanceLists(pCur,&pCur)) - { - DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure"); - return false; - } - DefaultLogger::get()->debug("PLY::DOM::ParseInstance() succeeded"); - return true; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::ElementInstanceList::ParseInstanceList ( - const char* pCur, - const char** pCurOut, - const PLY::Element* pcElement, - PLY::ElementInstanceList* p_pcOut) -{ - ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut); - - if (EEST_INVALID == pcElement->eSemantic || pcElement->alProperties.empty()) - { - // if the element has an unknown semantic we can skip all lines - // However, there could be comments - for (unsigned int i = 0; i < pcElement->NumOccur;++i) - { - PLY::DOM::SkipComments(pCur,&pCur); - SkipLine(pCur,&pCur); - } + PLY::ElementInstanceList::ParseInstanceListBinary(streamBuffer, buffer, pCur, bufferSize, &(*i), NULL, loader, p_bBE); } else { - // be sure to have enough storage - for (unsigned int i = 0; i < pcElement->NumOccur;++i) - { - PLY::DOM::SkipComments(pCur,&pCur); - PLY::ElementInstance::ParseInstance(pCur, &pCur,pcElement, - &p_pcOut->alInstances[i]); - } + (*a).alInstances.resize((*i).NumOccur); + PLY::ElementInstanceList::ParseInstanceListBinary(streamBuffer, buffer, pCur, bufferSize, &(*i), &(*a), NULL, p_bBE); } - *pCurOut = pCur; - return true; + } + + DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() succeeded"); + return true; } // ------------------------------------------------------------------------------------------------ -bool PLY::ElementInstanceList::ParseInstanceListBinary ( - const char* pCur, - const char** pCurOut, - const PLY::Element* pcElement, - PLY::ElementInstanceList* p_pcOut, - bool p_bBE /* = false */) +bool PLY::DOM::ParseInstanceBinary(IOStreamBuffer &streamBuffer, DOM* p_pcOut, PLYImporter* loader, bool p_bBE) { - ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut); + ai_assert(NULL != p_pcOut); + ai_assert(NULL != loader); - // we can add special handling code for unknown element semantics since - // we can't skip it as a whole block (we don't know its exact size - // due to the fact that lists could be contained in the property list - // of the unknown element) - for (unsigned int i = 0; i < pcElement->NumOccur;++i) - { - PLY::ElementInstance::ParseInstanceBinary(pCur, &pCur,pcElement, - &p_pcOut->alInstances[i], p_bBE); - } - *pCurOut = pCur; - return true; + std::vector buffer; + streamBuffer.getNextLine(buffer); + + DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() begin"); + + if (!p_pcOut->ParseHeader(streamBuffer, buffer, true)) + { + DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure"); + return false; + } + + streamBuffer.getNextBlock(buffer); + unsigned int bufferSize = static_cast(buffer.size()); + const char* pCur = (char*)&buffer[0]; + if (!p_pcOut->ParseElementInstanceListsBinary(streamBuffer, buffer, pCur, bufferSize, loader, p_bBE)) + { + DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure"); + return false; + } + DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() succeeded"); + return true; } // ------------------------------------------------------------------------------------------------ -bool PLY::ElementInstance::ParseInstance ( - const char* pCur, - const char** pCurOut, - const PLY::Element* pcElement, - PLY::ElementInstance* p_pcOut) +bool PLY::DOM::ParseInstance(IOStreamBuffer &streamBuffer, DOM* p_pcOut, PLYImporter* loader) { - ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut); + ai_assert(NULL != p_pcOut); + ai_assert(NULL != loader); - if (!SkipSpaces(pCur, &pCur))return false; + std::vector buffer; + streamBuffer.getNextLine(buffer); - // allocate enough storage - p_pcOut->alProperties.resize(pcElement->alProperties.size()); + DefaultLogger::get()->debug("PLY::DOM::ParseInstance() begin"); - std::vector::iterator i = p_pcOut->alProperties.begin(); - std::vector::const_iterator a = pcElement->alProperties.begin(); - for (;i != p_pcOut->alProperties.end();++i,++a) - { - if(!(PLY::PropertyInstance::ParseInstance(pCur, &pCur,&(*a),&(*i)))) - { - DefaultLogger::get()->warn("Unable to parse property instance. " - "Skipping this element instance"); + if (!p_pcOut->ParseHeader(streamBuffer, buffer, false)) + { + DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure"); + return false; + } - // skip the rest of the instance - SkipLine(pCur, &pCur); - - PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a).eType); - (*i).avList.push_back(v); - } - } - *pCurOut = pCur; - return true; + //get next line after header + streamBuffer.getNextLine(buffer); + if (!p_pcOut->ParseElementInstanceLists(streamBuffer, buffer, loader)) + { + DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure"); + return false; + } + DefaultLogger::get()->debug("PLY::DOM::ParseInstance() succeeded"); + return true; } // ------------------------------------------------------------------------------------------------ -bool PLY::ElementInstance::ParseInstanceBinary ( - const char* pCur, - const char** pCurOut, - const PLY::Element* pcElement, - PLY::ElementInstance* p_pcOut, - bool p_bBE /* = false */) +bool PLY::ElementInstanceList::ParseInstanceList( + IOStreamBuffer &streamBuffer, + std::vector &buffer, + const PLY::Element* pcElement, + PLY::ElementInstanceList* p_pcOut, + PLYImporter* loader) { - ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut); + ai_assert(NULL != pcElement); - // allocate enough storage - p_pcOut->alProperties.resize(pcElement->alProperties.size()); - - std::vector::iterator i = p_pcOut->alProperties.begin(); - std::vector::const_iterator a = pcElement->alProperties.begin(); - for (;i != p_pcOut->alProperties.end();++i,++a) + // parse all elements + if (EEST_INVALID == pcElement->eSemantic || pcElement->alProperties.empty()) + { + // if the element has an unknown semantic we can skip all lines + // However, there could be comments + for (unsigned int i = 0; i < pcElement->NumOccur; ++i) { - if(!(PLY::PropertyInstance::ParseInstanceBinary(pCur, &pCur,&(*a),&(*i),p_bBE))) - { - DefaultLogger::get()->warn("Unable to parse binary property instance. " - "Skipping this element instance"); - - (*i).avList.push_back(PLY::PropertyInstance::DefaultValue((*a).eType)); - } + PLY::DOM::SkipComments(buffer); + PLY::DOM::SkipLine(buffer); + streamBuffer.getNextLine(buffer); } - *pCurOut = pCur; - return true; + } + else + { + const char* pCur = (const char*)&buffer[0]; + // be sure to have enough storage + for (unsigned int i = 0; i < pcElement->NumOccur; ++i) + { + if (p_pcOut) + PLY::ElementInstance::ParseInstance(pCur, pcElement, &p_pcOut->alInstances[i]); + else + { + ElementInstance elt; + PLY::ElementInstance::ParseInstance(pCur, pcElement, &elt); + + // Create vertex or face + if (pcElement->eSemantic == EEST_Vertex) + { + //call loader instance from here + loader->LoadVertex(pcElement, &elt, i); + } + else if (pcElement->eSemantic == EEST_Face) + { + //call loader instance from here + loader->LoadFace(pcElement, &elt, i); + } + else if (pcElement->eSemantic == EEST_TriStrip) + { + //call loader instance from here + loader->LoadFace(pcElement, &elt, i); + } + } + + streamBuffer.getNextLine(buffer); + pCur = (buffer.empty()) ? NULL : (const char*)&buffer[0]; + } + } + return true; } // ------------------------------------------------------------------------------------------------ -bool PLY::PropertyInstance::ParseInstance (const char* pCur,const char** pCurOut, - const PLY::Property* prop, PLY::PropertyInstance* p_pcOut) +bool PLY::ElementInstanceList::ParseInstanceListBinary( + IOStreamBuffer &streamBuffer, + std::vector &buffer, + const char* &pCur, + unsigned int &bufferSize, + const PLY::Element* pcElement, + PLY::ElementInstanceList* p_pcOut, + PLYImporter* loader, + bool p_bBE /* = false */) { - ai_assert(NULL != pCur && NULL != pCurOut && NULL != prop && NULL != p_pcOut); + ai_assert(NULL != pcElement); - *pCurOut = pCur; - - // skip spaces at the beginning - if (!SkipSpaces(pCur, &pCur))return false; - - if (prop->bIsList) - { - // parse the number of elements in the list - PLY::PropertyInstance::ValueUnion v; - PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eFirstType,&v); - - // convert to unsigned int - unsigned int iNum = PLY::PropertyInstance::ConvertTo(v,prop->eFirstType); - - // parse all list elements - p_pcOut->avList.resize(iNum); - for (unsigned int i = 0; i < iNum;++i) - { - if (!SkipSpaces(pCur, &pCur))return false; - PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eType,&p_pcOut->avList[i]); - } - } + // we can add special handling code for unknown element semantics since + // we can't skip it as a whole block (we don't know its exact size + // due to the fact that lists could be contained in the property list + // of the unknown element) + for (unsigned int i = 0; i < pcElement->NumOccur; ++i) + { + if (p_pcOut) + PLY::ElementInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, pcElement, &p_pcOut->alInstances[i], p_bBE); else { - // parse the property - PLY::PropertyInstance::ValueUnion v; + ElementInstance elt; + PLY::ElementInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, pcElement, &elt, p_bBE); - PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eType,&v); - p_pcOut->avList.push_back(v); + // Create vertex or face + if (pcElement->eSemantic == EEST_Vertex) + { + //call loader instance from here + loader->LoadVertex(pcElement, &elt, i); + } + else if (pcElement->eSemantic == EEST_Face) + { + //call loader instance from here + loader->LoadFace(pcElement, &elt, i); + } + else if (pcElement->eSemantic == EEST_TriStrip) + { + //call loader instance from here + loader->LoadFace(pcElement, &elt, i); + } } - SkipSpacesAndLineEnd(pCur, &pCur); - *pCurOut = pCur; - return true; + } + return true; } // ------------------------------------------------------------------------------------------------ -bool PLY::PropertyInstance::ParseInstanceBinary ( - const char* pCur, - const char** pCurOut, - const PLY::Property* prop, - PLY::PropertyInstance* p_pcOut, - bool p_bBE) +bool PLY::ElementInstance::ParseInstance(const char* &pCur, + const PLY::Element* pcElement, + PLY::ElementInstance* p_pcOut) { - ai_assert(NULL != pCur && NULL != pCurOut && NULL != prop && NULL != p_pcOut); + ai_assert(NULL != pcElement); + ai_assert(NULL != p_pcOut); - if (prop->bIsList) + // allocate enough storage + p_pcOut->alProperties.resize(pcElement->alProperties.size()); + + std::vector::iterator i = p_pcOut->alProperties.begin(); + std::vector::const_iterator a = pcElement->alProperties.begin(); + for (; i != p_pcOut->alProperties.end(); ++i, ++a) + { + if (!(PLY::PropertyInstance::ParseInstance(pCur, &(*a), &(*i)))) { - // parse the number of elements in the list - PLY::PropertyInstance::ValueUnion v; - PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eFirstType,&v,p_bBE); + DefaultLogger::get()->warn("Unable to parse property instance. " + "Skipping this element instance"); - // convert to unsigned int - unsigned int iNum = PLY::PropertyInstance::ConvertTo(v,prop->eFirstType); - - // parse all list elements - p_pcOut->avList.resize(iNum); - for (unsigned int i = 0; i < iNum;++i){ - PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eType,&p_pcOut->avList[i],p_bBE); - } + PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a).eType); + (*i).avList.push_back(v); } - else - { - // parse the property - PLY::PropertyInstance::ValueUnion v; - PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eType,&v,p_bBE); - p_pcOut->avList.push_back(v); - } - *pCurOut = pCur; - return true; + } + return true; } // ------------------------------------------------------------------------------------------------ -PLY::PropertyInstance::ValueUnion PLY::PropertyInstance::DefaultValue( - PLY::EDataType eType) +bool PLY::ElementInstance::ParseInstanceBinary( + IOStreamBuffer &streamBuffer, + std::vector &buffer, + const char* &pCur, + unsigned int &bufferSize, + const PLY::Element* pcElement, + PLY::ElementInstance* p_pcOut, + bool p_bBE /* = false */) { - PLY::PropertyInstance::ValueUnion out; + ai_assert(NULL != pcElement); + ai_assert(NULL != p_pcOut); - switch (eType) + // allocate enough storage + p_pcOut->alProperties.resize(pcElement->alProperties.size()); + + std::vector::iterator i = p_pcOut->alProperties.begin(); + std::vector::const_iterator a = pcElement->alProperties.begin(); + for (; i != p_pcOut->alProperties.end(); ++i, ++a) + { + if (!(PLY::PropertyInstance::ParseInstanceBinary(streamBuffer, buffer, pCur, bufferSize, &(*a), &(*i), p_bBE))) { - case EDT_Float: - out.fFloat = 0.f; - return out; + DefaultLogger::get()->warn("Unable to parse binary property instance. " + "Skipping this element instance"); - case EDT_Double: - out.fDouble = 0.; - return out; + (*i).avList.push_back(PLY::PropertyInstance::DefaultValue((*a).eType)); + } + } + return true; +} - default: ; - }; - out.iUInt = 0; +// ------------------------------------------------------------------------------------------------ +bool PLY::PropertyInstance::ParseInstance(const char* &pCur, + const PLY::Property* prop, PLY::PropertyInstance* p_pcOut) +{ + ai_assert(NULL != prop); + ai_assert(NULL != p_pcOut); + + // skip spaces at the beginning + if (!SkipSpaces(&pCur)) + { + return false; + } + + if (prop->bIsList) + { + // parse the number of elements in the list + PLY::PropertyInstance::ValueUnion v; + PLY::PropertyInstance::ParseValue(pCur, prop->eFirstType, &v); + + // convert to unsigned int + unsigned int iNum = PLY::PropertyInstance::ConvertTo(v, prop->eFirstType); + + // parse all list elements + p_pcOut->avList.resize(iNum); + for (unsigned int i = 0; i < iNum; ++i) + { + if (!SkipSpaces(&pCur)) + return false; + + PLY::PropertyInstance::ParseValue(pCur, prop->eType, &p_pcOut->avList[i]); + } + } + else + { + // parse the property + PLY::PropertyInstance::ValueUnion v; + + PLY::PropertyInstance::ParseValue(pCur, prop->eType, &v); + p_pcOut->avList.push_back(v); + } + SkipSpacesAndLineEnd(&pCur); + return true; +} + +// ------------------------------------------------------------------------------------------------ +bool PLY::PropertyInstance::ParseInstanceBinary(IOStreamBuffer &streamBuffer, std::vector &buffer, + const char* &pCur, + unsigned int &bufferSize, + const PLY::Property* prop, + PLY::PropertyInstance* p_pcOut, + bool p_bBE) +{ + ai_assert(NULL != prop); + ai_assert(NULL != p_pcOut); + + // parse all elements + if (prop->bIsList) + { + // parse the number of elements in the list + PLY::PropertyInstance::ValueUnion v; + PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, prop->eFirstType, &v, p_bBE); + + // convert to unsigned int + unsigned int iNum = PLY::PropertyInstance::ConvertTo(v, prop->eFirstType); + + // parse all list elements + p_pcOut->avList.resize(iNum); + for (unsigned int i = 0; i < iNum; ++i) + { + PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, prop->eType, &p_pcOut->avList[i], p_bBE); + } + } + else + { + // parse the property + PLY::PropertyInstance::ValueUnion v; + PLY::PropertyInstance::ParseValueBinary(streamBuffer, buffer, pCur, bufferSize, prop->eType, &v, p_bBE); + p_pcOut->avList.push_back(v); + } + return true; +} + +// ------------------------------------------------------------------------------------------------ +PLY::PropertyInstance::ValueUnion PLY::PropertyInstance::DefaultValue(PLY::EDataType eType) +{ + PLY::PropertyInstance::ValueUnion out; + + switch (eType) + { + case EDT_Float: + out.fFloat = 0.f; return out; + + case EDT_Double: + out.fDouble = 0.; + return out; + + default:; + }; + out.iUInt = 0; + return out; } // ------------------------------------------------------------------------------------------------ -bool PLY::PropertyInstance::ParseValue( - const char* pCur, - const char** pCurOut, - PLY::EDataType eType, - PLY::PropertyInstance::ValueUnion* out) +bool PLY::PropertyInstance::ParseValue(const char* &pCur, + PLY::EDataType eType, + PLY::PropertyInstance::ValueUnion* out) { - ai_assert(NULL != pCur && NULL != pCurOut && NULL != out); + ai_assert(NULL != pCur); + ai_assert(NULL != out); - bool ret = true; - *pCurOut = pCur; - switch (eType) - { - case EDT_UInt: - case EDT_UShort: - case EDT_UChar: + //calc element size + bool ret = true; + switch (eType) + { + case EDT_UInt: + case EDT_UShort: + case EDT_UChar: - out->iUInt = (uint32_t)strtoul10(pCur, &pCur); - break; + out->iUInt = (uint32_t)strtoul10(pCur, &pCur); + break; - case EDT_Int: - case EDT_Short: - case EDT_Char: + case EDT_Int: + case EDT_Short: + case EDT_Char: - out->iInt = (int32_t)strtol10(pCur, &pCur); - break; + out->iInt = (int32_t)strtol10(pCur, &pCur); + break; - case EDT_Float: - // technically this should cast to float, but people tend to use float descriptors for double data - // this is the best way to not risk losing precision on import and it doesn't hurt to do this - ai_real f; - pCur = fast_atoreal_move(pCur,f); - out->fFloat = (ai_real)f; - break; + case EDT_Float: + // technically this should cast to float, but people tend to use float descriptors for double data + // this is the best way to not risk losing precision on import and it doesn't hurt to do this + ai_real f; + pCur = fast_atoreal_move(pCur, f); + out->fFloat = (ai_real)f; + break; - case EDT_Double: + case EDT_Double: + double d; + pCur = fast_atoreal_move(pCur, d); + out->fDouble = (double)d; + break; - double d; - pCur = fast_atoreal_move(pCur,d); - out->fDouble = (double)d; - break; + case EDT_INVALID: + default: + ret = false; + break; + } - default: - ret = false; - } - *pCurOut = pCur; - return ret; + return ret; } // ------------------------------------------------------------------------------------------------ -bool PLY::PropertyInstance::ParseValueBinary( - const char* pCur, - const char** pCurOut, - PLY::EDataType eType, - PLY::PropertyInstance::ValueUnion* out, - bool p_bBE) +bool PLY::PropertyInstance::ParseValueBinary(IOStreamBuffer &streamBuffer, + std::vector &buffer, + const char* &pCur, + unsigned int &bufferSize, + PLY::EDataType eType, + PLY::PropertyInstance::ValueUnion* out, + bool p_bBE) { - ai_assert(NULL != pCur && NULL != pCurOut && NULL != out); + ai_assert(NULL != out); - bool ret = true; - switch (eType) + //calc element size + unsigned int lsize = 0; + switch (eType) + { + case EDT_Char: + case EDT_UChar: + lsize = 1; + break; + + case EDT_UShort: + case EDT_Short: + lsize = 2; + break; + + case EDT_UInt: + case EDT_Int: + case EDT_Float: + lsize = 4; + break; + + case EDT_Double: + lsize = 8; + break; + + case EDT_INVALID: + default: + break; + } + + //read the next file block if needed + if (bufferSize < lsize) + { + std::vector nbuffer; + if (streamBuffer.getNextBlock(nbuffer)) { - case EDT_UInt: - out->iUInt = (uint32_t)*((uint32_t*)pCur); - pCur += 4; - - // Swap endianness - if (p_bBE)ByteSwap::Swap((int32_t*)&out->iUInt); - break; - - case EDT_UShort: - { - uint16_t i = *((uint16_t*)pCur); - - // Swap endianness - if (p_bBE)ByteSwap::Swap(&i); - out->iUInt = (uint32_t)i; - pCur += 2; - break; - } - - case EDT_UChar: - { - out->iUInt = (uint32_t)(*((uint8_t*)pCur)); - pCur ++; - break; - } - - case EDT_Int: - out->iInt = *((int32_t*)pCur); - pCur += 4; - - // Swap endianness - if (p_bBE)ByteSwap::Swap(&out->iInt); - break; - - case EDT_Short: - { - int16_t i = *((int16_t*)pCur); - - // Swap endianness - if (p_bBE)ByteSwap::Swap(&i); - out->iInt = (int32_t)i; - pCur += 2; - break; - } - - case EDT_Char: - out->iInt = (int32_t)*((int8_t*)pCur); - pCur ++; - break; - - case EDT_Float: - { - out->fFloat = *((float*)pCur); - - // Swap endianness - if (p_bBE)ByteSwap::Swap((int32_t*)&out->fFloat); - pCur += 4; - break; - } - case EDT_Double: - { - out->fDouble = *((double*)pCur); - - // Swap endianness - if (p_bBE)ByteSwap::Swap((int64_t*)&out->fDouble); - pCur += 8; - break; - } - default: - ret = false; + //concat buffer contents + buffer = std::vector(buffer.end() - bufferSize, buffer.end()); + buffer.insert(buffer.end(), nbuffer.begin(), nbuffer.end()); + nbuffer.clear(); + bufferSize = static_cast(buffer.size()); + pCur = (char*)&buffer[0]; } - *pCurOut = pCur; - return ret; + else + { + throw DeadlyImportError("Invalid .ply file: File corrupted"); + } + } + + bool ret = true; + switch (eType) + { + case EDT_UInt: + out->iUInt = (uint32_t)*((uint32_t*)pCur); + pCur += 4; + + // Swap endianness + if (p_bBE)ByteSwap::Swap((int32_t*)&out->iUInt); + break; + + case EDT_UShort: + { + uint16_t i = *((uint16_t*)pCur); + + // Swap endianness + if (p_bBE)ByteSwap::Swap(&i); + out->iUInt = (uint32_t)i; + pCur += 2; + break; + } + + case EDT_UChar: + { + out->iUInt = (uint32_t)(*((uint8_t*)pCur)); + pCur++; + break; + } + + case EDT_Int: + out->iInt = *((int32_t*)pCur); + pCur += 4; + + // Swap endianness + if (p_bBE)ByteSwap::Swap(&out->iInt); + break; + + case EDT_Short: + { + int16_t i = *((int16_t*)pCur); + + // Swap endianness + if (p_bBE)ByteSwap::Swap(&i); + out->iInt = (int32_t)i; + pCur += 2; + break; + } + + case EDT_Char: + out->iInt = (int32_t)*((int8_t*)pCur); + pCur++; + break; + + case EDT_Float: + { + out->fFloat = *((float*)pCur); + + // Swap endianness + if (p_bBE)ByteSwap::Swap((int32_t*)&out->fFloat); + pCur += 4; + break; + } + case EDT_Double: + { + out->fDouble = *((double*)pCur); + + // Swap endianness + if (p_bBE)ByteSwap::Swap((int64_t*)&out->fDouble); + pCur += 8; + break; + } + default: + ret = false; + } + + bufferSize -= lsize; + + return ret; } #endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER diff --git a/code/PlyParser.h b/code/PlyParser.h index 2753c1004..b17b07341 100644 --- a/code/PlyParser.h +++ b/code/PlyParser.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team All rights reserved. Redistribution and use of this software in source and binary forms, @@ -45,19 +45,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ParsingUtils.h" +#include "IOStreamBuffer.h" #include - namespace Assimp { +//pre-declaration +class PLYImporter; + // http://local.wasp.uwa.edu.au/~pbourke/dataformats/ply/ // http://w3.impa.br/~lvelho/outgoing/sossai/old/ViHAP_D4.4.2_PLY_format_v1.1.pdf // http://www.okino.com/conv/exp_ply.htm namespace PLY { - // --------------------------------------------------------------------------------- /* name type number of bytes @@ -196,6 +198,9 @@ enum EElementSemantic //! The element is a material description EEST_Material, + //! texture path + EEST_TextureFile, + //! Marks invalid entries EEST_INVALID }; @@ -234,19 +239,18 @@ public: // ------------------------------------------------------------------- //! Parse a property from a string. The end of the - //! string is either '\n', '\r' or '\0'. Return valie is false + //! string is either '\n', '\r' or '\0'. Return value is false //! if the input string is NOT a valid property (E.g. does //! not start with the "property" keyword) - static bool ParseProperty (const char* pCur, const char** pCurOut, - Property* pOut); + static bool ParseProperty(std::vector &buffer, Property* pOut); // ------------------------------------------------------------------- //! Parse a data type from a string - static EDataType ParseDataType(const char* pCur,const char** pCurOut); + static EDataType ParseDataType(std::vector &buffer); // ------------------------------------------------------------------- //! Parse a semantic from a string - static ESemantic ParseSemantic(const char* pCur,const char** pCurOut); + static ESemantic ParseSemantic(std::vector &buffer); }; // --------------------------------------------------------------------------------- @@ -284,13 +288,11 @@ public: //! Parse an element from a string. //! The function will parse all properties contained in the //! element, too. - static bool ParseElement (const char* pCur, const char** pCurOut, - Element* pOut); + static bool ParseElement(IOStreamBuffer &streamBuffer, std::vector &buffer, Element* pOut); // ------------------------------------------------------------------- //! Parse a semantic from a string - static EElementSemantic ParseSemantic(const char* pCur, - const char** pCurOut); + static EElementSemantic ParseSemantic(std::vector &buffer); }; // --------------------------------------------------------------------------------- @@ -330,13 +332,13 @@ public: // ------------------------------------------------------------------- //! Parse a property instance - static bool ParseInstance (const char* pCur,const char** pCurOut, + static bool ParseInstance(const char* &pCur, const Property* prop, PropertyInstance* p_pcOut); // ------------------------------------------------------------------- //! Parse a property instance in binary format - static bool ParseInstanceBinary (const char* pCur,const char** pCurOut, - const Property* prop, PropertyInstance* p_pcOut,bool p_bBE); + static bool ParseInstanceBinary(IOStreamBuffer &streamBuffer, std::vector &buffer, + const char* &pCur, unsigned int &bufferSize, const Property* prop, PropertyInstance* p_pcOut, bool p_bBE); // ------------------------------------------------------------------- //! Get the default value for a given data type @@ -344,13 +346,12 @@ public: // ------------------------------------------------------------------- //! Parse a value - static bool ParseValue(const char* pCur,const char** pCurOut, - EDataType eType,ValueUnion* out); + static bool ParseValue(const char* &pCur, EDataType eType, ValueUnion* out); // ------------------------------------------------------------------- //! Parse a binary value - static bool ParseValueBinary(const char* pCur,const char** pCurOut, - EDataType eType,ValueUnion* out,bool p_bBE); + static bool ParseValueBinary(IOStreamBuffer &streamBuffer, std::vector &buffer, + const char* &pCur, unsigned int &bufferSize, EDataType eType, ValueUnion* out, bool p_bBE); // ------------------------------------------------------------------- //! Convert a property value to a given type TYPE @@ -374,13 +375,13 @@ public: // ------------------------------------------------------------------- //! Parse an element instance - static bool ParseInstance (const char* pCur,const char** pCurOut, + static bool ParseInstance(const char* &pCur, const Element* pcElement, ElementInstance* p_pcOut); // ------------------------------------------------------------------- //! Parse a binary element instance - static bool ParseInstanceBinary (const char* pCur,const char** pCurOut, - const Element* pcElement, ElementInstance* p_pcOut,bool p_bBE); + static bool ParseInstanceBinary(IOStreamBuffer &streamBuffer, std::vector &buffer, + const char* &pCur, unsigned int &bufferSize, const Element* pcElement, ElementInstance* p_pcOut, bool p_bBE); }; // --------------------------------------------------------------------------------- @@ -399,13 +400,13 @@ public: // ------------------------------------------------------------------- //! Parse an element instance list - static bool ParseInstanceList (const char* pCur,const char** pCurOut, - const Element* pcElement, ElementInstanceList* p_pcOut); + static bool ParseInstanceList(IOStreamBuffer &streamBuffer, std::vector &buffer, + const Element* pcElement, ElementInstanceList* p_pcOut, PLYImporter* loader); // ------------------------------------------------------------------- //! Parse a binary element instance list - static bool ParseInstanceListBinary (const char* pCur,const char** pCurOut, - const Element* pcElement, ElementInstanceList* p_pcOut,bool p_bBE); + static bool ParseInstanceListBinary(IOStreamBuffer &streamBuffer, std::vector &buffer, + const char* &pCur, unsigned int &bufferSize, const Element* pcElement, ElementInstanceList* p_pcOut, PLYImporter* loader, bool p_bBE); }; // --------------------------------------------------------------------------------- /** \brief Class to represent the document object model of an ASCII or binary @@ -427,50 +428,33 @@ public: //! Parse the DOM for a PLY file. The input string is assumed //! to be terminated with zero - static bool ParseInstance (const char* pCur,DOM* p_pcOut); - static bool ParseInstanceBinary (const char* pCur, - DOM* p_pcOut,bool p_bBE); + static bool ParseInstance(IOStreamBuffer &streamBuffer, DOM* p_pcOut, PLYImporter* loader); + static bool ParseInstanceBinary(IOStreamBuffer &streamBuffer, DOM* p_pcOut, PLYImporter* loader, bool p_bBE); //! Skip all comment lines after this - static bool SkipComments (const char* pCur,const char** pCurOut); + static bool SkipComments(std::vector &buffer); + + static bool SkipSpaces(std::vector &buffer); + + static bool SkipLine(std::vector &buffer); + + static bool TokenMatch(std::vector &buffer, const char* token, unsigned int len); + + static bool SkipSpacesAndLineEnd(std::vector &buffer); private: // ------------------------------------------------------------------- //! Handle the file header and read all element descriptions - bool ParseHeader (const char* pCur,const char** pCurOut, bool p_bBE); + bool ParseHeader(IOStreamBuffer &streamBuffer, std::vector &buffer, bool p_bBE); // ------------------------------------------------------------------- //! Read in all element instance lists - bool ParseElementInstanceLists (const char* pCur,const char** pCurOut); + bool ParseElementInstanceLists(IOStreamBuffer &streamBuffer, std::vector &buffer, PLYImporter* loader); // ------------------------------------------------------------------- //! Read in all element instance lists for a binary file format - bool ParseElementInstanceListsBinary (const char* pCur, - const char** pCurOut,bool p_bBE); -}; - -// --------------------------------------------------------------------------------- -/** \brief Helper class to represent a loaded PLY face - */ -class Face -{ -public: - - Face() - : iMaterialIndex(0xFFFFFFFF) - { - // set all indices to zero by default - mIndices.resize(3,0); - } - -public: - - //! List of vertex indices - std::vector mIndices; - - //! Material index - unsigned int iMaterialIndex; + bool ParseElementInstanceListsBinary(IOStreamBuffer &streamBuffer, std::vector &buffer, const char* &pCur, unsigned int &bufferSize, PLYImporter* loader, bool p_bBE); }; // --------------------------------------------------------------------------------- diff --git a/code/PolyTools.h b/code/PolyTools.h index 80e1dd173..1089327ae 100644 --- a/code/PolyTools.h +++ b/code/PolyTools.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/PostStepRegistry.cpp b/code/PostStepRegistry.cpp index 31518c132..c80c373e5 100644 --- a/code/PostStepRegistry.cpp +++ b/code/PostStepRegistry.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/PretransformVertices.cpp b/code/PretransformVertices.cpp index bcb3913c3..0751c4556 100644 --- a/code/PretransformVertices.cpp +++ b/code/PretransformVertices.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -46,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "PretransformVertices.h" #include "ProcessHelper.h" -#include "SceneCombiner.h" +#include #include "Exceptional.h" using namespace Assimp; @@ -103,7 +104,7 @@ unsigned int PretransformVertices::CountNodes( aiNode* pcNode ) // ------------------------------------------------------------------------------------------------ // Get a bitwise combination identifying the vertex format of a mesh -unsigned int PretransformVertices::GetMeshVFormat(aiMesh* pcMesh) +unsigned int PretransformVertices::GetMeshVFormat( aiMesh* pcMesh ) { // the vertex format is stored in aiMesh::mBones for later retrieval. // there isn't a good reason to compute it a few hundred times @@ -159,6 +160,11 @@ void PretransformVertices::CollectData( aiScene* pcScene, aiNode* pcNode, unsign unsigned int& num_ref = num_refs[pcNode->mMeshes[i]]; ai_assert(0 != num_ref); --num_ref; + // Save the name of the last mesh + if (num_ref==0) + { + pcMeshOut->mName = pcMesh->mName; + } if (identity) { // copy positions without modifying them @@ -625,9 +631,10 @@ void PretransformVertices::Execute( aiScene* pScene) // now delete all nodes in the scene and build a new // flat node graph with a root node and some level 1 children + aiNode* newRoot = new aiNode(); + newRoot->mName = pScene->mRootNode->mName; delete pScene->mRootNode; - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mName.Set(""); + pScene->mRootNode = newRoot; if (1 == pScene->mNumMeshes && !pScene->mNumLights && !pScene->mNumCameras) { @@ -645,7 +652,7 @@ void PretransformVertices::Execute( aiScene* pScene) { aiNode* pcNode = *nodes = new aiNode(); pcNode->mParent = pScene->mRootNode; - pcNode->mName.length = ::ai_snprintf(pcNode->mName.data,MAXLEN,"mesh_%u",i); + pcNode->mName = pScene->mMeshes[i]->mName; // setup mesh indices pcNode->mNumMeshes = 1; diff --git a/code/PretransformVertices.h b/code/PretransformVertices.h index 28bd95a67..65b4938b0 100644 --- a/code/PretransformVertices.h +++ b/code/PretransformVertices.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/ProcessHelper.cpp b/code/ProcessHelper.cpp index 501d44484..c255979bd 100644 --- a/code/ProcessHelper.cpp +++ b/code/ProcessHelper.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/ProcessHelper.h b/code/ProcessHelper.h index c70e23f5f..a49115936 100644 --- a/code/ProcessHelper.h +++ b/code/ProcessHelper.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/Profiler.h b/code/Profiler.h index 9354339a2..1c9ca60b5 100644 --- a/code/Profiler.h +++ b/code/Profiler.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -51,21 +52,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include namespace Assimp { - namespace Profiling { - - using namespace Formatter; +namespace Profiling { +using namespace Formatter; // ------------------------------------------------------------------------------------------------ /** Simple wrapper around boost::timer to simplify reporting. Timings are automatically * dumped to the log file. */ -class Profiler -{ - +class Profiler { public: - - Profiler() {} + Profiler() { + // empty + } public: @@ -83,17 +82,17 @@ public: return; } - auto elapsedSeconds = std::chrono::system_clock::now() - regions[region]; + std::chrono::duration elapsedSeconds = std::chrono::system_clock::now() - regions[region]; DefaultLogger::get()->debug((format("END `"),region,"`, dt= ", elapsedSeconds.count()," s")); } private: - typedef std::map> RegionMap; RegionMap regions; }; - } +} } #endif + diff --git a/code/Q3BSPFileData.h b/code/Q3BSPFileData.h index ab46db24f..b836795f8 100644 --- a/code/Q3BSPFileData.h +++ b/code/Q3BSPFileData.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/Q3BSPFileImporter.cpp b/code/Q3BSPFileImporter.cpp index 198ecdd73..9d6d8e870 100644 --- a/code/Q3BSPFileImporter.cpp +++ b/code/Q3BSPFileImporter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -40,7 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER -#include "DefaultIOSystem.h" #include "Q3BSPFileImporter.h" #include "Q3BSPZipArchive.h" #include "Q3BSPFileParser.h" @@ -56,6 +56,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include +#include #include #include #include "StringComparison.h" diff --git a/code/Q3BSPFileImporter.h b/code/Q3BSPFileImporter.h index ee8991bea..cf53d4db0 100644 --- a/code/Q3BSPFileImporter.h +++ b/code/Q3BSPFileImporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -42,30 +43,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BaseImporter.h" +#include + struct aiMesh; struct aiNode; struct aiFace; struct aiMaterial; struct aiTexture; -namespace Assimp -{ -namespace Q3BSP -{ - -class Q3BSPZipArchive; -struct Q3BSPModel; -struct sQ3BSPFace; - +namespace Assimp { +namespace Q3BSP { + class Q3BSPZipArchive; + struct Q3BSPModel; + struct sQ3BSPFace; } + // ------------------------------------------------------------------------------------------------ /** Loader to import BSP-levels from a PK3 archive or from a unpacked BSP-level. */ // ------------------------------------------------------------------------------------------------ -class Q3BSPFileImporter : public BaseImporter -{ +class Q3BSPFileImporter : public BaseImporter { public: - /// @brief Default constructor. Q3BSPFileImporter(); diff --git a/code/Q3BSPFileParser.cpp b/code/Q3BSPFileParser.cpp index 0dabaf87d..69721fc2d 100644 --- a/code/Q3BSPFileParser.cpp +++ b/code/Q3BSPFileParser.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -42,10 +43,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER #include "Q3BSPFileParser.h" -#include "DefaultIOSystem.h" #include "Q3BSPFileData.h" #include "Q3BSPZipArchive.h" #include +#include #include namespace Assimp { diff --git a/code/Q3BSPFileParser.h b/code/Q3BSPFileParser.h index 8363d31c0..1ee6d4aef 100644 --- a/code/Q3BSPFileParser.h +++ b/code/Q3BSPFileParser.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/Q3BSPZipArchive.cpp b/code/Q3BSPZipArchive.cpp index 16455c10a..86c966d8e 100644 --- a/code/Q3BSPZipArchive.cpp +++ b/code/Q3BSPZipArchive.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -38,14 +39,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ - - #ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER #include "Q3BSPZipArchive.h" -#include #include -#include #include namespace Assimp { @@ -136,7 +133,6 @@ zlib_filefunc_def IOSystem2Unzip::get(IOSystem* pIOHandler) { return mapping; } -// ------------------------------------------------------------------------------------------------ ZipFile::ZipFile(size_t size) : m_Size(size) { ai_assert(m_Size != 0); @@ -259,6 +255,7 @@ IOStream *Q3BSPZipArchive::Open(const char* pFile, const char* /*pMode*/) { // ------------------------------------------------------------------------------------------------ // Close a filestream. void Q3BSPZipArchive::Close(IOStream *pFile) { + (void)(pFile); ai_assert(pFile != NULL); // We don't do anything in case the file would be opened again in the future diff --git a/code/Q3BSPZipArchive.h b/code/Q3BSPZipArchive.h index 4dcd7a849..5430bac6f 100644 --- a/code/Q3BSPZipArchive.h +++ b/code/Q3BSPZipArchive.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -43,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include #include #include #include diff --git a/code/Q3DLoader.cpp b/code/Q3DLoader.cpp index d9dc29672..5aa639d09 100644 --- a/code/Q3DLoader.cpp +++ b/code/Q3DLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -53,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include using namespace Assimp; diff --git a/code/Q3DLoader.h b/code/Q3DLoader.h index fb1dd1818..97184a5ff 100644 --- a/code/Q3DLoader.h +++ b/code/Q3DLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/RawLoader.cpp b/code/RawLoader.cpp index 57e0fc119..2b76455d7 100644 --- a/code/RawLoader.cpp +++ b/code/RawLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -54,7 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include - +#include using namespace Assimp; @@ -259,7 +260,7 @@ void RAWImporter::InternReadFile( const std::string& pFile, node = *cc = new aiNode(); node->mParent = pScene->mRootNode; } - else node = *cc;++cc; + else node = *cc; node->mName.Set(outGroup.name); // add all meshes diff --git a/code/RawLoader.h b/code/RawLoader.h index 984141a04..0a1a35815 100644 --- a/code/RawLoader.h +++ b/code/RawLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/RemoveComments.cpp b/code/RemoveComments.cpp index 8290d2217..37d74124d 100644 --- a/code/RemoveComments.cpp +++ b/code/RemoveComments.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/RemoveComments.h b/code/RemoveComments.h index 856ed74bf..0a00a8f0f 100644 --- a/code/RemoveComments.h +++ b/code/RemoveComments.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -44,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_REMOVE_COMMENTS_H_INC #define AI_REMOVE_COMMENTS_H_INC -#include + #include namespace Assimp { diff --git a/code/RemoveRedundantMaterials.cpp b/code/RemoveRedundantMaterials.cpp index a9954b946..c6319f892 100644 --- a/code/RemoveRedundantMaterials.cpp +++ b/code/RemoveRedundantMaterials.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -144,6 +145,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) if (!abReferenced[i]) { ++unreferencedRemoved; delete pScene->mMaterials[i]; + pScene->mMaterials[i] = nullptr; continue; } @@ -157,6 +159,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) me = 0; aiMappingTable[i] = aiMappingTable[a]; delete pScene->mMaterials[i]; + pScene->mMaterials[i] = nullptr; break; } } @@ -168,6 +171,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) // If the new material count differs from the original, // we need to rebuild the material list and remap mesh material indexes. if (iNewNum != pScene->mNumMaterials) { + ai_assert(iNewNum > 0); aiMaterial** ppcMaterials = new aiMaterial*[iNewNum]; ::memset(ppcMaterials,0,sizeof(void*)*iNewNum); for (unsigned int p = 0; p < pScene->mNumMaterials;++p) diff --git a/code/RemoveRedundantMaterials.h b/code/RemoveRedundantMaterials.h index 60efad9a4..cb4ec02bb 100644 --- a/code/RemoveRedundantMaterials.h +++ b/code/RemoveRedundantMaterials.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/RemoveVCProcess.cpp b/code/RemoveVCProcess.cpp index 473460452..016757dbb 100644 --- a/code/RemoveVCProcess.cpp +++ b/code/RemoveVCProcess.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -305,7 +306,7 @@ bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh) if (!pMesh->mColors[i])break; if (configDeleteFlags & aiComponent_COLORSn(i) || b) { - delete pMesh->mColors[i]; + delete [] pMesh->mColors[i]; pMesh->mColors[i] = NULL; ret = true; diff --git a/code/RemoveVCProcess.h b/code/RemoveVCProcess.h index a9173a815..d7d45e73e 100644 --- a/code/RemoveVCProcess.h +++ b/code/RemoveVCProcess.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -53,8 +54,7 @@ namespace Assimp { /** RemoveVCProcess: Class to exclude specific parts of the data structure * from further processing by removing them, */ -class ASSIMP_API RemoveVCProcess : public BaseProcess -{ +class ASSIMP_API RemoveVCProcess : public BaseProcess { public: /// The default class constructor. RemoveVCProcess(); @@ -62,7 +62,6 @@ public: /// The class destructor. ~RemoveVCProcess(); -public: // ------------------------------------------------------------------- /** Returns whether the processing step is present in the given flag field. * @param pFlags The processing flags the importer was called with. A bitwise diff --git a/code/SGSpatialSort.cpp b/code/SGSpatialSort.cpp index 84061888e..7a80381e2 100644 --- a/code/SGSpatialSort.cpp +++ b/code/SGSpatialSort.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -47,7 +48,6 @@ the 3ds loader handling smooth groups correctly */ using namespace Assimp; - // ------------------------------------------------------------------------------------------------ SGSpatialSort::SGSpatialSort() { @@ -88,12 +88,11 @@ void SGSpatialSort::FindPositions( const aiVector3D& pPosition, float dist = pPosition * mPlaneNormal; float minDist = dist - pRadius, maxDist = dist + pRadius; - // clear the array in this strange fashion because a simple clear() would also deallocate - // the array which we want to avoid - poResults.erase( poResults.begin(), poResults.end()); + // clear the array + poResults.clear(); // quick check for positions outside the range - if( mPositions.size() == 0) + if( mPositions.empty() ) return; if( maxDist < mPositions.front().mDistance) return; diff --git a/code/SGSpatialSort.h b/code/SGSpatialSort.h index 59a5c37d6..e7cd38724 100644 --- a/code/SGSpatialSort.h +++ b/code/SGSpatialSort.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/SIBImporter.cpp b/code/SIBImporter.cpp index aaf4b0b26..2127e2e0c 100644 --- a/code/SIBImporter.cpp +++ b/code/SIBImporter.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -57,11 +58,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ByteSwapper.h" #include "StreamReader.h" #include "TinyFormatter.h" -#include "../contrib/ConvertUTF/ConvertUTF.h" +//#include "../contrib/ConvertUTF/ConvertUTF.h" +#include "../contrib/utf8cpp/source/utf8.h" #include #include #include +#include +#include using namespace Assimp; @@ -76,25 +80,26 @@ static const aiImporterDesc desc = { "sib" }; -struct SIBChunk -{ +struct SIBChunk { uint32_t Tag; uint32_t Size; } PACK_STRUCT; -enum { POS, NRM, UV, N }; +enum { + POS, + NRM, + UV, + N +}; typedef std::pair SIBPair; -static SIBPair makePair(uint32_t a, uint32_t b) { return (a pos, nrm, uv; @@ -105,15 +110,13 @@ struct SIBMesh std::map edgeMap; }; -struct SIBObject -{ +struct SIBObject { aiString name; aiMatrix4x4 axis; size_t meshIdx, meshCount; }; -struct SIB -{ +struct SIB { std::vector mtls; std::vector meshes; std::vector lights; @@ -121,8 +124,7 @@ struct SIB }; // ------------------------------------------------------------------------------------------------ -static SIBEdge& GetEdge(SIBMesh* mesh, uint32_t posA, uint32_t posB) -{ +static SIBEdge& GetEdge(SIBMesh* mesh, uint32_t posA, uint32_t posB) { SIBPair pair = (posA < posB) ? SIBPair(posA, posB) : SIBPair(posB, posA); std::map::iterator it = mesh->edgeMap.find(pair); if (it != mesh->edgeMap.end()) @@ -161,7 +163,7 @@ static aiColor3D ReadColor(StreamReaderLE* stream) return aiColor3D(r, g, b); } -static void UnknownChunk(StreamReaderLE* stream, const SIBChunk& chunk) +static void UnknownChunk(StreamReaderLE* /*stream*/, const SIBChunk& chunk) { char temp[5] = { static_cast(( chunk.Tag>>24 ) & 0xff), @@ -174,24 +176,29 @@ static void UnknownChunk(StreamReaderLE* stream, const SIBChunk& chunk) } // Reads a UTF-16LE string and returns it at UTF-8. -static aiString ReadString(StreamReaderLE* stream, uint32_t numWChars) -{ +static aiString ReadString(StreamReaderLE *stream, uint32_t numWChars) { + if ( nullptr == stream || 0 == numWChars ) { + static const aiString empty; + return empty; + } + // Allocate buffers (max expansion is 1 byte -> 4 bytes for UTF-8) - UTF16* temp = new UTF16[numWChars]; - UTF8* str = new UTF8[numWChars * 4 + 1]; - for (uint32_t n=0;nGetU2(); + std::vector str; + str.reserve( numWChars * 4 + 1 ); + uint16_t *temp = new uint16_t[ numWChars ]; + for ( uint32_t n = 0; n < numWChars; ++n ) { + temp[ n ] = stream->GetU2(); + } // Convert it and NUL-terminate. - const UTF16 *start = temp, *end = temp + numWChars; - UTF8 *dest = str, *limit = str + numWChars*4; - ConvertUTF16toUTF8(&start, end, &dest, limit, lenientConversion); - *dest = '\0'; + const uint16_t *start( temp ), *end( temp + numWChars ); + utf8::utf16to8( start, end, back_inserter( str ) ); + str[ str.size() - 1 ] = '\0'; // Return the final string. - aiString result = aiString((const char *)str); - delete[] str; + aiString result = aiString((const char *)&str[0]); delete[] temp; + return result; } @@ -209,26 +216,26 @@ SIBImporter::~SIBImporter() { // ------------------------------------------------------------------------------------------------ // Returns whether the class can handle the format of the given file. -bool SIBImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const -{ +bool SIBImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const { return SimpleExtensionCheck(pFile, "sib"); } // ------------------------------------------------------------------------------------------------ -const aiImporterDesc* SIBImporter::GetInfo () const -{ +const aiImporterDesc* SIBImporter::GetInfo () const { return &desc; } // ------------------------------------------------------------------------------------------------ -static void ReadVerts(SIBMesh* mesh, StreamReaderLE* stream, uint32_t count) -{ - mesh->pos.resize(count); +static void ReadVerts(SIBMesh* mesh, StreamReaderLE* stream, uint32_t count) { + if ( nullptr == mesh || nullptr == stream ) { + return; + } - for (uint32_t n=0;npos[n].x = stream->GetF4(); - mesh->pos[n].y = stream->GetF4(); - mesh->pos[n].z = stream->GetF4(); + mesh->pos.resize(count); + for ( uint32_t n=0; npos[ n ].x = stream->GetF4(); + mesh->pos[ n ].y = stream->GetF4(); + mesh->pos[ n ].z = stream->GetF4(); } } @@ -388,7 +395,7 @@ static void ConnectFaces(SIBMesh* mesh) // with non-2-manifold surfaces, but then so does Silo to begin with. if (edge.faceA == 0xffffffff) edge.faceA = static_cast(faceIdx); - else + else if (edge.faceB == 0xffffffff) edge.faceB = static_cast(faceIdx); prev = next; @@ -432,12 +439,17 @@ static aiVector3D CalculateVertexNormal(SIBMesh* mesh, uint32_t faceIdx, uint32_ { SIBEdge& edge = GetEdge(mesh, posA, posB); - // Move to whichever side we didn't just come from. - if (!edge.creased) { - if (edge.faceA != prevFaceIdx && edge.faceA != faceIdx) - nextFaceIdx = edge.faceA; - else if (edge.faceB != prevFaceIdx && edge.faceB != faceIdx) - nextFaceIdx = edge.faceB; + // Non-manifold meshes can produce faces which share + // positions but have no edge entry, so check it. + if (edge.faceA == faceIdx || edge.faceB == faceIdx) + { + // Move to whichever side we didn't just come from. + if (!edge.creased) { + if (edge.faceA != prevFaceIdx && edge.faceA != faceIdx && edge.faceA != 0xffffffff) + nextFaceIdx = edge.faceA; + else if (edge.faceB != prevFaceIdx && edge.faceB != faceIdx && edge.faceB != 0xffffffff) + nextFaceIdx = edge.faceB; + } } } @@ -808,7 +820,7 @@ static void ReadInstance(SIB* sib, StreamReaderLE* stream) static void CheckVersion(StreamReaderLE* stream) { uint32_t version = stream->GetU4(); - if ( version != 1 ) { + if ( version < 1 || version > 2 ) { throw DeadlyImportError( "SIB: Unsupported file version." ); } } @@ -890,6 +902,7 @@ void SIBImporter::InternReadFile(const std::string& pFile, // Add nodes for each object. for (size_t n=0;nmChildren); SIBObject& obj = sib.objs[n]; aiNode* node = new aiNode; root->mChildren[childIdx++] = node; @@ -914,6 +927,7 @@ void SIBImporter::InternReadFile(const std::string& pFile, // (no transformation as the light is already in world space) for (size_t n=0;nmChildren); aiLight* light = sib.lights[n]; if ( nullptr != light ) { aiNode* node = new aiNode; diff --git a/code/SIBImporter.h b/code/SIBImporter.h index bd71104c6..e7e2ec0b9 100644 --- a/code/SIBImporter.h +++ b/code/SIBImporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/SMDLoader.cpp b/code/SMDLoader.cpp index b06fa8c96..60e3f63c8 100644 --- a/code/SMDLoader.cpp +++ b/code/SMDLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -54,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include using namespace Assimp; @@ -448,7 +450,9 @@ void SMDImporter::CreateOutputMeshes() // add bone child nodes void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent) { - ai_assert(NULL != pcNode && 0 == pcNode->mNumChildren && NULL == pcNode->mChildren); + ai_assert( NULL != pcNode ); + ai_assert( 0 == pcNode->mNumChildren ); + ai_assert( NULL == pcNode->mChildren); // first count ... for (unsigned int i = 0; i < asBones.size();++i) @@ -646,12 +650,14 @@ void SMDImporter::ComputeAbsoluteBoneTransformations() // create output materials void SMDImporter::CreateOutputMaterials() { + ai_assert( nullptr != pScene ); + pScene->mNumMaterials = (unsigned int)aszTextures.size(); pScene->mMaterials = new aiMaterial*[std::max(1u, pScene->mNumMaterials)]; - for (unsigned int iMat = 0; iMat < pScene->mNumMaterials;++iMat) - { + for (unsigned int iMat = 0; iMat < pScene->mNumMaterials; ++iMat) { aiMaterial* pcMat = new aiMaterial(); + ai_assert( nullptr != pcMat ); pScene->mMaterials[iMat] = pcMat; aiString szName; @@ -702,7 +708,7 @@ void SMDImporter::ParseFile() { if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break; - // "version \n", should be 1 for hl and hl� SMD files + // "version \n", should be 1 for hl and hl2 SMD files if (TokenMatch(szCurrent,"version",7)) { if(!SkipSpaces(szCurrent,&szCurrent)) break; @@ -1020,7 +1026,7 @@ void SMDImporter::ParseTriangle(const char* szCurrent, // read the texture file name const char* szLast = szCurrent; - while (!IsSpaceOrNewLine(*szCurrent++)); + while (!IsSpaceOrNewLine(*++szCurrent)); // ... and get the index that belongs to this file name face.iTexture = GetTextureIndex(std::string(szLast,(uintptr_t)szCurrent-(uintptr_t)szLast)); diff --git a/code/SMDLoader.h b/code/SMDLoader.h index 96ea1d195..c50b327e3 100644 --- a/code/SMDLoader.h +++ b/code/SMDLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -171,7 +172,7 @@ struct Bone // --------------------------------------------------------------------------- /** Used to load Half-life 1 and 2 SMD models */ -class SMDImporter : public BaseImporter +class ASSIMP_API SMDImporter : public BaseImporter { public: SMDImporter(); diff --git a/code/STEPFile.h b/code/STEPFile.h index 9a830c068..8a30beb3f 100644 --- a/code/STEPFile.h +++ b/code/STEPFile.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -54,7 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #if _MSC_VER > 1500 || (defined __GNUC___) # define ASSIMP_STEP_USE_UNORDERED_MULTIMAP -# else +#else # define step_unordered_map map # define step_unordered_multimap multimap #endif @@ -438,13 +439,17 @@ namespace STEP { // ------------------------------------------------------------------------------ /** Base class for all concrete object instances */ // ------------------------------------------------------------------------------ - class Object - { + class Object { public: - - virtual ~Object() {} Object(const char* classname = "unknown") - : classname(classname) {} + : id( 0 ) + , classname(classname) { + // empty + } + + virtual ~Object() { + // empty + } public: @@ -459,7 +464,6 @@ namespace STEP { return dynamic_cast(*this); } - template const T* ToPtr() const { return dynamic_cast(this); @@ -471,7 +475,6 @@ namespace STEP { } public: - uint64_t GetID() const { return id; } @@ -489,7 +492,6 @@ namespace STEP { const char* const classname; }; - template size_t GenericFill(const STEP::DB& db, const EXPRESS::LIST& params, T* in); // (intentionally undefined) diff --git a/code/STEPFileEncoding.cpp b/code/STEPFileEncoding.cpp index aff0b618d..7204f802b 100644 --- a/code/STEPFileEncoding.cpp +++ b/code/STEPFileEncoding.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -39,18 +40,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file STEPFileEncoding.cpp - * @brief STEP character handling, string unescaping + * @brief STEP character handling, string un-escaping */ #include "STEPFileEncoding.h" #include "fast_atof.h" +#include -#include "../contrib/ConvertUTF/ConvertUTF.h" #include using namespace Assimp; // roman1 to utf16 table -static const UTF16 mac_codetable[] = { +static const uint16_t mac_codetable[] = { // 0x20 unassig./nonprint. slots 0x0020 , 0x0021 , @@ -308,14 +309,12 @@ bool STEP::StringToUTF8(std::string& s) ai_assert(sizeof(mac_codetable) / sizeof(mac_codetable[0]) == 0x100-0x20); - const UTF32 unival = mac_codetable[macval - 0x20], *univalp = &unival; + const uint32_t unival = mac_codetable[macval - 0x20], *univalp = &unival; - UTF8 temp[5], *tempp = temp; - ai_assert(sizeof(UTF8) == 1); + unsigned char temp[5], *tempp = temp; + ai_assert(sizeof( unsigned char ) == 1); - if(ConvertUTF32toUTF8(&univalp, univalp+1, &tempp, tempp+sizeof(temp), lenientConversion) != conversionOK) { - return false; - } + utf8::utf32to8( univalp, univalp + 1, tempp ); const size_t outcount = static_cast(tempp-temp); @@ -335,7 +334,7 @@ bool STEP::StringToUTF8(std::string& s) size_t j = basei, jend = s.size()-3; for (; j < jend; ++j) { - if (s[j] == '\\' && s[j] == 'X' && s[j] == '0' && s[j] == '\\') { + if (s[j] == '\\' && s[j+1] == 'X' && s[j+2] == '0' && s[j+3] == '\\') { break; } } @@ -354,28 +353,26 @@ bool STEP::StringToUTF8(std::string& s) } const size_t count = (j-basei)/4; - std::unique_ptr src(new UTF16[count]); + std::unique_ptr src(new uint16_t[count]); const char* cur = s.c_str() + basei; for (size_t k = 0; k < count; ++k, cur += 4) { - src[k] = (static_cast(HexOctetToDecimal(cur)) << 8u) | - static_cast(HexOctetToDecimal(cur+2)); + src[k] = (static_cast(HexOctetToDecimal(cur)) << 8u) | + static_cast(HexOctetToDecimal(cur+2)); } const size_t dcount = count * 3; // this is enough to hold all possible outputs - std::unique_ptr dest(new UTF8[dcount]); + std::unique_ptr dest(new unsigned char[dcount]); - const UTF16* srct = src.get(); - UTF8* destt = dest.get(); - if(ConvertUTF16toUTF8(&srct, srct+count, &destt, destt+dcount, lenientConversion) != conversionOK) { - return false; - } + const uint16_t* srct = src.get(); + unsigned char* destt = dest.get(); + utf8::utf16to8( srct, srct + count, destt ); const size_t outcount = static_cast(destt-dest.get()); s.erase(i,(j+4-i)); - ai_assert(sizeof(UTF8) == 1); + ai_assert(sizeof(unsigned char) == 1); s.insert(i, reinterpret_cast(dest.get()), outcount); i += outcount; @@ -387,37 +384,34 @@ bool STEP::StringToUTF8(std::string& s) } const size_t count = (j-basei)/8; - std::unique_ptr src(new UTF32[count]); + std::unique_ptr src(new uint32_t[count]); const char* cur = s.c_str() + basei; for (size_t k = 0; k < count; ++k, cur += 8) { - src[k] = (static_cast(HexOctetToDecimal(cur )) << 24u) | - (static_cast(HexOctetToDecimal(cur+2)) << 16u) | - (static_cast(HexOctetToDecimal(cur+4)) << 8u) | - (static_cast(HexOctetToDecimal(cur+6))); + src[k] = (static_cast(HexOctetToDecimal(cur )) << 24u) | + (static_cast(HexOctetToDecimal(cur+2)) << 16u) | + (static_cast(HexOctetToDecimal(cur+4)) << 8u) | + (static_cast(HexOctetToDecimal(cur+6))); } const size_t dcount = count * 5; // this is enough to hold all possible outputs - std::unique_ptr dest(new UTF8[dcount]); + std::unique_ptr dest(new unsigned char[dcount]); - const UTF32* srct = src.get(); - UTF8* destt = dest.get(); - if(ConvertUTF32toUTF8(&srct, srct+count, &destt, destt+dcount, lenientConversion) != conversionOK) { - return false; - } + const uint32_t* srct = src.get(); + unsigned char* destt = dest.get(); + utf8::utf32to8( srct, srct + count, destt ); const size_t outcount = static_cast(destt-dest.get()); s.erase(i,(j+4-i)); - ai_assert(sizeof(UTF8) == 1); + ai_assert(sizeof(unsigned char) == 1); s.insert(i, reinterpret_cast(dest.get()), outcount); i += outcount; continue; } } - break; // TODO: other encoding patterns? diff --git a/code/STEPFileEncoding.h b/code/STEPFileEncoding.h index 3aec83056..56615c8f6 100644 --- a/code/STEPFileEncoding.h +++ b/code/STEPFileEncoding.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/STEPFileReader.cpp b/code/STEPFileReader.cpp index afaa53a45..d014c1a5d 100644 --- a/code/STEPFileReader.cpp +++ b/code/STEPFileReader.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/STEPFileReader.h b/code/STEPFileReader.h index c5bc88a5e..fb8c86f59 100644 --- a/code/STEPFileReader.h +++ b/code/STEPFileReader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/STLExporter.cpp b/code/STLExporter.cpp index 3905cbcaf..60b5d8bf3 100644 --- a/code/STLExporter.cpp +++ b/code/STLExporter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -56,11 +57,15 @@ namespace Assimp { // ------------------------------------------------------------------------------------------------ // Worker function for exporting a scene to Stereolithograpy. Prototyped and registered in Exporter.cpp -void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) +void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { // invoke the exporter STLExporter exporter(pFile, pScene); + if (exporter.mOutput.fail()) { + throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); + } + // we're still here - export successfully completed. Write the file. std::unique_ptr outfile (pIOSystem->Open(pFile,"wt")); if(outfile == NULL) { @@ -69,11 +74,15 @@ void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene outfile->Write( exporter.mOutput.str().c_str(), static_cast(exporter.mOutput.tellp()),1); } -void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) +void ExportSceneSTLBinary(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) { // invoke the exporter STLExporter exporter(pFile, pScene, true); + if (exporter.mOutput.fail()) { + throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); + } + // we're still here - export successfully completed. Write the file. std::unique_ptr outfile (pIOSystem->Open(pFile,"wb")); if(outfile == NULL) { diff --git a/code/STLExporter.h b/code/STLExporter.h index 44b12344f..7fb6a3e75 100644 --- a/code/STLExporter.h +++ b/code/STLExporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/STLLoader.cpp b/code/STLLoader.cpp index 7d3e3224c..be4c7584d 100644 --- a/code/STLLoader.cpp +++ b/code/STLLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -52,10 +53,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include using namespace Assimp; namespace { + static const aiImporterDesc desc = { "Stereolithography (STL) Importer", "", @@ -78,7 +81,9 @@ static bool IsBinarySTL(const char* buffer, unsigned int fileSize) { return false; } - const uint32_t faceCount = *reinterpret_cast(buffer + 80); + const char *facecount_pos = buffer + 80; + uint32_t faceCount( 0 ); + ::memcpy( &faceCount, facecount_pos, sizeof( uint32_t ) ); const uint32_t expectedBinaryFileSize = faceCount * 50 + 84; return expectedBinaryFileSize == fileSize; @@ -198,42 +203,37 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS if (IsBinarySTL(mBuffer, fileSize)) { bMatClr = LoadBinaryFile(); } else if (IsAsciiSTL(mBuffer, fileSize)) { - LoadASCIIFile(); + LoadASCIIFile( pScene->mRootNode ); } else { throw DeadlyImportError( "Failed to determine STL storage representation for " + pFile + "."); } - // add all created meshes to the single node - pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; - pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; - for (unsigned int i = 0; i < pScene->mNumMeshes; i++) - pScene->mRootNode->mMeshes[i] = i; - - // create a single default material, using a light gray diffuse color for consistency with + // create a single default material, using a white diffuse color for consistency with // other geometric types (e.g., PLY). aiMaterial* pcMat = new aiMaterial(); aiString s; s.Set(AI_DEFAULT_MATERIAL_NAME); pcMat->AddProperty(&s, AI_MATKEY_NAME); - aiColor4D clrDiffuse(ai_real(0.6),ai_real(0.6),ai_real(0.6),ai_real(1.0)); + aiColor4D clrDiffuse(ai_real(1.0),ai_real(1.0),ai_real(1.0),ai_real(1.0)); if (bMatClr) { clrDiffuse = clrColorDefault; } pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE); pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR); - clrDiffuse = aiColor4D( ai_real( 0.05), ai_real( 0.05), ai_real( 0.05), ai_real( 1.0)); + clrDiffuse = aiColor4D( ai_real(1.0), ai_real(1.0), ai_real(1.0), ai_real(1.0)); pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT); pScene->mNumMaterials = 1; pScene->mMaterials = new aiMaterial*[1]; pScene->mMaterials[0] = pcMat; } + // ------------------------------------------------------------------------------------------------ // Read an ASCII STL file -void STLImporter::LoadASCIIFile() -{ +void STLImporter::LoadASCIIFile( aiNode *root ) { std::vector meshes; + std::vector nodes; const char* sz = mBuffer; const char* bufferEnd = mBuffer + fileSize; std::vector positionBuffer; @@ -245,12 +245,15 @@ void STLImporter::LoadASCIIFile() positionBuffer.reserve(sizeEstimate); normalBuffer.reserve(sizeEstimate); - while (IsAsciiSTL(sz, static_cast(bufferEnd - sz))) - { + while (IsAsciiSTL(sz, static_cast(bufferEnd - sz))) { + std::vector meshIndices; aiMesh* pMesh = new aiMesh(); pMesh->mMaterialIndex = 0; + meshIndices.push_back((unsigned int) meshes.size() ); meshes.push_back(pMesh); - + aiNode *node = new aiNode; + node->mParent = root; + nodes.push_back( node ); SkipSpaces(&sz); ai_assert(!IsLineEnd(sz)); @@ -263,20 +266,21 @@ void STLImporter::LoadASCIIFile() size_t temp; // setup the name of the node - if ((temp = (size_t)(sz-szMe))) { + if ((temp = (size_t)(sz-szMe))) { if (temp >= MAXLEN) { throw DeadlyImportError( "STL: Node name too long" ); } - - pScene->mRootNode->mName.length = temp; - memcpy(pScene->mRootNode->mName.data,szMe,temp); - pScene->mRootNode->mName.data[temp] = '\0'; + std::string name( szMe, temp ); + node->mName.Set( name.c_str() ); + //pScene->mRootNode->mName.length = temp; + //memcpy(pScene->mRootNode->mName.data,szMe,temp); + //pScene->mRootNode->mName.data[temp] = '\0'; + } else { + pScene->mRootNode->mName.Set(""); } - else pScene->mRootNode->mName.Set(""); unsigned int faceVertexCounter = 3; - for ( ;; ) - { + for ( ;; ) { // go to the next token if(!SkipSpacesAndLineEnd(&sz)) { @@ -298,9 +302,7 @@ void STLImporter::LoadASCIIFile() SkipSpaces(&sz); if (strncmp(sz,"normal",6)) { DefaultLogger::get()->warn("STL: a facet normal vector was expected but not found"); - } - else - { + } else { if (sz[6] == '\0') { throw DeadlyImportError("STL: unexpected EOF while parsing facet"); } @@ -314,16 +316,11 @@ void STLImporter::LoadASCIIFile() normalBuffer.push_back(*vn); normalBuffer.push_back(*vn); } - } - // vertex 1.50000 1.50000 0.00000 - else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6))) - { + } else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6))) { // vertex 1.50000 1.50000 0.00000 if (faceVertexCounter >= 3) { DefaultLogger::get()->error("STL: a facet with more than 3 vertices has been found"); ++sz; - } - else - { + } else { if (sz[6] == '\0') { throw DeadlyImportError("STL: unexpected EOF while parsing facet"); } @@ -338,17 +335,14 @@ void STLImporter::LoadASCIIFile() sz = fast_atoreal_move(sz, (ai_real&)vn->z ); faceVertexCounter++; } - } - else if (!::strncmp(sz,"endsolid",8)) { + } else if (!::strncmp(sz,"endsolid",8)) { do { ++sz; } while (!::IsLineEnd(*sz)); SkipSpacesAndLineEnd(&sz); // finished! break; - } - // else skip the whole identifier - else { + } else { // else skip the whole identifier do { ++sz; } while (!::IsSpaceOrNewLine(*sz)); @@ -378,13 +372,22 @@ void STLImporter::LoadASCIIFile() // now copy faces addFacesToMesh(pMesh); + + // assign the meshes to the current node + pushMeshesToNode( meshIndices, node ); } + // now add the loaded meshes pScene->mNumMeshes = (unsigned int)meshes.size(); pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - for (size_t i = 0; i < meshes.size(); i++) - { - pScene->mMeshes[i] = meshes[i]; + for (size_t i = 0; i < meshes.size(); i++) { + pScene->mMeshes[ i ] = meshes[i]; + } + + root->mNumChildren = (unsigned int) nodes.size(); + root->mChildren = new aiNode*[ root->mNumChildren ]; + for ( size_t i=0; imChildren[ i ] = nodes[ i ]; } } @@ -503,6 +506,12 @@ bool STLImporter::LoadBinaryFile() // now copy faces addFacesToMesh(pMesh); + // add all created meshes to the single node + pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; + pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; + for (unsigned int i = 0; i < pScene->mNumMeshes; i++) + pScene->mRootNode->mMeshes[i] = i; + if (bIsMaterialise && !pMesh->mColors[0]) { // use the color as diffuse material color @@ -511,4 +520,18 @@ bool STLImporter::LoadBinaryFile() return false; } +void STLImporter::pushMeshesToNode( std::vector &meshIndices, aiNode *node ) { + ai_assert( nullptr != node ); + if ( meshIndices.empty() ) { + return; + } + + node->mNumMeshes = static_cast( meshIndices.size() ); + node->mMeshes = new unsigned int[ meshIndices.size() ]; + for ( size_t i=0; imMeshes[ i ] = meshIndices[ i ]; + } + meshIndices.clear(); +} + #endif // !! ASSIMP_BUILD_NO_STL_IMPORTER diff --git a/code/STLLoader.h b/code/STLLoader.h index a0d82dbe8..c51604861 100644 --- a/code/STLLoader.h +++ b/code/STLLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -47,53 +48,61 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BaseImporter.h" #include -namespace Assimp { +// Forward declarations +struct aiNode; + +namespace Assimp { + // --------------------------------------------------------------------------- -/** Importer class for the sterolithography STL file format -*/ -class STLImporter : public BaseImporter -{ +/** + * @brief Importer class for the sterolithography STL file format. + */ +class STLImporter : public BaseImporter { public: + /** + * @brief STLImporter, the class default constructor. + */ STLImporter(); + + /** + * @brief The class destructor. + */ ~STLImporter(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. + /** + * @brief Returns whether the class can handle the format of the given file. + * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; + bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const; protected: - // ------------------------------------------------------------------- - /** Return importer meta information. - * See #BaseImporter::GetInfo for the details + /** + * @brief Return importer meta information. + * See #BaseImporter::GetInfo for the details */ const aiImporterDesc* GetInfo () const; - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. + /** + * @brief Imports the given file into the given scene structure. * See BaseImporter::InternReadFile() for details */ void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); - - // ------------------------------------------------------------------- - /** Loads a binary .stl file + /** + * @brief Loads a binary .stl file * @return true if the default vertex color must be used as material color - */ + */ bool LoadBinaryFile(); - // ------------------------------------------------------------------- - /** Loads a ASCII text .stl file - */ - void LoadASCIIFile(); + /** + * @brief Loads a ASCII text .stl file + */ + void LoadASCIIFile( aiNode *root ); + + void pushMeshesToNode( std::vector &meshIndices, aiNode *node ); protected: diff --git a/code/ScaleProcess.cpp b/code/ScaleProcess.cpp new file mode 100644 index 000000000..ada978e82 --- /dev/null +++ b/code/ScaleProcess.cpp @@ -0,0 +1,105 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ +#include "ScaleProcess.h" + +#include +#include + +namespace Assimp { + +ScaleProcess::ScaleProcess() +: BaseProcess() +, mScale( AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT ) { + // empty +} + +ScaleProcess::~ScaleProcess() { + // empty +} + +void ScaleProcess::setScale( ai_real scale ) { + mScale = scale; +} + +ai_real ScaleProcess::getScale() const { + return mScale; +} + +bool ScaleProcess::IsActive( unsigned int pFlags ) const { + return ( pFlags & aiProcess_GlobalScale ) != 0; +} + +void ScaleProcess::SetupProperties( const Importer* pImp ) { + mScale = pImp->GetPropertyFloat( AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY, 0 ); +} + +void ScaleProcess::Execute( aiScene* pScene ) { + if ( nullptr == pScene ) { + return; + } + + if ( nullptr == pScene->mRootNode ) { + return; + } + + traverseNodes( pScene->mRootNode ); +} + +void ScaleProcess::traverseNodes( aiNode *node ) { + applyScaling( node ); + + /*for ( unsigned int i = 0; i < node->mNumChildren; ++i ) { + aiNode *currentNode = currentNode->mChildren[ i ]; + if ( nullptr != currentNode ) { + traverseNodes( currentNode ); + } + }*/ +} + +void ScaleProcess::applyScaling( aiNode *currentNode ) { + if ( nullptr != currentNode ) { + currentNode->mTransformation.a1 = currentNode->mTransformation.a1 * mScale; + currentNode->mTransformation.b2 = currentNode->mTransformation.b2 * mScale; + currentNode->mTransformation.c3 = currentNode->mTransformation.c3 * mScale; + } +} + +} // Namespace Assimp diff --git a/code/ScaleProcess.h b/code/ScaleProcess.h new file mode 100644 index 000000000..7eb91fd5c --- /dev/null +++ b/code/ScaleProcess.h @@ -0,0 +1,87 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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. + +---------------------------------------------------------------------- +*/ +#pragma once + +#include "BaseProcess.h" + +struct aiNode; + +#if (!defined AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT) +# define AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT 1.0f +#endif // !! AI_DEBONE_THRESHOLD + +namespace Assimp { + +// --------------------------------------------------------------------------- +/** ScaleProcess: Class to rescale the whole model. +*/ +class ASSIMP_API ScaleProcess : public BaseProcess { +public: + /// The default class constructor. + ScaleProcess(); + + /// The class destructor. + virtual ~ScaleProcess(); + + /// Will set the scale manually. + void setScale( ai_real scale ); + + /// Returns the current scaling value. + ai_real getScale() const; + + /// Overwritten, @see BaseProcess + virtual bool IsActive( unsigned int pFlags ) const; + + /// Overwritten, @see BaseProcess + virtual void SetupProperties( const Importer* pImp ); + + /// Overwritten, @see BaseProcess + virtual void Execute( aiScene* pScene ); + +private: + void traverseNodes( aiNode *currentNode ); + void applyScaling( aiNode *currentNode ); + +private: + ai_real mScale; +}; + +} // Namespace Assimp diff --git a/code/SceneCombiner.cpp b/code/SceneCombiner.cpp index a4f832e8f..4b77bb2db 100644 --- a/code/SceneCombiner.cpp +++ b/code/SceneCombiner.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -50,13 +51,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OptimizeGraph step. */ // ---------------------------------------------------------------------------- -#include "SceneCombiner.h" +#include #include "StringUtils.h" #include "fast_atof.h" #include "Hash.h" #include "time.h" #include #include +#include #include #include "ScenePrivate.h" @@ -64,8 +66,8 @@ namespace Assimp { // ------------------------------------------------------------------------------------------------ // Add a prefix to a string -inline void PrefixString(aiString& string,const char* prefix, unsigned int len) -{ +inline +void PrefixString(aiString& string,const char* prefix, unsigned int len) { // If the string is already prefixed, we won't prefix it a second time if (string.length >= 1 && string.data[0] == '$') return; @@ -86,8 +88,7 @@ inline void PrefixString(aiString& string,const char* prefix, unsigned int len) // ------------------------------------------------------------------------------------------------ // Add node identifiers to a hashing set -void SceneCombiner::AddNodeHashes(aiNode* node, std::set& hashes) -{ +void SceneCombiner::AddNodeHashes(aiNode* node, std::set& hashes) { // Add node name to hashing set if it is non-empty - empty nodes are allowed // and they can't have any anims assigned so its absolutely safe to duplicate them. if (node->mName.length) { @@ -101,25 +102,23 @@ void SceneCombiner::AddNodeHashes(aiNode* node, std::set& hashes) // ------------------------------------------------------------------------------------------------ // Add a name prefix to all nodes in a hierarchy -void SceneCombiner::AddNodePrefixes(aiNode* node, const char* prefix, unsigned int len) -{ +void SceneCombiner::AddNodePrefixes(aiNode* node, const char* prefix, unsigned int len) { ai_assert(NULL != prefix); PrefixString(node->mName,prefix,len); // Process all children recursively - for (unsigned int i = 0; i < node->mNumChildren;++i) - AddNodePrefixes(node->mChildren[i],prefix,len); + for ( unsigned int i = 0; i < node->mNumChildren; ++i ) { + AddNodePrefixes( node->mChildren[ i ], prefix, len ); + } } // ------------------------------------------------------------------------------------------------ // Search for matching names -bool SceneCombiner::FindNameMatch(const aiString& name, std::vector& input, unsigned int cur) -{ +bool SceneCombiner::FindNameMatch(const aiString& name, std::vector& input, unsigned int cur) { const unsigned int hash = SuperFastHash(name.data, static_cast(name.length)); // Check whether we find a positive match in one of the given sets for (unsigned int i = 0; i < input.size(); ++i) { - if (cur != i && input[i].hashes.find(hash) != input[i].hashes.end()) { return true; } @@ -130,14 +129,12 @@ bool SceneCombiner::FindNameMatch(const aiString& name, std::vector // ------------------------------------------------------------------------------------------------ // Add a name prefix to all nodes in a hierarchy if a hash match is found void SceneCombiner::AddNodePrefixesChecked(aiNode* node, const char* prefix, unsigned int len, - std::vector& input, unsigned int cur) -{ + std::vector& input, unsigned int cur) { ai_assert(NULL != prefix); const unsigned int hash = SuperFastHash(node->mName.data, static_cast(node->mName.length)); // Check whether we find a positive match in one of the given sets for (unsigned int i = 0; i < input.size(); ++i) { - if (cur != i && input[i].hashes.find(hash) != input[i].hashes.end()) { PrefixString(node->mName,prefix,len); break; @@ -151,27 +148,25 @@ void SceneCombiner::AddNodePrefixesChecked(aiNode* node, const char* prefix, uns // ------------------------------------------------------------------------------------------------ // Add an offset to all mesh indices in a node graph -void SceneCombiner::OffsetNodeMeshIndices (aiNode* node, unsigned int offset) -{ +void SceneCombiner::OffsetNodeMeshIndices (aiNode* node, unsigned int offset) { for (unsigned int i = 0; i < node->mNumMeshes;++i) node->mMeshes[i] += offset; - for (unsigned int i = 0; i < node->mNumChildren;++i) - OffsetNodeMeshIndices(node->mChildren[i],offset); + for ( unsigned int i = 0; i < node->mNumChildren; ++i ) { + OffsetNodeMeshIndices( node->mChildren[ i ], offset ); + } } // ------------------------------------------------------------------------------------------------ // Merges two scenes. Currently only used by the LWS loader. -void SceneCombiner::MergeScenes(aiScene** _dest,std::vector& src, - unsigned int flags) -{ - ai_assert(NULL != _dest); +void SceneCombiner::MergeScenes(aiScene** _dest,std::vector& src, unsigned int flags) { + if ( nullptr == _dest ) { + return; + } // if _dest points to NULL allocate a new scene. Otherwise clear the old and reuse it - if (src.empty()) - { - if (*_dest) - { + if (src.empty()) { + if (*_dest) { (*_dest)->~aiScene(); SceneCombiner::CopySceneFlat(_dest,src[0]); } @@ -196,8 +191,7 @@ void SceneCombiner::MergeScenes(aiScene** _dest,std::vector& src, } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::AttachToGraph (aiNode* attach, std::vector& srcList) -{ +void SceneCombiner::AttachToGraph (aiNode* attach, std::vector& srcList) { unsigned int cnt; for ( cnt = 0; cnt < attach->mNumChildren; ++cnt ) { AttachToGraph( attach->mChildren[ cnt ], srcList ); @@ -237,19 +231,16 @@ void SceneCombiner::AttachToGraph (aiNode* attach, std::vector& src) -{ +void SceneCombiner::AttachToGraph ( aiScene* master, std::vector& src) { ai_assert(NULL != master); AttachToGraph(master->mRootNode,src); } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master, - std::vector& srcList, - unsigned int flags) -{ - ai_assert(NULL != _dest); +void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master, std::vector& srcList, unsigned int flags) { + if ( nullptr == _dest ) { + return; + } // if _dest points to NULL allocate a new scene. Otherwise clear the old and reuse it if (srcList.empty()) { @@ -706,7 +697,9 @@ void SceneCombiner::BuildUniqueBoneList(std::list& asBones, void SceneCombiner::MergeBones(aiMesh* out,std::vector::const_iterator it, std::vector::const_iterator end) { - ai_assert(NULL != out && !out->mNumBones); + if ( nullptr == out || out->mNumBones == 0 ) { + return; + } // find we need to build an unique list of all bones. // we work with hashes to make the comparisons MUCH faster, @@ -756,11 +749,13 @@ void SceneCombiner::MergeBones(aiMesh* out,std::vector::const_iterator // ------------------------------------------------------------------------------------------------ // Merge a list of meshes -void SceneCombiner::MergeMeshes(aiMesh** _out,unsigned int /*flags*/, +void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/, std::vector::const_iterator begin, std::vector::const_iterator end) { - ai_assert(NULL != _out); + if ( nullptr == _out ) { + return; + } if (begin == end) { *_out = NULL; // no meshes ... @@ -771,8 +766,14 @@ void SceneCombiner::MergeMeshes(aiMesh** _out,unsigned int /*flags*/, aiMesh* out = *_out = new aiMesh(); out->mMaterialIndex = (*begin)->mMaterialIndex; + std::string name; // Find out how much output storage we'll need - for (std::vector::const_iterator it = begin; it != end;++it) { + for (std::vector::const_iterator it = begin; it != end; ++it) { + const char *meshName( (*it)->mName.C_Str() ); + name += std::string( meshName ); + if ( it != end - 1 ) { + name += "."; + } out->mNumVertices += (*it)->mNumVertices; out->mNumFaces += (*it)->mNumFaces; out->mNumBones += (*it)->mNumBones; @@ -780,6 +781,7 @@ void SceneCombiner::MergeMeshes(aiMesh** _out,unsigned int /*flags*/, // combine primitive type flags out->mPrimitiveTypes |= (*it)->mPrimitiveTypes; } + out->mName.Set( name.c_str() ); if (out->mNumVertices) { aiVector3D* pv2; @@ -788,7 +790,7 @@ void SceneCombiner::MergeMeshes(aiMesh** _out,unsigned int /*flags*/, if ((**begin).HasPositions()) { pv2 = out->mVertices = new aiVector3D[out->mNumVertices]; - for (std::vector::const_iterator it = begin; it != end;++it) { + for (std::vector::const_iterator it = begin; it != end; ++it) { if ((*it)->mVertices) { ::memcpy(pv2,(*it)->mVertices,(*it)->mNumVertices*sizeof(aiVector3D)); } @@ -808,7 +810,7 @@ void SceneCombiner::MergeMeshes(aiMesh** _out,unsigned int /*flags*/, pv2 += (*it)->mNumVertices; } } - // copy tangents and bitangents + // copy tangents and bi-tangents if ((**begin).HasTangentsAndBitangents()) { pv2 = out->mTangents = new aiVector3D[out->mNumVertices]; @@ -894,7 +896,9 @@ void SceneCombiner::MergeMaterials(aiMaterial** dest, std::vector::const_iterator begin, std::vector::const_iterator end) { - ai_assert(NULL != dest); + if ( nullptr == dest ) { + return; + } if (begin == end) { *dest = NULL; // no materials ... @@ -944,10 +948,9 @@ void SceneCombiner::MergeMaterials(aiMaterial** dest, // ------------------------------------------------------------------------------------------------ template -inline void CopyPtrArray (Type**& dest, const Type* const * src, ai_uint num) -{ - if (!num) - { +inline +void CopyPtrArray (Type**& dest, const Type* const * src, ai_uint num) { + if (!num) { dest = NULL; return; } @@ -959,9 +962,11 @@ inline void CopyPtrArray (Type**& dest, const Type* const * src, ai_uint num) // ------------------------------------------------------------------------------------------------ template -inline void GetArrayCopy (Type*& dest, ai_uint num ) -{ - if (!dest)return; +inline +void GetArrayCopy(Type*& dest, ai_uint num ) { + if ( !dest ) { + return; + } Type* old = dest; dest = new Type[num]; @@ -969,22 +974,27 @@ inline void GetArrayCopy (Type*& dest, ai_uint num ) } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::CopySceneFlat(aiScene** _dest,const aiScene* src) -{ +void SceneCombiner::CopySceneFlat(aiScene** _dest,const aiScene* src) { + if ( nullptr == _dest || nullptr == src ) { + return; + } + // reuse the old scene or allocate a new? if (*_dest) { (*_dest)->~aiScene(); new (*_dest) aiScene(); + } else { + *_dest = new aiScene(); } - else *_dest = new aiScene(); ::memcpy(*_dest,src,sizeof(aiScene)); } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::CopyScene(aiScene** _dest,const aiScene* src,bool allocate) -{ - ai_assert(NULL != _dest && NULL != src); +void SceneCombiner::CopyScene(aiScene** _dest,const aiScene* src,bool allocate) { + if ( nullptr == _dest || nullptr == src ) { + return; + } if (allocate) { *_dest = new aiScene(); @@ -1035,9 +1045,10 @@ void SceneCombiner::CopyScene(aiScene** _dest,const aiScene* src,bool allocate) } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy (aiMesh** _dest, const aiMesh* src) -{ - ai_assert(NULL != _dest && NULL != src); +void SceneCombiner::Copy( aiMesh** _dest, const aiMesh* src ) { + if ( nullptr == _dest || nullptr == src ) { + return; + } aiMesh* dest = *_dest = new aiMesh(); @@ -1063,17 +1074,17 @@ void SceneCombiner::Copy (aiMesh** _dest, const aiMesh* src) // make a deep copy of all faces GetArrayCopy(dest->mFaces,dest->mNumFaces); - for (unsigned int i = 0; i < dest->mNumFaces;++i) - { + for (unsigned int i = 0; i < dest->mNumFaces;++i) { aiFace& f = dest->mFaces[i]; GetArrayCopy(f.mIndices,f.mNumIndices); } } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy (aiMaterial** _dest, const aiMaterial* src) -{ - ai_assert(NULL != _dest && NULL != src); +void SceneCombiner::Copy (aiMaterial** _dest, const aiMaterial* src) { + if ( nullptr == _dest || nullptr == src ) { + return; + } aiMaterial* dest = (aiMaterial*) ( *_dest = new aiMaterial() ); @@ -1101,9 +1112,10 @@ void SceneCombiner::Copy (aiMaterial** _dest, const aiMaterial* src) } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy (aiTexture** _dest, const aiTexture* src) -{ - ai_assert(NULL != _dest && NULL != src); +void SceneCombiner::Copy(aiTexture** _dest, const aiTexture* src) { + if ( nullptr == _dest || nullptr == src ) { + return; + } aiTexture* dest = *_dest = new aiTexture(); @@ -1130,10 +1142,10 @@ void SceneCombiner::Copy (aiTexture** _dest, const aiTexture* src) } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy( aiAnimation** _dest, const aiAnimation* src ) -{ - ai_assert( NULL != _dest ); - ai_assert( NULL != src ); +void SceneCombiner::Copy( aiAnimation** _dest, const aiAnimation* src ) { + if ( nullptr == _dest || nullptr == src ) { + return; + } aiAnimation* dest = *_dest = new aiAnimation(); @@ -1145,9 +1157,10 @@ void SceneCombiner::Copy( aiAnimation** _dest, const aiAnimation* src ) } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy (aiNodeAnim** _dest, const aiNodeAnim* src) -{ - ai_assert(NULL != _dest && NULL != src); +void SceneCombiner::Copy(aiNodeAnim** _dest, const aiNodeAnim* src) { + if ( nullptr == _dest || nullptr == src ) { + return; + } aiNodeAnim* dest = *_dest = new aiNodeAnim(); @@ -1161,9 +1174,10 @@ void SceneCombiner::Copy (aiNodeAnim** _dest, const aiNodeAnim* src) } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy (aiCamera** _dest,const aiCamera* src) -{ - ai_assert(NULL != _dest && NULL != src); +void SceneCombiner::Copy( aiCamera** _dest,const aiCamera* src) { + if ( nullptr == _dest || nullptr == src ) { + return; + } aiCamera* dest = *_dest = new aiCamera(); @@ -1172,9 +1186,10 @@ void SceneCombiner::Copy (aiCamera** _dest,const aiCamera* src) } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy (aiLight** _dest, const aiLight* src) -{ - ai_assert(NULL != _dest && NULL != src); +void SceneCombiner::Copy(aiLight** _dest, const aiLight* src) { + if ( nullptr == _dest || nullptr == src ) { + return; + } aiLight* dest = *_dest = new aiLight(); @@ -1183,9 +1198,10 @@ void SceneCombiner::Copy (aiLight** _dest, const aiLight* src) } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy (aiBone** _dest, const aiBone* src) -{ - ai_assert(NULL != _dest && NULL != src); +void SceneCombiner::Copy(aiBone** _dest, const aiBone* src) { + if ( nullptr == _dest || nullptr == src ) { + return; + } aiBone* dest = *_dest = new aiBone(); @@ -1221,10 +1237,14 @@ void SceneCombiner::Copy (aiNode** _dest, const aiNode* src) } // ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy(aiMetadata** _dest, const aiMetadata* src) -{ - ai_assert( NULL != _dest ); - ai_assert( NULL != src); +void SceneCombiner::Copy(aiMetadata** _dest, const aiMetadata* src) { + if ( nullptr == _dest || nullptr == src ) { + return; + } + + if ( 0 == src->mNumProperties ) { + return; + } aiMetadata* dest = *_dest = aiMetadata::Alloc( src->mNumProperties ); std::copy(src->mKeys, src->mKeys + src->mNumProperties, dest->mKeys); @@ -1262,4 +1282,5 @@ void SceneCombiner::Copy(aiMetadata** _dest, const aiMetadata* src) } } -} +} // Namespace Assimp + diff --git a/code/ScenePreprocessor.cpp b/code/ScenePreprocessor.cpp index 327da0b35..0a6366b7d 100644 --- a/code/ScenePreprocessor.cpp +++ b/code/ScenePreprocessor.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/ScenePreprocessor.h b/code/ScenePreprocessor.h index 9c4b422a2..3311036c3 100644 --- a/code/ScenePreprocessor.h +++ b/code/ScenePreprocessor.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/ScenePrivate.h b/code/ScenePrivate.h index dd4d0a5e1..90d34bade 100644 --- a/code/ScenePrivate.h +++ b/code/ScenePrivate.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/SkeletonMeshBuilder.cpp b/code/SkeletonMeshBuilder.cpp index c01b575da..e9f427113 100644 --- a/code/SkeletonMeshBuilder.cpp +++ b/code/SkeletonMeshBuilder.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/SkeletonMeshBuilder.h b/code/SkeletonMeshBuilder.h index 3c518e8cd..7a7e7b8ff 100644 --- a/code/SkeletonMeshBuilder.h +++ b/code/SkeletonMeshBuilder.h @@ -4,7 +4,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/SmoothingGroups.h b/code/SmoothingGroups.h index 75c59d1cb..7a7e2e429 100644 --- a/code/SmoothingGroups.h +++ b/code/SmoothingGroups.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/SortByPTypeProcess.cpp b/code/SortByPTypeProcess.cpp index 74867184a..e4b314e02 100644 --- a/code/SortByPTypeProcess.cpp +++ b/code/SortByPTypeProcess.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/SortByPTypeProcess.h b/code/SortByPTypeProcess.h index f96985cb3..0be7925ff 100644 --- a/code/SortByPTypeProcess.h +++ b/code/SortByPTypeProcess.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/SpatialSort.cpp b/code/SpatialSort.cpp index e7d64fec5..35724c2cd 100644 --- a/code/SpatialSort.cpp +++ b/code/SpatialSort.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -125,9 +126,8 @@ void SpatialSort::FindPositions( const aiVector3D& pPosition, const ai_real dist = pPosition * mPlaneNormal; const ai_real minDist = dist - pRadius, maxDist = dist + pRadius; - // clear the array in this strange fashion because a simple clear() would also deallocate - // the array which we want to avoid - poResults.erase( poResults.begin(), poResults.end()); + // clear the array + poResults.clear(); // quick check for positions outside the range if( mPositions.size() == 0) @@ -245,7 +245,7 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition, // The best way to overcome this is the unit in the last place (ULP). A precision of 2 ULPs // tells us that a float does not differ more than 2 bits from the "real" value. ULPs are of - // logarithmic precision - around 1, they are 1�(2^24) and around 10000, they are 0.00125. + // logarithmic precision - around 1, they are 1*(2^24) and around 10000, they are 0.00125. // For standard C math, we can assume a precision of 0.5 ULPs according to IEEE 754. The // incoming vertex positions might have already been transformed, probably using rather @@ -269,7 +269,7 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition, // clear the array in this strange fashion because a simple clear() would also deallocate // the array which we want to avoid - poResults.erase( poResults.begin(), poResults.end()); + poResults.resize( 0 ); // do a binary search for the minimal distance to start the iteration there unsigned int index = (unsigned int)mPositions.size() / 2; diff --git a/code/SpatialSort.h b/code/SpatialSort.h index 367e0f6a6..36b7a2767 100644 --- a/code/SpatialSort.h +++ b/code/SpatialSort.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/SplitByBoneCountProcess.cpp b/code/SplitByBoneCountProcess.cpp index 4d01bf0ee..a73dfe81e 100644 --- a/code/SplitByBoneCountProcess.cpp +++ b/code/SplitByBoneCountProcess.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/SplitByBoneCountProcess.h b/code/SplitByBoneCountProcess.h index 816d18357..434ef9866 100644 --- a/code/SplitByBoneCountProcess.h +++ b/code/SplitByBoneCountProcess.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/SplitLargeMeshes.cpp b/code/SplitLargeMeshes.cpp index 5e21ec6b8..2066f7989 100644 --- a/code/SplitLargeMeshes.cpp +++ b/code/SplitLargeMeshes.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/SplitLargeMeshes.h b/code/SplitLargeMeshes.h index 9be27a8f1..7556e9fe8 100644 --- a/code/SplitLargeMeshes.h +++ b/code/SplitLargeMeshes.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/StandardShapes.cpp b/code/StandardShapes.cpp index eed8ddabc..4346a8d76 100644 --- a/code/StandardShapes.cpp +++ b/code/StandardShapes.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -47,8 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "StandardShapes.h" #include "StringComparison.h" -#include "Defines.h" #include +#include #include namespace Assimp { diff --git a/code/StandardShapes.h b/code/StandardShapes.h index faa250a2e..a31de566c 100644 --- a/code/StandardShapes.h +++ b/code/StandardShapes.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/StdOStreamLogStream.h b/code/StdOStreamLogStream.h index 249e30458..d9993b246 100644 --- a/code/StdOStreamLogStream.h +++ b/code/StdOStreamLogStream.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/StepExporter.cpp b/code/StepExporter.cpp index eb84ac594..acf1b6dad 100644 --- a/code/StepExporter.cpp +++ b/code/StepExporter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -42,13 +43,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_STEP_EXPORTER + #include "StepExporter.h" #include "ConvertToLHProcess.h" #include "Bitmap.h" #include "BaseImporter.h" #include "fast_atof.h" -#include "SceneCombiner.h" -#include "DefaultIOSystem.h" +#include #include #include #include @@ -56,6 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "Exceptional.h" +#include #include #include #include diff --git a/code/StepExporter.h b/code/StepExporter.h index b51280c6c..e5cdda7a1 100644 --- a/code/StepExporter.h +++ b/code/StepExporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/StreamReader.h b/code/StreamReader.h index 89367494a..6220de9a8 100644 --- a/code/StreamReader.h +++ b/code/StreamReader.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -50,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Exceptional.h" #include #include -#include "Defines.h" +#include namespace Assimp { @@ -243,7 +244,7 @@ public: * * @param limit Maximum number of bytes to be read from * the beginning of the file. Specifying UINT_MAX - * resets the limit to the original end of the stream. + * resets the limit to the original end of the stream. * Returns the previously set limit. */ unsigned int SetReadLimit(unsigned int _limit) { unsigned int prev = GetReadLimit(); @@ -290,15 +291,11 @@ private: throw DeadlyImportError("End of file or stream limit was reached"); } -#ifdef __arm__ T f; ::memcpy (&f, current, sizeof(T)); -#else - T f = *((const T*)current); -#endif - Intern :: Getter() (&f,le); - + Intern::Getter() (&f,le); current += sizeof(T); + return f; } diff --git a/code/StreamWriter.h b/code/StreamWriter.h index 12239bf7f..26873fb5b 100644 --- a/code/StreamWriter.h +++ b/code/StreamWriter.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/StringComparison.h b/code/StringComparison.h index 0e1dbe4b8..ed5f4bd6a 100644 --- a/code/StringComparison.h +++ b/code/StringComparison.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -56,7 +57,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include namespace Assimp { diff --git a/code/StringUtils.h b/code/StringUtils.h index 15f7db2e7..64f66e6b9 100644 --- a/code/StringUtils.h +++ b/code/StringUtils.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -40,12 +41,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INCLUDED_AI_STRINGUTILS_H #define INCLUDED_AI_STRINGUTILS_H -#include -#include -#include -#include #include -#include +#include +#include /// @fn ai_snprintf /// @brief The portable version of the function snprintf ( C99 standard ), which works on visual studio compilers 2013 and earlier. diff --git a/code/Subdivision.cpp b/code/Subdivision.cpp index eafb3ebd1..bc5292dbe 100644 --- a/code/Subdivision.cpp +++ b/code/Subdivision.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -39,7 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "Subdivision.h" -#include "SceneCombiner.h" +#include #include "SpatialSort.h" #include "ProcessHelper.h" #include "Vertex.h" @@ -532,9 +533,7 @@ void CatmullClarkSubdivider::InternSubdivide ( ai_assert(adj[o]-moffsets[nidx].first < mp->mNumFaces); const aiFace& f = mp->mFaces[adj[o]-moffsets[nidx].first]; -# ifdef ASSIMP_BUILD_DEBUG bool haveit = false; -# endif // find our original point in the face for (unsigned int m = 0; m < f.mNumIndices; ++m) { @@ -555,15 +554,16 @@ void CatmullClarkSubdivider::InternSubdivide ( // fixme: replace with mod face.mNumIndices? R += c0.midpoint+c1.midpoint; -# ifdef ASSIMP_BUILD_DEBUG haveit = true; -# endif break; } } // this invariant *must* hold if the vertex-to-face adjacency table is valid ai_assert(haveit); + if ( !haveit ) { + DefaultLogger::get()->warn( "OBJ: no name for material library specified." ); + } } const float div = static_cast(cnt), divsq = 1.f/(div*div); diff --git a/code/Subdivision.h b/code/Subdivision.h index 658640f55..d06bc09d6 100644 --- a/code/Subdivision.h +++ b/code/Subdivision.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -39,10 +40,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file Defines a helper class to evaluate subdivision surfaces.*/ +#pragma once #ifndef AI_SUBDISIVION_H_INC #define AI_SUBDISIVION_H_INC #include +#include + struct aiMesh; namespace Assimp { @@ -51,8 +55,7 @@ namespace Assimp { /** Helper class to evaluate subdivision surfaces. Different algorithms * are provided for choice. */ // ------------------------------------------------------------------------------ -class Subdivider -{ +class ASSIMP_API Subdivider { public: /** Enumerates all supported subvidision algorithms */ @@ -60,12 +63,7 @@ public: CATMULL_CLARKE = 0x1 }; -public: - - virtual ~Subdivider() { - } - -public: + virtual ~Subdivider(); // --------------------------------------------------------------- /** Create a subdivider of a specific type @@ -118,9 +116,13 @@ public: unsigned int num, bool discard_input = false) = 0; -private: }; +inline +Subdivider::~Subdivider() { + // empty +} + } // end namespace Assimp diff --git a/code/TargetAnimation.cpp b/code/TargetAnimation.cpp index ecf6f0dcf..ab6b3d12f 100644 --- a/code/TargetAnimation.cpp +++ b/code/TargetAnimation.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/TargetAnimation.h b/code/TargetAnimation.h index 79cef599e..21b66e591 100644 --- a/code/TargetAnimation.h +++ b/code/TargetAnimation.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/TerragenLoader.cpp b/code/TerragenLoader.cpp index 854959f19..0126229ac 100644 --- a/code/TerragenLoader.cpp +++ b/code/TerragenLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -51,7 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include - +#include using namespace Assimp; @@ -140,9 +141,6 @@ void TerragenImporter::InternReadFile( const std::string& pFile, throw DeadlyImportError( "TER: Magic string \'TERRAIN\' not found" ); unsigned int x = 0,y = 0,mode = 0; - float rad = 6370.f; - (void)rad; - aiNode* root = pScene->mRootNode = new aiNode(); root->mName.Set(""); @@ -186,7 +184,7 @@ void TerragenImporter::InternReadFile( const std::string& pFile, // mapping == 1: earth radius else if (!::strncmp(head,AI_TERR_CHUNK_CRAD,4)) { - rad = reader.GetF4(); + reader.GetF4(); } // mapping mode else if (!::strncmp(head,AI_TERR_CHUNK_CRVM,4)) diff --git a/code/TerragenLoader.h b/code/TerragenLoader.h index c216a2186..a95bd6bff 100644 --- a/code/TerragenLoader.h +++ b/code/TerragenLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/TextureTransform.cpp b/code/TextureTransform.cpp index 948ec013b..30953113e 100644 --- a/code/TextureTransform.cpp +++ b/code/TextureTransform.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -316,7 +317,7 @@ void TextureTransformStep::Execute( aiScene* pScene) info.lockedPos = AI_TT_UV_IDX_LOCK_TBD; } - // Get all coresponding meshes + // Get all corresponding meshes for (unsigned int n = 0; n < pScene->mNumMeshes;++n) { aiMesh* mesh = pScene->mMeshes[n]; if (mesh->mMaterialIndex != i || !mesh->mTextureCoords[0]) diff --git a/code/TextureTransform.h b/code/TextureTransform.h index ccad3bdd9..7f1e4572f 100644 --- a/code/TextureTransform.h +++ b/code/TextureTransform.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/TinyFormatter.h b/code/TinyFormatter.h index 1182e3a5a..1612282fb 100644 --- a/code/TinyFormatter.h +++ b/code/TinyFormatter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/TriangulateProcess.cpp b/code/TriangulateProcess.cpp index 883a45e3d..e2d77a80f 100644 --- a/code/TriangulateProcess.cpp +++ b/code/TriangulateProcess.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/TriangulateProcess.h b/code/TriangulateProcess.h index 97b5004e1..6775eca7c 100644 --- a/code/TriangulateProcess.h +++ b/code/TriangulateProcess.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/UnrealLoader.cpp b/code/UnrealLoader.cpp index 790002235..a79a2a5c5 100644 --- a/code/UnrealLoader.cpp +++ b/code/UnrealLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -60,6 +61,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include @@ -155,7 +157,7 @@ void UnrealImporter::InternReadFile( const std::string& pFile, DefaultLogger::get()->debug("UNREAL: uc file is " + uc_path); // and open the files ... we can't live without them - IOStream* p = pIOHandler->Open(d_path); + std::unique_ptr p(pIOHandler->Open(d_path)); if (!p) throw DeadlyImportError("UNREAL: Unable to open _d file"); StreamReaderLE d_reader(pIOHandler->Open(d_path)); @@ -201,7 +203,7 @@ void UnrealImporter::InternReadFile( const std::string& pFile, d_reader.IncPtr(1); } - p = pIOHandler->Open(a_path); + p.reset(pIOHandler->Open(a_path)); if (!p) throw DeadlyImportError("UNREAL: Unable to open _a file"); StreamReaderLE a_reader(pIOHandler->Open(a_path)); diff --git a/code/UnrealLoader.h b/code/UnrealLoader.h index 93648ca82..a2ceb3d54 100644 --- a/code/UnrealLoader.h +++ b/code/UnrealLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/ValidateDataStructure.cpp b/code/ValidateDataStructure.cpp index 44e361f71..c036eac18 100644 --- a/code/ValidateDataStructure.cpp +++ b/code/ValidateDataStructure.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -88,9 +89,7 @@ AI_WONT_RETURN void ValidateDSProcess::ReportError(const char* msg,...) ai_assert(iLen > 0); va_end(args); -#ifdef ASSIMP_BUILD_DEBUG - ai_assert( false ); -#endif + throw DeadlyImportError("Validation failed: " + std::string(szBuffer,iLen)); } // ------------------------------------------------------------------------------------------------ @@ -335,28 +334,28 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh) case 1: if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POINT)) { - ReportError("aiMesh::mFaces[%i] is a POINT but aiMesh::mPrimtiveTypes " + ReportError("aiMesh::mFaces[%i] is a POINT but aiMesh::mPrimitiveTypes " "does not report the POINT flag",i); } break; case 2: if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_LINE)) { - ReportError("aiMesh::mFaces[%i] is a LINE but aiMesh::mPrimtiveTypes " + ReportError("aiMesh::mFaces[%i] is a LINE but aiMesh::mPrimitiveTypes " "does not report the LINE flag",i); } break; case 3: if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE)) { - ReportError("aiMesh::mFaces[%i] is a TRIANGLE but aiMesh::mPrimtiveTypes " + ReportError("aiMesh::mFaces[%i] is a TRIANGLE but aiMesh::mPrimitiveTypes " "does not report the TRIANGLE flag",i); } break; default: if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) { - this->ReportError("aiMesh::mFaces[%i] is a POLYGON but aiMesh::mPrimtiveTypes " + this->ReportError("aiMesh::mFaces[%i] is a POLYGON but aiMesh::mPrimitiveTypes " "does not report the POLYGON flag",i); } break; @@ -408,12 +407,12 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh) // the MSB flag is temporarily used by the extra verbose // mode to tell us that the JoinVerticesProcess might have // been executed already. - if ( !(this->mScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT ) && !(this->mScene->mFlags & AI_SCENE_FLAGS_ALLOW_SHARED) && + /*if ( !(this->mScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT ) && !(this->mScene->mFlags & AI_SCENE_FLAGS_ALLOW_SHARED) && abRefList[face.mIndices[a]]) { ReportError("aiMesh::mVertices[%i] is referenced twice - second " "time by aiMesh::mFaces[%i]::mIndices[%i]",face.mIndices[a],i,a); - } + }*/ abRefList[face.mIndices[a]] = true; } } diff --git a/code/ValidateDataStructure.h b/code/ValidateDataStructure.h index 87f158b37..084a2b083 100644 --- a/code/ValidateDataStructure.h +++ b/code/ValidateDataStructure.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -90,7 +91,7 @@ protected: // ------------------------------------------------------------------- /** Report a validation warning. This won't throw an exception, - * control will return to the callera. + * control will return to the caller. * @param msg Format string for sprintf().*/ void ReportWarning(const char* msg,...); @@ -164,7 +165,7 @@ private: inline void DoValidation(T** array, unsigned int size, const char* firstName, const char* secondName); - // extended version: checks whethr T::mName occurs twice + // extended version: checks whether T::mName occurs twice template inline void DoValidationEx(T** array, unsigned int size, const char* firstName, const char* secondName); diff --git a/code/Version.cpp b/code/Version.cpp index 556156392..fe9a2fdaa 100644 --- a/code/Version.cpp +++ b/code/Version.cpp @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team All rights reserved. @@ -41,12 +41,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Actually just a dummy, used by the compiler to build the precompiled header. -#include "./../include/assimp/version.h" -#include "./../include/assimp/scene.h" +#include +#include #include "ScenePrivate.h" -static const unsigned int MajorVersion = 3; -static const unsigned int MinorVersion = 3; +static const unsigned int MajorVersion = 4; +static const unsigned int MinorVersion = 1; // -------------------------------------------------------------------------------- // Legal information string - dont't remove this. @@ -55,7 +55,7 @@ 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-2016, assimp team\n" +"(c) 2008-2017, assimp team\n" "License under the terms and conditions of the 3-clause BSD license\n" "http://assimp.sourceforge.net\n" ; @@ -107,34 +107,32 @@ ASSIMP_API unsigned int aiGetCompileFlags () { #include "revision.h" // ------------------------------------------------------------------------------------------------ -ASSIMP_API unsigned int aiGetVersionRevision () -{ +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()) - { - } +: 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()) { + // empty +} // ------------------------------------------------------------------------------------------------ -ASSIMP_API aiScene::~aiScene() -{ +ASSIMP_API aiScene::~aiScene() { // delete all sub-objects recursively delete mRootNode; diff --git a/code/Vertex.h b/code/Vertex.h index 88840eab7..1f1685ae9 100644 --- a/code/Vertex.h +++ b/code/Vertex.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/VertexTriangleAdjacency.cpp b/code/VertexTriangleAdjacency.cpp index 6de55ab34..09c0a51a7 100644 --- a/code/VertexTriangleAdjacency.cpp +++ b/code/VertexTriangleAdjacency.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/VertexTriangleAdjacency.h b/code/VertexTriangleAdjacency.h index 218607508..ed7b83a6b 100644 --- a/code/VertexTriangleAdjacency.h +++ b/code/VertexTriangleAdjacency.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/Win32DebugLogStream.h b/code/Win32DebugLogStream.h index de8606ebc..0833712f9 100644 --- a/code/Win32DebugLogStream.h +++ b/code/Win32DebugLogStream.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/X3DExporter.cpp b/code/X3DExporter.cpp index 9e89b5b9e..b560855fb 100644 --- a/code/X3DExporter.cpp +++ b/code/X3DExporter.cpp @@ -140,7 +140,7 @@ void X3DExporter::AttrHelper_Col3DArrToString(const aiColor3D* pArray, const siz AttrHelper_CommaToPoint(pTargetString); } -void X3DExporter::AttrHelper_Color3ToAttrList(std::list pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue) +void X3DExporter::AttrHelper_Color3ToAttrList(std::list& pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue) { string tstr; @@ -150,7 +150,7 @@ string tstr; pList.push_back({pName, tstr}); } -void X3DExporter::AttrHelper_FloatToAttrList(std::list pList, const string& pName, const float pValue, const float pDefaultValue) +void X3DExporter::AttrHelper_FloatToAttrList(std::list& pList, const string& pName, const float pValue, const float pDefaultValue) { string tstr; @@ -240,8 +240,12 @@ list attr_list; if((rotate_angle != 0) && (rotate_axis.Length() > 0)) attr_list.push_back({"rotation", Rotation2String(rotate_axis, rotate_angle)}); - if(!scale.Equal({1, 1, 1})) attr_list.push_back({"scale", Vector2String(scale)}); - if(translate.Length() > 0) attr_list.push_back({"translation", Vector2String(translate)}); + if(!scale.Equal({1.0,1.0,1.0})) { + attr_list.push_back({"scale", Vector2String(scale)}); + } + if(translate.Length() > 0) { + attr_list.push_back({"translation", Vector2String(translate)}); + } } // Begin node if need. @@ -692,7 +696,7 @@ bool found = false; return true; } -X3DExporter::X3DExporter(const char* pFileName, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) +X3DExporter::X3DExporter(const char* pFileName, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/) : mScene(pScene) { list attr_list; diff --git a/code/X3DExporter.hpp b/code/X3DExporter.hpp index 20aec951b..45f302d8d 100644 --- a/code/X3DExporter.hpp +++ b/code/X3DExporter.hpp @@ -27,7 +27,7 @@ namespace Assimp /// /// Pay attention that X3D is format for interactive graphic and simulations for web browsers. aiScene can not contain all features of the X3D format. /// Also, aiScene contain rasterized-like data. For example, X3D can describe circle all cylinder with one tag, but aiScene contain result of tesselation: -/// vertices, faces etc. Yes, you can use algorithm for detecting figures or shapes, but thats not good idea at all. +/// vertices, faces etc. Yes, you can use algorithm for detecting figures or shapes, but that's not a good idea at all. /// /// Supported nodes: /// Core component: @@ -96,7 +96,7 @@ private: aiMatrix4x4 Matrix_GlobalToCurrent(const aiNode& pNode) const; /// \fn void AttrHelper_CommaToPoint(std::string& pStringWithComma) - /// Convert commas in string to points. Thats need because "std::to_string" result depend on locale (regional settings). + /// Convert commas in string to points. That's needed because "std::to_string" result depends on locale (regional settings). /// \param [in, out] pStringWithComma - reference to string, which must be modified. void AttrHelper_CommaToPoint(std::string& pStringWithComma) { for(char& c: pStringWithComma) { if(c == ',') c = '.'; } } @@ -134,7 +134,7 @@ private: /// \fn void AttrHelper_FloatToAttrList(std::list pList, const std::string& pName, const float pValue, const float pDefaultValue) /// \overload void AttrHelper_Col3DArrToString(const aiColor3D* pArray, const size_t pArray_Size, std::string& pTargetString) - void AttrHelper_FloatToAttrList(std::list pList, const std::string& pName, const float pValue, const float pDefaultValue); + void AttrHelper_FloatToAttrList(std::list &pList, const std::string& pName, const float pValue, const float pDefaultValue); /// \fn void AttrHelper_Color3ToAttrList(std::list pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue) /// Add attribute to list if value not equal to default. @@ -142,7 +142,7 @@ private: /// \param [in] pName - name of new attribute. /// \param [in] pValue - value of the new attribute. /// \param [in] pDefaultValue - default value for checking: if pValue is equal to pDefaultValue then attribute will not be added. - void AttrHelper_Color3ToAttrList(std::list pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue); + void AttrHelper_Color3ToAttrList(std::list &pList, const std::string& pName, const aiColor3D& pValue, const aiColor3D& pDefaultValue); /// \fn void NodeHelper_OpenNode(const std::string& pNodeName, const size_t pTabLevel, const bool pEmptyElement, const std::list& pAttrList) /// Begin new XML-node element. diff --git a/code/X3DImporter.cpp b/code/X3DImporter.cpp index cbeaa4623..aaf99b309 100644 --- a/code/X3DImporter.cpp +++ b/code/X3DImporter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -49,12 +50,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "StringUtils.h" // Header files, Assimp. -#include "DefaultIOSystem.h" +#include #include "fast_atof.h" +#include "FIReader.hpp" // Header files, stdlib. #include #include +#include namespace Assimp { @@ -65,32 +68,75 @@ const aiImporterDesc X3DImporter::Description = { "smalcom", "", "See documentation in source code. Chapter: Limitations.", - aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, + aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, 0, 0, 0, 0, - "x3d" + "x3d x3db" }; -void X3DImporter::Clear() -{ +//const std::regex X3DImporter::pattern_nws(R"([^, \t\r\n]+)"); +//const std::regex X3DImporter::pattern_true(R"(^\s*(?:true|1)\s*$)", std::regex::icase); + +struct WordIterator: public std::iterator { + static const char *whitespace; + const char *start_, *end_; + WordIterator(const char *start, const char *end): start_(start), end_(end) { + start_ = start + strspn(start, whitespace); + if (start_ >= end_) { + start_ = 0; + } + } + WordIterator(): start_(0), end_(0) {} + WordIterator(const WordIterator &other): start_(other.start_), end_(other.end_) {} + WordIterator &operator=(const WordIterator &other) { + start_ = other.start_; + end_ = other.end_; + return *this; + } + bool operator==(const WordIterator &other) const { return start_ == other.start_; } + bool operator!=(const WordIterator &other) const { return start_ != other.start_; } + WordIterator &operator++() { + start_ += strcspn(start_, whitespace); + start_ += strspn(start_, whitespace); + if (start_ >= end_) { + start_ = 0; + } + return *this; + } + WordIterator operator++(int) { + WordIterator result(*this); + ++(*this); + return result; + } + const char *operator*() const { return start_; } +}; + +const char *WordIterator::whitespace = ", \t\r\n"; + +X3DImporter::X3DImporter() +: NodeElement_Cur( nullptr ) +, mReader( nullptr ) { + // empty +} + +X3DImporter::~X3DImporter() { + // Clear() is accounting if data already is deleted. So, just check again if all data is deleted. + Clear(); +} + +void X3DImporter::Clear() { NodeElement_Cur = nullptr; // Delete all elements - if(NodeElement_List.size()) - { - for(std::list::iterator it = NodeElement_List.begin(); it != NodeElement_List.end(); it++) delete *it; - + if(NodeElement_List.size()) { + for ( std::list::iterator it = NodeElement_List.begin(); it != NodeElement_List.end(); it++ ) { + delete *it; + } NodeElement_List.clear(); } } -X3DImporter::~X3DImporter() -{ - delete mReader; - // Clear() is accounting if data already is deleted. So, just check again if all data is deleted. - Clear(); -} /*********************************************************************************************************************************************/ /************************************************************ Functions: find set ************************************************************/ @@ -235,7 +281,7 @@ void X3DImporter::XML_CheckNode_MustBeEmpty() void X3DImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName) { - const size_t Uns_Skip_Len = 189; + static const size_t Uns_Skip_Len = 192; const char* Uns_Skip[ Uns_Skip_Len ] = { // CAD geometry component "CADAssembly", "CADFace", "CADLayer", "CADPart", "IndexedQuadSet", "QuadSet", @@ -262,7 +308,7 @@ void X3DImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeNa "PositionInterpolator", "PositionInterpolator2D", "ScalarInterpolator", "SplinePositionInterpolator", "SplinePositionInterpolator2D", "SplineScalarInterpolator", "SquadOrientationInterpolator", // Key device sensor component - "KeySensor", "StringSensor" + "KeySensor", "StringSensor", // Layering component "Layer", "LayerSet", "Viewport", // Layout component @@ -270,7 +316,7 @@ void X3DImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeNa // Navigation component "Billboard", "Collision", "LOD", "NavigationInfo", "OrthoViewpoint", "Viewpoint", "ViewpointGroup", // Networking component - "Anchor", "LoadSensor", + "EXPORT", "IMPORT", "Anchor", "LoadSensor", // NURBS component "Contour2D", "ContourPolyline2D", "CoordinateDouble", "NurbsCurve", "NurbsCurve2D", "NurbsOrientationInterpolator", "NurbsPatchSurface", "NurbsPositionInterpolator", "NurbsSet", "NurbsSurfaceInterpolator", "NurbsSweptSurface", "NurbsSwungSurface", "NurbsTextureCoordinate", @@ -362,38 +408,65 @@ bool X3DImporter::XML_SearchNode(const std::string& pNodeName) bool X3DImporter::XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx) { -std::string val(mReader->getAttributeValue(pAttrIdx)); + auto boolValue = std::dynamic_pointer_cast(mReader->getAttributeEncodedValue(pAttrIdx)); + if (boolValue) { + if (boolValue->value.size() == 1) { + return boolValue->value.front(); + } + throw DeadlyImportError("Invalid bool value"); + } + else { + std::string val(mReader->getAttributeValue(pAttrIdx)); - if(val == "false") - return false; - else if(val == "true") - return true; - else - throw DeadlyImportError("Bool attribute value can contain \"false\" or \"true\" not the \"" + val + "\""); + if(val == "false") + return false; + else if(val == "true") + return true; + else + throw DeadlyImportError("Bool attribute value can contain \"false\" or \"true\" not the \"" + val + "\""); + } } float X3DImporter::XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx) { - std::string val; - float tvalf; + auto floatValue = std::dynamic_pointer_cast(mReader->getAttributeEncodedValue(pAttrIdx)); + if (floatValue) { + if (floatValue->value.size() == 1) { + return floatValue->value.front(); + } + throw DeadlyImportError("Invalid float value"); + } + else { + std::string val; + float tvalf; - ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), val); - fast_atoreal_move(val.c_str(), tvalf, false); + ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), val); + fast_atoreal_move(val.c_str(), tvalf, false); - return tvalf; + return tvalf; + } } int32_t X3DImporter::XML_ReadNode_GetAttrVal_AsI32(const int pAttrIdx) { - return strtol10(mReader->getAttributeValue(pAttrIdx)); + auto intValue = std::dynamic_pointer_cast(mReader->getAttributeEncodedValue(pAttrIdx)); + if (intValue) { + if (intValue->value.size() == 1) { + return intValue->value.front(); + } + throw DeadlyImportError("Invalid int value"); + } + else { + return strtol10(mReader->getAttributeValue(pAttrIdx)); + } } void X3DImporter::XML_ReadNode_GetAttrVal_AsCol3f(const int pAttrIdx, aiColor3D& pValue) { - std::list tlist; - std::list::iterator it; + std::vector tlist; + std::vector::iterator it; - XML_ReadNode_GetAttrVal_AsListF(pAttrIdx, tlist); + XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist); if(tlist.size() != 3) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx)); it = tlist.begin(); @@ -404,10 +477,10 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsCol3f(const int pAttrIdx, aiColor3D& void X3DImporter::XML_ReadNode_GetAttrVal_AsVec2f(const int pAttrIdx, aiVector2D& pValue) { - std::list tlist; - std::list::iterator it; + std::vector tlist; + std::vector::iterator it; - XML_ReadNode_GetAttrVal_AsListF(pAttrIdx, tlist); + XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist); if(tlist.size() != 2) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx)); it = tlist.begin(); @@ -417,10 +490,10 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsVec2f(const int pAttrIdx, aiVector2D void X3DImporter::XML_ReadNode_GetAttrVal_AsVec3f(const int pAttrIdx, aiVector3D& pValue) { - std::list tlist; - std::list::iterator it; + std::vector tlist; + std::vector::iterator it; - XML_ReadNode_GetAttrVal_AsListF(pAttrIdx, tlist); + XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist); if(tlist.size() != 3) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx)); it = tlist.begin(); @@ -429,181 +502,95 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsVec3f(const int pAttrIdx, aiVector3D pValue.z = *it; } -void X3DImporter::XML_ReadNode_GetAttrVal_AsListB(const int pAttrIdx, std::list& pValue) -{ - // make copy of attribute value - string with list of bool values. Also all bool values is strings. - size_t tok_str_len = strlen(mReader->getAttributeValue(pAttrIdx)); - if ( 0 == tok_str_len ) { - Throw_IncorrectAttrValue( mReader->getAttributeName( pAttrIdx ) ); - } - - tok_str_len++;// take in account terminating '\0'. - char *tok_str = new char[tok_str_len]; - - strcpy(tok_str, mReader->getAttributeValue(pAttrIdx)); - // change all spacebars to symbol '\0'. That is needed for parsing. - for(size_t i = 0; i < tok_str_len; i++) - { - if(tok_str[i] == ' ') tok_str[i] = 0; - } - - // at now check what current token is - for(char *tok_cur = tok_str, *tok_end = (tok_str + tok_str_len); tok_cur < tok_end;) - { - if(strncmp(tok_cur, "true", 4) == 0) - { - pValue.push_back(true); - tok_cur += 5;// five, not four. Because '\0' must be skipped too. - } - else if(strncmp(tok_cur, "false", 5) == 0) - { - pValue.push_back(true); - tok_cur += 6;// six, not five. Because '\0' must be skipped too. - } - else - { - Throw_IncorrectAttrValue(mReader->getAttributeName(pAttrIdx)); - } - }// for(char* tok_cur = tok_str, tok_end = (tok_str + tok_str_len); tok_cur < tok_end;) - - // delete temporary string - delete [] tok_str; -} - void X3DImporter::XML_ReadNode_GetAttrVal_AsArrB(const int pAttrIdx, std::vector& pValue) { - std::list tlist; + auto boolValue = std::dynamic_pointer_cast(mReader->getAttributeEncodedValue(pAttrIdx)); + if (boolValue) { + pValue = boolValue->value; + } + else { + const char *val = mReader->getAttributeValue(pAttrIdx); + pValue.clear(); - XML_ReadNode_GetAttrVal_AsListB(pAttrIdx, tlist);// read as list - // and copy to array - if(tlist.size() > 0) - { - pValue.reserve(tlist.size()); - for(std::list::iterator it = tlist.begin(); it != tlist.end(); it++) pValue.push_back(*it); - } -} + //std::cregex_iterator wordItBegin(val, val + strlen(val), pattern_nws); + //const std::cregex_iterator wordItEnd; + //std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const std::cmatch &match) { return std::regex_match(match.str(), pattern_true); }); -void X3DImporter::XML_ReadNode_GetAttrVal_AsListI32(const int pAttrIdx, std::list& pValue) -{ - const char* tstr = mReader->getAttributeValue(pAttrIdx); - const char* tstr_end = tstr + strlen(tstr); - - do - { - const char* ostr; - - int32_t tval32; - - tval32 = strtol10(tstr, &ostr); - if(ostr == tstr) break; - - while((ostr < tstr_end) && (*ostr == ' ')) ostr++;// skip spaces between values. - - tstr = ostr; - pValue.push_back(tval32); - } while(tstr < tstr_end); + WordIterator wordItBegin(val, val + strlen(val)); + WordIterator wordItEnd; + std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const char *match) { return (::tolower(match[0]) == 't') || (match[0] == '1'); }); + } } void X3DImporter::XML_ReadNode_GetAttrVal_AsArrI32(const int pAttrIdx, std::vector& pValue) { - std::list tlist; + auto intValue = std::dynamic_pointer_cast(mReader->getAttributeEncodedValue(pAttrIdx)); + if (intValue) { + pValue = intValue->value; + } + else { + const char *val = mReader->getAttributeValue(pAttrIdx); + pValue.clear(); - XML_ReadNode_GetAttrVal_AsListI32(pAttrIdx, tlist);// read as list - // and copy to array - if(tlist.size() > 0) - { - pValue.reserve(tlist.size()); - for(std::list::iterator it = tlist.begin(); it != tlist.end(); it++) pValue.push_back(*it); - } -} + //std::cregex_iterator wordItBegin(val, val + strlen(val), pattern_nws); + //const std::cregex_iterator wordItEnd; + //std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const std::cmatch &match) { return std::stoi(match.str()); }); -void X3DImporter::XML_ReadNode_GetAttrVal_AsListF(const int pAttrIdx, std::list& pValue) -{ - std::string str_fixed; - - // at first check string values like '.xxx'. - ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), str_fixed); - if(!str_fixed.size()) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx)); - - // and convert all values and place it in list. - const char* pstr = str_fixed.c_str(); - const char* pstr_end = pstr + str_fixed.size(); - - do - { - float tvalf; - - while((*pstr == ' ') && (pstr < pstr_end)) pstr++;// skip spaces between values. - - if(pstr < pstr_end)// additional check, because attribute value can be ended with spaces. - { - pstr = fast_atoreal_move(pstr, tvalf, false); - pValue.push_back(tvalf); - } - } while(pstr < pstr_end); + WordIterator wordItBegin(val, val + strlen(val)); + WordIterator wordItEnd; + std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const char *match) { return atoi(match); }); + } } void X3DImporter::XML_ReadNode_GetAttrVal_AsArrF(const int pAttrIdx, std::vector& pValue) { - std::list tlist; + auto floatValue = std::dynamic_pointer_cast(mReader->getAttributeEncodedValue(pAttrIdx)); + if (floatValue) { + pValue = floatValue->value; + } + else { + const char *val = mReader->getAttributeValue(pAttrIdx); + pValue.clear(); - XML_ReadNode_GetAttrVal_AsListF(pAttrIdx, tlist);// read as list - // and copy to array - if(tlist.size() > 0) - { - pValue.reserve(tlist.size()); - for(std::list::iterator it = tlist.begin(); it != tlist.end(); it++) pValue.push_back(*it); - } -} + //std::cregex_iterator wordItBegin(val, val + strlen(val), pattern_nws); + //const std::cregex_iterator wordItEnd; + //std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const std::cmatch &match) { return std::stof(match.str()); }); -void X3DImporter::XML_ReadNode_GetAttrVal_AsListD(const int pAttrIdx, std::list& pValue) -{ - std::string str_fixed; - - // at first check string values like '.xxx'. - ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), str_fixed); - if(!str_fixed.size()) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx)); - - // and convert all values and place it in list. - const char* pstr = str_fixed.c_str(); - const char* pstr_end = pstr + str_fixed.size(); - - do - { - double tvald; - - while((*pstr == ' ') && (pstr < pstr_end)) pstr++;// skip spaces between values. - - if(pstr < pstr_end)// additional check, because attribute value can be ended with spaces. - { - pstr = fast_atoreal_move(pstr, tvald, false); - pValue.push_back(tvald); - } - } while(pstr < pstr_end); + WordIterator wordItBegin(val, val + strlen(val)); + WordIterator wordItEnd; + std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const char *match) { return static_cast(atof(match)); }); + } } void X3DImporter::XML_ReadNode_GetAttrVal_AsArrD(const int pAttrIdx, std::vector& pValue) { - std::list tlist; + auto doubleValue = std::dynamic_pointer_cast(mReader->getAttributeEncodedValue(pAttrIdx)); + if (doubleValue) { + pValue = doubleValue->value; + } + else { + const char *val = mReader->getAttributeValue(pAttrIdx); + pValue.clear(); - XML_ReadNode_GetAttrVal_AsListD(pAttrIdx, tlist);// read as list - // and copy to array - if(tlist.size() > 0) - { - pValue.reserve(tlist.size()); - for(std::list::iterator it = tlist.begin(); it != tlist.end(); it++) pValue.push_back(*it); - } + //std::cregex_iterator wordItBegin(val, val + strlen(val), pattern_nws); + //const std::cregex_iterator wordItEnd; + //std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const std::cmatch &match) { return std::stod(match.str()); }); + + WordIterator wordItBegin(val, val + strlen(val)); + WordIterator wordItEnd; + std::transform(wordItBegin, wordItEnd, std::back_inserter(pValue), [](const char *match) { return atof(match); }); + } } void X3DImporter::XML_ReadNode_GetAttrVal_AsListCol3f(const int pAttrIdx, std::list& pValue) { - std::list tlist; + std::vector tlist; - XML_ReadNode_GetAttrVal_AsListF(pAttrIdx, tlist);// read as list + XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist);// read as list if(tlist.size() % 3) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx)); // copy data to array - for(std::list::iterator it = tlist.begin(); it != tlist.end();) + for(std::vector::iterator it = tlist.begin(); it != tlist.end();) { aiColor3D tcol; @@ -629,13 +616,13 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsArrCol3f(const int pAttrIdx, std::ve void X3DImporter::XML_ReadNode_GetAttrVal_AsListCol4f(const int pAttrIdx, std::list& pValue) { - std::list tlist; + std::vector tlist; - XML_ReadNode_GetAttrVal_AsListF(pAttrIdx, tlist);// read as list + XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist);// read as list if(tlist.size() % 4) Throw_ConvertFail_Str2ArrF(mReader->getAttributeValue(pAttrIdx)); // copy data to array - for(std::list::iterator it = tlist.begin(); it != tlist.end();) + for(std::vector::iterator it = tlist.begin(); it != tlist.end();) { aiColor4D tcol; @@ -665,16 +652,16 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsArrCol4f(const int pAttrIdx, std::ve void X3DImporter::XML_ReadNode_GetAttrVal_AsListVec2f(const int pAttrIdx, std::list& pValue) { - std::list tlist; + std::vector tlist; - XML_ReadNode_GetAttrVal_AsListF(pAttrIdx, tlist);// read as list + XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist);// read as list if ( tlist.size() % 2 ) { Throw_ConvertFail_Str2ArrF( mReader->getAttributeValue( pAttrIdx ) ); } // copy data to array - for(std::list::iterator it = tlist.begin(); it != tlist.end();) + for(std::vector::iterator it = tlist.begin(); it != tlist.end();) { aiVector2D tvec; @@ -702,16 +689,16 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsArrVec2f(const int pAttrIdx, std::ve void X3DImporter::XML_ReadNode_GetAttrVal_AsListVec3f(const int pAttrIdx, std::list& pValue) { - std::list tlist; + std::vector tlist; - XML_ReadNode_GetAttrVal_AsListF(pAttrIdx, tlist);// read as list + XML_ReadNode_GetAttrVal_AsArrF(pAttrIdx, tlist);// read as list if ( tlist.size() % 3 ) { Throw_ConvertFail_Str2ArrF( mReader->getAttributeValue( pAttrIdx ) ); } // copy data to array - for(std::list::iterator it = tlist.begin(); it != tlist.end();) + for(std::vector::iterator it = tlist.begin(); it != tlist.end();) { aiVector3D tvec; @@ -901,9 +888,9 @@ void X3DImporter::GeometryHelper_MakeQL_RectParallelepiped(const aiVector3D& pSi #undef MESH_RectParallelepiped_CREATE_VERT -void X3DImporter::GeometryHelper_CoordIdxStr2FacesArr(const std::list& pCoordIdx, std::vector& pFaces, unsigned int& pPrimitiveTypes) const +void X3DImporter::GeometryHelper_CoordIdxStr2FacesArr(const std::vector& pCoordIdx, std::vector& pFaces, unsigned int& pPrimitiveTypes) const { - std::list f_data(pCoordIdx); + std::vector f_data(pCoordIdx); std::vector inds; unsigned int prim_type = 0; @@ -916,7 +903,7 @@ void X3DImporter::GeometryHelper_CoordIdxStr2FacesArr(const std::list& pFaces.reserve(f_data.size() / 3); inds.reserve(4); //PrintVectorSet("build. ci", pCoordIdx); - for(std::list::iterator it = f_data.begin(); it != f_data.end(); it++) + for(std::vector::iterator it = f_data.begin(); it != f_data.end(); it++) { // when face is got count how many indices in it. if(*it == (-1)) @@ -1008,7 +995,7 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::list& pCoordIdx, const std::list& pColorIdx, +void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::vector& pCoordIdx, const std::vector& pColorIdx, const std::list& pColors, const bool pColorPerVertex) const { std::list tcol; @@ -1023,7 +1010,7 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::list& MeshGeometry_AddColor(pMesh, pCoordIdx, pColorIdx, tcol, pColorPerVertex); } -void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::list& pCoordIdx, const std::list& pColorIdx, +void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::vector& pCoordIdx, const std::vector& pColorIdx, const std::list& pColors, const bool pColorPerVertex) const { std::vector col_tgt_arr; @@ -1054,7 +1041,7 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::list& } // create list with colors for every vertex. col_tgt_arr.resize(pMesh.mNumVertices); - for(std::list::const_iterator colidx_it = pColorIdx.begin(), coordidx_it = pCoordIdx.begin(); colidx_it != pColorIdx.end(); colidx_it++, coordidx_it++) + for(std::vector::const_iterator colidx_it = pColorIdx.begin(), coordidx_it = pCoordIdx.begin(); colidx_it != pColorIdx.end(); colidx_it++, coordidx_it++) { if ( *colidx_it == ( -1 ) ) { @@ -1102,7 +1089,7 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::list& // create list with colors for every vertex using faces indices. col_tgt_arr.resize(pMesh.mNumFaces); - std::list::const_iterator colidx_it = pColorIdx.begin(); + std::vector::const_iterator colidx_it = pColorIdx.begin(); for(size_t fi = 0; fi < pMesh.mNumFaces; fi++) { if((unsigned int)*colidx_it > pMesh.mNumFaces) throw DeadlyImportError("MeshGeometry_AddColor2. Face idx is out of range."); @@ -1132,7 +1119,7 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::list& MeshGeometry_AddColor(pMesh, col_tgt_list, pColorPerVertex); } -void X3DImporter::MeshGeometry_AddNormal(aiMesh& pMesh, const std::list& pCoordIdx, const std::list& pNormalIdx, +void X3DImporter::MeshGeometry_AddNormal(aiMesh& pMesh, const std::vector& pCoordIdx, const std::vector& pNormalIdx, const std::list& pNormals, const bool pNormalPerVertex) const { std::vector tind; @@ -1147,35 +1134,36 @@ void X3DImporter::MeshGeometry_AddNormal(aiMesh& pMesh, const std::list if(pNormalPerVertex) { - const std::list* srcidx; - if(pNormalIdx.size() > 0) { // check indices array count. if(pNormalIdx.size() != pCoordIdx.size()) throw DeadlyImportError("Normals and Coords inidces count must be equal."); - srcidx = &pNormalIdx; + tind.reserve(pNormalIdx.size()); + for(std::vector::const_iterator it = pNormalIdx.begin(); it != pNormalIdx.end(); it++) + { + if(*it != (-1)) tind.push_back(*it); + } + + // copy normals to mesh + pMesh.mNormals = new aiVector3D[pMesh.mNumVertices]; + for(size_t i = 0; (i < pMesh.mNumVertices) && (i < tind.size()); i++) + { + if(tind[i] >= norm_arr_copy.size()) + throw DeadlyImportError("MeshGeometry_AddNormal. Normal index(" + to_string(tind[i]) + + ") is out of range. Normals count: " + to_string(norm_arr_copy.size()) + "."); + + pMesh.mNormals[i] = norm_arr_copy[tind[i]]; + } } else { - srcidx = &pCoordIdx; - } + if(pNormals.size() != pMesh.mNumVertices) throw DeadlyImportError("MeshGeometry_AddNormal. Normals and vertices count must be equal."); - tind.reserve(srcidx->size()); - for(std::list::const_iterator it = srcidx->begin(); it != srcidx->end(); it++) - { - if(*it != (-1)) tind.push_back(*it); - } - - // copy normals to mesh - pMesh.mNormals = new aiVector3D[pMesh.mNumVertices]; - for(size_t i = 0; (i < pMesh.mNumVertices) && (i < tind.size()); i++) - { - if(tind[i] >= norm_arr_copy.size()) - throw DeadlyImportError("MeshGeometry_AddNormal. Normal index(" + to_string(tind[i]) + - ") is out of range. Normals count: " + to_string(norm_arr_copy.size()) + "."); - - pMesh.mNormals[i] = norm_arr_copy[tind[i]]; + // copy normals to mesh + pMesh.mNormals = new aiVector3D[pMesh.mNumVertices]; + std::list::const_iterator norm_it = pNormals.begin(); + for(size_t i = 0; i < pMesh.mNumVertices; i++) pMesh.mNormals[i] = *norm_it++; } }// if(pNormalPerVertex) else @@ -1184,7 +1172,7 @@ void X3DImporter::MeshGeometry_AddNormal(aiMesh& pMesh, const std::list { if(pMesh.mNumFaces != pNormalIdx.size()) throw DeadlyImportError("Normals faces count must be equal to mesh faces count."); - std::list::const_iterator normidx_it = pNormalIdx.begin(); + std::vector::const_iterator normidx_it = pNormalIdx.begin(); tind.reserve(pNormalIdx.size()); for(size_t i = 0, i_e = pNormalIdx.size(); i < i_e; i++) tind.push_back(*normidx_it++); @@ -1237,7 +1225,7 @@ void X3DImporter::MeshGeometry_AddNormal(aiMesh& pMesh, const std::list& pCoordIdx, const std::list& pTexCoordIdx, +void X3DImporter::MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::vector& pCoordIdx, const std::vector& pTexCoordIdx, const std::list& pTexCoords) const { std::vector texcoord_arr_copy; @@ -1310,7 +1298,7 @@ void X3DImporter::MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::list& pCoordIdx, const std::list& pVertices) const +aiMesh* X3DImporter::GeometryHelper_MakeMesh(const std::vector& pCoordIdx, const std::list& pVertices) const { std::vector faces; unsigned int prim_type = 0; @@ -1413,9 +1401,12 @@ void X3DImporter::ParseHelper_FixTruncatedFloatString(const char* pInStr, std::s } } +extern FIVocabulary X3D_vocabulary_3_2; +extern FIVocabulary X3D_vocabulary_3_3; + void X3DImporter::ParseFile(const std::string& pFile, IOSystem* pIOHandler) { - irr::io::IrrXMLReader* OldReader = mReader;// store current XMLreader. + std::unique_ptr OldReader = std::move(mReader);// store current XMLreader. std::unique_ptr file(pIOHandler->Open(pFile, "rb")); // Check whether we can read from the file @@ -1423,19 +1414,18 @@ void X3DImporter::ParseFile(const std::string& pFile, IOSystem* pIOHandler) { throw DeadlyImportError( "Failed to open X3D file " + pFile + "." ); } - // generate a XML reader for it - std::unique_ptr mIOWrapper(new CIrrXML_IOStreamReader(file.get())); - mReader = irr::io::createIrrXMLReader(mIOWrapper.get()); + mReader = FIReader::create(file.get()); if ( !mReader ) { throw DeadlyImportError( "Failed to create XML reader for file" + pFile + "." ); } + mReader->registerVocabulary("urn:web3d:x3d:fi-vocabulary-3.2", &X3D_vocabulary_3_2); + mReader->registerVocabulary("urn:web3d:x3d:fi-vocabulary-3.3", &X3D_vocabulary_3_3); // start reading ParseNode_Root(); - delete mReader; // restore old XMLreader - mReader = OldReader; + mReader = std::move(OldReader); } void X3DImporter::ParseNode_Root() @@ -1649,7 +1639,7 @@ bool X3DImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool p { const std::string extension = GetExtension(pFile); - if(extension == "x3d") return true; + if((extension == "x3d") || (extension == "x3db")) return true; if(!extension.length() || pCheckSig) { @@ -1664,6 +1654,7 @@ bool X3DImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool p void X3DImporter::GetExtensionList(std::set& pExtensionList) { pExtensionList.insert("x3d"); + pExtensionList.insert("x3db"); } const aiImporterDesc* X3DImporter::GetInfo () const @@ -1673,9 +1664,13 @@ const aiImporterDesc* X3DImporter::GetInfo () const void X3DImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { + mpIOHandler = pIOHandler; + Clear();// delete old graph. - mFileDir = DefaultIOSystem::absolutePath(pFile); + std::string::size_type slashPos = pFile.find_last_of("\\/"); + pIOHandler->PushDirectory(slashPos == std::string::npos ? std::string() : pFile.substr(0, slashPos + 1)); ParseFile(pFile, pIOHandler); + pIOHandler->PopDirectory(); // // Assimp use static arrays of objects for fast speed of rendering. That's good, but need some additional operations/ // We know that geometry objects(meshes) are stored in , also in -> materials(in Assimp logical view) diff --git a/code/X3DImporter.hpp b/code/X3DImporter.hpp index f19fc0195..468db5f3e 100644 --- a/code/X3DImporter.hpp +++ b/code/X3DImporter.hpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -55,9 +56,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "BaseImporter.h" #include "irrXMLWrapper.h" +#include "FIReader.hpp" +//#include -namespace Assimp -{ +namespace Assimp { /// \class X3DImporter /// Class that holding scene graph which include: groups, geometry, metadata etc. @@ -101,7 +103,7 @@ namespace Assimp /// Navigation component: /// "Billboard", "Collision", "LOD", "NavigationInfo", "OrthoViewpoint", "Viewpoint", "ViewpointGroup" /// Networking component: -/// "Anchor", "LoadSensor" +/// "EXPORT", "IMPORT", "Anchor", "LoadSensor" /// NURBS component: /// "Contour2D", "ContourPolyline2D", "CoordinateDouble", "NurbsCurve", "NurbsCurve2D", "NurbsOrientationInterpolator", "NurbsPatchSurface", /// "NurbsPositionInterpolator", "NurbsSet", "NurbsSurfaceInterpolator", "NurbsSweptSurface", "NurbsSwungSurface", "NurbsTextureCoordinate", @@ -174,7 +176,7 @@ namespace Assimp /// Ignored attributes: "creaseAngle", "convex", "solid". /// /// Texture coordinates generating: only for Sphere, Cone, Cylinder. In all other case used PLANE mapping. -/// It's better that Assimp main code has powerfull texture coordinates generator. Then is not needed to +/// It's better that Assimp main code has powerful texture coordinates generator. Then is not needed to /// duplicate this code in every importer. /// /// Lighting limitations. @@ -199,9 +201,7 @@ public: /***********************************************/ /// Default constructor. - X3DImporter() - : NodeElement_Cur( nullptr ), mReader( nullptr ) - {} + X3DImporter(); /// Default destructor. ~X3DImporter(); @@ -211,7 +211,7 @@ public: /***********************************************/ /// Parse X3D 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. + /// Also exception can be thrown 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 ); @@ -401,10 +401,10 @@ private: /************** Functions: XML set *************/ /***********************************************/ - /// Chek if current node is empty: . If not then exception will throwed. + /// Check if current node is empty: . If not then exception will throwed. void XML_CheckNode_MustBeEmpty(); - /// Chek if current node name is equal to pNodeName. + /// Check 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; } @@ -451,33 +451,21 @@ private: /// Read attribute value. /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set). /// \param [out] pValue - read data. - void XML_ReadNode_GetAttrVal_AsListB(const int pAttrIdx, std::list& pValue); - - /// \overload void XML_ReadNode_GetAttrVal_AsListBool(const int pAttrIdx, std::list& pValue) void XML_ReadNode_GetAttrVal_AsArrB(const int pAttrIdx, std::vector& pValue); /// Read attribute value. /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set). /// \param [out] pValue - read data. - void XML_ReadNode_GetAttrVal_AsListI32(const int pAttrIdx, std::list& pValue); - - /// \overload void XML_ReadNode_GetAttrVal_AsListI32(const int pAttrIdx, std::list& pValue) void XML_ReadNode_GetAttrVal_AsArrI32(const int pAttrIdx, std::vector& pValue); /// Read attribute value. /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set). /// \param [out] pValue - read data. - void XML_ReadNode_GetAttrVal_AsListF(const int pAttrIdx, std::list& pValue); - - /// \overload void XML_ReadNode_GetAttrVal_AsListF(const int pAttrIdx, std::list& pValue) void XML_ReadNode_GetAttrVal_AsArrF(const int pAttrIdx, std::vector& pValue); /// Read attribute value. /// \param [in] pAttrIdx - attribute index (\ref mReader->getAttribute* set). /// \param [out] pValue - read data. - void XML_ReadNode_GetAttrVal_AsListD(const int pAttrIdx, std::list& pValue); - - /// \overload void XML_ReadNode_GetAttrVal_AsListD(const int pAttrIdx, std::list& pValue) void XML_ReadNode_GetAttrVal_AsArrD(const int pAttrIdx, std::vector& pValue); /// Read attribute value. @@ -556,7 +544,7 @@ private: /// \param [in] pCoordIdx - vertices indices divided by delimiter "-1". /// \param [in] pFaces - created faces array. /// \param [in] pPrimitiveTypes - type of primitives in faces. - void GeometryHelper_CoordIdxStr2FacesArr(const std::list& pCoordIdx, std::vector& pFaces, unsigned int& pPrimitiveTypes) const; + void GeometryHelper_CoordIdxStr2FacesArr(const std::vector& pCoordIdx, std::vector& pFaces, unsigned int& pPrimitiveTypes) const; /// Add colors to mesh. /// a. If colorPerVertex is FALSE, colours are applied to each face, as follows: @@ -566,7 +554,7 @@ private: /// There shall be at least as many colours in the X3DColorNode node as there are faces. /// b. If colorPerVertex is TRUE, colours are applied to each vertex, as follows: /// If the colorIndex field is not empty, colours are applied to each vertex of the mesh in exactly the same manner that the coordIndex - /// field is used to choose coordinates for each vertex from the node. The colorIndex field shall contain end-of-face markers (−1) + /// field is used to choose coordinates for each vertex from the node. The colorIndex field shall contain end-of-face markers (-1) /// in exactly the same places as the coordIndex field. /// If the colorIndex field is empty, the coordIndex field is used to choose colours from the X3DColorNode node. /// \param [in] pMesh - mesh for adding data. @@ -575,11 +563,11 @@ private: /// then pColorIdx contain color indices for every faces and must not contain delimiter "-1". /// \param [in] pColors - defined colors. /// \param [in] pColorPerVertex - if \ref pColorPerVertex is true then color in \ref pColors defined for every vertex, if false - for every face. - void MeshGeometry_AddColor(aiMesh& pMesh, const std::list& pCoordIdx, const std::list& pColorIdx, + void MeshGeometry_AddColor(aiMesh& pMesh, const std::vector& pCoordIdx, const std::vector& pColorIdx, const std::list& pColors, const bool pColorPerVertex) const; /// \overload void MeshGeometry_AddColor(aiMesh& pMesh, const std::list& pCoordIdx, const std::list& pColorIdx, const std::list& pColors, const bool pColorPerVertex) const; - void MeshGeometry_AddColor(aiMesh& pMesh, const std::list& pCoordIdx, const std::list& pColorIdx, + void MeshGeometry_AddColor(aiMesh& pMesh, const std::vector& pCoordIdx, const std::vector& pColorIdx, const std::list& pColors, const bool pColorPerVertex) const; /// Add colors to mesh. @@ -592,14 +580,14 @@ private: void MeshGeometry_AddColor(aiMesh& pMesh, const std::list& pColors, const bool pColorPerVertex) const; /// Add normals to mesh. Function work similar to \ref MeshGeometry_AddColor; - void MeshGeometry_AddNormal(aiMesh& pMesh, const std::list& pCoordIdx, const std::list& pNormalIdx, + void MeshGeometry_AddNormal(aiMesh& pMesh, const std::vector& pCoordIdx, const std::vector& pNormalIdx, const std::list& pNormals, const bool pNormalPerVertex) const; /// Add normals to mesh. Function work similar to \ref MeshGeometry_AddColor; void MeshGeometry_AddNormal(aiMesh& pMesh, const std::list& pNormals, const bool pNormalPerVertex) const; /// Add texture coordinates to mesh. Function work similar to \ref MeshGeometry_AddColor; - void MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::list& pCoordIdx, const std::list& pTexCoordIdx, + void MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::vector& pCoordIdx, const std::vector& pTexCoordIdx, const std::list& pTexCoords) const; /// Add texture coordinates to mesh. Function work similar to \ref MeshGeometry_AddColor; @@ -609,7 +597,7 @@ private: /// \param [in] pCoordIdx - vertices indices divided by delimiter "-1". /// \param [in] pVertices - vertices of mesh. /// \return created mesh. - aiMesh* GeometryHelper_MakeMesh(const std::list& pCoordIdx, const std::list& pVertices) const; + aiMesh* GeometryHelper_MakeMesh(const std::vector& pCoordIdx, const std::list& pVertices) const; /***********************************************/ /******** Functions: parse set private *********/ @@ -828,13 +816,16 @@ private: /****************** Constants ******************/ /***********************************************/ static const aiImporterDesc Description; + //static const std::regex pattern_nws; + //static const std::regex pattern_true; + /***********************************************/ /****************** Variables ******************/ /***********************************************/ CX3DImporter_NodeElement* NodeElement_Cur;///< Current element. - irr::io::IrrXMLReader* mReader;///< Pointer to XML-reader object - std::string mFileDir; + std::unique_ptr mReader;///< Pointer to XML-reader object + IOSystem *mpIOHandler; };// class X3DImporter }// namespace Assimp diff --git a/code/X3DImporter_Geometry2D.cpp b/code/X3DImporter_Geometry2D.cpp index bfa1834ec..895ba8798 100644 --- a/code/X3DImporter_Geometry2D.cpp +++ b/code/X3DImporter_Geometry2D.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/X3DImporter_Geometry3D.cpp b/code/X3DImporter_Geometry3D.cpp index e8bc958e8..b2e9a28f8 100644 --- a/code/X3DImporter_Geometry3D.cpp +++ b/code/X3DImporter_Geometry3D.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -284,7 +285,7 @@ void X3DImporter::ParseNode_Geometry3D_ElevationGrid() bool ccw = true; bool colorPerVertex = true; float creaseAngle = 0; - std::list height; + std::vector height; bool normalPerVertex = true; bool solid = true; int32_t xDimension = 0; @@ -300,7 +301,7 @@ void X3DImporter::ParseNode_Geometry3D_ElevationGrid() MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool); MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool); MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat); - MACRO_ATTRREAD_CHECK_REF("height", height, XML_ReadNode_GetAttrVal_AsListF); + MACRO_ATTRREAD_CHECK_REF("height", height, XML_ReadNode_GetAttrVal_AsArrF); MACRO_ATTRREAD_CHECK_RET("xDimension", xDimension, XML_ReadNode_GetAttrVal_AsI32); MACRO_ATTRREAD_CHECK_RET("xSpacing", xSpacing, XML_ReadNode_GetAttrVal_AsFloat); MACRO_ATTRREAD_CHECK_RET("zDimension", zDimension, XML_ReadNode_GetAttrVal_AsI32); @@ -325,7 +326,7 @@ void X3DImporter::ParseNode_Geometry3D_ElevationGrid() CX3DImporter_NodeElement_ElevationGrid& grid_alias = *((CX3DImporter_NodeElement_ElevationGrid*)ne);// create alias for conveience {// create grid vertices list - std::list::const_iterator he_it = height.begin(); + std::vector::const_iterator he_it = height.begin(); for(int32_t zi = 0; zi < zDimension; zi++)// rows { @@ -467,7 +468,7 @@ static aiVector3D GeometryHelper_Extrusion_GetNextY(const size_t pSpine_PointIdx if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last))// at first special cases { if(pSpine_Closed) - {// If the spine curve is closed: The SCP for the first and last points is the same and is found using (spine[1] − spine[n − 2]) to compute the Y-axis. + {// If the spine curve is closed: The SCP for the first and last points is the same and is found using (spine[1] - spine[n - 2]) to compute the Y-axis. // As we even for closed spine curve last and first point in pSpine are not the same: duplicates(spine[n - 1] which are equivalent to spine[0]) // in tail are removed. // So, last point in pSpine is a spine[n - 2] @@ -478,13 +479,13 @@ static aiVector3D GeometryHelper_Extrusion_GetNextY(const size_t pSpine_PointIdx tvec = pSpine[1] - pSpine[0]; } else - {// The Y-axis used for the last point it is the vector from spine[n−2] to spine[n−1]. In our case(see above about droping tail) spine[n - 1] is + {// The Y-axis used for the last point it is the vector from spine[n-2] to spine[n-1]. In our case(see above about droping tail) spine[n - 1] is // the spine[0]. tvec = pSpine[spine_idx_last] - pSpine[spine_idx_last - 1]; } }// if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last)) else - {// For all points other than the first or last: The Y-axis for spine[i] is found by normalizing the vector defined by (spine[i+1] − spine[i−1]). + {// For all points other than the first or last: The Y-axis for spine[i] is found by normalizing the vector defined by (spine[i+1] - spine[i-1]). tvec = pSpine[pSpine_PointIdx + 1] - pSpine[pSpine_PointIdx - 1]; }// if((pSpine_PointIdx == 0) || (pSpine_PointIdx == spine_idx_last)) else @@ -549,7 +550,7 @@ static aiVector3D GeometryHelper_Extrusion_GetNextZ(const size_t pSpine_PointIdx } // After determining the Z-axis, its dot product with the Z-axis of the previous spine point is computed. If this value is negative, the Z-axis - // is flipped (multiplied by −1). + // is flipped (multiplied by -1). if((tvec * pVecZ_Prev) < 0) tvec = -tvec; return tvec.Normalize(); @@ -862,29 +863,29 @@ void X3DImporter::ParseNode_Geometry3D_IndexedFaceSet() { std::string use, def; bool ccw = true; - std::list colorIndex; + std::vector colorIndex; bool colorPerVertex = true; bool convex = true; - std::list coordIndex; + std::vector coordIndex; float creaseAngle = 0; - std::list normalIndex; + std::vector normalIndex; bool normalPerVertex = true; bool solid = true; - std::list texCoordIndex; + std::vector texCoordIndex; CX3DImporter_NodeElement* ne( nullptr ); MACRO_ATTRREAD_LOOPBEG; MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use); MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool); - MACRO_ATTRREAD_CHECK_REF("colorIndex", colorIndex, XML_ReadNode_GetAttrVal_AsListI32); + MACRO_ATTRREAD_CHECK_REF("colorIndex", colorIndex, XML_ReadNode_GetAttrVal_AsArrI32); MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool); MACRO_ATTRREAD_CHECK_RET("convex", convex, XML_ReadNode_GetAttrVal_AsBool); - MACRO_ATTRREAD_CHECK_REF("coordIndex", coordIndex, XML_ReadNode_GetAttrVal_AsListI32); + MACRO_ATTRREAD_CHECK_REF("coordIndex", coordIndex, XML_ReadNode_GetAttrVal_AsArrI32); MACRO_ATTRREAD_CHECK_RET("creaseAngle", creaseAngle, XML_ReadNode_GetAttrVal_AsFloat); - MACRO_ATTRREAD_CHECK_REF("normalIndex", normalIndex, XML_ReadNode_GetAttrVal_AsListI32); + MACRO_ATTRREAD_CHECK_REF("normalIndex", normalIndex, XML_ReadNode_GetAttrVal_AsArrI32); MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool); MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool); - MACRO_ATTRREAD_CHECK_REF("texCoordIndex", texCoordIndex, XML_ReadNode_GetAttrVal_AsListI32); + MACRO_ATTRREAD_CHECK_REF("texCoordIndex", texCoordIndex, XML_ReadNode_GetAttrVal_AsArrI32); MACRO_ATTRREAD_LOOPEND; // if "USE" defined then find already defined element. @@ -948,7 +949,7 @@ void X3DImporter::ParseNode_Geometry3D_IndexedFaceSet() void X3DImporter::ParseNode_Geometry3D_Sphere() { std::string use, def; - float radius = 1; + ai_real radius = 1; bool solid = true; CX3DImporter_NodeElement* ne( nullptr ); diff --git a/code/X3DImporter_Group.cpp b/code/X3DImporter_Group.cpp index e476ba58b..e7df97b4b 100644 --- a/code/X3DImporter_Group.cpp +++ b/code/X3DImporter_Group.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/X3DImporter_Light.cpp b/code/X3DImporter_Light.cpp index 54f56e76e..ff450f7a9 100644 --- a/code/X3DImporter_Light.cpp +++ b/code/X3DImporter_Light.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/X3DImporter_Macro.hpp b/code/X3DImporter_Macro.hpp index 445edfe91..6281efcd5 100644 --- a/code/X3DImporter_Macro.hpp +++ b/code/X3DImporter_Macro.hpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/X3DImporter_Metadata.cpp b/code/X3DImporter_Metadata.cpp index 1f57d9f63..0fa1b27b3 100644 --- a/code/X3DImporter_Metadata.cpp +++ b/code/X3DImporter_Metadata.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -104,7 +105,7 @@ bool X3DImporter::ParseHelper_CheckRead_X3DMetadataObject() return true; } -void X3DImporter::ParseNode_Metadata(CX3DImporter_NodeElement* pParentElement, const std::string& pNodeName) +void X3DImporter::ParseNode_Metadata(CX3DImporter_NodeElement* pParentElement, const std::string& /*pNodeName*/) { ParseHelper_Node_Enter(pParentElement); MACRO_NODECHECK_METADATA(mReader->getNodeName()); @@ -122,14 +123,14 @@ void X3DImporter::ParseNode_MetadataBoolean() { std::string def, use; std::string name, reference; - std::list value; + std::vector value; CX3DImporter_NodeElement* ne( nullptr ); MACRO_ATTRREAD_LOOPBEG; MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use); MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue); MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue); - MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsListB); + MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrB); MACRO_ATTRREAD_LOOPEND; MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaBoolean, "MetadataBoolean", ENET_MetaBoolean); @@ -146,14 +147,14 @@ void X3DImporter::ParseNode_MetadataDouble() { std::string def, use; std::string name, reference; - std::list value; + std::vector value; CX3DImporter_NodeElement* ne( nullptr ); MACRO_ATTRREAD_LOOPBEG; MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use); MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue); MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue); - MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsListD); + MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrD); MACRO_ATTRREAD_LOOPEND; MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaDouble, "MetadataDouble", ENET_MetaDouble); @@ -170,14 +171,14 @@ void X3DImporter::ParseNode_MetadataFloat() { std::string def, use; std::string name, reference; - std::list value; + std::vector value; CX3DImporter_NodeElement* ne( nullptr ); MACRO_ATTRREAD_LOOPBEG; MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use); MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue); MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue); - MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsListF); + MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrF); MACRO_ATTRREAD_LOOPEND; MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaFloat, "MetadataFloat", ENET_MetaFloat); @@ -194,14 +195,14 @@ void X3DImporter::ParseNode_MetadataInteger() { std::string def, use; std::string name, reference; - std::list value; + std::vector value; CX3DImporter_NodeElement* ne( nullptr ); MACRO_ATTRREAD_LOOPBEG; MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use); MACRO_ATTRREAD_CHECK_RET("name", name, mReader->getAttributeValue); MACRO_ATTRREAD_CHECK_RET("reference", reference, mReader->getAttributeValue); - MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsListI32); + MACRO_ATTRREAD_CHECK_REF("value", value, XML_ReadNode_GetAttrVal_AsArrI32); MACRO_ATTRREAD_LOOPEND; MACRO_METADATA_FINDCREATE(def, use, reference, value, ne, CX3DImporter_NodeElement_MetaInteger, "MetadataInteger", ENET_MetaInteger); diff --git a/code/X3DImporter_Networking.cpp b/code/X3DImporter_Networking.cpp index 4a75c9e66..269c58ba3 100644 --- a/code/X3DImporter_Networking.cpp +++ b/code/X3DImporter_Networking.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -48,11 +49,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "X3DImporter_Macro.hpp" // Header files, Assimp. -#include "DefaultIOSystem.h" +#include + +//#include namespace Assimp { +//static std::regex pattern_parentDir(R"((^|/)[^/]+/../)"); +static std::string parentDir("/../"); + // 0)) { - DefaultIOSystem io_handler; - std::string full_path; + std::string full_path = mpIOHandler->CurrentDirectory() + url.front(); - full_path = mFileDir + "/" + url.front(); + //full_path = std::regex_replace(full_path, pattern_parentDir, "$1"); + for (std::string::size_type pos = full_path.find(parentDir); pos != std::string::npos; pos = full_path.find(parentDir, pos)) { + if (pos > 0) { + std::string::size_type pos2 = full_path.rfind('/', pos - 1); + if (pos2 != std::string::npos) { + full_path.erase(pos2, pos - pos2 + 3); + pos = pos2; + } + else { + full_path.erase(0, pos + 4); + pos = 0; + } + } + else { + pos += 3; + } + } // Attribute "url" can contain list of strings. But we need only one - first. - ParseFile(full_path, &io_handler); + std::string::size_type slashPos = full_path.find_last_of("\\/"); + mpIOHandler->PushDirectory(slashPos == std::string::npos ? std::string() : full_path.substr(0, slashPos + 1)); + ParseFile(full_path, mpIOHandler); + mpIOHandler->PopDirectory(); } // check for X3DMetadataObject childs. diff --git a/code/X3DImporter_Node.hpp b/code/X3DImporter_Node.hpp index f1f4bc57e..6ed96c2f9 100644 --- a/code/X3DImporter_Node.hpp +++ b/code/X3DImporter_Node.hpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -51,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Header files, stdlib. #include +#include #include /// \class CX3DImporter_NodeElement @@ -263,7 +265,7 @@ public: /// This struct describe metavalue of type boolean. struct CX3DImporter_NodeElement_MetaBoolean : public CX3DImporter_NodeElement_Meta { - std::list Value;///< Stored value. + std::vector Value;///< Stored value. /// \fn CX3DImporter_NodeElement_MetaBoolean(CX3DImporter_NodeElement* pParent) /// Constructor @@ -278,7 +280,7 @@ struct CX3DImporter_NodeElement_MetaBoolean : public CX3DImporter_NodeElement_Me /// This struct describe metavalue of type double. struct CX3DImporter_NodeElement_MetaDouble : public CX3DImporter_NodeElement_Meta { - std::list Value;///< Stored value. + std::vector Value;///< Stored value. /// \fn CX3DImporter_NodeElement_MetaDouble(CX3DImporter_NodeElement* pParent) /// Constructor @@ -293,7 +295,7 @@ struct CX3DImporter_NodeElement_MetaDouble : public CX3DImporter_NodeElement_Met /// This struct describe metavalue of type float. struct CX3DImporter_NodeElement_MetaFloat : public CX3DImporter_NodeElement_Meta { - std::list Value;///< Stored value. + std::vector Value;///< Stored value. /// \fn CX3DImporter_NodeElement_MetaFloat(CX3DImporter_NodeElement* pParent) /// Constructor @@ -308,7 +310,7 @@ struct CX3DImporter_NodeElement_MetaFloat : public CX3DImporter_NodeElement_Meta /// This struct describe metavalue of type integer. struct CX3DImporter_NodeElement_MetaInteger : public CX3DImporter_NodeElement_Meta { - std::list Value;///< Stored value. + std::vector Value;///< Stored value. /// \fn CX3DImporter_NodeElement_MetaInteger(CX3DImporter_NodeElement* pParent) /// Constructor @@ -466,42 +468,29 @@ public: /// \class CX3DImporter_NodeElement_Geometry3D /// Three-dimensional body. -class CX3DImporter_NodeElement_Geometry3D : public CX3DImporter_NodeElement -{ - /***********************************************/ - /****************** Variables ******************/ - /***********************************************/ - +class CX3DImporter_NodeElement_Geometry3D : public CX3DImporter_NodeElement { public: + std::list Vertices; ///< Vertices list. + size_t NumIndices;///< Number of indices in one face. + bool Solid; ///< Flag: if true then render must use back-face culling, else render must draw both sides of object. - std::list Vertices;///< Vertices list. - size_t NumIndices;///< Number of indices in one face. - bool Solid;///< Flag: if true then render must use back-face culling, else render must draw both sides of object. - - /***********************************************/ - /****************** Functions ******************/ - /***********************************************/ - -private: - - /// \fn CX3DImporter_NodeElement_Geometry3D(const CX3DImporter_NodeElement_Geometry3D& pNode) - /// Disabled copy constructor. - CX3DImporter_NodeElement_Geometry3D(const CX3DImporter_NodeElement_Geometry3D& pNode); - - /// \fn CX3DImporter_NodeElement_Geometry3D& operator=(const CX3DImporter_NodeElement_Geometry3D& pNode) - /// Disabled assign operator. - CX3DImporter_NodeElement_Geometry3D& operator=(const CX3DImporter_NodeElement_Geometry3D& pNode); - -public: - - /// \fn CX3DImporter_NodeElement_Geometry3D(const EType pType, CX3DImporter_NodeElement* pParent) /// Constructor. /// \param [in] pParent - pointer to parent node. /// \param [in] pType - type of geometry object. CX3DImporter_NodeElement_Geometry3D(const EType pType, CX3DImporter_NodeElement* pParent) - : CX3DImporter_NodeElement(pType, pParent), Solid(true) - {} + : CX3DImporter_NodeElement(pType, pParent) + , Vertices() + , NumIndices( 0 ) + , Solid(true) { + // empty + } +private: + /// Disabled copy constructor. + CX3DImporter_NodeElement_Geometry3D(const CX3DImporter_NodeElement_Geometry3D& pNode); + + /// Disabled assign operator. + CX3DImporter_NodeElement_Geometry3D& operator=(const CX3DImporter_NodeElement_Geometry3D& pNode); };// class CX3DImporter_NodeElement_Geometry3D /// \class CX3DImporter_NodeElement_ElevationGrid @@ -520,7 +509,7 @@ public: /// If the angle between the geometric normals of two adjacent faces is less than the crease angle, normals shall be calculated so that the faces are /// shaded smoothly across the edge; otherwise, normals shall be calculated so that a lighting discontinuity across the edge is produced. float CreaseAngle; - std::list CoordIdx;///< Coordinates list by faces. In X3D format: "-1" - delimiter for faces. + std::vector CoordIdx;///< Coordinates list by faces. In X3D format: "-1" - delimiter for faces. /***********************************************/ /****************** Functions ******************/ @@ -566,21 +555,21 @@ public: /// direction. If normals are not generated but are supplied using a Normal node, and the orientation of the normals does not match the setting of the /// ccw field, results are undefined. bool CCW; - std::list ColorIndex;///< Field to specify the polygonal faces by indexing into the or . + std::vector ColorIndex;///< Field to specify the polygonal faces by indexing into the or . bool ColorPerVertex;///< If true then colors are defined for every vertex, else for every face(line). /// \var Convex /// The convex field indicates whether all polygons in the shape are convex (TRUE). A polygon is convex if it is planar, does not intersect itself, /// and all of the interior angles at its vertices are less than 180 degrees. Non planar and self intersecting polygons may produce undefined results /// even if the convex field is FALSE. bool Convex; - std::list CoordIndex;///< Field to specify the polygonal faces by indexing into the . + std::vector CoordIndex;///< Field to specify the polygonal faces by indexing into the . /// \var CreaseAngle /// If the angle between the geometric normals of two adjacent faces is less than the crease angle, normals shall be calculated so that the faces are /// shaded smoothly across the edge; otherwise, normals shall be calculated so that a lighting discontinuity across the edge is produced. float CreaseAngle; - std::list NormalIndex;///< Field to specify the polygonal faces by indexing into the . + std::vector NormalIndex;///< Field to specify the polygonal faces by indexing into the . bool NormalPerVertex;///< If true then normals are defined for every vertex, else for every face(line). - std::list TexCoordIndex;///< Field to specify the polygonal faces by indexing into the . + std::vector TexCoordIndex;///< Field to specify the polygonal faces by indexing into the . /***********************************************/ /****************** Functions ******************/ @@ -628,10 +617,10 @@ public: bool CCW; bool ColorPerVertex;///< If true then colors are defined for every vertex, else for every face(line). bool NormalPerVertex;///< If true then normals are defined for every vertex, else for every face(line). - std::list CoordIndex;///< Field to specify the polygonal faces by indexing into the . - std::list NormalIndex;///< Field to specify the polygonal faces by indexing into the . - std::list TexCoordIndex;///< Field to specify the polygonal faces by indexing into the . - std::list VertexCount;///< Field describes how many vertices are to be used in each polyline(polygon) from the field. + std::vector CoordIndex;///< Field to specify the polygonal faces by indexing into the . + std::vector NormalIndex;///< Field to specify the polygonal faces by indexing into the . + std::vector TexCoordIndex;///< Field to specify the polygonal faces by indexing into the . + std::vector VertexCount;///< Field describes how many vertices are to be used in each polyline(polygon) from the field. /***********************************************/ /****************** Functions ******************/ @@ -687,45 +676,35 @@ struct CX3DImporter_NodeElement_Appearance : public CX3DImporter_NodeElement /// \class CX3DImporter_NodeElement_Material /// Material. -class CX3DImporter_NodeElement_Material : public CX3DImporter_NodeElement -{ - /***********************************************/ - /****************** Variables ******************/ - /***********************************************/ - +class CX3DImporter_NodeElement_Material : public CX3DImporter_NodeElement { public: + float AmbientIntensity;///< Specifies how much ambient light from light sources this surface shall reflect. + aiColor3D DiffuseColor; ///< Reflects all X3D light sources depending on the angle of the surface with respect to the light source. + aiColor3D EmissiveColor; ///< Models "glowing" objects. This can be useful for displaying pre-lit models. + float Shininess; ///< Lower shininess values produce soft glows, while higher values result in sharper, smaller highlights. + aiColor3D SpecularColor; ///< The specularColor and shininess fields determine the specular highlights. + float Transparency; ///< Specifies how "clear" an object is, with 1.0 being completely transparent, and 0.0 completely opaque. - float AmbientIntensity;///< Specifies how much ambient light from light sources this surface shall reflect. - aiColor3D DiffuseColor;///< Reflects all X3D light sources depending on the angle of the surface with respect to the light source. - aiColor3D EmissiveColor;///< Models "glowing" objects. This can be useful for displaying pre-lit models. - float Shininess;///< Lower shininess values produce soft glows, while higher values result in sharper, smaller highlights. - aiColor3D SpecularColor;///< The specularColor and shininess fields determine the specular highlights. - float Transparency;///< Specifies how "clear" an object is, with 1.0 being completely transparent, and 0.0 completely opaque. - - /***********************************************/ - /****************** Functions ******************/ - /***********************************************/ - -private: - - /// \fn CX3DImporter_NodeElement_Material(const CX3DImporter_NodeElement_Material& pNode) - /// Disabled copy constructor. - CX3DImporter_NodeElement_Material(const CX3DImporter_NodeElement_Material& pNode); - - /// \fn CX3DImporter_NodeElement_Material& operator=(const CX3DImporter_NodeElement_Material& pNode) - /// Disabled assign operator. - CX3DImporter_NodeElement_Material& operator=(const CX3DImporter_NodeElement_Material& pNode); - -public: - - /// \fn CX3DImporter_NodeElement_Material(const EType pType, CX3DImporter_NodeElement* pParent) /// Constructor. /// \param [in] pParent - pointer to parent node. /// \param [in] pType - type of geometry object. CX3DImporter_NodeElement_Material(CX3DImporter_NodeElement* pParent) - : CX3DImporter_NodeElement(ENET_Material, pParent) - {} + : CX3DImporter_NodeElement(ENET_Material, pParent) + , AmbientIntensity( 0.0f ) + , DiffuseColor() + , EmissiveColor() + , Shininess( 0.0f ) + , SpecularColor() + , Transparency( 1.0f ) { + // empty + } +private: + /// Disabled copy constructor. + CX3DImporter_NodeElement_Material(const CX3DImporter_NodeElement_Material& pNode); + + /// Disabled assign operator. + CX3DImporter_NodeElement_Material& operator=(const CX3DImporter_NodeElement_Material& pNode); };// class CX3DImporter_NodeElement_Material /// \struct CX3DImporter_NodeElement_ImageTexture @@ -780,7 +759,7 @@ struct CX3DImporter_NodeElement_Light : public CX3DImporter_NodeElement float Intensity;///< Specifies the brightness of the direct emission from the light. /// \var Attenuation /// PointLight node's illumination falls off with distance as specified by three attenuation coefficients. The attenuation factor - /// is: "1 / max(attenuation[0] + attenuation[1] × r + attenuation[2] × r2, 1)", where r is the distance from the light to the surface being illuminated. + /// is: "1 / max(attenuation[0] + attenuation[1] * r + attenuation[2] * r2, 1)", where r is the distance from the light to the surface being illuminated. aiVector3D Attenuation; aiVector3D Location;///< Specifies a translation offset of the centre point of the light source from the light's local coordinate system origin. float Radius;///< Specifies the radial extent of the solid angle and the maximum distance from location that may be illuminated by the light source. diff --git a/code/X3DImporter_Postprocess.cpp b/code/X3DImporter_Postprocess.cpp index 6ae47b736..390ef8995 100644 --- a/code/X3DImporter_Postprocess.cpp +++ b/code/X3DImporter_Postprocess.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -47,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "X3DImporter.hpp" // Header files, Assimp. +#include #include "StandardShapes.h" #include "StringUtils.h" @@ -356,6 +358,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle // copy additional information from children for(std::list::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) { + ai_assert(*pMesh); if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex); else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) @@ -388,6 +391,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle // copy additional information from children for(std::list::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) { + ai_assert(*pMesh); if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex); else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) @@ -445,6 +449,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle // copy additional information from children for(std::list::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) { + ai_assert(*pMesh); if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, true); else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) @@ -474,6 +479,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle // copy additional information from children for(std::list::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) { + ai_assert(*pMesh); if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, true); else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) @@ -503,6 +509,9 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle // copy additional information from children for(std::list::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) { + if ( nullptr == *pMesh ) { + break; + } if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value,tnemesh.ColorPerVertex); else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) @@ -546,6 +555,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle // copy additional information from children for(std::list::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) { + ai_assert(*pMesh); if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex); else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) @@ -580,6 +590,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle // copy additional information from children for(std::list::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++) { + ai_assert(*pMesh); if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color) MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex); else if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_ColorRGBA) @@ -627,10 +638,10 @@ void X3DImporter::Postprocess_BuildNode(const CX3DImporter_NodeElement& pNodeEle } else { - for(size_t i = 0; i < (size_t)tne_group.Choice; i++) chit_begin++;// forward iterator to choosen node. + for(size_t i = 0; i < (size_t)tne_group.Choice; i++) chit_begin++;// forward iterator to chosen node. chit_end = chit_begin; - chit_end++;// point end iterator to next element after choosen. + chit_end++;// point end iterator to next element after chosen node. } }// if(tne_group.UseChoice) }// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Group) diff --git a/code/X3DImporter_Rendering.cpp b/code/X3DImporter_Rendering.cpp index 29dc28765..1d4632f32 100644 --- a/code/X3DImporter_Rendering.cpp +++ b/code/X3DImporter_Rendering.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -179,16 +180,16 @@ void X3DImporter::ParseNode_Rendering_Coordinate() void X3DImporter::ParseNode_Rendering_IndexedLineSet() { std::string use, def; - std::list colorIndex; + std::vector colorIndex; bool colorPerVertex = true; - std::list coordIndex; + std::vector coordIndex; CX3DImporter_NodeElement* ne( nullptr ); MACRO_ATTRREAD_LOOPBEG; MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use); - MACRO_ATTRREAD_CHECK_REF("colorIndex", colorIndex, XML_ReadNode_GetAttrVal_AsListI32); + MACRO_ATTRREAD_CHECK_REF("colorIndex", colorIndex, XML_ReadNode_GetAttrVal_AsArrI32); MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool); - MACRO_ATTRREAD_CHECK_REF("coordIndex", coordIndex, XML_ReadNode_GetAttrVal_AsListI32); + MACRO_ATTRREAD_CHECK_REF("coordIndex", coordIndex, XML_ReadNode_GetAttrVal_AsArrI32); MACRO_ATTRREAD_LOOPEND; // if "USE" defined then find already defined element. @@ -255,7 +256,7 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleFanSet() std::string use, def; bool ccw = true; bool colorPerVertex = true; - std::list index; + std::vector index; bool normalPerVertex = true; bool solid = true; CX3DImporter_NodeElement* ne( nullptr ); @@ -264,7 +265,7 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleFanSet() MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use); MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool); MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool); - MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsListI32); + MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsArrI32); MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool); MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool); MACRO_ATTRREAD_LOOPEND; @@ -287,9 +288,46 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleFanSet() ne_alias.CCW = ccw; ne_alias.ColorPerVertex = colorPerVertex; - ne_alias.CoordIndex = index; ne_alias.NormalPerVertex = normalPerVertex; ne_alias.Solid = solid; + + ne_alias.CoordIndex.clear(); + int counter = 0; + int32_t idx[3]; + for(std::vector::const_iterator idx_it = index.begin(); idx_it != index.end(); idx_it++) + { + idx[2] = *idx_it; + if (idx[2] < 0) + { + counter = 0; + } + else + { + if (counter >= 2) + { + if(ccw) + { + ne_alias.CoordIndex.push_back(idx[0]); + ne_alias.CoordIndex.push_back(idx[1]); + ne_alias.CoordIndex.push_back(idx[2]); + } + else + { + ne_alias.CoordIndex.push_back(idx[0]); + ne_alias.CoordIndex.push_back(idx[2]); + ne_alias.CoordIndex.push_back(idx[1]); + } + ne_alias.CoordIndex.push_back(-1); + idx[1] = idx[2]; + } + else + { + idx[counter] = idx[2]; + } + ++counter; + } + }// for(std::list::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++) + // check for child nodes if(!mReader->isEmptyElement()) { @@ -336,7 +374,7 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleSet() std::string use, def; bool ccw = true; bool colorPerVertex = true; - std::list index; + std::vector index; bool normalPerVertex = true; bool solid = true; CX3DImporter_NodeElement* ne( nullptr ); @@ -345,7 +383,7 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleSet() MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use); MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool); MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool); - MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsListI32); + MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsArrI32); MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool); MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool); MACRO_ATTRREAD_LOOPEND; @@ -368,9 +406,34 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleSet() ne_alias.CCW = ccw; ne_alias.ColorPerVertex = colorPerVertex; - ne_alias.CoordIndex = index; ne_alias.NormalPerVertex = normalPerVertex; ne_alias.Solid = solid; + + ne_alias.CoordIndex.clear(); + int counter = 0; + int32_t idx[3]; + for(std::vector::const_iterator idx_it = index.begin(); idx_it != index.end(); idx_it++) + { + idx[counter++] = *idx_it; + if (counter > 2) + { + counter = 0; + if(ccw) + { + ne_alias.CoordIndex.push_back(idx[0]); + ne_alias.CoordIndex.push_back(idx[1]); + ne_alias.CoordIndex.push_back(idx[2]); + } + else + { + ne_alias.CoordIndex.push_back(idx[0]); + ne_alias.CoordIndex.push_back(idx[2]); + ne_alias.CoordIndex.push_back(idx[1]); + } + ne_alias.CoordIndex.push_back(-1); + } + }// for(std::list::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++) + // check for child nodes if(!mReader->isEmptyElement()) { @@ -417,7 +480,7 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleStripSet() std::string use, def; bool ccw = true; bool colorPerVertex = true; - std::list index; + std::vector index; bool normalPerVertex = true; bool solid = true; CX3DImporter_NodeElement* ne( nullptr ); @@ -426,7 +489,7 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleStripSet() MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use); MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool); MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool); - MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsListI32); + MACRO_ATTRREAD_CHECK_REF("index", index, XML_ReadNode_GetAttrVal_AsArrI32); MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool); MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool); MACRO_ATTRREAD_LOOPEND; @@ -449,9 +512,42 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleStripSet() ne_alias.CCW = ccw; ne_alias.ColorPerVertex = colorPerVertex; - ne_alias.CoordIndex = index; ne_alias.NormalPerVertex = normalPerVertex; ne_alias.Solid = solid; + + ne_alias.CoordIndex.clear(); + int counter = 0; + int32_t idx[3]; + for(std::vector::const_iterator idx_it = index.begin(); idx_it != index.end(); idx_it++) + { + idx[2] = *idx_it; + if (idx[2] < 0) + { + counter = 0; + } + else + { + if (counter >= 2) + { + if(ccw) + { + ne_alias.CoordIndex.push_back(idx[0]); + ne_alias.CoordIndex.push_back(idx[1]); + ne_alias.CoordIndex.push_back(idx[2]); + } + else + { + ne_alias.CoordIndex.push_back(idx[0]); + ne_alias.CoordIndex.push_back(idx[2]); + ne_alias.CoordIndex.push_back(idx[1]); + } + ne_alias.CoordIndex.push_back(-1); + } + idx[counter & 1] = idx[2]; + ++counter; + } + }// for(std::list::const_iterator idx_it = index.begin(); idx_it != ne_alias.index.end(); idx_it++) + // check for child nodes if(!mReader->isEmptyElement()) { @@ -491,12 +587,12 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleStripSet() void X3DImporter::ParseNode_Rendering_LineSet() { std::string use, def; - std::list vertexCount; + std::vector vertexCount; CX3DImporter_NodeElement* ne( nullptr ); MACRO_ATTRREAD_LOOPBEG; MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use); - MACRO_ATTRREAD_CHECK_REF("vertexCount", vertexCount, XML_ReadNode_GetAttrVal_AsListI32); + MACRO_ATTRREAD_CHECK_REF("vertexCount", vertexCount, XML_ReadNode_GetAttrVal_AsArrI32); MACRO_ATTRREAD_LOOPEND; // if "USE" defined then find already defined element. @@ -520,7 +616,7 @@ void X3DImporter::ParseNode_Rendering_LineSet() size_t coord_num = 0; ne_alias.CoordIndex.clear(); - for(std::list::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++) + for(std::vector::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++) { if(*vc_it < 2) throw DeadlyImportError("LineSet. vertexCount shall be greater than or equal to two."); @@ -626,7 +722,7 @@ void X3DImporter::ParseNode_Rendering_TriangleFanSet() std::string use, def; bool ccw = true; bool colorPerVertex = true; - std::list fanCount; + std::vector fanCount; bool normalPerVertex = true; bool solid = true; CX3DImporter_NodeElement* ne( nullptr ); @@ -635,7 +731,7 @@ void X3DImporter::ParseNode_Rendering_TriangleFanSet() MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use); MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool); MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool); - MACRO_ATTRREAD_CHECK_REF("fanCount", fanCount, XML_ReadNode_GetAttrVal_AsListI32); + MACRO_ATTRREAD_CHECK_REF("fanCount", fanCount, XML_ReadNode_GetAttrVal_AsArrI32); MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool); MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool); MACRO_ATTRREAD_LOOPEND; @@ -668,7 +764,7 @@ void X3DImporter::ParseNode_Rendering_TriangleFanSet() // assign indices for first triangle coord_num_first = 0; coord_num_prev = 1; - for(std::list::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++) + for(std::vector::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++) { if(*vc_it < 3) throw DeadlyImportError("TriangleFanSet. fanCount shall be greater than or equal to three."); @@ -817,7 +913,7 @@ void X3DImporter::ParseNode_Rendering_TriangleStripSet() std::string use, def; bool ccw = true; bool colorPerVertex = true; - std::list stripCount; + std::vector stripCount; bool normalPerVertex = true; bool solid = true; CX3DImporter_NodeElement* ne( nullptr ); @@ -826,7 +922,7 @@ void X3DImporter::ParseNode_Rendering_TriangleStripSet() MACRO_ATTRREAD_CHECKUSEDEF_RET(def, use); MACRO_ATTRREAD_CHECK_RET("ccw", ccw, XML_ReadNode_GetAttrVal_AsBool); MACRO_ATTRREAD_CHECK_RET("colorPerVertex", colorPerVertex, XML_ReadNode_GetAttrVal_AsBool); - MACRO_ATTRREAD_CHECK_REF("stripCount", stripCount, XML_ReadNode_GetAttrVal_AsListI32); + MACRO_ATTRREAD_CHECK_REF("stripCount", stripCount, XML_ReadNode_GetAttrVal_AsArrI32); MACRO_ATTRREAD_CHECK_RET("normalPerVertex", normalPerVertex, XML_ReadNode_GetAttrVal_AsBool); MACRO_ATTRREAD_CHECK_RET("solid", solid, XML_ReadNode_GetAttrVal_AsBool); MACRO_ATTRREAD_LOOPEND; @@ -859,7 +955,7 @@ void X3DImporter::ParseNode_Rendering_TriangleStripSet() ne_alias.CoordIndex.clear(); coord_num_sb = 0; - for(std::list::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++) + for(std::vector::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++) { if(*vc_it < 3) throw DeadlyImportError("TriangleStripSet. stripCount shall be greater than or equal to three."); diff --git a/code/X3DImporter_Shape.cpp b/code/X3DImporter_Shape.cpp index 7b3c7da77..55ce7fa99 100644 --- a/code/X3DImporter_Shape.cpp +++ b/code/X3DImporter_Shape.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/X3DImporter_Texturing.cpp b/code/X3DImporter_Texturing.cpp index 8372a231b..40ea47797 100644 --- a/code/X3DImporter_Texturing.cpp +++ b/code/X3DImporter_Texturing.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/X3DVocabulary.cpp b/code/X3DVocabulary.cpp new file mode 100644 index 000000000..780c4ffc2 --- /dev/null +++ b/code/X3DVocabulary.cpp @@ -0,0 +1,1675 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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 X3DVocabulary.cpp +/// \brief Vocabulary for Fast Infoset encoded binary X3D files. +/// \date 2017 +/// \author Patrick Daehne + +#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER + +#include "FIReader.hpp" + +namespace Assimp { + +static const char *encodingAlgorithmTable_3_2[] = { + "encoder://web3d.org/QuantizedFloatArrayEncoder", + "encoder://web3d.org/DeltazlibIntArrayEncoder", + "encoder://web3d.org/QuantizedzlibFloatArrayEncoder", + "encoder://web3d.org/zlibFloatArrayEncoder", + "encoder://web3d.org/QuantizedDoubleArrayEncoder", + "encoder://web3d.org/zlibDoubleArrayEncoder", + "encoder://web3d.org/QuantizedzlibDoubleArrayEncoder", + "encoder://web3d.org/RangeIntArrayEncoder" +}; + +static const std::shared_ptr attributeValueTable_3_2[] = { + FIStringValue::create("false"), + FIStringValue::create("true") +}; + +static const FIQName elementNameTable_3_2[] = { + { "Shape", nullptr, nullptr }, + { "Appearance", nullptr, nullptr }, + { "Material", nullptr, nullptr }, + { "IndexedFaceSet", nullptr, nullptr }, + { "ProtoInstance", nullptr, nullptr }, + { "Transform", nullptr, nullptr }, + { "ImageTexture", nullptr, nullptr }, + { "TextureTransform", nullptr, nullptr }, + { "Coordinate", nullptr, nullptr }, + { "Normal", nullptr, nullptr }, + { "Color", nullptr, nullptr }, + { "ColorRGBA", nullptr, nullptr }, + { "TextureCoordinate", nullptr, nullptr }, + { "ROUTE", nullptr, nullptr }, + { "fieldValue", nullptr, nullptr }, + { "Group", nullptr, nullptr }, + { "LOD", nullptr, nullptr }, + { "Switch", nullptr, nullptr }, + { "Script", nullptr, nullptr }, + { "IndexedTriangleFanSet", nullptr, nullptr }, + { "IndexedTriangleSet", nullptr, nullptr }, + { "IndexedTriangleStripSet", nullptr, nullptr }, + { "MultiTexture", nullptr, nullptr }, + { "MultiTextureCoordinate", nullptr, nullptr }, + { "MultiTextureTransform", nullptr, nullptr }, + { "IndexedLineSet", nullptr, nullptr }, + { "PointSet", nullptr, nullptr }, + { "StaticGroup", nullptr, nullptr }, + { "Sphere", nullptr, nullptr }, + { "Box", nullptr, nullptr }, + { "Cone", nullptr, nullptr }, + { "Anchor", nullptr, nullptr }, + { "Arc2D", nullptr, nullptr }, + { "ArcClose2D", nullptr, nullptr }, + { "AudioClip", nullptr, nullptr }, + { "Background", nullptr, nullptr }, + { "Billboard", nullptr, nullptr }, + { "BooleanFilter", nullptr, nullptr }, + { "BooleanSequencer", nullptr, nullptr }, + { "BooleanToggle", nullptr, nullptr }, + { "BooleanTrigger", nullptr, nullptr }, + { "Circle2D", nullptr, nullptr }, + { "Collision", nullptr, nullptr }, + { "ColorInterpolator", nullptr, nullptr }, + { "Contour2D", nullptr, nullptr }, + { "ContourPolyline2D", nullptr, nullptr }, + { "CoordinateDouble", nullptr, nullptr }, + { "CoordinateInterpolator", nullptr, nullptr }, + { "CoordinateInterpolator2D", nullptr, nullptr }, + { "Cylinder", nullptr, nullptr }, + { "CylinderSensor", nullptr, nullptr }, + { "DirectionalLight", nullptr, nullptr }, + { "Disk2D", nullptr, nullptr }, + { "EXPORT", nullptr, nullptr }, + { "ElevationGrid", nullptr, nullptr }, + { "EspduTransform", nullptr, nullptr }, + { "ExternProtoDeclare", nullptr, nullptr }, + { "Extrusion", nullptr, nullptr }, + { "FillProperties", nullptr, nullptr }, + { "Fog", nullptr, nullptr }, + { "FontStyle", nullptr, nullptr }, + { "GeoCoordinate", nullptr, nullptr }, + { "GeoElevationGrid", nullptr, nullptr }, + { "GeoLOD", nullptr, nullptr }, + { "GeoLocation", nullptr, nullptr }, + { "GeoMetadata", nullptr, nullptr }, + { "GeoOrigin", nullptr, nullptr }, + { "GeoPositionInterpolator", nullptr, nullptr }, + { "GeoTouchSensor", nullptr, nullptr }, + { "GeoViewpoint", nullptr, nullptr }, + { "HAnimDisplacer", nullptr, nullptr }, + { "HAnimHumanoid", nullptr, nullptr }, + { "HAnimJoint", nullptr, nullptr }, + { "HAnimSegment", nullptr, nullptr }, + { "HAnimSite", nullptr, nullptr }, + { "IMPORT", nullptr, nullptr }, + { "IS", nullptr, nullptr }, + { "Inline", nullptr, nullptr }, + { "IntegerSequencer", nullptr, nullptr }, + { "IntegerTrigger", nullptr, nullptr }, + { "KeySensor", nullptr, nullptr }, + { "LineProperties", nullptr, nullptr }, + { "LineSet", nullptr, nullptr }, + { "LoadSensor", nullptr, nullptr }, + { "MetadataDouble", nullptr, nullptr }, + { "MetadataFloat", nullptr, nullptr }, + { "MetadataInteger", nullptr, nullptr }, + { "MetadataSet", nullptr, nullptr }, + { "MetadataString", nullptr, nullptr }, + { "MovieTexture", nullptr, nullptr }, + { "NavigationInfo", nullptr, nullptr }, + { "NormalInterpolator", nullptr, nullptr }, + { "NurbsCurve", nullptr, nullptr }, + { "NurbsCurve2D", nullptr, nullptr }, + { "NurbsOrientationInterpolator", nullptr, nullptr }, + { "NurbsPatchSurface", nullptr, nullptr }, + { "NurbsPositionInterpolator", nullptr, nullptr }, + { "NurbsSet", nullptr, nullptr }, + { "NurbsSurfaceInterpolator", nullptr, nullptr }, + { "NurbsSweptSurface", nullptr, nullptr }, + { "NurbsSwungSurface", nullptr, nullptr }, + { "NurbsTextureCoordinate", nullptr, nullptr }, + { "NurbsTrimmedSurface", nullptr, nullptr }, + { "OrientationInterpolator", nullptr, nullptr }, + { "PixelTexture", nullptr, nullptr }, + { "PlaneSensor", nullptr, nullptr }, + { "PointLight", nullptr, nullptr }, + { "Polyline2D", nullptr, nullptr }, + { "Polypoint2D", nullptr, nullptr }, + { "PositionInterpolator", nullptr, nullptr }, + { "PositionInterpolator2D", nullptr, nullptr }, + { "ProtoBody", nullptr, nullptr }, + { "ProtoDeclare", nullptr, nullptr }, + { "ProtoInterface", nullptr, nullptr }, + { "ProximitySensor", nullptr, nullptr }, + { "ReceiverPdu", nullptr, nullptr }, + { "Rectangle2D", nullptr, nullptr }, + { "ScalarInterpolator", nullptr, nullptr }, + { "Scene", nullptr, nullptr }, + { "SignalPdu", nullptr, nullptr }, + { "Sound", nullptr, nullptr }, + { "SphereSensor", nullptr, nullptr }, + { "SpotLight", nullptr, nullptr }, + { "StringSensor", nullptr, nullptr }, + { "Text", nullptr, nullptr }, + { "TextureBackground", nullptr, nullptr }, + { "TextureCoordinateGenerator", nullptr, nullptr }, + { "TimeSensor", nullptr, nullptr }, + { "TimeTrigger", nullptr, nullptr }, + { "TouchSensor", nullptr, nullptr }, + { "TransmitterPdu", nullptr, nullptr }, + { "TriangleFanSet", nullptr, nullptr }, + { "TriangleSet", nullptr, nullptr }, + { "TriangleSet2D", nullptr, nullptr }, + { "TriangleStripSet", nullptr, nullptr }, + { "Viewpoint", nullptr, nullptr }, + { "VisibilitySensor", nullptr, nullptr }, + { "WorldInfo", nullptr, nullptr }, + { "X3D", nullptr, nullptr }, + { "component", nullptr, nullptr }, + { "connect", nullptr, nullptr }, + { "field", nullptr, nullptr }, + { "head", nullptr, nullptr }, + { "humanoidBodyType", nullptr, nullptr }, + { "meta", nullptr, nullptr }, + { "CADAssembly", nullptr, nullptr }, + { "CADFace", nullptr, nullptr }, + { "CADLayer", nullptr, nullptr }, + { "CADPart", nullptr, nullptr }, + { "ComposedCubeMapTexture", nullptr, nullptr }, + { "ComposedShader", nullptr, nullptr }, + { "ComposedTexture3D", nullptr, nullptr }, + { "FloatVertexAttribute", nullptr, nullptr }, + { "FogCoordinate", nullptr, nullptr }, + { "GeneratedCubeMapTexture", nullptr, nullptr }, + { "ImageCubeMapTexture", nullptr, nullptr }, + { "ImageTexture3D", nullptr, nullptr }, + { "IndexedQuadSet", nullptr, nullptr }, + { "LocalFog", nullptr, nullptr }, + { "Matrix3VertexAttribute", nullptr, nullptr }, + { "Matrix4VertexAttribute", nullptr, nullptr }, + { "PackagedShader", nullptr, nullptr }, + { "PixelTexture3D", nullptr, nullptr }, + { "ProgramShader", nullptr, nullptr }, + { "QuadSet", nullptr, nullptr }, + { "ShaderPart", nullptr, nullptr }, + { "ShaderProgram", nullptr, nullptr }, + { "TextureCoordinate3D", nullptr, nullptr }, + { "TextureCoordinate4D", nullptr, nullptr }, + { "TextureTransform3D", nullptr, nullptr }, + { "TextureTransformMatrix3D", nullptr, nullptr }, + { "BallJoint", nullptr, nullptr }, + { "BoundedPhysicsModel", nullptr, nullptr }, + { "ClipPlane", nullptr, nullptr }, + { "CollidableOffset", nullptr, nullptr }, + { "CollidableShape", nullptr, nullptr }, + { "CollisionCollection", nullptr, nullptr }, + { "CollisionSensor", nullptr, nullptr }, + { "CollisionSpace", nullptr, nullptr }, + { "ColorDamper", nullptr, nullptr }, + { "ConeEmitter", nullptr, nullptr }, + { "Contact", nullptr, nullptr }, + { "CoordinateDamper", nullptr, nullptr }, + { "DISEntityManager", nullptr, nullptr }, + { "DISEntityTypeMapping", nullptr, nullptr }, + { "DoubleAxisHingeJoint", nullptr, nullptr }, + { "EaseInEaseOut", nullptr, nullptr }, + { "ExplosionEmitter", nullptr, nullptr }, + { "ForcePhysicsModel", nullptr, nullptr }, + { "GeoProximitySensor", nullptr, nullptr }, + { "GeoTransform", nullptr, nullptr }, + { "Layer", nullptr, nullptr }, + { "LayerSet", nullptr, nullptr }, + { "Layout", nullptr, nullptr }, + { "LayoutGroup", nullptr, nullptr }, + { "LayoutLayer", nullptr, nullptr }, + { "LinePickSensor", nullptr, nullptr }, + { "MotorJoint", nullptr, nullptr }, + { "OrientationChaser", nullptr, nullptr }, + { "OrientationDamper", nullptr, nullptr }, + { "OrthoViewpoint", nullptr, nullptr }, + { "ParticleSystem", nullptr, nullptr }, + { "PickableGroup", nullptr, nullptr }, + { "PointEmitter", nullptr, nullptr }, + { "PointPickSensor", nullptr, nullptr }, + { "PolylineEmitter", nullptr, nullptr }, + { "PositionChaser", nullptr, nullptr }, + { "PositionChaser2D", nullptr, nullptr }, + { "PositionDamper", nullptr, nullptr }, + { "PositionDamper2D", nullptr, nullptr }, + { "PrimitivePickSensor", nullptr, nullptr }, + { "RigidBody", nullptr, nullptr }, + { "RigidBodyCollection", nullptr, nullptr }, + { "ScalarChaser", nullptr, nullptr }, + { "ScreenFontStyle", nullptr, nullptr }, + { "ScreenGroup", nullptr, nullptr }, + { "SingleAxisHingeJoint", nullptr, nullptr }, + { "SliderJoint", nullptr, nullptr }, + { "SplinePositionInterpolator", nullptr, nullptr }, + { "SplinePositionInterpolator2D", nullptr, nullptr }, + { "SplineScalarInterpolator", nullptr, nullptr }, + { "SquadOrientationInterpolator", nullptr, nullptr }, + { "SurfaceEmitter", nullptr, nullptr }, + { "TexCoordDamper", nullptr, nullptr }, + { "TextureProperties", nullptr, nullptr }, + { "TransformSensor", nullptr, nullptr }, + { "TwoSidedMaterial", nullptr, nullptr }, + { "UniversalJoint", nullptr, nullptr }, + { "ViewpointGroup", nullptr, nullptr }, + { "Viewport", nullptr, nullptr }, + { "VolumeEmitter", nullptr, nullptr }, + { "VolumePickSensor", nullptr, nullptr }, + { "WindPhysicsModel", nullptr, nullptr } +}; + +static const FIQName attributeNameTable_3_2[] = { + { "DEF", nullptr, nullptr }, + { "USE", nullptr, nullptr }, + { "containerField", nullptr, nullptr }, + { "fromNode", nullptr, nullptr }, + { "fromField", nullptr, nullptr }, + { "toNode", nullptr, nullptr }, + { "toField", nullptr, nullptr }, + { "name", nullptr, nullptr }, + { "value", nullptr, nullptr }, + { "color", nullptr, nullptr }, + { "colorIndex", nullptr, nullptr }, + { "coordIndex", nullptr, nullptr }, + { "texCoordIndex", nullptr, nullptr }, + { "normalIndex", nullptr, nullptr }, + { "colorPerVertex", nullptr, nullptr }, + { "normalPerVertex", nullptr, nullptr }, + { "rotation", nullptr, nullptr }, + { "scale", nullptr, nullptr }, + { "center", nullptr, nullptr }, + { "scaleOrientation", nullptr, nullptr }, + { "translation", nullptr, nullptr }, + { "url", nullptr, nullptr }, + { "repeatS", nullptr, nullptr }, + { "repeatT", nullptr, nullptr }, + { "point", nullptr, nullptr }, + { "vector", nullptr, nullptr }, + { "range", nullptr, nullptr }, + { "ambientIntensity", nullptr, nullptr }, + { "diffuseColor", nullptr, nullptr }, + { "emissiveColor", nullptr, nullptr }, + { "shininess", nullptr, nullptr }, + { "specularColor", nullptr, nullptr }, + { "transparency", nullptr, nullptr }, + { "whichChoice", nullptr, nullptr }, + { "index", nullptr, nullptr }, + { "mode", nullptr, nullptr }, + { "source", nullptr, nullptr }, + { "function", nullptr, nullptr }, + { "alpha", nullptr, nullptr }, + { "vertexCount", nullptr, nullptr }, + { "radius", nullptr, nullptr }, + { "size", nullptr, nullptr }, + { "height", nullptr, nullptr }, + { "solid", nullptr, nullptr }, + { "ccw", nullptr, nullptr }, + { "key", nullptr, nullptr }, + { "keyValue", nullptr, nullptr }, + { "enabled", nullptr, nullptr }, + { "direction", nullptr, nullptr }, + { "position", nullptr, nullptr }, + { "orientation", nullptr, nullptr }, + { "bboxCenter", nullptr, nullptr }, + { "bboxSize", nullptr, nullptr }, + { "AS", nullptr, nullptr }, + { "InlineDEF", nullptr, nullptr }, + { "accessType", nullptr, nullptr }, + { "actionKeyPress", nullptr, nullptr }, + { "actionKeyRelease", nullptr, nullptr }, + { "address", nullptr, nullptr }, + { "altKey", nullptr, nullptr }, + { "antennaLocation", nullptr, nullptr }, + { "antennaPatternLength", nullptr, nullptr }, + { "antennaPatternType", nullptr, nullptr }, + { "applicationID", nullptr, nullptr }, + { "articulationParameterArray", nullptr, nullptr }, + { "articulationParameterChangeIndicatorArray", nullptr, nullptr }, + { "articulationParameterCount", nullptr, nullptr }, + { "articulationParameterDesignatorArray", nullptr, nullptr }, + { "articulationParameterIdPartAttachedArray", nullptr, nullptr }, + { "articulationParameterTypeArray", nullptr, nullptr }, + { "attenuation", nullptr, nullptr }, + { "autoOffset", nullptr, nullptr }, + { "avatarSize", nullptr, nullptr }, + { "axisOfRotation", nullptr, nullptr }, + { "backUrl", nullptr, nullptr }, + { "beamWidth", nullptr, nullptr }, + { "beginCap", nullptr, nullptr }, + { "bindTime", nullptr, nullptr }, + { "bottom", nullptr, nullptr }, + { "bottomRadius", nullptr, nullptr }, + { "bottomUrl", nullptr, nullptr }, + { "centerOfMass", nullptr, nullptr }, + { "centerOfRotation", nullptr, nullptr }, + { "child1Url", nullptr, nullptr }, + { "child2Url", nullptr, nullptr }, + { "child3Url", nullptr, nullptr }, + { "child4Url", nullptr, nullptr }, + { "class", nullptr, nullptr }, + { "closureType", nullptr, nullptr }, + { "collideTime", nullptr, nullptr }, + { "content", nullptr, nullptr }, + { "controlKey", nullptr, nullptr }, + { "controlPoint", nullptr, nullptr }, + { "convex", nullptr, nullptr }, + { "coordinateSystem", nullptr, nullptr }, + { "copyright", nullptr, nullptr }, + { "creaseAngle", nullptr, nullptr }, + { "crossSection", nullptr, nullptr }, + { "cryptoKeyID", nullptr, nullptr }, + { "cryptoSystem", nullptr, nullptr }, + { "cutOffAngle", nullptr, nullptr }, + { "cycleInterval", nullptr, nullptr }, + { "cycleTime", nullptr, nullptr }, + { "data", nullptr, nullptr }, + { "dataFormat", nullptr, nullptr }, + { "dataLength", nullptr, nullptr }, + { "dataUrl", nullptr, nullptr }, + { "date", nullptr, nullptr }, + { "deadReckoning", nullptr, nullptr }, + { "deletionAllowed", nullptr, nullptr }, + { "description", nullptr, nullptr }, + { "detonateTime", nullptr, nullptr }, + { "dir", nullptr, nullptr }, + { "directOutput", nullptr, nullptr }, + { "diskAngle", nullptr, nullptr }, + { "displacements", nullptr, nullptr }, + { "documentation", nullptr, nullptr }, + { "elapsedTime", nullptr, nullptr }, + { "ellipsoid", nullptr, nullptr }, + { "encodingScheme", nullptr, nullptr }, + { "endAngle", nullptr, nullptr }, + { "endCap", nullptr, nullptr }, + { "enterTime", nullptr, nullptr }, + { "enteredText", nullptr, nullptr }, + { "entityCategory", nullptr, nullptr }, + { "entityCountry", nullptr, nullptr }, + { "entityDomain", nullptr, nullptr }, + { "entityExtra", nullptr, nullptr }, + { "entityID", nullptr, nullptr }, + { "entityKind", nullptr, nullptr }, + { "entitySpecific", nullptr, nullptr }, + { "entitySubCategory", nullptr, nullptr }, + { "exitTime", nullptr, nullptr }, + { "extent", nullptr, nullptr }, + { "family", nullptr, nullptr }, + { "fanCount", nullptr, nullptr }, + { "fieldOfView", nullptr, nullptr }, + { "filled", nullptr, nullptr }, + { "finalText", nullptr, nullptr }, + { "fireMissionIndex", nullptr, nullptr }, + { "fired1", nullptr, nullptr }, + { "fired2", nullptr, nullptr }, + { "firedTime", nullptr, nullptr }, + { "firingRange", nullptr, nullptr }, + { "firingRate", nullptr, nullptr }, + { "fogType", nullptr, nullptr }, + { "forceID", nullptr, nullptr }, + { "frequency", nullptr, nullptr }, + { "frontUrl", nullptr, nullptr }, + { "fuse", nullptr, nullptr }, + { "geoCoords", nullptr, nullptr }, + { "geoGridOrigin", nullptr, nullptr }, + { "geoSystem", nullptr, nullptr }, + { "groundAngle", nullptr, nullptr }, + { "groundColor", nullptr, nullptr }, + { "hatchColor", nullptr, nullptr }, + { "hatchStyle", nullptr, nullptr }, + { "hatched", nullptr, nullptr }, + { "headlight", nullptr, nullptr }, + { "horizontal", nullptr, nullptr }, + { "horizontalDatum", nullptr, nullptr }, + { "http-equiv", nullptr, nullptr }, + { "image", nullptr, nullptr }, + { "importedDEF", nullptr, nullptr }, + { "info", nullptr, nullptr }, + { "innerRadius", nullptr, nullptr }, + { "inputFalse", nullptr, nullptr }, + { "inputNegate", nullptr, nullptr }, + { "inputSource", nullptr, nullptr }, + { "inputTrue", nullptr, nullptr }, + { "integerKey", nullptr, nullptr }, + { "intensity", nullptr, nullptr }, + { "jump", nullptr, nullptr }, + { "justify", nullptr, nullptr }, + { "keyPress", nullptr, nullptr }, + { "keyRelease", nullptr, nullptr }, + { "knot", nullptr, nullptr }, + { "lang", nullptr, nullptr }, + { "language", nullptr, nullptr }, + { "leftToRight", nullptr, nullptr }, + { "leftUrl", nullptr, nullptr }, + { "length", nullptr, nullptr }, + { "lengthOfModulationParameters", nullptr, nullptr }, + { "level", nullptr, nullptr }, + { "limitOrientation", nullptr, nullptr }, + { "lineSegments", nullptr, nullptr }, + { "linearAcceleration", nullptr, nullptr }, + { "linearVelocity", nullptr, nullptr }, + { "linetype", nullptr, nullptr }, + { "linewidthScaleFactor", nullptr, nullptr }, + { "llimit", nullptr, nullptr }, + { "load", nullptr, nullptr }, + { "loadTime", nullptr, nullptr }, + { "localDEF", nullptr, nullptr }, + { "location", nullptr, nullptr }, + { "loop", nullptr, nullptr }, + { "marking", nullptr, nullptr }, + { "mass", nullptr, nullptr }, + { "maxAngle", nullptr, nullptr }, + { "maxBack", nullptr, nullptr }, + { "maxExtent", nullptr, nullptr }, + { "maxFront", nullptr, nullptr }, + { "maxPosition", nullptr, nullptr }, + { "metadataFormat", nullptr, nullptr }, + { "minAngle", nullptr, nullptr }, + { "minBack", nullptr, nullptr }, + { "minFront", nullptr, nullptr }, + { "minPosition", nullptr, nullptr }, + { "modulationTypeDetail", nullptr, nullptr }, + { "modulationTypeMajor", nullptr, nullptr }, + { "modulationTypeSpreadSpectrum", nullptr, nullptr }, + { "modulationTypeSystem", nullptr, nullptr }, + { "momentsOfInertia", nullptr, nullptr }, + { "multicastRelayHost", nullptr, nullptr }, + { "multicastRelayPort", nullptr, nullptr }, + { "munitionApplicationID", nullptr, nullptr }, + { "munitionEndPoint", nullptr, nullptr }, + { "munitionEntityID", nullptr, nullptr }, + { "munitionQuantity", nullptr, nullptr }, + { "munitionSiteID", nullptr, nullptr }, + { "munitionStartPoint", nullptr, nullptr }, + { "mustEvaluate", nullptr, nullptr }, + { "navType", nullptr, nullptr }, + { "networkMode", nullptr, nullptr }, + { "next", nullptr, nullptr }, + { "nodeField", nullptr, nullptr }, + { "offset", nullptr, nullptr }, + { "on", nullptr, nullptr }, + { "order", nullptr, nullptr }, + { "originator", nullptr, nullptr }, + { "outerRadius", nullptr, nullptr }, + { "parameter", nullptr, nullptr }, + { "pauseTime", nullptr, nullptr }, + { "pitch", nullptr, nullptr }, + { "points", nullptr, nullptr }, + { "port", nullptr, nullptr }, + { "power", nullptr, nullptr }, + { "previous", nullptr, nullptr }, + { "priority", nullptr, nullptr }, + { "profile", nullptr, nullptr }, + { "progress", nullptr, nullptr }, + { "protoField", nullptr, nullptr }, + { "radioEntityTypeCategory", nullptr, nullptr }, + { "radioEntityTypeCountry", nullptr, nullptr }, + { "radioEntityTypeDomain", nullptr, nullptr }, + { "radioEntityTypeKind", nullptr, nullptr }, + { "radioEntityTypeNomenclature", nullptr, nullptr }, + { "radioEntityTypeNomenclatureVersion", nullptr, nullptr }, + { "radioID", nullptr, nullptr }, + { "readInterval", nullptr, nullptr }, + { "receivedPower", nullptr, nullptr }, + { "receiverState", nullptr, nullptr }, + { "reference", nullptr, nullptr }, + { "relativeAntennaLocation", nullptr, nullptr }, + { "resolution", nullptr, nullptr }, + { "resumeTime", nullptr, nullptr }, + { "rightUrl", nullptr, nullptr }, + { "rootUrl", nullptr, nullptr }, + { "rotateYUp", nullptr, nullptr }, + { "rtpHeaderExpected", nullptr, nullptr }, + { "sampleRate", nullptr, nullptr }, + { "samples", nullptr, nullptr }, + { "shiftKey", nullptr, nullptr }, + { "side", nullptr, nullptr }, + { "siteID", nullptr, nullptr }, + { "skinCoordIndex", nullptr, nullptr }, + { "skinCoordWeight", nullptr, nullptr }, + { "skyAngle", nullptr, nullptr }, + { "skyColor", nullptr, nullptr }, + { "spacing", nullptr, nullptr }, + { "spatialize", nullptr, nullptr }, + { "speed", nullptr, nullptr }, + { "speedFactor", nullptr, nullptr }, + { "spine", nullptr, nullptr }, + { "startAngle", nullptr, nullptr }, + { "startTime", nullptr, nullptr }, + { "stiffness", nullptr, nullptr }, + { "stopTime", nullptr, nullptr }, + { "string", nullptr, nullptr }, + { "stripCount", nullptr, nullptr }, + { "style", nullptr, nullptr }, + { "summary", nullptr, nullptr }, + { "tdlType", nullptr, nullptr }, + { "tessellation", nullptr, nullptr }, + { "tessellationScale", nullptr, nullptr }, + { "time", nullptr, nullptr }, + { "timeOut", nullptr, nullptr }, + { "timestamp", nullptr, nullptr }, + { "title", nullptr, nullptr }, + { "toggle", nullptr, nullptr }, + { "top", nullptr, nullptr }, + { "topToBottom", nullptr, nullptr }, + { "topUrl", nullptr, nullptr }, + { "touchTime", nullptr, nullptr }, + { "transmitFrequencyBandwidth", nullptr, nullptr }, + { "transmitState", nullptr, nullptr }, + { "transmitterApplicationID", nullptr, nullptr }, + { "transmitterEntityID", nullptr, nullptr }, + { "transmitterRadioID", nullptr, nullptr }, + { "transmitterSiteID", nullptr, nullptr }, + { "transparent", nullptr, nullptr }, + { "triggerTime", nullptr, nullptr }, + { "triggerTrue", nullptr, nullptr }, + { "triggerValue", nullptr, nullptr }, + { "type", nullptr, nullptr }, + { "uDimension", nullptr, nullptr }, + { "uKnot", nullptr, nullptr }, + { "uOrder", nullptr, nullptr }, + { "uTessellation", nullptr, nullptr }, + { "ulimit", nullptr, nullptr }, + { "vDimension", nullptr, nullptr }, + { "vKnot", nullptr, nullptr }, + { "vOrder", nullptr, nullptr }, + { "vTessellation", nullptr, nullptr }, + { "version", nullptr, nullptr }, + { "verticalDatum", nullptr, nullptr }, + { "vertices", nullptr, nullptr }, + { "visibilityLimit", nullptr, nullptr }, + { "visibilityRange", nullptr, nullptr }, + { "warhead", nullptr, nullptr }, + { "weight", nullptr, nullptr }, + { "whichGeometry", nullptr, nullptr }, + { "writeInterval", nullptr, nullptr }, + { "xDimension", nullptr, nullptr }, + { "xSpacing", nullptr, nullptr }, + { "yScale", nullptr, nullptr }, + { "zDimension", nullptr, nullptr }, + { "zSpacing", nullptr, nullptr }, + { "visible", nullptr, nullptr }, + { "repeatR", nullptr, nullptr }, + { "texture", nullptr, nullptr }, + { "back", nullptr, nullptr }, + { "front", nullptr, nullptr }, + { "left", nullptr, nullptr }, + { "right", nullptr, nullptr }, + { "parts", nullptr, nullptr }, + { "isSelected", nullptr, nullptr }, + { "isValid", nullptr, nullptr }, + { "numComponents", nullptr, nullptr }, + { "depth", nullptr, nullptr }, + { "update", nullptr, nullptr }, + { "fogCoord", nullptr, nullptr }, + { "texCoord", nullptr, nullptr }, + { "activate", nullptr, nullptr }, + { "programs", nullptr, nullptr }, + { "matrix", nullptr, nullptr }, + { "anchorPoint", nullptr, nullptr }, + { "body1", nullptr, nullptr }, + { "body2", nullptr, nullptr }, + { "mustOutput", nullptr, nullptr }, + { "body1AnchorPoint", nullptr, nullptr }, + { "body2AnchorPoint", nullptr, nullptr }, + { "plane", nullptr, nullptr }, + { "appliedParameters", nullptr, nullptr }, + { "bounce", nullptr, nullptr }, + { "frictionCoefficients", nullptr, nullptr }, + { "minBounceSpeed", nullptr, nullptr }, + { "slipFactors", nullptr, nullptr }, + { "softnessConstantForceMix", nullptr, nullptr }, + { "softnessErrorCorrection", nullptr, nullptr }, + { "surfaceSpeed", nullptr, nullptr }, + { "isActive", nullptr, nullptr }, + { "useGeometry", nullptr, nullptr }, + { "set_destination", nullptr, nullptr }, + { "set_value", nullptr, nullptr }, + { "tau", nullptr, nullptr }, + { "tolerance", nullptr, nullptr }, + { "value_changed", nullptr, nullptr }, + { "initialDestination", nullptr, nullptr }, + { "initialValue", nullptr, nullptr }, + { "angle", nullptr, nullptr }, + { "variation", nullptr, nullptr }, + { "surfaceArea", nullptr, nullptr }, + { "frictionDirection", nullptr, nullptr }, + { "slipCoefficients", nullptr, nullptr }, + { "category", nullptr, nullptr }, + { "country", nullptr, nullptr }, + { "domain", nullptr, nullptr }, + { "extra", nullptr, nullptr }, + { "kind", nullptr, nullptr }, + { "specific", nullptr, nullptr }, + { "subcategory", nullptr, nullptr }, + { "axis1", nullptr, nullptr }, + { "axis2", nullptr, nullptr }, + { "desiredAngularVelocity1", nullptr, nullptr }, + { "desiredAngularVelocity2", nullptr, nullptr }, + { "maxAngle1", nullptr, nullptr }, + { "maxTorque1", nullptr, nullptr }, + { "maxTorque2", nullptr, nullptr }, + { "minAngle1", nullptr, nullptr }, + { "stopBounce1", nullptr, nullptr }, + { "stopConstantForceMix1", nullptr, nullptr }, + { "stopErrorCorrection1", nullptr, nullptr }, + { "suspensionErrorCorrection", nullptr, nullptr }, + { "suspensionForce", nullptr, nullptr }, + { "body1Axis", nullptr, nullptr }, + { "body2Axis", nullptr, nullptr }, + { "hinge1Angle", nullptr, nullptr }, + { "hinge1AngleRate", nullptr, nullptr }, + { "hinge2Angle", nullptr, nullptr }, + { "hinge2AngleRate", nullptr, nullptr }, + { "set_fraction", nullptr, nullptr }, + { "easeInEaseOut", nullptr, nullptr }, + { "modifiedFraction_changed", nullptr, nullptr }, + { "force", nullptr, nullptr }, + { "geoCenter", nullptr, nullptr }, + { "centerOfRotation_changed", nullptr, nullptr }, + { "geoCoord_changed", nullptr, nullptr }, + { "orientation_changed", nullptr, nullptr }, + { "position_changed", nullptr, nullptr }, + { "isPickable", nullptr, nullptr }, + { "viewport", nullptr, nullptr }, + { "activeLayer", nullptr, nullptr }, + { "align", nullptr, nullptr }, + { "offsetUnits", nullptr, nullptr }, + { "scaleMode", nullptr, nullptr }, + { "sizeUnits", nullptr, nullptr }, + { "layout", nullptr, nullptr }, + { "objectType", nullptr, nullptr }, + { "pickedNormal", nullptr, nullptr }, + { "pickedPoint", nullptr, nullptr }, + { "pickedTextureCoordinate", nullptr, nullptr }, + { "intersectionType", nullptr, nullptr }, + { "sortOrder", nullptr, nullptr }, + { "axis1Angle", nullptr, nullptr }, + { "axis1Torque", nullptr, nullptr }, + { "axis2Angle", nullptr, nullptr }, + { "axis2Torque", nullptr, nullptr }, + { "axis3Angle", nullptr, nullptr }, + { "axis3Torque", nullptr, nullptr }, + { "enabledAxies", nullptr, nullptr }, + { "motor1Axis", nullptr, nullptr }, + { "motor2Axis", nullptr, nullptr }, + { "motor3Axis", nullptr, nullptr }, + { "stop1Bounce", nullptr, nullptr }, + { "stop1ErrorCorrection", nullptr, nullptr }, + { "stop2Bounce", nullptr, nullptr }, + { "stop2ErrorCorrection", nullptr, nullptr }, + { "stop3Bounce", nullptr, nullptr }, + { "stop3ErrorCorrection", nullptr, nullptr }, + { "motor1Angle", nullptr, nullptr }, + { "motor1AngleRate", nullptr, nullptr }, + { "motor2Angle", nullptr, nullptr }, + { "motor2AngleRate", nullptr, nullptr }, + { "motor3Angle", nullptr, nullptr }, + { "motor3AngleRate", nullptr, nullptr }, + { "autoCalc", nullptr, nullptr }, + { "duration", nullptr, nullptr }, + { "retainUserOffsets", nullptr, nullptr }, + { "isBound", nullptr, nullptr }, + { "appearance", nullptr, nullptr }, + { "createParticles", nullptr, nullptr }, + { "lifetimeVariation", nullptr, nullptr }, + { "maxParticles", nullptr, nullptr }, + { "particleLifetime", nullptr, nullptr }, + { "particleSize", nullptr, nullptr }, + { "colorKey", nullptr, nullptr }, + { "geometryType", nullptr, nullptr }, + { "texCoordKey", nullptr, nullptr }, + { "pickable", nullptr, nullptr }, + { "angularDampingFactor", nullptr, nullptr }, + { "angularVelocity", nullptr, nullptr }, + { "autoDamp", nullptr, nullptr }, + { "autoDisable", nullptr, nullptr }, + { "disableAngularSpeed", nullptr, nullptr }, + { "disableLinearSpeed", nullptr, nullptr }, + { "disableTime", nullptr, nullptr }, + { "finiteRotationAxis", nullptr, nullptr }, + { "fixed", nullptr, nullptr }, + { "forces", nullptr, nullptr }, + { "inertia", nullptr, nullptr }, + { "linearDampingFactor", nullptr, nullptr }, + { "torques", nullptr, nullptr }, + { "useFiniteRotation", nullptr, nullptr }, + { "useGlobalForce", nullptr, nullptr }, + { "constantForceMix", nullptr, nullptr }, + { "constantSurfaceThickness", nullptr, nullptr }, + { "errorCorrection", nullptr, nullptr }, + { "iterations", nullptr, nullptr }, + { "maxCorrectionSpeed", nullptr, nullptr }, + { "preferAccuracy", nullptr, nullptr }, + { "pointSize", nullptr, nullptr }, + { "stopBounce", nullptr, nullptr }, + { "stopErrorCorrection", nullptr, nullptr }, + { "angleRate", nullptr, nullptr }, + { "maxSeparation", nullptr, nullptr }, + { "minSeparation", nullptr, nullptr }, + { "separation", nullptr, nullptr }, + { "separationRate", nullptr, nullptr }, + { "closed", nullptr, nullptr }, + { "keyVelocity", nullptr, nullptr }, + { "normalizeVelocity", nullptr, nullptr }, + { "surface", nullptr, nullptr }, + { "anisotropicDegree", nullptr, nullptr }, + { "borderColor", nullptr, nullptr }, + { "borderWidth", nullptr, nullptr }, + { "boundaryModeS", nullptr, nullptr }, + { "boundaryModeT", nullptr, nullptr }, + { "boundaryModeR", nullptr, nullptr }, + { "magnificationFilter", nullptr, nullptr }, + { "minificationFilter", nullptr, nullptr }, + { "textureCompression", nullptr, nullptr }, + { "texturePriority", nullptr, nullptr }, + { "generateMipMaps", nullptr, nullptr }, + { "targetObject", nullptr, nullptr }, + { "backAmbientIntensity", nullptr, nullptr }, + { "backDiffuseColor", nullptr, nullptr }, + { "backEmissiveColor", nullptr, nullptr }, + { "backShininess", nullptr, nullptr }, + { "backSpecularColor", nullptr, nullptr }, + { "separateBackColor", nullptr, nullptr }, + { "displayed", nullptr, nullptr }, + { "clipBoundary", nullptr, nullptr }, + { "internal", nullptr, nullptr }, + { "gustiness", nullptr, nullptr }, + { "turbulence", nullptr, nullptr } +}; + +FIVocabulary X3D_vocabulary_3_2 = { + nullptr, 0, + encodingAlgorithmTable_3_2, 8, + nullptr, 0, + nullptr, 0, + nullptr, 0, + nullptr, 0, + nullptr, 0, + attributeValueTable_3_2, 2, + nullptr, 0, + nullptr, 0, + elementNameTable_3_2, 233, + attributeNameTable_3_2, 516 +}; + +static const char *encodingAlgorithmTable_3_3[] = { + "encoder://web3d.org/QuantizedFloatArrayEncoder", + "encoder://web3d.org/DeltazlibIntArrayEncoder", + "encoder://web3d.org/QuantizedzlibFloatArrayEncoder", + "encoder://web3d.org/zlibFloatArrayEncoder", + "encoder://web3d.org/QuantizedDoubleArrayEncoder", + "encoder://web3d.org/zlibDoubleArrayEncoder", + "encoder://web3d.org/QuantizedzlibDoubleArrayEncoder", + "encoder://web3d.org/RangeIntArrayEncoder" +}; + +static const std::shared_ptr attributeValueTable_3_3[] = { + FIStringValue::create("false"), + FIStringValue::create("true") +}; + +static const FIQName elementNameTable_3_3[] = { + { "Shape", nullptr, nullptr }, + { "Appearance", nullptr, nullptr }, + { "Material", nullptr, nullptr }, + { "IndexedFaceSet", nullptr, nullptr }, + { "ProtoInstance", nullptr, nullptr }, + { "Transform", nullptr, nullptr }, + { "ImageTexture", nullptr, nullptr }, + { "TextureTransform", nullptr, nullptr }, + { "Coordinate", nullptr, nullptr }, + { "Normal", nullptr, nullptr }, + { "Color", nullptr, nullptr }, + { "ColorRGBA", nullptr, nullptr }, + { "TextureCoordinate", nullptr, nullptr }, + { "ROUTE", nullptr, nullptr }, + { "fieldValue", nullptr, nullptr }, + { "Group", nullptr, nullptr }, + { "LOD", nullptr, nullptr }, + { "Switch", nullptr, nullptr }, + { "Script", nullptr, nullptr }, + { "IndexedTriangleFanSet", nullptr, nullptr }, + { "IndexedTriangleSet", nullptr, nullptr }, + { "IndexedTriangleStripSet", nullptr, nullptr }, + { "MultiTexture", nullptr, nullptr }, + { "MultiTextureCoordinate", nullptr, nullptr }, + { "MultiTextureTransform", nullptr, nullptr }, + { "IndexedLineSet", nullptr, nullptr }, + { "PointSet", nullptr, nullptr }, + { "StaticGroup", nullptr, nullptr }, + { "Sphere", nullptr, nullptr }, + { "Box", nullptr, nullptr }, + { "Cone", nullptr, nullptr }, + { "Anchor", nullptr, nullptr }, + { "Arc2D", nullptr, nullptr }, + { "ArcClose2D", nullptr, nullptr }, + { "AudioClip", nullptr, nullptr }, + { "Background", nullptr, nullptr }, + { "Billboard", nullptr, nullptr }, + { "BooleanFilter", nullptr, nullptr }, + { "BooleanSequencer", nullptr, nullptr }, + { "BooleanToggle", nullptr, nullptr }, + { "BooleanTrigger", nullptr, nullptr }, + { "Circle2D", nullptr, nullptr }, + { "Collision", nullptr, nullptr }, + { "ColorInterpolator", nullptr, nullptr }, + { "Contour2D", nullptr, nullptr }, + { "ContourPolyline2D", nullptr, nullptr }, + { "CoordinateDouble", nullptr, nullptr }, + { "CoordinateInterpolator", nullptr, nullptr }, + { "CoordinateInterpolator2D", nullptr, nullptr }, + { "Cylinder", nullptr, nullptr }, + { "CylinderSensor", nullptr, nullptr }, + { "DirectionalLight", nullptr, nullptr }, + { "Disk2D", nullptr, nullptr }, + { "EXPORT", nullptr, nullptr }, + { "ElevationGrid", nullptr, nullptr }, + { "EspduTransform", nullptr, nullptr }, + { "ExternProtoDeclare", nullptr, nullptr }, + { "Extrusion", nullptr, nullptr }, + { "FillProperties", nullptr, nullptr }, + { "Fog", nullptr, nullptr }, + { "FontStyle", nullptr, nullptr }, + { "GeoCoordinate", nullptr, nullptr }, + { "GeoElevationGrid", nullptr, nullptr }, + { "GeoLOD", nullptr, nullptr }, + { "GeoLocation", nullptr, nullptr }, + { "GeoMetadata", nullptr, nullptr }, + { "GeoOrigin", nullptr, nullptr }, + { "GeoPositionInterpolator", nullptr, nullptr }, + { "GeoTouchSensor", nullptr, nullptr }, + { "GeoViewpoint", nullptr, nullptr }, + { "HAnimDisplacer", nullptr, nullptr }, + { "HAnimHumanoid", nullptr, nullptr }, + { "HAnimJoint", nullptr, nullptr }, + { "HAnimSegment", nullptr, nullptr }, + { "HAnimSite", nullptr, nullptr }, + { "IMPORT", nullptr, nullptr }, + { "IS", nullptr, nullptr }, + { "Inline", nullptr, nullptr }, + { "IntegerSequencer", nullptr, nullptr }, + { "IntegerTrigger", nullptr, nullptr }, + { "KeySensor", nullptr, nullptr }, + { "LineProperties", nullptr, nullptr }, + { "LineSet", nullptr, nullptr }, + { "LoadSensor", nullptr, nullptr }, + { "MetadataDouble", nullptr, nullptr }, + { "MetadataFloat", nullptr, nullptr }, + { "MetadataInteger", nullptr, nullptr }, + { "MetadataSet", nullptr, nullptr }, + { "MetadataString", nullptr, nullptr }, + { "MovieTexture", nullptr, nullptr }, + { "NavigationInfo", nullptr, nullptr }, + { "NormalInterpolator", nullptr, nullptr }, + { "NurbsCurve", nullptr, nullptr }, + { "NurbsCurve2D", nullptr, nullptr }, + { "NurbsOrientationInterpolator", nullptr, nullptr }, + { "NurbsPatchSurface", nullptr, nullptr }, + { "NurbsPositionInterpolator", nullptr, nullptr }, + { "NurbsSet", nullptr, nullptr }, + { "NurbsSurfaceInterpolator", nullptr, nullptr }, + { "NurbsSweptSurface", nullptr, nullptr }, + { "NurbsSwungSurface", nullptr, nullptr }, + { "NurbsTextureCoordinate", nullptr, nullptr }, + { "NurbsTrimmedSurface", nullptr, nullptr }, + { "OrientationInterpolator", nullptr, nullptr }, + { "PixelTexture", nullptr, nullptr }, + { "PlaneSensor", nullptr, nullptr }, + { "PointLight", nullptr, nullptr }, + { "Polyline2D", nullptr, nullptr }, + { "Polypoint2D", nullptr, nullptr }, + { "PositionInterpolator", nullptr, nullptr }, + { "PositionInterpolator2D", nullptr, nullptr }, + { "ProtoBody", nullptr, nullptr }, + { "ProtoDeclare", nullptr, nullptr }, + { "ProtoInterface", nullptr, nullptr }, + { "ProximitySensor", nullptr, nullptr }, + { "ReceiverPdu", nullptr, nullptr }, + { "Rectangle2D", nullptr, nullptr }, + { "ScalarInterpolator", nullptr, nullptr }, + { "Scene", nullptr, nullptr }, + { "SignalPdu", nullptr, nullptr }, + { "Sound", nullptr, nullptr }, + { "SphereSensor", nullptr, nullptr }, + { "SpotLight", nullptr, nullptr }, + { "StringSensor", nullptr, nullptr }, + { "Text", nullptr, nullptr }, + { "TextureBackground", nullptr, nullptr }, + { "TextureCoordinateGenerator", nullptr, nullptr }, + { "TimeSensor", nullptr, nullptr }, + { "TimeTrigger", nullptr, nullptr }, + { "TouchSensor", nullptr, nullptr }, + { "TransmitterPdu", nullptr, nullptr }, + { "TriangleFanSet", nullptr, nullptr }, + { "TriangleSet", nullptr, nullptr }, + { "TriangleSet2D", nullptr, nullptr }, + { "TriangleStripSet", nullptr, nullptr }, + { "Viewpoint", nullptr, nullptr }, + { "VisibilitySensor", nullptr, nullptr }, + { "WorldInfo", nullptr, nullptr }, + { "X3D", nullptr, nullptr }, + { "component", nullptr, nullptr }, + { "connect", nullptr, nullptr }, + { "field", nullptr, nullptr }, + { "head", nullptr, nullptr }, + { "humanoidBodyType", nullptr, nullptr }, + { "meta", nullptr, nullptr }, + { "CADAssembly", nullptr, nullptr }, + { "CADFace", nullptr, nullptr }, + { "CADLayer", nullptr, nullptr }, + { "CADPart", nullptr, nullptr }, + { "ComposedCubeMapTexture", nullptr, nullptr }, + { "ComposedShader", nullptr, nullptr }, + { "ComposedTexture3D", nullptr, nullptr }, + { "FloatVertexAttribute", nullptr, nullptr }, + { "FogCoordinate", nullptr, nullptr }, + { "GeneratedCubeMapTexture", nullptr, nullptr }, + { "ImageCubeMapTexture", nullptr, nullptr }, + { "ImageTexture3D", nullptr, nullptr }, + { "IndexedQuadSet", nullptr, nullptr }, + { "LocalFog", nullptr, nullptr }, + { "Matrix3VertexAttribute", nullptr, nullptr }, + { "Matrix4VertexAttribute", nullptr, nullptr }, + { "PackagedShader", nullptr, nullptr }, + { "PixelTexture3D", nullptr, nullptr }, + { "ProgramShader", nullptr, nullptr }, + { "QuadSet", nullptr, nullptr }, + { "ShaderPart", nullptr, nullptr }, + { "ShaderProgram", nullptr, nullptr }, + { "TextureCoordinate3D", nullptr, nullptr }, + { "TextureCoordinate4D", nullptr, nullptr }, + { "TextureTransform3D", nullptr, nullptr }, + { "TextureTransformMatrix3D", nullptr, nullptr }, + { "BallJoint", nullptr, nullptr }, + { "BoundedPhysicsModel", nullptr, nullptr }, + { "ClipPlane", nullptr, nullptr }, + { "CollidableOffset", nullptr, nullptr }, + { "CollidableShape", nullptr, nullptr }, + { "CollisionCollection", nullptr, nullptr }, + { "CollisionSensor", nullptr, nullptr }, + { "CollisionSpace", nullptr, nullptr }, + { "ColorDamper", nullptr, nullptr }, + { "ConeEmitter", nullptr, nullptr }, + { "Contact", nullptr, nullptr }, + { "CoordinateDamper", nullptr, nullptr }, + { "DISEntityManager", nullptr, nullptr }, + { "DISEntityTypeMapping", nullptr, nullptr }, + { "DoubleAxisHingeJoint", nullptr, nullptr }, + { "EaseInEaseOut", nullptr, nullptr }, + { "ExplosionEmitter", nullptr, nullptr }, + { "ForcePhysicsModel", nullptr, nullptr }, + { "GeoProximitySensor", nullptr, nullptr }, + { "GeoTransform", nullptr, nullptr }, + { "Layer", nullptr, nullptr }, + { "LayerSet", nullptr, nullptr }, + { "Layout", nullptr, nullptr }, + { "LayoutGroup", nullptr, nullptr }, + { "LayoutLayer", nullptr, nullptr }, + { "LinePickSensor", nullptr, nullptr }, + { "MotorJoint", nullptr, nullptr }, + { "OrientationChaser", nullptr, nullptr }, + { "OrientationDamper", nullptr, nullptr }, + { "OrthoViewpoint", nullptr, nullptr }, + { "ParticleSystem", nullptr, nullptr }, + { "PickableGroup", nullptr, nullptr }, + { "PointEmitter", nullptr, nullptr }, + { "PointPickSensor", nullptr, nullptr }, + { "PolylineEmitter", nullptr, nullptr }, + { "PositionChaser", nullptr, nullptr }, + { "PositionChaser2D", nullptr, nullptr }, + { "PositionDamper", nullptr, nullptr }, + { "PositionDamper2D", nullptr, nullptr }, + { "PrimitivePickSensor", nullptr, nullptr }, + { "RigidBody", nullptr, nullptr }, + { "RigidBodyCollection", nullptr, nullptr }, + { "ScalarChaser", nullptr, nullptr }, + { "ScreenFontStyle", nullptr, nullptr }, + { "ScreenGroup", nullptr, nullptr }, + { "SingleAxisHingeJoint", nullptr, nullptr }, + { "SliderJoint", nullptr, nullptr }, + { "SplinePositionInterpolator", nullptr, nullptr }, + { "SplinePositionInterpolator2D", nullptr, nullptr }, + { "SplineScalarInterpolator", nullptr, nullptr }, + { "SquadOrientationInterpolator", nullptr, nullptr }, + { "SurfaceEmitter", nullptr, nullptr }, + { "TexCoordDamper2D", nullptr, nullptr }, + { "TextureProperties", nullptr, nullptr }, + { "TransformSensor", nullptr, nullptr }, + { "TwoSidedMaterial", nullptr, nullptr }, + { "UniversalJoint", nullptr, nullptr }, + { "ViewpointGroup", nullptr, nullptr }, + { "Viewport", nullptr, nullptr }, + { "VolumeEmitter", nullptr, nullptr }, + { "VolumePickSensor", nullptr, nullptr }, + { "WindPhysicsModel", nullptr, nullptr }, + { "BlendedVolumeStyle", nullptr, nullptr }, + { "BoundaryEnhancementVolumeStyle", nullptr, nullptr }, + { "CartoonVolumeStyle", nullptr, nullptr }, + { "ComposedVolumeStyle", nullptr, nullptr }, + { "EdgeEnhancementVolumeStyle", nullptr, nullptr }, + { "IsoSurfaceVolumeData", nullptr, nullptr }, + { "MetadataBoolean", nullptr, nullptr }, + { "OpacityMapVolumeStyle", nullptr, nullptr }, + { "ProjectionVolumeStyle", nullptr, nullptr }, + { "SegmentedVolumeData", nullptr, nullptr }, + { "ShadedVolumeStyle", nullptr, nullptr }, + { "SilhouetteEnhancementVolumeStyle", nullptr, nullptr }, + { "ToneMappedVolumeStyle", nullptr, nullptr }, + { "VolumeData", nullptr, nullptr }, + { "ColorChaser", nullptr, nullptr }, + { "CoordinateChaser", nullptr, nullptr }, + { "ScalarDamper", nullptr, nullptr }, + { "TexCoordChaser2D", nullptr, nullptr }, + { "unit", nullptr, nullptr } +}; + +static const FIQName attributeNameTable_3_3[] = { + { "DEF", nullptr, nullptr }, + { "USE", nullptr, nullptr }, + { "containerField", nullptr, nullptr }, + { "fromNode", nullptr, nullptr }, + { "fromField", nullptr, nullptr }, + { "toNode", nullptr, nullptr }, + { "toField", nullptr, nullptr }, + { "name", nullptr, nullptr }, + { "value", nullptr, nullptr }, + { "color", nullptr, nullptr }, + { "colorIndex", nullptr, nullptr }, + { "coordIndex", nullptr, nullptr }, + { "texCoordIndex", nullptr, nullptr }, + { "normalIndex", nullptr, nullptr }, + { "colorPerVertex", nullptr, nullptr }, + { "normalPerVertex", nullptr, nullptr }, + { "rotation", nullptr, nullptr }, + { "scale", nullptr, nullptr }, + { "center", nullptr, nullptr }, + { "scaleOrientation", nullptr, nullptr }, + { "translation", nullptr, nullptr }, + { "url", nullptr, nullptr }, + { "repeatS", nullptr, nullptr }, + { "repeatT", nullptr, nullptr }, + { "point", nullptr, nullptr }, + { "vector", nullptr, nullptr }, + { "range", nullptr, nullptr }, + { "ambientIntensity", nullptr, nullptr }, + { "diffuseColor", nullptr, nullptr }, + { "emissiveColor", nullptr, nullptr }, + { "shininess", nullptr, nullptr }, + { "specularColor", nullptr, nullptr }, + { "transparency", nullptr, nullptr }, + { "whichChoice", nullptr, nullptr }, + { "index", nullptr, nullptr }, + { "mode", nullptr, nullptr }, + { "source", nullptr, nullptr }, + { "function", nullptr, nullptr }, + { "alpha", nullptr, nullptr }, + { "vertexCount", nullptr, nullptr }, + { "radius", nullptr, nullptr }, + { "size", nullptr, nullptr }, + { "height", nullptr, nullptr }, + { "solid", nullptr, nullptr }, + { "ccw", nullptr, nullptr }, + { "key", nullptr, nullptr }, + { "keyValue", nullptr, nullptr }, + { "enabled", nullptr, nullptr }, + { "direction", nullptr, nullptr }, + { "position", nullptr, nullptr }, + { "orientation", nullptr, nullptr }, + { "bboxCenter", nullptr, nullptr }, + { "bboxSize", nullptr, nullptr }, + { "AS", nullptr, nullptr }, + { "InlineDEF", nullptr, nullptr }, + { "accessType", nullptr, nullptr }, + { "actionKeyPress", nullptr, nullptr }, + { "actionKeyRelease", nullptr, nullptr }, + { "address", nullptr, nullptr }, + { "altKey", nullptr, nullptr }, + { "antennaLocation", nullptr, nullptr }, + { "antennaPatternLength", nullptr, nullptr }, + { "antennaPatternType", nullptr, nullptr }, + { "applicationID", nullptr, nullptr }, + { "articulationParameterArray", nullptr, nullptr }, + { "articulationParameterChangeIndicatorArray", nullptr, nullptr }, + { "articulationParameterCount", nullptr, nullptr }, + { "articulationParameterDesignatorArray", nullptr, nullptr }, + { "articulationParameterIdPartAttachedArray", nullptr, nullptr }, + { "articulationParameterTypeArray", nullptr, nullptr }, + { "attenuation", nullptr, nullptr }, + { "autoOffset", nullptr, nullptr }, + { "avatarSize", nullptr, nullptr }, + { "axisOfRotation", nullptr, nullptr }, + { "backUrl", nullptr, nullptr }, + { "beamWidth", nullptr, nullptr }, + { "beginCap", nullptr, nullptr }, + { "bindTime", nullptr, nullptr }, + { "bottom", nullptr, nullptr }, + { "bottomRadius", nullptr, nullptr }, + { "bottomUrl", nullptr, nullptr }, + { "centerOfMass", nullptr, nullptr }, + { "centerOfRotation", nullptr, nullptr }, + { "child1Url", nullptr, nullptr }, + { "child2Url", nullptr, nullptr }, + { "child3Url", nullptr, nullptr }, + { "child4Url", nullptr, nullptr }, + { "class", nullptr, nullptr }, + { "closureType", nullptr, nullptr }, + { "collideTime", nullptr, nullptr }, + { "content", nullptr, nullptr }, + { "controlKey", nullptr, nullptr }, + { "controlPoint", nullptr, nullptr }, + { "convex", nullptr, nullptr }, + { "coordinateSystem", nullptr, nullptr }, + { "copyright", nullptr, nullptr }, + { "creaseAngle", nullptr, nullptr }, + { "crossSection", nullptr, nullptr }, + { "cryptoKeyID", nullptr, nullptr }, + { "cryptoSystem", nullptr, nullptr }, + { "cutOffAngle", nullptr, nullptr }, + { "cycleInterval", nullptr, nullptr }, + { "cycleTime", nullptr, nullptr }, + { "data", nullptr, nullptr }, + { "dataFormat", nullptr, nullptr }, + { "dataLength", nullptr, nullptr }, + { "dataUrl", nullptr, nullptr }, + { "date", nullptr, nullptr }, + { "deadReckoning", nullptr, nullptr }, + { "deletionAllowed", nullptr, nullptr }, + { "description", nullptr, nullptr }, + { "detonateTime", nullptr, nullptr }, + { "dir", nullptr, nullptr }, + { "directOutput", nullptr, nullptr }, + { "diskAngle", nullptr, nullptr }, + { "displacements", nullptr, nullptr }, + { "documentation", nullptr, nullptr }, + { "elapsedTime", nullptr, nullptr }, + { "ellipsoid", nullptr, nullptr }, + { "encodingScheme", nullptr, nullptr }, + { "endAngle", nullptr, nullptr }, + { "endCap", nullptr, nullptr }, + { "enterTime", nullptr, nullptr }, + { "enteredText", nullptr, nullptr }, + { "entityCategory", nullptr, nullptr }, + { "entityCountry", nullptr, nullptr }, + { "entityDomain", nullptr, nullptr }, + { "entityExtra", nullptr, nullptr }, + { "entityID", nullptr, nullptr }, + { "entityKind", nullptr, nullptr }, + { "entitySpecific", nullptr, nullptr }, + { "entitySubCategory", nullptr, nullptr }, + { "exitTime", nullptr, nullptr }, + { "extent", nullptr, nullptr }, + { "family", nullptr, nullptr }, + { "fanCount", nullptr, nullptr }, + { "fieldOfView", nullptr, nullptr }, + { "filled", nullptr, nullptr }, + { "finalText", nullptr, nullptr }, + { "fireMissionIndex", nullptr, nullptr }, + { "fired1", nullptr, nullptr }, + { "fired2", nullptr, nullptr }, + { "firedTime", nullptr, nullptr }, + { "firingRange", nullptr, nullptr }, + { "firingRate", nullptr, nullptr }, + { "fogType", nullptr, nullptr }, + { "forceID", nullptr, nullptr }, + { "frequency", nullptr, nullptr }, + { "frontUrl", nullptr, nullptr }, + { "fuse", nullptr, nullptr }, + { "geoCoords", nullptr, nullptr }, + { "geoGridOrigin", nullptr, nullptr }, + { "geoSystem", nullptr, nullptr }, + { "groundAngle", nullptr, nullptr }, + { "groundColor", nullptr, nullptr }, + { "hatchColor", nullptr, nullptr }, + { "hatchStyle", nullptr, nullptr }, + { "hatched", nullptr, nullptr }, + { "headlight", nullptr, nullptr }, + { "horizontal", nullptr, nullptr }, + { "horizontalDatum", nullptr, nullptr }, + { "http-equiv", nullptr, nullptr }, + { "image", nullptr, nullptr }, + { "importedDEF", nullptr, nullptr }, + { "info", nullptr, nullptr }, + { "innerRadius", nullptr, nullptr }, + { "inputFalse", nullptr, nullptr }, + { "inputNegate", nullptr, nullptr }, + { "inputSource", nullptr, nullptr }, + { "inputTrue", nullptr, nullptr }, + { "integerKey", nullptr, nullptr }, + { "intensity", nullptr, nullptr }, + { "jump", nullptr, nullptr }, + { "justify", nullptr, nullptr }, + { "keyPress", nullptr, nullptr }, + { "keyRelease", nullptr, nullptr }, + { "knot", nullptr, nullptr }, + { "lang", nullptr, nullptr }, + { "language", nullptr, nullptr }, + { "leftToRight", nullptr, nullptr }, + { "leftUrl", nullptr, nullptr }, + { "length", nullptr, nullptr }, + { "lengthOfModulationParameters", nullptr, nullptr }, + { "level", nullptr, nullptr }, + { "limitOrientation", nullptr, nullptr }, + { "lineSegments", nullptr, nullptr }, + { "linearAcceleration", nullptr, nullptr }, + { "linearVelocity", nullptr, nullptr }, + { "linetype", nullptr, nullptr }, + { "linewidthScaleFactor", nullptr, nullptr }, + { "llimit", nullptr, nullptr }, + { "load", nullptr, nullptr }, + { "loadTime", nullptr, nullptr }, + { "localDEF", nullptr, nullptr }, + { "location", nullptr, nullptr }, + { "loop", nullptr, nullptr }, + { "marking", nullptr, nullptr }, + { "mass", nullptr, nullptr }, + { "maxAngle", nullptr, nullptr }, + { "maxBack", nullptr, nullptr }, + { "maxExtent", nullptr, nullptr }, + { "maxFront", nullptr, nullptr }, + { "maxPosition", nullptr, nullptr }, + { "metadataFormat", nullptr, nullptr }, + { "minAngle", nullptr, nullptr }, + { "minBack", nullptr, nullptr }, + { "minFront", nullptr, nullptr }, + { "minPosition", nullptr, nullptr }, + { "modulationTypeDetail", nullptr, nullptr }, + { "modulationTypeMajor", nullptr, nullptr }, + { "modulationTypeSpreadSpectrum", nullptr, nullptr }, + { "modulationTypeSystem", nullptr, nullptr }, + { "momentsOfInertia", nullptr, nullptr }, + { "multicastRelayHost", nullptr, nullptr }, + { "multicastRelayPort", nullptr, nullptr }, + { "munitionApplicationID", nullptr, nullptr }, + { "munitionEndPoint", nullptr, nullptr }, + { "munitionEntityID", nullptr, nullptr }, + { "munitionQuantity", nullptr, nullptr }, + { "munitionSiteID", nullptr, nullptr }, + { "munitionStartPoint", nullptr, nullptr }, + { "mustEvaluate", nullptr, nullptr }, + { "navType", nullptr, nullptr }, + { "networkMode", nullptr, nullptr }, + { "next", nullptr, nullptr }, + { "nodeField", nullptr, nullptr }, + { "offset", nullptr, nullptr }, + { "on", nullptr, nullptr }, + { "order", nullptr, nullptr }, + { "originator", nullptr, nullptr }, + { "outerRadius", nullptr, nullptr }, + { "parameter", nullptr, nullptr }, + { "pauseTime", nullptr, nullptr }, + { "pitch", nullptr, nullptr }, + { "points", nullptr, nullptr }, + { "port", nullptr, nullptr }, + { "power", nullptr, nullptr }, + { "previous", nullptr, nullptr }, + { "priority", nullptr, nullptr }, + { "profile", nullptr, nullptr }, + { "progress", nullptr, nullptr }, + { "protoField", nullptr, nullptr }, + { "radioEntityTypeCategory", nullptr, nullptr }, + { "radioEntityTypeCountry", nullptr, nullptr }, + { "radioEntityTypeDomain", nullptr, nullptr }, + { "radioEntityTypeKind", nullptr, nullptr }, + { "radioEntityTypeNomenclature", nullptr, nullptr }, + { "radioEntityTypeNomenclatureVersion", nullptr, nullptr }, + { "radioID", nullptr, nullptr }, + { "readInterval", nullptr, nullptr }, + { "receivedPower", nullptr, nullptr }, + { "receiverState", nullptr, nullptr }, + { "reference", nullptr, nullptr }, + { "relativeAntennaLocation", nullptr, nullptr }, + { "resolution", nullptr, nullptr }, + { "resumeTime", nullptr, nullptr }, + { "rightUrl", nullptr, nullptr }, + { "rootUrl", nullptr, nullptr }, + { "rotateYUp", nullptr, nullptr }, + { "rtpHeaderExpected", nullptr, nullptr }, + { "sampleRate", nullptr, nullptr }, + { "samples", nullptr, nullptr }, + { "shiftKey", nullptr, nullptr }, + { "side", nullptr, nullptr }, + { "siteID", nullptr, nullptr }, + { "skinCoordIndex", nullptr, nullptr }, + { "skinCoordWeight", nullptr, nullptr }, + { "skyAngle", nullptr, nullptr }, + { "skyColor", nullptr, nullptr }, + { "spacing", nullptr, nullptr }, + { "spatialize", nullptr, nullptr }, + { "speed", nullptr, nullptr }, + { "speedFactor", nullptr, nullptr }, + { "spine", nullptr, nullptr }, + { "startAngle", nullptr, nullptr }, + { "startTime", nullptr, nullptr }, + { "stiffness", nullptr, nullptr }, + { "stopTime", nullptr, nullptr }, + { "string", nullptr, nullptr }, + { "stripCount", nullptr, nullptr }, + { "style", nullptr, nullptr }, + { "summary", nullptr, nullptr }, + { "tdlType", nullptr, nullptr }, + { "tessellation", nullptr, nullptr }, + { "tessellationScale", nullptr, nullptr }, + { "time", nullptr, nullptr }, + { "timeOut", nullptr, nullptr }, + { "timestamp", nullptr, nullptr }, + { "title", nullptr, nullptr }, + { "toggle", nullptr, nullptr }, + { "top", nullptr, nullptr }, + { "topToBottom", nullptr, nullptr }, + { "topUrl", nullptr, nullptr }, + { "touchTime", nullptr, nullptr }, + { "transmitFrequencyBandwidth", nullptr, nullptr }, + { "transmitState", nullptr, nullptr }, + { "transmitterApplicationID", nullptr, nullptr }, + { "transmitterEntityID", nullptr, nullptr }, + { "transmitterRadioID", nullptr, nullptr }, + { "transmitterSiteID", nullptr, nullptr }, + { "transparent", nullptr, nullptr }, + { "triggerTime", nullptr, nullptr }, + { "triggerTrue", nullptr, nullptr }, + { "triggerValue", nullptr, nullptr }, + { "type", nullptr, nullptr }, + { "uDimension", nullptr, nullptr }, + { "uKnot", nullptr, nullptr }, + { "uOrder", nullptr, nullptr }, + { "uTessellation", nullptr, nullptr }, + { "ulimit", nullptr, nullptr }, + { "vDimension", nullptr, nullptr }, + { "vKnot", nullptr, nullptr }, + { "vOrder", nullptr, nullptr }, + { "vTessellation", nullptr, nullptr }, + { "version", nullptr, nullptr }, + { "verticalDatum", nullptr, nullptr }, + { "vertices", nullptr, nullptr }, + { "visibilityLimit", nullptr, nullptr }, + { "visibilityRange", nullptr, nullptr }, + { "warhead", nullptr, nullptr }, + { "weight", nullptr, nullptr }, + { "whichGeometry", nullptr, nullptr }, + { "writeInterval", nullptr, nullptr }, + { "xDimension", nullptr, nullptr }, + { "xSpacing", nullptr, nullptr }, + { "yScale", nullptr, nullptr }, + { "zDimension", nullptr, nullptr }, + { "zSpacing", nullptr, nullptr }, + { "visible", nullptr, nullptr }, + { "repeatR", nullptr, nullptr }, + { "texture", nullptr, nullptr }, + { "back", nullptr, nullptr }, + { "front", nullptr, nullptr }, + { "left", nullptr, nullptr }, + { "right", nullptr, nullptr }, + { "parts", nullptr, nullptr }, + { "isSelected", nullptr, nullptr }, + { "isValid", nullptr, nullptr }, + { "numComponents", nullptr, nullptr }, + { "depth", nullptr, nullptr }, + { "update", nullptr, nullptr }, + { "fogCoord", nullptr, nullptr }, + { "texCoord", nullptr, nullptr }, + { "activate", nullptr, nullptr }, + { "programs", nullptr, nullptr }, + { "matrix", nullptr, nullptr }, + { "anchorPoint", nullptr, nullptr }, + { "body1", nullptr, nullptr }, + { "body2", nullptr, nullptr }, + { "forceOutput", nullptr, nullptr }, + { "body1AnchorPoint", nullptr, nullptr }, + { "body2AnchorPoint", nullptr, nullptr }, + { "plane", nullptr, nullptr }, + { "appliedParameters", nullptr, nullptr }, + { "bounce", nullptr, nullptr }, + { "frictionCoefficients", nullptr, nullptr }, + { "minBounceSpeed", nullptr, nullptr }, + { "slipFactors", nullptr, nullptr }, + { "softnessConstantForceMix", nullptr, nullptr }, + { "softnessErrorCorrection", nullptr, nullptr }, + { "surfaceSpeed", nullptr, nullptr }, + { "isActive", nullptr, nullptr }, + { "useGeometry", nullptr, nullptr }, + { "set_destination", nullptr, nullptr }, + { "set_value", nullptr, nullptr }, + { "tau", nullptr, nullptr }, + { "tolerance", nullptr, nullptr }, + { "value_changed", nullptr, nullptr }, + { "initialDestination", nullptr, nullptr }, + { "initialValue", nullptr, nullptr }, + { "angle", nullptr, nullptr }, + { "variation", nullptr, nullptr }, + { "surfaceArea", nullptr, nullptr }, + { "frictionDirection", nullptr, nullptr }, + { "slipCoefficients", nullptr, nullptr }, + { "category", nullptr, nullptr }, + { "country", nullptr, nullptr }, + { "domain", nullptr, nullptr }, + { "extra", nullptr, nullptr }, + { "kind", nullptr, nullptr }, + { "specific", nullptr, nullptr }, + { "subcategory", nullptr, nullptr }, + { "axis1", nullptr, nullptr }, + { "axis2", nullptr, nullptr }, + { "desiredAngularVelocity1", nullptr, nullptr }, + { "desiredAngularVelocity2", nullptr, nullptr }, + { "maxAngle1", nullptr, nullptr }, + { "maxTorque1", nullptr, nullptr }, + { "maxTorque2", nullptr, nullptr }, + { "minAngle1", nullptr, nullptr }, + { "stopBounce1", nullptr, nullptr }, + { "stopConstantForceMix1", nullptr, nullptr }, + { "stopErrorCorrection1", nullptr, nullptr }, + { "suspensionErrorCorrection", nullptr, nullptr }, + { "suspensionForce", nullptr, nullptr }, + { "body1Axis", nullptr, nullptr }, + { "body2Axis", nullptr, nullptr }, + { "hinge1Angle", nullptr, nullptr }, + { "hinge1AngleRate", nullptr, nullptr }, + { "hinge2Angle", nullptr, nullptr }, + { "hinge2AngleRate", nullptr, nullptr }, + { "set_fraction", nullptr, nullptr }, + { "easeInEaseOut", nullptr, nullptr }, + { "modifiedFraction_changed", nullptr, nullptr }, + { "force", nullptr, nullptr }, + { "geoCenter", nullptr, nullptr }, + { "centerOfRotation_changed", nullptr, nullptr }, + { "geoCoord_changed", nullptr, nullptr }, + { "orientation_changed", nullptr, nullptr }, + { "position_changed", nullptr, nullptr }, + { "isPickable", nullptr, nullptr }, + { "viewport", nullptr, nullptr }, + { "activeLayer", nullptr, nullptr }, + { "align", nullptr, nullptr }, + { "offsetUnits", nullptr, nullptr }, + { "scaleMode", nullptr, nullptr }, + { "sizeUnits", nullptr, nullptr }, + { "layout", nullptr, nullptr }, + { "objectType", nullptr, nullptr }, + { "pickedNormal", nullptr, nullptr }, + { "pickedPoint", nullptr, nullptr }, + { "pickedTextureCoordinate", nullptr, nullptr }, + { "intersectionType", nullptr, nullptr }, + { "sortOrder", nullptr, nullptr }, + { "axis1Angle", nullptr, nullptr }, + { "axis1Torque", nullptr, nullptr }, + { "axis2Angle", nullptr, nullptr }, + { "axis2Torque", nullptr, nullptr }, + { "axis3Angle", nullptr, nullptr }, + { "axis3Torque", nullptr, nullptr }, + { "enabledAxies", nullptr, nullptr }, + { "motor1Axis", nullptr, nullptr }, + { "motor2Axis", nullptr, nullptr }, + { "motor3Axis", nullptr, nullptr }, + { "stop1Bounce", nullptr, nullptr }, + { "stop1ErrorCorrection", nullptr, nullptr }, + { "stop2Bounce", nullptr, nullptr }, + { "stop2ErrorCorrection", nullptr, nullptr }, + { "stop3Bounce", nullptr, nullptr }, + { "stop3ErrorCorrection", nullptr, nullptr }, + { "motor1Angle", nullptr, nullptr }, + { "motor1AngleRate", nullptr, nullptr }, + { "motor2Angle", nullptr, nullptr }, + { "motor2AngleRate", nullptr, nullptr }, + { "motor3Angle", nullptr, nullptr }, + { "motor3AngleRate", nullptr, nullptr }, + { "autoCalc", nullptr, nullptr }, + { "duration", nullptr, nullptr }, + { "retainUserOffsets", nullptr, nullptr }, + { "isBound", nullptr, nullptr }, + { "appearance", nullptr, nullptr }, + { "createParticles", nullptr, nullptr }, + { "lifetimeVariation", nullptr, nullptr }, + { "maxParticles", nullptr, nullptr }, + { "particleLifetime", nullptr, nullptr }, + { "particleSize", nullptr, nullptr }, + { "colorKey", nullptr, nullptr }, + { "geometryType", nullptr, nullptr }, + { "texCoordKey", nullptr, nullptr }, + { "pickable", nullptr, nullptr }, + { "angularDampingFactor", nullptr, nullptr }, + { "angularVelocity", nullptr, nullptr }, + { "autoDamp", nullptr, nullptr }, + { "autoDisable", nullptr, nullptr }, + { "disableAngularSpeed", nullptr, nullptr }, + { "disableLinearSpeed", nullptr, nullptr }, + { "disableTime", nullptr, nullptr }, + { "finiteRotationAxis", nullptr, nullptr }, + { "fixed", nullptr, nullptr }, + { "forces", nullptr, nullptr }, + { "inertia", nullptr, nullptr }, + { "linearDampingFactor", nullptr, nullptr }, + { "torques", nullptr, nullptr }, + { "useFiniteRotation", nullptr, nullptr }, + { "useGlobalForce", nullptr, nullptr }, + { "constantForceMix", nullptr, nullptr }, + { "constantSurfaceThickness", nullptr, nullptr }, + { "errorCorrection", nullptr, nullptr }, + { "iterations", nullptr, nullptr }, + { "maxCorrectionSpeed", nullptr, nullptr }, + { "preferAccuracy", nullptr, nullptr }, + { "pointSize", nullptr, nullptr }, + { "stopBounce", nullptr, nullptr }, + { "stopErrorCorrection", nullptr, nullptr }, + { "angleRate", nullptr, nullptr }, + { "maxSeparation", nullptr, nullptr }, + { "minSeparation", nullptr, nullptr }, + { "separation", nullptr, nullptr }, + { "separationRate", nullptr, nullptr }, + { "closed", nullptr, nullptr }, + { "keyVelocity", nullptr, nullptr }, + { "normalizeVelocity", nullptr, nullptr }, + { "surface", nullptr, nullptr }, + { "anisotropicDegree", nullptr, nullptr }, + { "borderColor", nullptr, nullptr }, + { "borderWidth", nullptr, nullptr }, + { "boundaryModeS", nullptr, nullptr }, + { "boundaryModeT", nullptr, nullptr }, + { "boundaryModeR", nullptr, nullptr }, + { "magnificationFilter", nullptr, nullptr }, + { "minificationFilter", nullptr, nullptr }, + { "textureCompression", nullptr, nullptr }, + { "texturePriority", nullptr, nullptr }, + { "generateMipMaps", nullptr, nullptr }, + { "targetObject", nullptr, nullptr }, + { "backAmbientIntensity", nullptr, nullptr }, + { "backDiffuseColor", nullptr, nullptr }, + { "backEmissiveColor", nullptr, nullptr }, + { "backShininess", nullptr, nullptr }, + { "backSpecularColor", nullptr, nullptr }, + { "separateBackColor", nullptr, nullptr }, + { "displayed", nullptr, nullptr }, + { "clipBoundary", nullptr, nullptr }, + { "internal", nullptr, nullptr }, + { "gustiness", nullptr, nullptr }, + { "turbulence", nullptr, nullptr }, + { "unitCategory", nullptr, nullptr }, + { "unitName", nullptr, nullptr }, + { "unitConversionFactor", nullptr, nullptr }, + { "weightConstant1", nullptr, nullptr }, + { "weightConstant2", nullptr, nullptr }, + { "weightFunction1", nullptr, nullptr }, + { "weightFunction2", nullptr, nullptr }, + { "boundaryOpacity", nullptr, nullptr }, + { "opacityFactor", nullptr, nullptr }, + { "retainedOpacity", nullptr, nullptr }, + { "colorSteps", nullptr, nullptr }, + { "orthogonalColor", nullptr, nullptr }, + { "parallelColor", nullptr, nullptr }, + { "ordered", nullptr, nullptr }, + { "edgeColor", nullptr, nullptr }, + { "gradientThreshold", nullptr, nullptr }, + { "contourStepSize", nullptr, nullptr }, + { "dimensions", nullptr, nullptr }, + { "surfaceTolerance", nullptr, nullptr }, + { "surfaceValues", nullptr, nullptr }, + { "intensityThreshold", nullptr, nullptr }, + { "segmentEnabled", nullptr, nullptr }, + { "lighting", nullptr, nullptr }, + { "shadows", nullptr, nullptr }, + { "phaseFunction", nullptr, nullptr }, + { "silhouetteBoundaryOpacity", nullptr, nullptr }, + { "silhouetteRetainedOpacity", nullptr, nullptr }, + { "silhouetteSharpness", nullptr, nullptr }, + { "coolColor", nullptr, nullptr }, + { "warmColor", nullptr, nullptr } +}; + +FIVocabulary X3D_vocabulary_3_3 = { + nullptr, 0, + encodingAlgorithmTable_3_3, 8, + nullptr, 0, + nullptr, 0, + nullptr, 0, + nullptr, 0, + nullptr, 0, + attributeValueTable_3_3, 2, + nullptr, 0, + nullptr, 0, + elementNameTable_3_3, 252, + attributeNameTable_3_3, 546 +}; + +}// namespace Assimp + +#endif // !ASSIMP_BUILD_NO_X3D_IMPORTER diff --git a/code/XFileExporter.cpp b/code/XFileExporter.cpp index eeb5a1de1..6407bf738 100644 --- a/code/XFileExporter.cpp +++ b/code/XFileExporter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -42,13 +43,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_EXPORT #ifndef ASSIMP_BUILD_NO_X_EXPORTER + #include "XFileExporter.h" #include "ConvertToLHProcess.h" #include "Bitmap.h" #include "BaseImporter.h" #include "fast_atof.h" -#include "SceneCombiner.h" -#include "DefaultIOSystem.h" +#include +#include #include #include #include @@ -78,6 +80,10 @@ void ExportSceneXFile(const char* pFile,IOSystem* pIOSystem, const aiScene* pSce // invoke the exporter XFileExporter iDoTheExportThing( pScene, pIOSystem, path, file, &props); + if (iDoTheExportThing.mOutput.fail()) { + throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile)); + } + // we're still here - export successfully completed. Write result to the given IOSYstem std::unique_ptr outfile (pIOSystem->Open(pFile,"wt")); if(outfile == NULL) { diff --git a/code/XFileExporter.h b/code/XFileExporter.h index 389c7010c..e45fd7983 100644 --- a/code/XFileExporter.h +++ b/code/XFileExporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -92,7 +93,10 @@ protected: void PushTag() { startstr.append( " "); } /// Leaves an element, decreasing the indentation - void PopTag() { ai_assert( startstr.length() > 1); startstr.erase( startstr.length() - 2); } + void PopTag() { + ai_assert( startstr.length() > 1); + startstr.erase( startstr.length() - 2); + } public: /// Stringstream to write all output into diff --git a/code/XFileHelper.h b/code/XFileHelper.h index 69f2a98f6..e7c02c7c6 100644 --- a/code/XFileHelper.h +++ b/code/XFileHelper.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -51,7 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include "Defines.h" +#include namespace Assimp { diff --git a/code/XFileImporter.cpp b/code/XFileImporter.cpp index 3b149a18a..00c32dcc2 100644 --- a/code/XFileImporter.cpp +++ b/code/XFileImporter.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -47,17 +48,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "XFileImporter.h" #include "XFileParser.h" -#include "Defines.h" #include "TinyFormatter.h" #include "ConvertToLHProcess.h" +#include #include #include #include +#include + #include #include - - using namespace Assimp; using namespace Assimp::Formatter; @@ -236,8 +237,9 @@ aiNode* XFileImporter::CreateNodes( aiScene* pScene, aiNode* pParent, const XFil // Creates the meshes for the given node. void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vector& pMeshes) { - if( pMeshes.size() == 0) + if (pMeshes.empty()) { return; + } // create a mesh for each mesh-material combination in the source node std::vector meshes; diff --git a/code/XFileImporter.h b/code/XFileImporter.h index 1de56cbc5..0fa6b52eb 100644 --- a/code/XFileImporter.h +++ b/code/XFileImporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -64,14 +65,11 @@ struct Node; /** The XFileImporter is a worker class capable of importing a scene from a * DirectX file .x */ -class XFileImporter : public BaseImporter -{ +class XFileImporter : public BaseImporter { public: XFileImporter(); ~XFileImporter(); - -public: // ------------------------------------------------------------------- /** Returns whether the class can handle the format of the given file. * See BaseImporter::CanRead() for details. */ diff --git a/code/XFileParser.cpp b/code/XFileParser.cpp index 83d017d92..1f8b8cbd3 100644 --- a/code/XFileParser.cpp +++ b/code/XFileParser.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -465,15 +466,12 @@ void XFileParser::ParseDataObjectMesh( Mesh* pMesh) pMesh->mPosFaces.resize( numPosFaces); for( unsigned int a = 0; a < numPosFaces; a++) { - unsigned int numIndices = ReadInt(); - if( numIndices < 3) { - ThrowException( format() << "Invalid index count " << numIndices << " for face " << a << "." ); - } - // read indices + unsigned int numIndices = ReadInt(); Face& face = pMesh->mPosFaces[a]; - for( unsigned int b = 0; b < numIndices; b++) - face.mIndices.push_back( ReadInt()); + for (unsigned int b = 0; b < numIndices; b++) { + face.mIndices.push_back( ReadInt() ); + } TestForSeparator(); } diff --git a/code/XFileParser.h b/code/XFileParser.h index b0c874627..ec823bac0 100644 --- a/code/XFileParser.h +++ b/code/XFileParser.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/XGLLoader.cpp b/code/XGLLoader.cpp index d14e9968d..8ef91afac 100644 --- a/code/XGLLoader.cpp +++ b/code/XGLLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -52,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "MemoryIOWrapper.h" #include #include +#include #include #include @@ -81,8 +83,11 @@ struct free_it }; namespace Assimp { // this has to be in here because LogFunctions is in ::Assimp -template<> const std::string LogFunctions::log_prefix = "XGL: "; - + template<> const char* LogFunctions::Prefix() + { + static auto prefix = "XGL: "; + return prefix; + } } static const aiImporterDesc desc = { @@ -354,7 +359,7 @@ void XGLImporter::ReadLighting(TempScope& scope) // ------------------------------------------------------------------------------------------------ aiLight* XGLImporter::ReadDirectionalLight() { - ScopeGuard l(new aiLight()); + std::unique_ptr l(new aiLight()); l->mType = aiLightSource_DIRECTIONAL; while (ReadElementUpToClosing("directionallight")) { @@ -369,13 +374,13 @@ aiLight* XGLImporter::ReadDirectionalLight() l->mColorSpecular = ReadCol3(); } } - return l.dismiss(); + return l.release(); } // ------------------------------------------------------------------------------------------------ aiNode* XGLImporter::ReadObject(TempScope& scope, bool skipFirst, const char* closetag) { - ScopeGuard nd(new aiNode()); + std::unique_ptr nd(new aiNode()); std::vector children; std::vector meshes; @@ -458,11 +463,11 @@ aiNode* XGLImporter::ReadObject(TempScope& scope, bool skipFirst, const char* cl nd->mChildren = new aiNode*[nd->mNumChildren](); for(unsigned int i = 0; i < nd->mNumChildren; ++i) { nd->mChildren[i] = children[i]; - children[i]->mParent = nd; + children[i]->mParent = nd.get(); } } - return nd.dismiss(); + return nd.release(); } // ------------------------------------------------------------------------------------------------ @@ -534,7 +539,7 @@ aiMatrix4x4 XGLImporter::ReadTrafo() // ------------------------------------------------------------------------------------------------ aiMesh* XGLImporter::ToOutputMesh(const TempMaterialMesh& m) { - ScopeGuard mesh(new aiMesh()); + std::unique_ptr mesh(new aiMesh()); mesh->mNumVertices = static_cast(m.positions.size()); mesh->mVertices = new aiVector3D[mesh->mNumVertices]; @@ -571,7 +576,7 @@ aiMesh* XGLImporter::ToOutputMesh(const TempMaterialMesh& m) mesh->mPrimitiveTypes = m.pflags; mesh->mMaterialIndex = m.matid; - return mesh.dismiss(); + return mesh.release(); } // ------------------------------------------------------------------------------------------------ @@ -740,7 +745,7 @@ void XGLImporter::ReadMaterial(TempScope& scope) { const unsigned int mat_id = ReadIDAttr(); - ScopeGuard mat(new aiMaterial()); + std::unique_ptr mat(new aiMaterial()); while (ReadElementUpToClosing("mat")) { const std::string& s = GetElementName(); if (s == "amb") { @@ -769,8 +774,8 @@ void XGLImporter::ReadMaterial(TempScope& scope) } } - scope.materials[mat_id] = mat; - scope.materials_linear.push_back(mat.dismiss()); + scope.materials[mat_id] = mat.get(); + scope.materials_linear.push_back(mat.release()); } diff --git a/code/XGLLoader.h b/code/XGLLoader.h index c8a68ba31..97ae5f8a3 100644 --- a/code/XGLLoader.h +++ b/code/XGLLoader.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -52,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include struct aiNode; diff --git a/code/XMLTools.h b/code/XMLTools.h index 7339a2fc8..5d31f885e 100644 --- a/code/XMLTools.h +++ b/code/XMLTools.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/fast_atof.h b/code/fast_atof.h index 965ff0717..058a7ff87 100644 --- a/code/fast_atof.h +++ b/code/fast_atof.h @@ -1,3 +1,5 @@ +#pragma once + // Copyright (C) 2002-2007 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine" and the "irrXML" project. // For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h @@ -22,6 +24,7 @@ #include #include "StringComparison.h" +#include #ifdef _MSC_VER @@ -192,7 +195,7 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* uint64_t value = 0; if ( *in < '0' || *in > '9' ) - throw std::invalid_argument(std::string("The string \"") + in + "\" cannot be converted into a value."); + throw std::invalid_argument(std::string("The string \"") + in + "\" cannot be converted into a value."); bool running = true; while ( running ) @@ -202,8 +205,12 @@ inline uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* const uint64_t new_value = ( value * 10 ) + ( *in - '0' ); - if (new_value < value) /* numeric overflow, we rely on you */ - throw std::overflow_error(std::string("Converting the string \"") + in + "\" into a value resulted in overflow."); + // numeric overflow, we rely on you + if ( new_value < value ) { + DefaultLogger::get()->warn( std::string( "Converting the string \"" ) + in + "\" into a value resulted in overflow." ); + return 0; + } + //throw std::overflow_error(); value = new_value; @@ -353,7 +360,7 @@ inline const char* fast_atoreal_move(const char* c, Real& out, bool check_comma // The same but more human. inline ai_real fast_atof(const char* c) { - ai_real ret; + ai_real ret(0.0); fast_atoreal_move(c, ret); return ret; } @@ -361,7 +368,7 @@ inline ai_real fast_atof(const char* c) inline ai_real fast_atof( const char* c, const char** cout) { - ai_real ret; + ai_real ret(0.0); *cout = fast_atoreal_move(c, ret); return ret; @@ -369,7 +376,7 @@ inline ai_real fast_atof( const char* c, const char** cout) inline ai_real fast_atof( const char** inout) { - ai_real ret; + ai_real ret(0.0); *inout = fast_atoreal_move(*inout, ret); return ret; diff --git a/code/glTF2Asset.h b/code/glTF2Asset.h new file mode 100644 index 000000000..cece307d9 --- /dev/null +++ b/code/glTF2Asset.h @@ -0,0 +1,1131 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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 glTFAsset.h + * Declares a glTF class to handle gltf/glb files + * + * glTF Extensions Support: + * KHR_materials_pbrSpecularGlossiness full + */ +#ifndef GLTF2ASSET_H_INC +#define GLTF2ASSET_H_INC + +#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER + +#include +#include +#include +#include +#include +#include + +#define RAPIDJSON_HAS_STDSTRING 1 +#include +#include +#include + +#ifdef ASSIMP_API +# include +# include +# include "ByteSwapper.h" +#else +# include +# define AI_SWAP4(p) +# define ai_assert +#endif + + +#if _MSC_VER > 1500 || (defined __GNUC___) +# define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP +# else +# define gltf_unordered_map map +#endif + +#ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP +# include +# if _MSC_VER > 1600 +# define gltf_unordered_map unordered_map +# else +# define gltf_unordered_map tr1::unordered_map +# endif +#endif + +#include "StringUtils.h" + +namespace glTF2 +{ +#ifdef ASSIMP_API + using Assimp::IOStream; + using Assimp::IOSystem; + using std::shared_ptr; +#else + using std::shared_ptr; + + typedef std::runtime_error DeadlyImportError; + typedef std::runtime_error DeadlyExportError; + + enum aiOrigin { aiOrigin_SET = 0, aiOrigin_CUR = 1, aiOrigin_END = 2 }; + class IOSystem; + class IOStream + { + FILE* f; + public: + IOStream(FILE* file) : f(file) {} + ~IOStream() { fclose(f); f = 0; } + + size_t Read(void* b, size_t sz, size_t n) { return fread(b, sz, n, f); } + size_t Write(const void* b, size_t sz, size_t n) { return fwrite(b, sz, n, f); } + int Seek(size_t off, aiOrigin orig) { return fseek(f, off, int(orig)); } + size_t Tell() const { return ftell(f); } + + size_t FileSize() { + long p = Tell(), len = (Seek(0, aiOrigin_END), Tell()); + return size_t((Seek(p, aiOrigin_SET), len)); + } + }; +#endif + + using rapidjson::Value; + using rapidjson::Document; + + class Asset; + class AssetWriter; + + struct BufferView; // here due to cross-reference + struct Texture; + struct Skin; + + // Vec/matrix types, as raw float arrays + typedef float (vec3)[3]; + typedef float (vec4)[4]; + typedef float (mat4)[16]; + + namespace Util + { + void EncodeBase64(const uint8_t* in, size_t inLength, std::string& out); + + size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out); + + inline size_t DecodeBase64(const char* in, uint8_t*& out) + { + return DecodeBase64(in, strlen(in), out); + } + + struct DataURI + { + const char* mediaType; + const char* charset; + bool base64; + const char* data; + size_t dataLength; + }; + + //! Check if a uri is a data URI + inline bool ParseDataURI(const char* uri, size_t uriLen, DataURI& out); + } + + + //! Magic number for GLB files + #define AI_GLB_MAGIC_NUMBER "glTF" + + #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR "$mat.gltf.pbrMetallicRoughness.baseColorFactor", 0, 0 + #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR "$mat.gltf.pbrMetallicRoughness.metallicFactor", 0, 0 + #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR "$mat.gltf.pbrMetallicRoughness.roughnessFactor", 0, 0 + #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE aiTextureType_DIFFUSE, 1 + #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE aiTextureType_UNKNOWN, 0 + #define AI_MATKEY_GLTF_ALPHAMODE "$mat.gltf.alphaMode", 0, 0 + #define AI_MATKEY_GLTF_ALPHACUTOFF "$mat.gltf.alphaCutoff", 0, 0 + #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0 + #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR "$mat.gltf.pbrMetallicRoughness.glossinessFactor", 0, 0 + + #define _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE "$tex.file.texCoord" + #define _AI_MATKEY_GLTF_MAPPINGNAME_BASE "$tex.mappingname" + #define _AI_MATKEY_GLTF_MAPPINGID_BASE "$tex.mappingid" + #define _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE "$tex.mappingfiltermag" + #define _AI_MATKEY_GLTF_MAPPINGFILTER_MIN_BASE "$tex.mappingfiltermin" + + #define AI_MATKEY_GLTF_TEXTURE_TEXCOORD _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, type, N + #define AI_MATKEY_GLTF_MAPPINGNAME(type, N) _AI_MATKEY_GLTF_MAPPINGNAME_BASE, type, N + #define AI_MATKEY_GLTF_MAPPINGID(type, N) _AI_MATKEY_GLTF_MAPPINGID_BASE, type, N + #define AI_MATKEY_GLTF_MAPPINGFILTER_MAG(type, N) _AI_MATKEY_GLTF_MAPPINGFILTER_MAG_BASE, type, N + #define AI_MATKEY_GLTF_MAPPINGFILTER_MIN(type, N) _AI_MATKEY_GLTF_MAPPINGFILTER_MIN_BASE, type, N + + #ifdef ASSIMP_API + #include "./../include/assimp/Compiler/pushpack1.h" + #endif + + //! For binary .glb files + //! 12-byte header (+ the JSON + a "body" data section) + struct GLB_Header + { + uint8_t magic[4]; //!< Magic number: "glTF" + uint32_t version; //!< Version number (always 2 as of the last update) + uint32_t length; //!< Total length of the Binary glTF, including header, scene, and body, in bytes + } PACK_STRUCT; + + struct GLB_Chunk + { + uint32_t chunkLength; + uint32_t chunkType; + } PACK_STRUCT; + + #ifdef ASSIMP_API + #include "./../include/assimp/Compiler/poppack1.h" + #endif + + + //! Values for the GLB_Chunk::chunkType field + enum ChunkType + { + ChunkType_JSON = 0x4E4F534A, + ChunkType_BIN = 0x004E4942 + }; + + //! Values for the mesh primitive modes + enum PrimitiveMode + { + PrimitiveMode_POINTS = 0, + PrimitiveMode_LINES = 1, + PrimitiveMode_LINE_LOOP = 2, + PrimitiveMode_LINE_STRIP = 3, + PrimitiveMode_TRIANGLES = 4, + PrimitiveMode_TRIANGLE_STRIP = 5, + PrimitiveMode_TRIANGLE_FAN = 6 + }; + + //! Values for the Accessor::componentType field + enum ComponentType + { + ComponentType_BYTE = 5120, + ComponentType_UNSIGNED_BYTE = 5121, + ComponentType_SHORT = 5122, + ComponentType_UNSIGNED_SHORT = 5123, + ComponentType_UNSIGNED_INT = 5125, + ComponentType_FLOAT = 5126 + }; + + inline unsigned int ComponentTypeSize(ComponentType t) + { + switch (t) { + case ComponentType_SHORT: + case ComponentType_UNSIGNED_SHORT: + return 2; + + case ComponentType_UNSIGNED_INT: + case ComponentType_FLOAT: + return 4; + + case ComponentType_BYTE: + case ComponentType_UNSIGNED_BYTE: + return 1; + default: + throw DeadlyImportError("GLTF: Unsupported Component Type " + to_string(t)); + } + } + + //! Values for the BufferView::target field + enum BufferViewTarget + { + BufferViewTarget_ARRAY_BUFFER = 34962, + BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963 + }; + + //! Values for the Sampler::magFilter field + enum class SamplerMagFilter: unsigned int + { + UNSET = 0, + SamplerMagFilter_Nearest = 9728, + SamplerMagFilter_Linear = 9729 + }; + + //! Values for the Sampler::minFilter field + enum class SamplerMinFilter: unsigned int + { + UNSET = 0, + SamplerMinFilter_Nearest = 9728, + SamplerMinFilter_Linear = 9729, + SamplerMinFilter_Nearest_Mipmap_Nearest = 9984, + SamplerMinFilter_Linear_Mipmap_Nearest = 9985, + SamplerMinFilter_Nearest_Mipmap_Linear = 9986, + SamplerMinFilter_Linear_Mipmap_Linear = 9987 + }; + + //! Values for the Sampler::wrapS and Sampler::wrapT field + enum class SamplerWrap: unsigned int + { + UNSET = 0, + Clamp_To_Edge = 33071, + Mirrored_Repeat = 33648, + Repeat = 10497 + }; + + //! Values for the Texture::format and Texture::internalFormat fields + enum TextureFormat + { + TextureFormat_ALPHA = 6406, + TextureFormat_RGB = 6407, + TextureFormat_RGBA = 6408, + TextureFormat_LUMINANCE = 6409, + TextureFormat_LUMINANCE_ALPHA = 6410 + }; + + //! Values for the Texture::target field + enum TextureTarget + { + TextureTarget_TEXTURE_2D = 3553 + }; + + //! Values for the Texture::type field + enum TextureType + { + TextureType_UNSIGNED_BYTE = 5121, + TextureType_UNSIGNED_SHORT_5_6_5 = 33635, + TextureType_UNSIGNED_SHORT_4_4_4_4 = 32819, + TextureType_UNSIGNED_SHORT_5_5_5_1 = 32820 + }; + + + //! Values for the Accessor::type field (helper class) + class AttribType + { + public: + enum Value + { SCALAR, VEC2, VEC3, VEC4, MAT2, MAT3, MAT4 }; + + private: + static const size_t NUM_VALUES = static_cast(MAT4)+1; + + struct Info + { const char* name; unsigned int numComponents; }; + + template struct data + { static const Info infos[NUM_VALUES]; }; + + public: + inline static Value FromString(const char* str) + { + for (size_t i = 0; i < NUM_VALUES; ++i) { + if (strcmp(data<0>::infos[i].name, str) == 0) { + return static_cast(i); + } + } + return SCALAR; + } + + inline static const char* ToString(Value type) + { + return data<0>::infos[static_cast(type)].name; + } + + inline static unsigned int GetNumComponents(Value type) + { + return data<0>::infos[static_cast(type)].numComponents; + } + }; + + // must match the order of the AttribTypeTraits::Value enum! + template const AttribType::Info + AttribType::data::infos[AttribType::NUM_VALUES] = { + { "SCALAR", 1 }, { "VEC2", 2 }, { "VEC3", 3 }, { "VEC4", 4 }, { "MAT2", 4 }, { "MAT3", 9 }, { "MAT4", 16 } + }; + + + + //! A reference to one top-level object, which is valid + //! until the Asset instance is destroyed + template + class Ref + { + std::vector* vector; + unsigned int index; + + public: + Ref() : vector(0), index(0) {} + Ref(std::vector& vec, unsigned int idx) : vector(&vec), index(idx) {} + + inline unsigned int GetIndex() const + { return index; } + + operator bool() const + { return vector != 0; } + + T* operator->() + { return (*vector)[index]; } + + T& operator*() + { return *((*vector)[index]); } + }; + + //! Helper struct to represent values that might not be present + template + struct Nullable + { + T value; + bool isPresent; + + Nullable() : isPresent(false) {} + Nullable(T& val) : value(val), isPresent(true) {} + }; + + + //! Base classe for all glTF top-level objects + struct Object + { + int index; //!< The index of this object within its property container + int oIndex; //!< The original index of this object defined in the JSON + std::string id; //!< The globally unique ID used to reference this object + std::string name; //!< The user-defined name of this object + + //! Objects marked as special are not exported (used to emulate the binary body buffer) + virtual bool IsSpecial() const + { return false; } + + virtual ~Object() {} + + //! Maps special IDs to another ID, where needed. Subclasses may override it (statically) + static const char* TranslateId(Asset& /*r*/, const char* id) + { return id; } + }; + + // + // Classes for each glTF top-level object type + // + + //! A typed view into a BufferView. A BufferView contains raw binary data. + //! An accessor provides a typed view into a BufferView or a subset of a BufferView + //! similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer. + struct Accessor : public Object + { + Ref bufferView; //!< The ID of the bufferView. (required) + unsigned int byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required) + ComponentType componentType; //!< The datatype of components in the attribute. (required) + unsigned int count; //!< The number of attributes referenced by this accessor. (required) + AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required) + std::vector max; //!< Maximum value of each component in this attribute. + std::vector min; //!< Minimum value of each component in this attribute. + + unsigned int GetNumComponents(); + unsigned int GetBytesPerComponent(); + unsigned int GetElementSize(); + + inline uint8_t* GetPointer(); + + template + bool ExtractData(T*& outData); + + void WriteData(size_t count, const void* src_buffer, size_t src_stride); + + //! Helper class to iterate the data + class Indexer + { + friend struct Accessor; + + Accessor& accessor; + uint8_t* data; + size_t elemSize, stride; + + Indexer(Accessor& acc); + + public: + + //! Accesses the i-th value as defined by the accessor + template + T GetValue(int i); + + //! Accesses the i-th value as defined by the accessor + inline unsigned int GetUInt(int i) + { + return GetValue(i); + } + + inline bool IsValid() const + { + return data != 0; + } + }; + + inline Indexer GetIndexer() + { + return Indexer(*this); + } + + Accessor() {} + void Read(Value& obj, Asset& r); + }; + + //! A buffer points to binary geometry, animation, or skins. + struct Buffer : public Object + { + /********************* Types *********************/ + public: + + enum Type + { + Type_arraybuffer, + Type_text + }; + + /// \struct SEncodedRegion + /// Descriptor of encoded region in "bufferView". + struct SEncodedRegion + { + const size_t Offset;///< Offset from begin of "bufferView" to encoded region, in bytes. + const size_t EncodedData_Length;///< Size of encoded region, in bytes. + uint8_t* const DecodedData;///< Cached encoded data. + const size_t DecodedData_Length;///< Size of decoded region, in bytes. + const std::string ID;///< ID of the region. + + /// \fn SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string pID) + /// Constructor. + /// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes. + /// \param [in] pEncodedData_Length - size of encoded region, in bytes. + /// \param [in] pDecodedData - pointer to decoded data array. + /// \param [in] pDecodedData_Length - size of encoded region, in bytes. + /// \param [in] pID - ID of the region. + SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string pID) + : Offset(pOffset), EncodedData_Length(pEncodedData_Length), DecodedData(pDecodedData), DecodedData_Length(pDecodedData_Length), ID(pID) + {} + + /// \fn ~SEncodedRegion() + /// Destructor. + ~SEncodedRegion() { delete[] DecodedData; } + }; + + /******************* Variables *******************/ + + //std::string uri; //!< The uri of the buffer. Can be a filepath, a data uri, etc. (required) + size_t byteLength; //!< The length of the buffer in bytes. (default: 0) + //std::string type; //!< XMLHttpRequest responseType (default: "arraybuffer") + + Type type; + + /// \var EncodedRegion_Current + /// Pointer to currently active encoded region. + /// Why not decoding all regions at once and not to set one buffer with decoded data? + /// Yes, why not? Even "accessor" point to decoded data. I mean that fields "byteOffset", "byteStride" and "count" has values which describes decoded + /// data array. But only in range of mesh while is active parameters from "compressedData". For another mesh accessors point to decoded data too. But + /// offset is counted for another regions is encoded. + /// Example. You have two meshes. For every of it you have 4 bytes of data. That data compressed to 2 bytes. So, you have buffer with encoded data: + /// M1_E0, M1_E1, M2_E0, M2_E1. + /// After decoding you'll get: + /// M1_D0, M1_D1, M1_D2, M1_D3, M2_D0, M2_D1, M2_D2, M2_D3. + /// "accessors" must to use values that point to decoded data - obviously. So, you'll expect "accessors" like + /// "accessor_0" : { byteOffset: 0, byteLength: 4}, "accessor_1" : { byteOffset: 4, byteLength: 4} + /// but in real life you'll get: + /// "accessor_0" : { byteOffset: 0, byteLength: 4}, "accessor_1" : { byteOffset: 2, byteLength: 4} + /// Yes, accessor of next mesh has offset and length which mean: current mesh data is decoded, all other data is encoded. + /// And when before you start to read data of current mesh (with encoded data ofcourse) you must decode region of "bufferView", after read finished + /// delete encoding mark. And after that you can repeat process: decode data of mesh, read, delete decoded data. + /// + /// Remark. Encoding all data at once is good in world with computers which do not has RAM limitation. So, you must use step by step encoding in + /// exporter and importer. And, thanks to such way, there is no need to load whole file into memory. + SEncodedRegion* EncodedRegion_Current; + + private: + + shared_ptr mData; //!< Pointer to the data + bool mIsSpecial; //!< Set to true for special cases (e.g. the body buffer) + + /// \var EncodedRegion_List + /// List of encoded regions. + std::list EncodedRegion_List; + + /******************* Functions *******************/ + + public: + + Buffer(); + ~Buffer(); + + void Read(Value& obj, Asset& r); + + bool LoadFromStream(IOStream& stream, size_t length = 0, size_t baseOffset = 0); + + /// \fn void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string& pID) + /// Mark region of "bufferView" as encoded. When data is request from such region then "bufferView" use decoded data. + /// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes. + /// \param [in] pEncodedData_Length - size of encoded region, in bytes. + /// \param [in] pDecodedData - pointer to decoded data array. + /// \param [in] pDecodedData_Length - size of encoded region, in bytes. + /// \param [in] pID - ID of the region. + void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string& pID); + + /// \fn void EncodedRegion_SetCurrent(const std::string& pID) + /// Select current encoded region by ID. \sa EncodedRegion_Current. + /// \param [in] pID - ID of the region. + void EncodedRegion_SetCurrent(const std::string& pID); + + /// \fn bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count) + /// Replace part of buffer data. Pay attention that function work with original array of data (\ref mData) not with encoded regions. + /// \param [in] pBufferData_Offset - index of first element in buffer from which new data will be placed. + /// \param [in] pBufferData_Count - count of bytes in buffer which will be replaced. + /// \param [in] pReplace_Data - pointer to array with new data for buffer. + /// \param [in] pReplace_Count - count of bytes in new data. + /// \return true - if successfully replaced, false if input arguments is out of range. + bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count); + + size_t AppendData(uint8_t* data, size_t length); + void Grow(size_t amount); + + uint8_t* GetPointer() + { return mData.get(); } + + void MarkAsSpecial() + { mIsSpecial = true; } + + bool IsSpecial() const + { return mIsSpecial; } + + std::string GetURI() + { return std::string(this->id) + ".bin"; } + + static const char* TranslateId(Asset& r, const char* id); + }; + + //! A view into a buffer generally representing a subset of the buffer. + struct BufferView : public Object + { + Ref buffer; //! The ID of the buffer. (required) + size_t byteOffset; //! The offset into the buffer in bytes. (required) + size_t byteLength; //! The length of the bufferView in bytes. (default: 0) + unsigned int byteStride; //!< The stride, in bytes, between attributes referenced by this accessor. (default: 0) + + BufferViewTarget target; //! The target that the WebGL buffer should be bound to. + + void Read(Value& obj, Asset& r); + }; + + struct Camera : public Object + { + enum Type + { + Perspective, + Orthographic + }; + + Type type; + + union + { + struct { + float aspectRatio; //! bufferView; + + std::string mimeType; + + int width, height; + + private: + uint8_t* mData; + size_t mDataLength; + + public: + + Image(); + void Read(Value& obj, Asset& r); + + inline bool HasData() const + { return mDataLength > 0; } + + inline size_t GetDataLength() const + { return mDataLength; } + + inline const uint8_t* GetData() const + { return mData; } + + inline uint8_t* StealData(); + + inline void SetData(uint8_t* data, size_t length, Asset& r); + }; + + const vec4 defaultBaseColor = {1, 1, 1, 1}; + const vec3 defaultEmissiveFactor = {0, 0, 0}; + const vec4 defaultDiffuseFactor = {1, 1, 1, 1}; + const vec3 defaultSpecularFactor = {1, 1, 1}; + + struct TextureInfo + { + Ref texture; + unsigned int index; + unsigned int texCoord = 0; + }; + + struct NormalTextureInfo : TextureInfo + { + float scale = 1; + }; + + struct OcclusionTextureInfo : TextureInfo + { + float strength = 1; + }; + + struct PbrMetallicRoughness + { + vec4 baseColorFactor; + TextureInfo baseColorTexture; + TextureInfo metallicRoughnessTexture; + float metallicFactor; + float roughnessFactor; + }; + + struct PbrSpecularGlossiness + { + vec4 diffuseFactor; + vec3 specularFactor; + float glossinessFactor; + TextureInfo diffuseTexture; + TextureInfo specularGlossinessTexture; + + PbrSpecularGlossiness() { SetDefaults(); } + void SetDefaults(); + }; + + //! The material appearance of a primitive. + struct Material : public Object + { + //PBR metallic roughness properties + PbrMetallicRoughness pbrMetallicRoughness; + + //other basic material properties + NormalTextureInfo normalTexture; + OcclusionTextureInfo occlusionTexture; + TextureInfo emissiveTexture; + vec3 emissiveFactor; + std::string alphaMode; + float alphaCutoff; + bool doubleSided; + + //extension: KHR_materials_pbrSpecularGlossiness + Nullable pbrSpecularGlossiness; + + Material() { SetDefaults(); } + void Read(Value& obj, Asset& r); + void SetDefaults(); + }; + + //! A set of primitives to be rendered. A node can contain one or more meshes. A node's transform places the mesh in the scene. + struct Mesh : public Object + { + typedef std::vector< Ref > AccessorList; + + struct Primitive + { + PrimitiveMode mode; + + struct Attributes { + AccessorList position, normal, tangent, texcoord, color, joint, jointmatrix, weight; + } attributes; + + Ref indices; + + Ref material; + }; + + std::vector primitives; + + Mesh() {} + + /// \fn void Read(Value& pJSON_Object, Asset& pAsset_Root) + /// Get mesh data from JSON-object and place them to root asset. + /// \param [in] pJSON_Object - reference to pJSON-object from which data are read. + /// \param [out] pAsset_Root - reference to root assed where data will be stored. + void Read(Value& pJSON_Object, Asset& pAsset_Root); + }; + + struct Node : public Object + { + std::vector< Ref > children; + std::vector< Ref > meshes; + + Nullable matrix; + Nullable translation; + Nullable rotation; + Nullable scale; + + Ref camera; + + std::vector< Ref > skeletons; //!< The ID of skeleton nodes. Each of which is the root of a node hierarchy. + Ref skin; //!< The ID of the skin referenced by this node. + std::string jointName; //!< Name used when this node is a joint in a skin. + + Ref parent; //!< This is not part of the glTF specification. Used as a helper. + + Node() {} + void Read(Value& obj, Asset& r); + }; + + struct Program : public Object + { + Program() {} + void Read(Value& obj, Asset& r); + }; + + + struct Sampler : public Object + { + SamplerMagFilter magFilter; //!< The texture magnification filter. + SamplerMinFilter minFilter; //!< The texture minification filter. + SamplerWrap wrapS; //!< The texture wrapping in the S direction. + SamplerWrap wrapT; //!< The texture wrapping in the T direction. + + Sampler() { SetDefaults(); } + void Read(Value& obj, Asset& r); + void SetDefaults(); + }; + + struct Scene : public Object + { + std::vector< Ref > nodes; + + Scene() {} + void Read(Value& obj, Asset& r); + }; + + struct Shader : public Object + { + Shader() {} + void Read(Value& obj, Asset& r); + }; + + struct Skin : public Object + { + Nullable bindShapeMatrix; //!< Floating-point 4x4 transformation matrix stored in column-major order. + Ref inverseBindMatrices; //!< The ID of the accessor containing the floating-point 4x4 inverse-bind matrices. + std::vector> jointNames; //!< Joint names of the joints (nodes with a jointName property) in this skin. + std::string name; //!< The user-defined name of this object. + + Skin() {} + void Read(Value& obj, Asset& r); + }; + + //! A texture and its sampler. + struct Texture : public Object + { + Ref sampler; //!< The ID of the sampler used by this texture. (required) + Ref source; //!< The ID of the image used by this texture. (required) + + //TextureFormat format; //!< The texture's format. (default: TextureFormat_RGBA) + //TextureFormat internalFormat; //!< The texture's internal format. (default: TextureFormat_RGBA) + + //TextureTarget target; //!< The target that the WebGL texture should be bound to. (default: TextureTarget_TEXTURE_2D) + //TextureType type; //!< Texel datatype. (default: TextureType_UNSIGNED_BYTE) + + Texture() {} + void Read(Value& obj, Asset& r); + }; + + struct Animation : public Object + { + struct AnimSampler { + std::string id; //!< The ID of this sampler. + std::string input; //!< The ID of a parameter in this animation to use as key-frame input. + std::string interpolation; //!< Type of interpolation algorithm to use between key-frames. + std::string output; //!< The ID of a parameter in this animation to use as key-frame output. + }; + + struct AnimChannel { + int sampler; //!< The index of a sampler in the containing animation's samplers property. + + struct AnimTarget { + Ref node; //!< The node to animate. + std::string path; //!< The name of property of the node to animate ("translation", "rotation", or "scale"). + } target; + }; + + struct AnimParameters { + Ref TIME; //!< Accessor reference to a buffer storing a array of floating point scalar values. + Ref rotation; //!< Accessor reference to a buffer storing a array of four-component floating-point vectors. + Ref scale; //!< Accessor reference to a buffer storing a array of three-component floating-point vectors. + Ref translation; //!< Accessor reference to a buffer storing a array of three-component floating-point vectors. + }; + + // AnimChannel Channels[3]; //!< Connect the output values of the key-frame animation to a specific node in the hierarchy. + // AnimParameters Parameters; //!< The samplers that interpolate between the key-frames. + // AnimSampler Samplers[3]; //!< The parameterized inputs representing the key-frame data. + + std::vector Channels; //!< Connect the output values of the key-frame animation to a specific node in the hierarchy. + AnimParameters Parameters; //!< The samplers that interpolate between the key-frames. + std::vector Samplers; //!< The parameterized inputs representing the key-frame data. + + Animation() {} + void Read(Value& obj, Asset& r); + + //! Get accessor given an animation parameter name. + Ref GetAccessor(std::string name) { + if (name == "TIME") { + return Parameters.TIME; + } else if (name == "rotation") { + return Parameters.rotation; + } else if (name == "scale") { + return Parameters.scale; + } else if (name == "translation") { + return Parameters.translation; + } + return Ref(); + } + }; + + + //! Base class for LazyDict that acts as an interface + class LazyDictBase + { + public: + virtual ~LazyDictBase() {} + + virtual void AttachToDocument(Document& doc) = 0; + virtual void DetachFromDocument() = 0; + + virtual void WriteObjects(AssetWriter& writer) = 0; + }; + + + template + class LazyDict; + + //! (Implemented in glTFAssetWriter.h) + template + void WriteLazyDict(LazyDict& d, AssetWriter& w); + + + //! Manages lazy loading of the glTF top-level objects, and keeps a reference to them by ID + //! It is the owner the loaded objects, so when it is destroyed it also deletes them + template + class LazyDict : public LazyDictBase + { + friend class Asset; + friend class AssetWriter; + + typedef typename std::gltf_unordered_map< unsigned int, unsigned int > Dict; + typedef typename std::gltf_unordered_map< std::string, unsigned int > IdDict; + + std::vector mObjs; //! The read objects + Dict mObjsByOIndex; //! The read objects accessible by original index + IdDict mObjsById; //! The read objects accessible by id + const char* mDictId; //! ID of the dictionary object + const char* mExtId; //! ID of the extension defining the dictionary + Value* mDict; //! JSON dictionary object + Asset& mAsset; //! The asset instance + + void AttachToDocument(Document& doc); + void DetachFromDocument(); + + void WriteObjects(AssetWriter& writer) + { WriteLazyDict(*this, writer); } + + Ref Add(T* obj); + + public: + LazyDict(Asset& asset, const char* dictId, const char* extId = 0); + ~LazyDict(); + + Ref Retrieve(unsigned int i); + + Ref Get(unsigned int i); + Ref Get(const char* id); + + Ref Create(const char* id); + Ref Create(const std::string& id) + { return Create(id.c_str()); } + + unsigned int Remove(const char* id); + + inline unsigned int Size() const + { return unsigned(mObjs.size()); } + + inline T& operator[](size_t i) + { return *mObjs[i]; } + + }; + + + struct AssetMetadata + { + std::string copyright; //!< A copyright message suitable for display to credit the content creator. + std::string generator; //!< Tool that generated this glTF model.Useful for debugging. + + struct { + std::string api; //!< Specifies the target rendering API (default: "WebGL") + std::string version; //!< Specifies the target rendering API (default: "1.0.3") + } profile; //!< Specifies the target rendering API and version, e.g., WebGL 1.0.3. (default: {}) + + std::string version; //!< The glTF format version + + void Read(Document& doc); + + AssetMetadata() : version("") {} + }; + + // + // glTF Asset class + // + + //! Root object for a glTF asset + class Asset + { + typedef std::gltf_unordered_map IdMap; + + template + friend class LazyDict; + + friend struct Buffer; // To access OpenFile + + friend class AssetWriter; + + private: + IOSystem* mIOSystem; + + std::string mCurrentAssetDir; + + size_t mSceneLength; + size_t mBodyOffset, mBodyLength; + + std::vector mDicts; + + IdMap mUsedIds; + + Ref mBodyBuffer; + + Asset(Asset&); + Asset& operator=(const Asset&); + + public: + + //! Keeps info about the enabled extensions + struct Extensions + { + bool KHR_materials_pbrSpecularGlossiness; + + } extensionsUsed; + + AssetMetadata asset; + + + // Dictionaries for each type of object + + LazyDict accessors; + LazyDict animations; + LazyDict buffers; + LazyDict bufferViews; + LazyDict cameras; + LazyDict images; + LazyDict materials; + LazyDict meshes; + LazyDict nodes; + LazyDict samplers; + LazyDict scenes; + LazyDict skins; + LazyDict textures; + + Ref scene; + + public: + Asset(IOSystem* io = 0) + : mIOSystem(io) + , asset() + , accessors (*this, "accessors") + , animations (*this, "animations") + , buffers (*this, "buffers") + , bufferViews (*this, "bufferViews") + , cameras (*this, "cameras") + , images (*this, "images") + , materials (*this, "materials") + , meshes (*this, "meshes") + , nodes (*this, "nodes") + , samplers (*this, "samplers") + , scenes (*this, "scenes") + , skins (*this, "skins") + , textures (*this, "textures") + { + memset(&extensionsUsed, 0, sizeof(extensionsUsed)); + } + + //! Main function + void Load(const std::string& file, bool isBinary = false); + + //! Enables binary encoding on the asset + void SetAsBinary(); + + //! Search for an available name, starting from the given strings + std::string FindUniqueID(const std::string& str, const char* suffix); + + Ref GetBodyBuffer() + { return mBodyBuffer; } + + private: + void ReadBinaryHeader(IOStream& stream, std::vector& sceneData); + + void ReadExtensionsUsed(Document& doc); + + IOStream* OpenFile(std::string path, const char* mode, bool absolute = false); + }; + +} + +// Include the implementation of the methods +#include "glTF2Asset.inl" + +#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER + +#endif // GLTF2ASSET_H_INC diff --git a/code/glTF2Asset.inl b/code/glTF2Asset.inl new file mode 100644 index 000000000..549df747e --- /dev/null +++ b/code/glTF2Asset.inl @@ -0,0 +1,1449 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +#include "StringUtils.h" + +// Header files, Assimp +#include + +using namespace Assimp; + +namespace glTF2 { + +namespace { + + // + // JSON Value reading helpers + // + + template + struct ReadHelper { static bool Read(Value& val, T& out) { + return val.IsInt() ? out = static_cast(val.GetInt()), true : false; + }}; + + template<> struct ReadHelper { static bool Read(Value& val, bool& out) { + return val.IsBool() ? out = val.GetBool(), true : false; + }}; + + template<> struct ReadHelper { static bool Read(Value& val, float& out) { + return val.IsNumber() ? out = static_cast(val.GetDouble()), true : false; + }}; + + template struct ReadHelper { static bool Read(Value& val, float (&out)[N]) { + if (!val.IsArray() || val.Size() != N) return false; + for (unsigned int i = 0; i < N; ++i) { + if (val[i].IsNumber()) + out[i] = static_cast(val[i].GetDouble()); + } + return true; + }}; + + template<> struct ReadHelper { static bool Read(Value& val, const char*& out) { + return val.IsString() ? (out = val.GetString(), true) : false; + }}; + + template<> struct ReadHelper { static bool Read(Value& val, std::string& out) { + return val.IsString() ? (out = std::string(val.GetString(), val.GetStringLength()), true) : false; + }}; + + template struct ReadHelper< Nullable > { static bool Read(Value& val, Nullable& out) { + return out.isPresent = ReadHelper::Read(val, out.value); + }}; + + template + inline static bool ReadValue(Value& val, T& out) + { + return ReadHelper::Read(val, out); + } + + template + inline static bool ReadMember(Value& obj, const char* id, T& out) + { + Value::MemberIterator it = obj.FindMember(id); + if (it != obj.MemberEnd()) { + return ReadHelper::Read(it->value, out); + } + return false; + } + + template + inline static T MemberOrDefault(Value& obj, const char* id, T defaultValue) + { + T out; + return ReadMember(obj, id, out) ? out : defaultValue; + } + + inline Value* FindMember(Value& val, const char* id) + { + Value::MemberIterator it = val.FindMember(id); + return (it != val.MemberEnd()) ? &it->value : 0; + } + + inline Value* FindString(Value& val, const char* id) + { + Value::MemberIterator it = val.FindMember(id); + return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0; + } + + inline Value* FindNumber(Value& val, const char* id) + { + Value::MemberIterator it = val.FindMember(id); + return (it != val.MemberEnd() && it->value.IsNumber()) ? &it->value : 0; + } + + inline Value* FindUInt(Value& val, const char* id) + { + Value::MemberIterator it = val.FindMember(id); + return (it != val.MemberEnd() && it->value.IsUint()) ? &it->value : 0; + } + + inline Value* FindArray(Value& val, const char* id) + { + Value::MemberIterator it = val.FindMember(id); + return (it != val.MemberEnd() && it->value.IsArray()) ? &it->value : 0; + } + + inline Value* FindObject(Value& val, const char* id) + { + Value::MemberIterator it = val.FindMember(id); + return (it != val.MemberEnd() && it->value.IsObject()) ? &it->value : 0; + } +} + +// +// LazyDict methods +// + +template +inline LazyDict::LazyDict(Asset& asset, const char* dictId, const char* extId) + : mDictId(dictId), mExtId(extId), mDict(0), mAsset(asset) +{ + asset.mDicts.push_back(this); // register to the list of dictionaries +} + +template +inline LazyDict::~LazyDict() +{ + for (size_t i = 0; i < mObjs.size(); ++i) { + delete mObjs[i]; + } +} + + +template +inline void LazyDict::AttachToDocument(Document& doc) +{ + Value* container = 0; + + if (mExtId) { + if (Value* exts = FindObject(doc, "extensions")) { + container = FindObject(*exts, mExtId); + } + } + else { + container = &doc; + } + + if (container) { + mDict = FindArray(*container, mDictId); + } +} + +template +inline void LazyDict::DetachFromDocument() +{ + mDict = 0; +} + +template +unsigned int LazyDict::Remove(const char* id) +{ + id = T::TranslateId(mAsset, id); + + typename IdDict::iterator it = mObjsById.find(id); + + if (it == mObjsById.end()) { + throw DeadlyExportError("GLTF: Object with id \"" + std::string(id) + "\" is not found"); + } + + const unsigned int index = it->second; + + mAsset.mUsedIds[id] = false; + mObjsById.erase(id); + mObjsByOIndex.erase(index); + mObjs.erase(mObjs.begin() + index); + + //update index of object in mObjs; + for (unsigned int i = index; i < mObjs.size(); ++i) { + T *obj = mObjs[i]; + + obj->index = i; + } + + for (IdDict::iterator it = mObjsById.begin(); it != mObjsById.end(); ++it) { + if (it->second <= index) { + continue; + } + + mObjsById[it->first] = it->second - 1; + } + + for (Dict::iterator it = mObjsByOIndex.begin(); it != mObjsByOIndex.end(); ++it) { + if (it->second <= index) { + continue; + } + + mObjsByOIndex[it->first] = it->second - 1; + } + + return index; +} + +template +Ref LazyDict::Retrieve(unsigned int i) +{ + + typename Dict::iterator it = mObjsByOIndex.find(i); + if (it != mObjsByOIndex.end()) {// already created? + return Ref(mObjs, it->second); + } + + // read it from the JSON object + if (!mDict) { + throw DeadlyImportError("GLTF: Missing section \"" + std::string(mDictId) + "\""); + } + + if (!mDict->IsArray()) { + throw DeadlyImportError("GLTF: Field is not an array \"" + std::string(mDictId) + "\""); + } + + Value &obj = (*mDict)[i]; + + if (!obj.IsObject()) { + throw DeadlyImportError("GLTF: Object at index \"" + to_string(i) + "\" is not a JSON object"); + } + + T* inst = new T(); + inst->id = std::string(mDictId) + "_" + to_string(i); + inst->oIndex = i; + ReadMember(obj, "name", inst->name); + inst->Read(obj, mAsset); + + return Add(inst); +} + +template +Ref LazyDict::Get(unsigned int i) +{ + + return Ref(mObjs, i); + +} + +template +Ref LazyDict::Get(const char* id) +{ + id = T::TranslateId(mAsset, id); + + typename IdDict::iterator it = mObjsById.find(id); + if (it != mObjsById.end()) { // already created? + return Ref(mObjs, it->second); + } + + return Ref(); +} + +template +Ref LazyDict::Add(T* obj) +{ + unsigned int idx = unsigned(mObjs.size()); + mObjs.push_back(obj); + mObjsByOIndex[obj->oIndex] = idx; + mObjsById[obj->id] = idx; + mAsset.mUsedIds[obj->id] = true; + return Ref(mObjs, idx); +} + +template +Ref LazyDict::Create(const char* id) +{ + Asset::IdMap::iterator it = mAsset.mUsedIds.find(id); + if (it != mAsset.mUsedIds.end()) { + throw DeadlyImportError("GLTF: two objects with the same ID exist"); + } + T* inst = new T(); + unsigned int idx = unsigned(mObjs.size()); + inst->id = id; + inst->index = idx; + inst->oIndex = idx; + return Add(inst); +} + + +// +// glTF dictionary objects methods +// + + +inline Buffer::Buffer() + : byteLength(0), type(Type_arraybuffer), EncodedRegion_Current(nullptr), mIsSpecial(false) +{ } + +inline Buffer::~Buffer() +{ + for(SEncodedRegion* reg : EncodedRegion_List) delete reg; +} + +inline const char* Buffer::TranslateId(Asset& /*r*/, const char* id) +{ + return id; +} + +inline void Buffer::Read(Value& obj, Asset& r) +{ + size_t statedLength = MemberOrDefault(obj, "byteLength", 0); + byteLength = statedLength; + + Value* it = FindString(obj, "uri"); + if (!it) { + if (statedLength > 0) { + throw DeadlyImportError("GLTF: buffer with non-zero length missing the \"uri\" attribute"); + } + return; + } + + const char* uri = it->GetString(); + + Util::DataURI dataURI; + if (ParseDataURI(uri, it->GetStringLength(), dataURI)) { + if (dataURI.base64) { + uint8_t* data = 0; + this->byteLength = Util::DecodeBase64(dataURI.data, dataURI.dataLength, data); + this->mData.reset(data, std::default_delete()); + + if (statedLength > 0 && this->byteLength != statedLength) { + throw DeadlyImportError("GLTF: buffer \"" + id + "\", expected " + to_string(statedLength) + + " bytes, but found " + to_string(dataURI.dataLength)); + } + } + else { // assume raw data + if (statedLength != dataURI.dataLength) { + throw DeadlyImportError("GLTF: buffer \"" + id + "\", expected " + to_string(statedLength) + + " bytes, but found " + to_string(dataURI.dataLength)); + } + + this->mData.reset(new uint8_t[dataURI.dataLength], std::default_delete()); + memcpy( this->mData.get(), dataURI.data, dataURI.dataLength ); + } + } + else { // Local file + if (byteLength > 0) { + std::string dir = !r.mCurrentAssetDir.empty() ? (r.mCurrentAssetDir + "/") : ""; + + IOStream* file = r.OpenFile(dir + uri, "rb"); + if (file) { + bool ok = LoadFromStream(*file, byteLength); + delete file; + + if (!ok) + throw DeadlyImportError("GLTF: error while reading referenced file \"" + std::string(uri) + "\"" ); + } + else { + throw DeadlyImportError("GLTF: could not open referenced file \"" + std::string(uri) + "\""); + } + } + } +} + +inline bool Buffer::LoadFromStream(IOStream& stream, size_t length, size_t baseOffset) +{ + byteLength = length ? length : stream.FileSize(); + + if (baseOffset) { + stream.Seek(baseOffset, aiOrigin_SET); + } + + mData.reset(new uint8_t[byteLength], std::default_delete()); + + if (stream.Read(mData.get(), byteLength, 1) != 1) { + return false; + } + return true; +} + +inline void Buffer::EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string& pID) +{ + // Check pointer to data + if(pDecodedData == nullptr) throw DeadlyImportError("GLTF: for marking encoded region pointer to decoded data must be provided."); + + // Check offset + if(pOffset > byteLength) + { + const uint8_t val_size = 32; + + char val[val_size]; + + ai_snprintf(val, val_size, "%llu", (long long)pOffset); + throw DeadlyImportError(std::string("GLTF: incorrect offset value (") + val + ") for marking encoded region."); + } + + // Check length + if((pOffset + pEncodedData_Length) > byteLength) + { + const uint8_t val_size = 64; + + char val[val_size]; + + ai_snprintf(val, val_size, "%llu, %llu", (long long)pOffset, (long long)pEncodedData_Length); + throw DeadlyImportError(std::string("GLTF: encoded region with offset/length (") + val + ") is out of range."); + } + + // Add new region + EncodedRegion_List.push_back(new SEncodedRegion(pOffset, pEncodedData_Length, pDecodedData, pDecodedData_Length, pID)); + // And set new value for "byteLength" + byteLength += (pDecodedData_Length - pEncodedData_Length); +} + +inline void Buffer::EncodedRegion_SetCurrent(const std::string& pID) +{ + if((EncodedRegion_Current != nullptr) && (EncodedRegion_Current->ID == pID)) return; + + for(SEncodedRegion* reg : EncodedRegion_List) + { + if(reg->ID == pID) + { + EncodedRegion_Current = reg; + + return; + } + + } + + throw DeadlyImportError("GLTF: EncodedRegion with ID: \"" + pID + "\" not found."); +} + +inline bool Buffer::ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count) +{ +const size_t new_data_size = byteLength + pReplace_Count - pBufferData_Count; + +uint8_t* new_data; + + if((pBufferData_Count == 0) || (pReplace_Count == 0) || (pReplace_Data == nullptr)) return false; + + new_data = new uint8_t[new_data_size]; + // Copy data which place before replacing part. + memcpy(new_data, mData.get(), pBufferData_Offset); + // Copy new data. + memcpy(&new_data[pBufferData_Offset], pReplace_Data, pReplace_Count); + // Copy data which place after replacing part. + memcpy(&new_data[pBufferData_Offset + pReplace_Count], &mData.get()[pBufferData_Offset + pBufferData_Count], pBufferData_Offset); + // Apply new data + mData.reset(new_data, std::default_delete()); + byteLength = new_data_size; + + return true; +} + +inline size_t Buffer::AppendData(uint8_t* data, size_t length) +{ + size_t offset = this->byteLength; + Grow(length); + memcpy(mData.get() + offset, data, length); + return offset; +} + +inline void Buffer::Grow(size_t amount) +{ + if (amount <= 0) return; + uint8_t* b = new uint8_t[byteLength + amount]; + if (mData) memcpy(b, mData.get(), byteLength); + mData.reset(b, std::default_delete()); + byteLength += amount; +} + +// +// struct BufferView +// + +inline void BufferView::Read(Value& obj, Asset& r) +{ + + if (Value* bufferVal = FindUInt(obj, "buffer")) { + buffer = r.buffers.Retrieve(bufferVal->GetUint()); + } + + byteOffset = MemberOrDefault(obj, "byteOffset", 0u); + byteLength = MemberOrDefault(obj, "byteLength", 0u); + byteStride = MemberOrDefault(obj, "byteStride", 0u); +} + +// +// struct Accessor +// + +inline void Accessor::Read(Value& obj, Asset& r) +{ + + if (Value* bufferViewVal = FindUInt(obj, "bufferView")) { + bufferView = r.bufferViews.Retrieve(bufferViewVal->GetUint()); + } + + byteOffset = MemberOrDefault(obj, "byteOffset", 0u); + componentType = MemberOrDefault(obj, "componentType", ComponentType_BYTE); + count = MemberOrDefault(obj, "count", 0u); + + const char* typestr; + type = ReadMember(obj, "type", typestr) ? AttribType::FromString(typestr) : AttribType::SCALAR; +} + +inline unsigned int Accessor::GetNumComponents() +{ + return AttribType::GetNumComponents(type); +} + +inline unsigned int Accessor::GetBytesPerComponent() +{ + return int(ComponentTypeSize(componentType)); +} + +inline unsigned int Accessor::GetElementSize() +{ + return GetNumComponents() * GetBytesPerComponent(); +} + +inline uint8_t* Accessor::GetPointer() +{ + if (!bufferView || !bufferView->buffer) return 0; + uint8_t* basePtr = bufferView->buffer->GetPointer(); + if (!basePtr) return 0; + + size_t offset = byteOffset + bufferView->byteOffset; + + // Check if region is encoded. + if(bufferView->buffer->EncodedRegion_Current != nullptr) + { + const size_t begin = bufferView->buffer->EncodedRegion_Current->Offset; + const size_t end = begin + bufferView->buffer->EncodedRegion_Current->DecodedData_Length; + + if((offset >= begin) && (offset < end)) + return &bufferView->buffer->EncodedRegion_Current->DecodedData[offset - begin]; + } + + return basePtr + offset; +} + +namespace { + inline void CopyData(size_t count, + const uint8_t* src, size_t src_stride, + uint8_t* dst, size_t dst_stride) + { + if (src_stride == dst_stride) { + memcpy(dst, src, count * src_stride); + } + else { + size_t sz = std::min(src_stride, dst_stride); + for (size_t i = 0; i < count; ++i) { + memcpy(dst, src, sz); + if (sz < dst_stride) { + memset(dst + sz, 0, dst_stride - sz); + } + src += src_stride; + dst += dst_stride; + } + } + } +} + +template +bool Accessor::ExtractData(T*& outData) +{ + uint8_t* data = GetPointer(); + if (!data) return false; + + const size_t elemSize = GetElementSize(); + const size_t totalSize = elemSize * count; + + const size_t stride = bufferView && bufferView->byteStride ? bufferView->byteStride : elemSize; + + const size_t targetElemSize = sizeof(T); + ai_assert(elemSize <= targetElemSize); + + ai_assert(count*stride <= bufferView->byteLength); + + outData = new T[count]; + if (stride == elemSize && targetElemSize == elemSize) { + memcpy(outData, data, totalSize); + } + else { + for (size_t i = 0; i < count; ++i) { + memcpy(outData + i, data + i*stride, elemSize); + } + } + + return true; +} + +inline void Accessor::WriteData(size_t count, const void* src_buffer, size_t src_stride) +{ + uint8_t* buffer_ptr = bufferView->buffer->GetPointer(); + size_t offset = byteOffset + bufferView->byteOffset; + + size_t dst_stride = GetNumComponents() * GetBytesPerComponent(); + + const uint8_t* src = reinterpret_cast(src_buffer); + uint8_t* dst = reinterpret_cast< uint8_t*>(buffer_ptr + offset); + + ai_assert(dst + count*dst_stride <= buffer_ptr + bufferView->buffer->byteLength); + CopyData(count, src, src_stride, dst, dst_stride); +} + + + +inline Accessor::Indexer::Indexer(Accessor& acc) + : accessor(acc) + , data(acc.GetPointer()) + , elemSize(acc.GetElementSize()) + , stride(acc.bufferView && acc.bufferView->byteStride ? acc.bufferView->byteStride : elemSize) +{ + +} + +//! Accesses the i-th value as defined by the accessor +template +T Accessor::Indexer::GetValue(int i) +{ + ai_assert(data); + ai_assert(i*stride < accessor.bufferView->byteLength); + T value = T(); + memcpy(&value, data + i*stride, elemSize); + //value >>= 8 * (sizeof(T) - elemSize); + return value; +} + +inline Image::Image() + : width(0) + , height(0) + , mData(0) + , mDataLength(0) +{ + +} + +inline void Image::Read(Value& obj, Asset& /*r*/) +{ + if (!mDataLength) { + if (Value* uri = FindString(obj, "uri")) { + const char* uristr = uri->GetString(); + + Util::DataURI dataURI; + if (ParseDataURI(uristr, uri->GetStringLength(), dataURI)) { + mimeType = dataURI.mediaType; + if (dataURI.base64) { + mDataLength = Util::DecodeBase64(dataURI.data, dataURI.dataLength, mData); + } + } + else { + this->uri = uristr; + } + } + } +} + +inline uint8_t* Image::StealData() +{ + uint8_t* data = mData; + mDataLength = 0; + mData = 0; + return data; +} + +inline void Image::SetData(uint8_t* data, size_t length, Asset& r) +{ + Ref b = r.GetBodyBuffer(); + if (b) { // binary file: append to body + std::string bvId = r.FindUniqueID(this->id, "imgdata"); + bufferView = r.bufferViews.Create(bvId); + + bufferView->buffer = b; + bufferView->byteLength = length; + bufferView->byteOffset = b->AppendData(data, length); + } + else { // text file: will be stored as a data uri + this->mData = data; + this->mDataLength = length; + } +} + +inline void Sampler::Read(Value& obj, Asset& /*r*/) +{ + SetDefaults(); + + ReadMember(obj, "name", name); + ReadMember(obj, "magFilter", magFilter); + ReadMember(obj, "minFilter", minFilter); + ReadMember(obj, "wrapS", wrapS); + ReadMember(obj, "wrapT", wrapT); +} + +inline void Sampler::SetDefaults() +{ + //only wrapping modes have defaults + wrapS = SamplerWrap::Repeat; + wrapT = SamplerWrap::Repeat; + magFilter = SamplerMagFilter::UNSET; + minFilter = SamplerMinFilter::UNSET; +} + +inline void Texture::Read(Value& obj, Asset& r) +{ + if (Value* sourceVal = FindUInt(obj, "source")) { + source = r.images.Retrieve(sourceVal->GetUint()); + } + + if (Value* samplerVal = FindUInt(obj, "sampler")) { + sampler = r.samplers.Retrieve(samplerVal->GetUint()); + } +} + +namespace { + inline void SetTextureProperties(Asset& r, Value* prop, TextureInfo& out) + { + if (Value* index = FindUInt(*prop, "index")) { + out.texture = r.textures.Retrieve(index->GetUint()); + } + + if (Value* texcoord = FindUInt(*prop, "texCoord")) { + out.texCoord = texcoord->GetUint(); + } + } + + inline void ReadTextureProperty(Asset& r, Value& vals, const char* propName, TextureInfo& out) + { + if (Value* prop = FindMember(vals, propName)) { + SetTextureProperties(r, prop, out); + } + } + + inline void ReadTextureProperty(Asset& r, Value& vals, const char* propName, NormalTextureInfo& out) + { + if (Value* prop = FindMember(vals, propName)) { + SetTextureProperties(r, prop, out); + + if (Value* scale = FindNumber(*prop, "scale")) { + out.scale = static_cast(scale->GetDouble()); + } + } + } + + inline void ReadTextureProperty(Asset& r, Value& vals, const char* propName, OcclusionTextureInfo& out) + { + if (Value* prop = FindMember(vals, propName)) { + SetTextureProperties(r, prop, out); + + if (Value* strength = FindNumber(*prop, "strength")) { + out.strength = static_cast(strength->GetDouble()); + } + } + } +} + +inline void Material::Read(Value& material, Asset& r) +{ + SetDefaults(); + + if (Value* pbrMetallicRoughness = FindObject(material, "pbrMetallicRoughness")) { + ReadMember(*pbrMetallicRoughness, "baseColorFactor", this->pbrMetallicRoughness.baseColorFactor); + ReadTextureProperty(r, *pbrMetallicRoughness, "baseColorTexture", this->pbrMetallicRoughness.baseColorTexture); + ReadTextureProperty(r, *pbrMetallicRoughness, "metallicRoughnessTexture", this->pbrMetallicRoughness.metallicRoughnessTexture); + ReadMember(*pbrMetallicRoughness, "metallicFactor", this->pbrMetallicRoughness.metallicFactor); + ReadMember(*pbrMetallicRoughness, "roughnessFactor", this->pbrMetallicRoughness.roughnessFactor); + } + + ReadTextureProperty(r, material, "normalTexture", this->normalTexture); + ReadTextureProperty(r, material, "occlusionTexture", this->occlusionTexture); + ReadTextureProperty(r, material, "emissiveTexture", this->emissiveTexture); + ReadMember(material, "emissiveFactor", this->emissiveFactor); + + ReadMember(material, "doubleSided", this->doubleSided); + ReadMember(material, "alphaMode", this->alphaMode); + ReadMember(material, "alphaCutoff", this->alphaCutoff); + + if (Value* extensions = FindObject(material, "extensions")) { + if (r.extensionsUsed.KHR_materials_pbrSpecularGlossiness) { + if (Value* pbrSpecularGlossiness = FindObject(*extensions, "KHR_materials_pbrSpecularGlossiness")) { + PbrSpecularGlossiness pbrSG; + + ReadMember(*pbrSpecularGlossiness, "diffuseFactor", pbrSG.diffuseFactor); + ReadTextureProperty(r, *pbrSpecularGlossiness, "diffuseTexture", pbrSG.diffuseTexture); + ReadTextureProperty(r, *pbrSpecularGlossiness, "specularGlossinessTexture", pbrSG.specularGlossinessTexture); + ReadMember(*pbrSpecularGlossiness, "specularFactor", pbrSG.specularFactor); + ReadMember(*pbrSpecularGlossiness, "glossinessFactor", pbrSG.glossinessFactor); + + this->pbrSpecularGlossiness = Nullable(pbrSG); + } + } + } +} + +namespace { + void SetVector(vec4& v, const float(&in)[4]) + { v[0] = in[0]; v[1] = in[1]; v[2] = in[2]; v[3] = in[3]; } + + void SetVector(vec3& v, const float(&in)[3]) + { v[0] = in[0]; v[1] = in[1]; v[2] = in[2]; } +} + +inline void Material::SetDefaults() +{ + //pbr materials + SetVector(pbrMetallicRoughness.baseColorFactor, defaultBaseColor); + pbrMetallicRoughness.metallicFactor = 1.0; + pbrMetallicRoughness.roughnessFactor = 1.0; + + SetVector(emissiveFactor, defaultEmissiveFactor); + alphaMode = "OPAQUE"; + alphaCutoff = 0.5; + doubleSided = false; +} + +inline void PbrSpecularGlossiness::SetDefaults() +{ + //pbrSpecularGlossiness properties + SetVector(diffuseFactor, defaultDiffuseFactor); + SetVector(specularFactor, defaultSpecularFactor); + glossinessFactor = 1.0; +} + +namespace { + + template + inline int Compare(const char* attr, const char (&str)[N]) { + return (strncmp(attr, str, N - 1) == 0) ? N - 1 : 0; + } + + inline bool GetAttribVector(Mesh::Primitive& p, const char* attr, Mesh::AccessorList*& v, int& pos) + { + if ((pos = Compare(attr, "POSITION"))) { + v = &(p.attributes.position); + } + else if ((pos = Compare(attr, "NORMAL"))) { + v = &(p.attributes.normal); + } + else if ((pos = Compare(attr, "TANGENT"))) { + v = &(p.attributes.tangent); + } + else if ((pos = Compare(attr, "TEXCOORD"))) { + v = &(p.attributes.texcoord); + } + else if ((pos = Compare(attr, "COLOR"))) { + v = &(p.attributes.color); + } + else if ((pos = Compare(attr, "JOINT"))) { + v = &(p.attributes.joint); + } + else if ((pos = Compare(attr, "JOINTMATRIX"))) { + v = &(p.attributes.jointmatrix); + } + else if ((pos = Compare(attr, "WEIGHT"))) { + v = &(p.attributes.weight); + } + else return false; + return true; + } +} + +inline void Mesh::Read(Value& pJSON_Object, Asset& pAsset_Root) +{ + if (Value* name = FindMember(pJSON_Object, "name")) { + this->name = name->GetString(); + } + + /****************** Mesh primitives ******************/ + if (Value* primitives = FindArray(pJSON_Object, "primitives")) { + this->primitives.resize(primitives->Size()); + for (unsigned int i = 0; i < primitives->Size(); ++i) { + Value& primitive = (*primitives)[i]; + + Primitive& prim = this->primitives[i]; + prim.mode = MemberOrDefault(primitive, "mode", PrimitiveMode_TRIANGLES); + + if (Value* attrs = FindObject(primitive, "attributes")) { + for (Value::MemberIterator it = attrs->MemberBegin(); it != attrs->MemberEnd(); ++it) { + if (!it->value.IsUint()) continue; + const char* attr = it->name.GetString(); + // Valid attribute semantics include POSITION, NORMAL, TANGENT, TEXCOORD, COLOR, JOINT, JOINTMATRIX, + // and WEIGHT.Attribute semantics can be of the form[semantic]_[set_index], e.g., TEXCOORD_0, TEXCOORD_1, etc. + + int undPos = 0; + Mesh::AccessorList* vec = 0; + if (GetAttribVector(prim, attr, vec, undPos)) { + size_t idx = (attr[undPos] == '_') ? atoi(attr + undPos + 1) : 0; + if ((*vec).size() <= idx) (*vec).resize(idx + 1); + (*vec)[idx] = pAsset_Root.accessors.Retrieve(it->value.GetUint()); + } + } + } + + if (Value* indices = FindUInt(primitive, "indices")) { + prim.indices = pAsset_Root.accessors.Retrieve(indices->GetUint()); + } + + if (Value* material = FindUInt(primitive, "material")) { + prim.material = pAsset_Root.materials.Retrieve(material->GetUint()); + } + } + } +} + +inline void Camera::Read(Value& obj, Asset& /*r*/) +{ + type = MemberOrDefault(obj, "type", Camera::Perspective); + + const char* subobjId = (type == Camera::Orthographic) ? "orthographic" : "perspective"; + + Value* it = FindObject(obj, subobjId); + if (!it) throw DeadlyImportError("GLTF: Camera missing its parameters"); + + if (type == Camera::Perspective) { + cameraProperties.perspective.aspectRatio = MemberOrDefault(*it, "aspectRatio", 0.f); + cameraProperties.perspective.yfov = MemberOrDefault(*it, "yfov", 3.1415f/2.f); + cameraProperties.perspective.zfar = MemberOrDefault(*it, "zfar", 100.f); + cameraProperties.perspective.znear = MemberOrDefault(*it, "znear", 0.01f); + } + else { + cameraProperties.ortographic.xmag = MemberOrDefault(obj, "xmag", 1.f); + cameraProperties.ortographic.ymag = MemberOrDefault(obj, "ymag", 1.f); + cameraProperties.ortographic.zfar = MemberOrDefault(obj, "zfar", 100.f); + cameraProperties.ortographic.znear = MemberOrDefault(obj, "znear", 0.01f); + } +} + +inline void Node::Read(Value& obj, Asset& r) +{ + + if (Value* children = FindArray(obj, "children")) { + this->children.reserve(children->Size()); + for (unsigned int i = 0; i < children->Size(); ++i) { + Value& child = (*children)[i]; + if (child.IsUint()) { + // get/create the child node + Ref chn = r.nodes.Retrieve(child.GetUint()); + if (chn) this->children.push_back(chn); + } + } + } + + if (Value* matrix = FindArray(obj, "matrix")) { + ReadValue(*matrix, this->matrix); + } + else { + ReadMember(obj, "translation", translation); + ReadMember(obj, "scale", scale); + ReadMember(obj, "rotation", rotation); + } + + if (Value* mesh = FindUInt(obj, "mesh")) { + unsigned numMeshes = 1; + + this->meshes.reserve(numMeshes); + + Ref meshRef = r.meshes.Retrieve((*mesh).GetUint()); + + if (meshRef) this->meshes.push_back(meshRef); + } + + if (Value* camera = FindUInt(obj, "camera")) { + this->camera = r.cameras.Retrieve(camera->GetUint()); + if (this->camera) + this->camera->id = this->id; + } +} + +inline void Scene::Read(Value& obj, Asset& r) +{ + if (Value* array = FindArray(obj, "nodes")) { + for (unsigned int i = 0; i < array->Size(); ++i) { + if (!(*array)[i].IsUint()) continue; + Ref node = r.nodes.Retrieve((*array)[i].GetUint()); + if (node) + this->nodes.push_back(node); + } + } +} + +inline void AssetMetadata::Read(Document& doc) +{ + if (Value* obj = FindObject(doc, "asset")) { + ReadMember(*obj, "copyright", copyright); + ReadMember(*obj, "generator", generator); + + if (Value* versionString = FindString(*obj, "version")) { + version = versionString->GetString(); + } else if (Value* versionNumber = FindNumber (*obj, "version")) { + char buf[4]; + + ai_snprintf(buf, 4, "%.1f", versionNumber->GetDouble()); + + version = buf; + } + + if (Value* profile = FindObject(*obj, "profile")) { + ReadMember(*profile, "api", this->profile.api); + ReadMember(*profile, "version", this->profile.version); + } + } + + if (version.empty() || version[0] != '2') { + throw DeadlyImportError("GLTF: Unsupported glTF version: " + version); + } +} + +// +// Asset methods implementation +// + +inline void Asset::ReadBinaryHeader(IOStream& stream, std::vector& sceneData) +{ + GLB_Header header; + if (stream.Read(&header, sizeof(header), 1) != 1) { + throw DeadlyImportError("GLTF: Unable to read the file header"); + } + + if (strncmp((char*)header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic)) != 0) { + throw DeadlyImportError("GLTF: Invalid binary glTF file"); + } + + AI_SWAP4(header.version); + asset.version = to_string(header.version); + if (header.version != 2) { + throw DeadlyImportError("GLTF: Unsupported binary glTF version"); + } + + GLB_Chunk chunk; + if (stream.Read(&chunk, sizeof(chunk), 1) != 1) { + throw DeadlyImportError("GLTF: Unable to read JSON chunk"); + } + + AI_SWAP4(chunk.chunkLength); + AI_SWAP4(chunk.chunkType); + + if (chunk.chunkType != ChunkType_JSON) { + throw DeadlyImportError("GLTF: JSON chunk missing"); + } + + // read the scene data + + mSceneLength = chunk.chunkLength; + sceneData.resize(mSceneLength + 1); + sceneData[mSceneLength] = '\0'; + + if (stream.Read(&sceneData[0], 1, mSceneLength) != mSceneLength) { + throw DeadlyImportError("GLTF: Could not read the file contents"); + } + + uint32_t padding = ((chunk.chunkLength + 3) & ~3) - chunk.chunkLength; + if (padding > 0) { + stream.Seek(padding, aiOrigin_CUR); + } + + AI_SWAP4(header.length); + mBodyOffset = 12 + 8 + chunk.chunkLength + padding + 8; + if (header.length >= mBodyOffset) { + if (stream.Read(&chunk, sizeof(chunk), 1) != 1) { + throw DeadlyImportError("GLTF: Unable to read BIN chunk"); + } + + AI_SWAP4(chunk.chunkLength); + AI_SWAP4(chunk.chunkType); + + if (chunk.chunkType != ChunkType_BIN) { + throw DeadlyImportError("GLTF: BIN chunk missing"); + } + + mBodyLength = chunk.chunkLength; + } + else { + mBodyOffset = mBodyLength = 0; + } +} + +inline void Asset::Load(const std::string& pFile, bool isBinary) +{ + mCurrentAssetDir.clear(); + int pos = std::max(int(pFile.rfind('/')), int(pFile.rfind('\\'))); + if (pos != int(std::string::npos)) mCurrentAssetDir = pFile.substr(0, pos + 1); + + shared_ptr stream(OpenFile(pFile.c_str(), "rb", true)); + if (!stream) { + throw DeadlyImportError("GLTF: Could not open file for reading"); + } + + // is binary? then read the header + std::vector sceneData; + if (isBinary) { + SetAsBinary(); // also creates the body buffer + ReadBinaryHeader(*stream, sceneData); + } + else { + mSceneLength = stream->FileSize(); + mBodyLength = 0; + + + // read the scene data + + sceneData.resize(mSceneLength + 1); + sceneData[mSceneLength] = '\0'; + + if (stream->Read(&sceneData[0], 1, mSceneLength) != mSceneLength) { + throw DeadlyImportError("GLTF: Could not read the file contents"); + } + } + + + // parse the JSON document + + Document doc; + doc.ParseInsitu(&sceneData[0]); + + if (doc.HasParseError()) { + char buffer[32]; + ai_snprintf(buffer, 32, "%d", static_cast(doc.GetErrorOffset())); + throw DeadlyImportError(std::string("GLTF: JSON parse error, offset ") + buffer + ": " + + GetParseError_En(doc.GetParseError())); + } + + if (!doc.IsObject()) { + throw DeadlyImportError("GLTF: JSON document root must be a JSON object"); + } + + // Fill the buffer instance for the current file embedded contents + if (mBodyLength > 0) { + if (!mBodyBuffer->LoadFromStream(*stream, mBodyLength, mBodyOffset)) { + throw DeadlyImportError("GLTF: Unable to read gltf file"); + } + } + + + // Load the metadata + asset.Read(doc); + ReadExtensionsUsed(doc); + + // Prepare the dictionaries + for (size_t i = 0; i < mDicts.size(); ++i) { + mDicts[i]->AttachToDocument(doc); + } + + // Read the "scene" property, which specifies which scene to load + // and recursively load everything referenced by it + if (Value* scene = FindUInt(doc, "scene")) { + unsigned int sceneIndex = scene->GetUint(); + + Ref s = scenes.Retrieve(sceneIndex); + + this->scene = s; + } + + // Clean up + for (size_t i = 0; i < mDicts.size(); ++i) { + mDicts[i]->DetachFromDocument(); + } +} + +inline void Asset::SetAsBinary() +{ + if (!mBodyBuffer) { + mBodyBuffer = buffers.Create("binary_glTF"); + mBodyBuffer->MarkAsSpecial(); + } +} + + +inline void Asset::ReadExtensionsUsed(Document& doc) +{ + Value* extsUsed = FindArray(doc, "extensionsUsed"); + if (!extsUsed) return; + + std::gltf_unordered_map exts; + + for (unsigned int i = 0; i < extsUsed->Size(); ++i) { + if ((*extsUsed)[i].IsString()) { + exts[(*extsUsed)[i].GetString()] = true; + } + } + + #define CHECK_EXT(EXT) \ + if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true; + + CHECK_EXT(KHR_materials_pbrSpecularGlossiness); + + #undef CHECK_EXT +} + +inline IOStream* Asset::OpenFile(std::string path, const char* mode, bool /*absolute*/) +{ + #ifdef ASSIMP_API + return mIOSystem->Open(path, mode); + #else + if (path.size() < 2) return 0; + if (!absolute && path[1] != ':' && path[0] != '/') { // relative? + path = mCurrentAssetDir + path; + } + FILE* f = fopen(path.c_str(), mode); + return f ? new IOStream(f) : 0; + #endif +} + +inline std::string Asset::FindUniqueID(const std::string& str, const char* suffix) +{ + std::string id = str; + + if (!id.empty()) { + if (mUsedIds.find(id) == mUsedIds.end()) + return id; + + id += "_"; + } + + id += suffix; + + Asset::IdMap::iterator it = mUsedIds.find(id); + if (it == mUsedIds.end()) + return id; + + std::vector buffer; + buffer.resize(id.size() + 16); + int offset = ai_snprintf(buffer.data(), buffer.size(), "%s_", id.c_str()); + for (int i = 0; it != mUsedIds.end(); ++i) { + ai_snprintf(buffer.data() + offset, buffer.size() - offset, "%d", i); + id = buffer.data(); + it = mUsedIds.find(id); + } + + return id; +} + +namespace Util { + + inline + bool ParseDataURI(const char* const_uri, size_t uriLen, DataURI& out) { + if ( NULL == const_uri ) { + return false; + } + + if (const_uri[0] != 0x10) { // we already parsed this uri? + if (strncmp(const_uri, "data:", 5) != 0) // not a data uri? + return false; + } + + // set defaults + out.mediaType = "text/plain"; + out.charset = "US-ASCII"; + out.base64 = false; + + char* uri = const_cast(const_uri); + if (uri[0] != 0x10) { + uri[0] = 0x10; + uri[1] = uri[2] = uri[3] = uri[4] = 0; + + size_t i = 5, j; + if (uri[i] != ';' && uri[i] != ',') { // has media type? + uri[1] = char(i); + for (; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) { + // nothing to do! + } + } + while (uri[i] == ';' && i < uriLen) { + uri[i++] = '\0'; + for (j = i; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) { + // nothing to do! + } + + if ( strncmp( uri + j, "charset=", 8 ) == 0 ) { + uri[2] = char(j + 8); + } else if ( strncmp( uri + j, "base64", 6 ) == 0 ) { + uri[3] = char(j); + } + } + if (i < uriLen) { + uri[i++] = '\0'; + uri[4] = char(i); + } else { + uri[1] = uri[2] = uri[3] = 0; + uri[4] = 5; + } + } + + if ( uri[ 1 ] != 0 ) { + out.mediaType = uri + uri[ 1 ]; + } + if ( uri[ 2 ] != 0 ) { + out.charset = uri + uri[ 2 ]; + } + if ( uri[ 3 ] != 0 ) { + out.base64 = true; + } + out.data = uri + uri[4]; + out.dataLength = (uri + uriLen) - out.data; + + return true; + } + + template + struct DATA + { + static const uint8_t tableDecodeBase64[128]; + }; + + template + const uint8_t DATA::tableDecodeBase64[128] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 64, 0, 0, + 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, + 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0 + }; + + inline char EncodeCharBase64(uint8_t b) + { + return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[size_t(b)]; + } + + inline uint8_t DecodeCharBase64(char c) + { + return DATA::tableDecodeBase64[size_t(c)]; // TODO faster with lookup table or ifs? + /*if (c >= 'A' && c <= 'Z') return c - 'A'; + if (c >= 'a' && c <= 'z') return c - 'a' + 26; + if (c >= '0' && c <= '9') return c - '0' + 52; + if (c == '+') return 62; + if (c == '/') return 63; + return 64; // '-' */ + } + + inline size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out) + { + ai_assert(inLength % 4 == 0); + + if (inLength < 4) { + out = 0; + return 0; + } + + int nEquals = int(in[inLength - 1] == '=') + + int(in[inLength - 2] == '='); + + size_t outLength = (inLength * 3) / 4 - nEquals; + out = new uint8_t[outLength]; + memset(out, 0, outLength); + + size_t i, j = 0; + + for (i = 0; i + 4 < inLength; i += 4) { + uint8_t b0 = DecodeCharBase64(in[i]); + uint8_t b1 = DecodeCharBase64(in[i + 1]); + uint8_t b2 = DecodeCharBase64(in[i + 2]); + uint8_t b3 = DecodeCharBase64(in[i + 3]); + + out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4)); + out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2)); + out[j++] = (uint8_t)((b2 << 6) | b3); + } + + { + uint8_t b0 = DecodeCharBase64(in[i]); + uint8_t b1 = DecodeCharBase64(in[i + 1]); + uint8_t b2 = DecodeCharBase64(in[i + 2]); + uint8_t b3 = DecodeCharBase64(in[i + 3]); + + out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4)); + if (b2 < 64) out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2)); + if (b3 < 64) out[j++] = (uint8_t)((b2 << 6) | b3); + } + + return outLength; + } + + + + inline void EncodeBase64( + const uint8_t* in, size_t inLength, + std::string& out) + { + size_t outLength = ((inLength + 2) / 3) * 4; + + size_t j = out.size(); + out.resize(j + outLength); + + for (size_t i = 0; i < inLength; i += 3) { + uint8_t b = (in[i] & 0xFC) >> 2; + out[j++] = EncodeCharBase64(b); + + b = (in[i] & 0x03) << 4; + if (i + 1 < inLength) { + b |= (in[i + 1] & 0xF0) >> 4; + out[j++] = EncodeCharBase64(b); + + b = (in[i + 1] & 0x0F) << 2; + if (i + 2 < inLength) { + b |= (in[i + 2] & 0xC0) >> 6; + out[j++] = EncodeCharBase64(b); + + b = in[i + 2] & 0x3F; + out[j++] = EncodeCharBase64(b); + } + else { + out[j++] = EncodeCharBase64(b); + out[j++] = '='; + } + } + else { + out[j++] = EncodeCharBase64(b); + out[j++] = '='; + out[j++] = '='; + } + } + } + +} + +} // ns glTF diff --git a/code/glTF2AssetWriter.h b/code/glTF2AssetWriter.h new file mode 100644 index 000000000..bce2b1bd1 --- /dev/null +++ b/code/glTF2AssetWriter.h @@ -0,0 +1,93 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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 glTFWriter.h + * Declares a class to write gltf/glb files + * + * glTF Extensions Support: + * KHR_materials_pbrSpecularGlossiness: full + */ +#ifndef GLTF2ASSETWRITER_H_INC +#define GLTF2ASSETWRITER_H_INC + +#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER + +#include "glTF2Asset.h" + +namespace glTF2 +{ + +using rapidjson::MemoryPoolAllocator; + +class AssetWriter +{ + template + friend void WriteLazyDict(LazyDict& d, AssetWriter& w); + +private: + + void WriteBinaryData(IOStream* outfile, size_t sceneLength); + + void WriteMetadata(); + void WriteExtensionsUsed(); + + template + void WriteObjects(LazyDict& d); + +public: + Document mDoc; + Asset& mAsset; + + MemoryPoolAllocator<>& mAl; + + AssetWriter(Asset& asset); + + void WriteFile(const char* path); +}; + +} + +// Include the implementation of the methods +#include "glTF2AssetWriter.inl" + +#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER + +#endif // GLTF2ASSETWRITER_H_INC diff --git a/code/glTF2AssetWriter.inl b/code/glTF2AssetWriter.inl new file mode 100644 index 000000000..8b2769a37 --- /dev/null +++ b/code/glTF2AssetWriter.inl @@ -0,0 +1,638 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +#include +#include +#include + +namespace glTF2 { + + using rapidjson::StringBuffer; + using rapidjson::PrettyWriter; + using rapidjson::Writer; + using rapidjson::StringRef; + using rapidjson::StringRef; + + namespace { + + template + inline Value& MakeValue(Value& val, float(&r)[N], MemoryPoolAllocator<>& al) { + val.SetArray(); + val.Reserve(N, al); + for (decltype(N) i = 0; i < N; ++i) { + val.PushBack(r[i], al); + } + return val; + } + + inline Value& MakeValue(Value& val, const std::vector & r, MemoryPoolAllocator<>& al) { + val.SetArray(); + val.Reserve(static_cast(r.size()), al); + for (unsigned int i = 0; i < r.size(); ++i) { + val.PushBack(r[i], al); + } + return val; + } + + inline Value& MakeValue(Value& val, float r, MemoryPoolAllocator<>& /*al*/) { + val.SetDouble(r); + + return val; + } + + template + inline void AddRefsVector(Value& obj, const char* fieldId, std::vector< Ref >& v, MemoryPoolAllocator<>& al) { + if (v.empty()) return; + Value lst; + lst.SetArray(); + lst.Reserve(unsigned(v.size()), al); + for (size_t i = 0; i < v.size(); ++i) { + lst.PushBack(v[i]->index, al); + } + obj.AddMember(StringRef(fieldId), lst, al); + } + + + } + + inline void Write(Value& obj, Accessor& a, AssetWriter& w) + { + obj.AddMember("bufferView", a.bufferView->index, w.mAl); + obj.AddMember("byteOffset", a.byteOffset, w.mAl); + + obj.AddMember("componentType", int(a.componentType), w.mAl); + obj.AddMember("count", a.count, w.mAl); + obj.AddMember("type", StringRef(AttribType::ToString(a.type)), w.mAl); + + Value vTmpMax, vTmpMin; + obj.AddMember("max", MakeValue(vTmpMax, a.max, w.mAl), w.mAl); + obj.AddMember("min", MakeValue(vTmpMin, a.min, w.mAl), w.mAl); + } + + inline void Write(Value& obj, Animation& a, AssetWriter& w) + { + /****************** Channels *******************/ + Value channels; + channels.SetArray(); + channels.Reserve(unsigned(a.Channels.size()), w.mAl); + + for (size_t i = 0; i < unsigned(a.Channels.size()); ++i) { + Animation::AnimChannel& c = a.Channels[i]; + Value valChannel; + valChannel.SetObject(); + { + valChannel.AddMember("sampler", c.sampler, w.mAl); + + Value valTarget; + valTarget.SetObject(); + { + valTarget.AddMember("node", c.target.node->index, w.mAl); + valTarget.AddMember("path", c.target.path, w.mAl); + } + valChannel.AddMember("target", valTarget, w.mAl); + } + channels.PushBack(valChannel, w.mAl); + } + obj.AddMember("channels", channels, w.mAl); + + /****************** Samplers *******************/ + Value valSamplers; + valSamplers.SetArray(); + + for (size_t i = 0; i < unsigned(a.Samplers.size()); ++i) { + Animation::AnimSampler& s = a.Samplers[i]; + Value valSampler; + valSampler.SetObject(); + { + Ref inputAccessor = a.GetAccessor(s.input); + Ref outputAccessor = a.GetAccessor(s.output); + valSampler.AddMember("input", inputAccessor->index, w.mAl); + valSampler.AddMember("interpolation", s.interpolation, w.mAl); + valSampler.AddMember("output", outputAccessor->index, w.mAl); + } + valSamplers.PushBack(valSampler, w.mAl); + } + obj.AddMember("samplers", valSamplers, w.mAl); + } + + inline void Write(Value& obj, Buffer& b, AssetWriter& w) + { + obj.AddMember("byteLength", static_cast(b.byteLength), w.mAl); + obj.AddMember("uri", Value(b.GetURI(), w.mAl).Move(), w.mAl); + } + + inline void Write(Value& obj, BufferView& bv, AssetWriter& w) + { + obj.AddMember("buffer", bv.buffer->index, w.mAl); + obj.AddMember("byteOffset", static_cast(bv.byteOffset), w.mAl); + obj.AddMember("byteLength", static_cast(bv.byteLength), w.mAl); + if (bv.byteStride != 0) { + obj.AddMember("byteStride", bv.byteStride, w.mAl); + } + obj.AddMember("target", int(bv.target), w.mAl); + } + + inline void Write(Value& /*obj*/, Camera& /*c*/, AssetWriter& /*w*/) + { + + } + + inline void Write(Value& obj, Image& img, AssetWriter& w) + { + std::string uri; + if (img.HasData()) { + uri = "data:" + (img.mimeType.empty() ? "application/octet-stream" : img.mimeType); + uri += ";base64,"; + Util::EncodeBase64(img.GetData(), img.GetDataLength(), uri); + } + else { + uri = img.uri; + } + + obj.AddMember("uri", Value(uri, w.mAl).Move(), w.mAl); + } + + namespace { + inline void SetTexBasic(TextureInfo t, Value& tex, MemoryPoolAllocator<>& al) + { + tex.SetObject(); + tex.AddMember("index", t.texture->index, al); + + if (t.texCoord != 0) { + tex.AddMember("texCoord", t.texCoord, al); + } + } + + inline void WriteTex(Value& obj, TextureInfo t, const char* propName, MemoryPoolAllocator<>& al) + { + + if (t.texture) { + Value tex; + + SetTexBasic(t, tex, al); + + obj.AddMember(StringRef(propName), tex, al); + } + } + + inline void WriteTex(Value& obj, NormalTextureInfo t, const char* propName, MemoryPoolAllocator<>& al) + { + + if (t.texture) { + Value tex; + + SetTexBasic(t, tex, al); + + if (t.scale != 1) { + tex.AddMember("scale", t.scale, al); + } + + obj.AddMember(StringRef(propName), tex, al); + } + } + + inline void WriteTex(Value& obj, OcclusionTextureInfo t, const char* propName, MemoryPoolAllocator<>& al) + { + + if (t.texture) { + Value tex; + + SetTexBasic(t, tex, al); + + if (t.strength != 1) { + tex.AddMember("strength", t.strength, al); + } + + obj.AddMember(StringRef(propName), tex, al); + } + } + + template + inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, MemoryPoolAllocator<>& al) + { + Value arr; + obj.AddMember(StringRef(propName), MakeValue(arr, prop, al), al); + } + + template + inline void WriteVec(Value& obj, float(&prop)[N], const char* propName, const float(&defaultVal)[N], MemoryPoolAllocator<>& al) + { + if (!std::equal(std::begin(prop), std::end(prop), std::begin(defaultVal))) { + WriteVec(obj, prop, propName, al); + } + } + + inline void WriteFloat(Value& obj, float prop, const char* propName, MemoryPoolAllocator<>& al) + { + Value num; + obj.AddMember(StringRef(propName), MakeValue(num, prop, al), al); + } + } + + inline void Write(Value& obj, Material& m, AssetWriter& w) + { + Value pbrMetallicRoughness; + pbrMetallicRoughness.SetObject(); + { + WriteTex(pbrMetallicRoughness, m.pbrMetallicRoughness.baseColorTexture, "baseColorTexture", w.mAl); + WriteTex(pbrMetallicRoughness, m.pbrMetallicRoughness.metallicRoughnessTexture, "metallicRoughnessTexture", w.mAl); + WriteVec(pbrMetallicRoughness, m.pbrMetallicRoughness.baseColorFactor, "baseColorFactor", defaultBaseColor, w.mAl); + + if (m.pbrMetallicRoughness.metallicFactor != 1) { + WriteFloat(pbrMetallicRoughness, m.pbrMetallicRoughness.metallicFactor, "metallicFactor", w.mAl); + } + + if (m.pbrMetallicRoughness.roughnessFactor != 1) { + WriteFloat(pbrMetallicRoughness, m.pbrMetallicRoughness.roughnessFactor, "roughnessFactor", w.mAl); + } + } + + if (!pbrMetallicRoughness.ObjectEmpty()) { + obj.AddMember("pbrMetallicRoughness", pbrMetallicRoughness, w.mAl); + } + + WriteTex(obj, m.normalTexture, "normalTexture", w.mAl); + WriteTex(obj, m.emissiveTexture, "emissiveTexture", w.mAl); + WriteTex(obj, m.occlusionTexture, "occlusionTexture", w.mAl); + WriteVec(obj, m.emissiveFactor, "emissiveFactor", defaultEmissiveFactor, w.mAl); + + if (m.alphaCutoff != 0.5) { + WriteFloat(obj, m.alphaCutoff, "alphaCutoff", w.mAl); + } + + if (m.alphaMode != "OPAQUE") { + obj.AddMember("alphaMode", Value(m.alphaMode, w.mAl).Move(), w.mAl); + } + + if (m.doubleSided) { + obj.AddMember("doubleSided", m.doubleSided, w.mAl); + } + + Value exts; + exts.SetObject(); + + if (m.pbrSpecularGlossiness.isPresent) { + Value pbrSpecularGlossiness; + pbrSpecularGlossiness.SetObject(); + + PbrSpecularGlossiness &pbrSG = m.pbrSpecularGlossiness.value; + + //pbrSpecularGlossiness + WriteVec(pbrSpecularGlossiness, pbrSG.diffuseFactor, "diffuseFactor", defaultDiffuseFactor, w.mAl); + WriteVec(pbrSpecularGlossiness, pbrSG.specularFactor, "specularFactor", defaultSpecularFactor, w.mAl); + + if (pbrSG.glossinessFactor != 1) { + WriteFloat(obj, pbrSG.glossinessFactor, "glossinessFactor", w.mAl); + } + + WriteTex(pbrSpecularGlossiness, pbrSG.diffuseTexture, "diffuseTexture", w.mAl); + WriteTex(pbrSpecularGlossiness, pbrSG.specularGlossinessTexture, "specularGlossinessTexture", w.mAl); + + if (!pbrSpecularGlossiness.ObjectEmpty()) { + exts.AddMember("KHR_materials_pbrSpecularGlossiness", pbrSpecularGlossiness, w.mAl); + } + } + + if (!exts.ObjectEmpty()) { + obj.AddMember("extensions", exts, w.mAl); + } + } + + namespace { + inline void WriteAttrs(AssetWriter& w, Value& attrs, Mesh::AccessorList& lst, + const char* semantic, bool forceNumber = false) + { + if (lst.empty()) return; + if (lst.size() == 1 && !forceNumber) { + attrs.AddMember(StringRef(semantic), lst[0]->index, w.mAl); + } + else { + for (size_t i = 0; i < lst.size(); ++i) { + char buffer[32]; + ai_snprintf(buffer, 32, "%s_%d", semantic, int(i)); + attrs.AddMember(Value(buffer, w.mAl).Move(), lst[i]->index, w.mAl); + } + } + } + } + + inline void Write(Value& obj, Mesh& m, AssetWriter& w) + { + /****************** Primitives *******************/ + Value primitives; + primitives.SetArray(); + primitives.Reserve(unsigned(m.primitives.size()), w.mAl); + + for (size_t i = 0; i < m.primitives.size(); ++i) { + Mesh::Primitive& p = m.primitives[i]; + Value prim; + prim.SetObject(); + { + prim.AddMember("mode", Value(int(p.mode)).Move(), w.mAl); + + if (p.material) + prim.AddMember("material", p.material->index, w.mAl); + + if (p.indices) + prim.AddMember("indices", p.indices->index, w.mAl); + + Value attrs; + attrs.SetObject(); + { + WriteAttrs(w, attrs, p.attributes.position, "POSITION"); + WriteAttrs(w, attrs, p.attributes.normal, "NORMAL"); + WriteAttrs(w, attrs, p.attributes.texcoord, "TEXCOORD", true); + WriteAttrs(w, attrs, p.attributes.color, "COLOR", true); + WriteAttrs(w, attrs, p.attributes.joint, "JOINTS", true); + WriteAttrs(w, attrs, p.attributes.weight, "WEIGHTS", true); + } + prim.AddMember("attributes", attrs, w.mAl); + } + primitives.PushBack(prim, w.mAl); + } + + obj.AddMember("primitives", primitives, w.mAl); + } + + inline void Write(Value& obj, Node& n, AssetWriter& w) + { + + if (n.matrix.isPresent) { + Value val; + obj.AddMember("matrix", MakeValue(val, n.matrix.value, w.mAl).Move(), w.mAl); + } + + if (n.translation.isPresent) { + Value val; + obj.AddMember("translation", MakeValue(val, n.translation.value, w.mAl).Move(), w.mAl); + } + + if (n.scale.isPresent) { + Value val; + obj.AddMember("scale", MakeValue(val, n.scale.value, w.mAl).Move(), w.mAl); + } + if (n.rotation.isPresent) { + Value val; + obj.AddMember("rotation", MakeValue(val, n.rotation.value, w.mAl).Move(), w.mAl); + } + + AddRefsVector(obj, "children", n.children, w.mAl); + + if (!n.meshes.empty()) { + obj.AddMember("mesh", n.meshes[0]->index, w.mAl); + } + + AddRefsVector(obj, "skeletons", n.skeletons, w.mAl); + + if (n.skin) { + obj.AddMember("skin", n.skin->index, w.mAl); + } + + if (!n.jointName.empty()) { + obj.AddMember("jointName", n.jointName, w.mAl); + } + } + + inline void Write(Value& /*obj*/, Program& /*b*/, AssetWriter& /*w*/) + { + + } + + inline void Write(Value& obj, Sampler& b, AssetWriter& w) + { + if (!b.name.empty()) { + obj.AddMember("name", b.name, w.mAl); + } + + if (b.wrapS != SamplerWrap::UNSET && b.wrapS != SamplerWrap::Repeat) { + obj.AddMember("wrapS", static_cast(b.wrapS), w.mAl); + } + + if (b.wrapT != SamplerWrap::UNSET && b.wrapT != SamplerWrap::Repeat) { + obj.AddMember("wrapT", static_cast(b.wrapT), w.mAl); + } + + if (b.magFilter != SamplerMagFilter::UNSET) { + obj.AddMember("magFilter", static_cast(b.magFilter), w.mAl); + } + + if (b.minFilter != SamplerMinFilter::UNSET) { + obj.AddMember("minFilter", static_cast(b.minFilter), w.mAl); + } + } + + inline void Write(Value& scene, Scene& s, AssetWriter& w) + { + AddRefsVector(scene, "nodes", s.nodes, w.mAl); + } + + inline void Write(Value& /*obj*/, Shader& /*b*/, AssetWriter& /*w*/) + { + + } + + inline void Write(Value& obj, Skin& b, AssetWriter& w) + { + /****************** jointNames *******************/ + Value vJointNames; + vJointNames.SetArray(); + vJointNames.Reserve(unsigned(b.jointNames.size()), w.mAl); + + for (size_t i = 0; i < unsigned(b.jointNames.size()); ++i) { + vJointNames.PushBack(b.jointNames[i]->index, w.mAl); + } + obj.AddMember("joints", vJointNames, w.mAl); + + if (b.bindShapeMatrix.isPresent) { + Value val; + obj.AddMember("bindShapeMatrix", MakeValue(val, b.bindShapeMatrix.value, w.mAl).Move(), w.mAl); + } + + if (b.inverseBindMatrices) { + obj.AddMember("inverseBindMatrices", b.inverseBindMatrices->index, w.mAl); + } + + } + + inline void Write(Value& obj, Texture& tex, AssetWriter& w) + { + if (tex.source) { + obj.AddMember("source", tex.source->index, w.mAl); + } + if (tex.sampler) { + obj.AddMember("sampler", tex.sampler->index, w.mAl); + } + } + + + inline AssetWriter::AssetWriter(Asset& a) + : mDoc() + , mAsset(a) + , mAl(mDoc.GetAllocator()) + { + mDoc.SetObject(); + + WriteMetadata(); + WriteExtensionsUsed(); + + // Dump the contents of the dictionaries + for (size_t i = 0; i < a.mDicts.size(); ++i) { + a.mDicts[i]->WriteObjects(*this); + } + + // Add the target scene field + if (mAsset.scene) { + mDoc.AddMember("scene", mAsset.scene->index, mAl); + } + } + + inline void AssetWriter::WriteFile(const char* path) + { + std::unique_ptr jsonOutFile(mAsset.OpenFile(path, "wt", true)); + + if (jsonOutFile == 0) { + throw DeadlyExportError("Could not open output file: " + std::string(path)); + } + + StringBuffer docBuffer; + + PrettyWriter writer(docBuffer); + mDoc.Accept(writer); + + if (jsonOutFile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) { + throw DeadlyExportError("Failed to write scene data!"); + } + + // Write buffer data to separate .bin files + for (unsigned int i = 0; i < mAsset.buffers.Size(); ++i) { + Ref b = mAsset.buffers.Get(i); + + std::string binPath = b->GetURI(); + + std::unique_ptr binOutFile(mAsset.OpenFile(binPath, "wb", true)); + + if (binOutFile == 0) { + throw DeadlyExportError("Could not open output file: " + binPath); + } + + if (b->byteLength > 0) { + if (binOutFile->Write(b->GetPointer(), b->byteLength, 1) != 1) { + throw DeadlyExportError("Failed to write binary file: " + binPath); + } + } + } + } + + inline void AssetWriter::WriteMetadata() + { + Value asset; + asset.SetObject(); + asset.AddMember("version", Value(mAsset.asset.version, mAl).Move(), mAl); + asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl); + mDoc.AddMember("asset", asset, mAl); + } + + inline void AssetWriter::WriteExtensionsUsed() + { + Value exts; + exts.SetArray(); + { + // This is used to export pbrSpecularGlossiness materials with GLTF 2. + if (this->mAsset.extensionsUsed.KHR_materials_pbrSpecularGlossiness) { + exts.PushBack(StringRef("KHR_materials_pbrSpecularGlossiness"), mAl); + } + } + + if (!exts.Empty()) + mDoc.AddMember("extensionsUsed", exts, mAl); + } + + template + void AssetWriter::WriteObjects(LazyDict& d) + { + if (d.mObjs.empty()) return; + + Value* container = &mDoc; + + if (d.mExtId) { + Value* exts = FindObject(mDoc, "extensions"); + if (!exts) { + mDoc.AddMember("extensions", Value().SetObject().Move(), mDoc.GetAllocator()); + exts = FindObject(mDoc, "extensions"); + } + + if (!(container = FindObject(*exts, d.mExtId))) { + exts->AddMember(StringRef(d.mExtId), Value().SetObject().Move(), mDoc.GetAllocator()); + container = FindObject(*exts, d.mExtId); + } + } + + Value* dict; + if (!(dict = FindArray(*container, d.mDictId))) { + container->AddMember(StringRef(d.mDictId), Value().SetArray().Move(), mDoc.GetAllocator()); + dict = FindArray(*container, d.mDictId); + } + + for (size_t i = 0; i < d.mObjs.size(); ++i) { + if (d.mObjs[i]->IsSpecial()) continue; + + Value obj; + obj.SetObject(); + + if (!d.mObjs[i]->name.empty()) { + obj.AddMember("name", StringRef(d.mObjs[i]->name.c_str()), mAl); + } + + Write(obj, *d.mObjs[i], *this); + + dict->PushBack(obj, mAl); + } + } + + template + void WriteLazyDict(LazyDict& d, AssetWriter& w) + { + w.WriteObjects(d); + } + +} + + diff --git a/code/glTF2Exporter.cpp b/code/glTF2Exporter.cpp new file mode 100644 index 000000000..c1a803c1f --- /dev/null +++ b/code/glTF2Exporter.cpp @@ -0,0 +1,1080 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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. + +---------------------------------------------------------------------- +*/ +#ifndef ASSIMP_BUILD_NO_EXPORT +#ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER + +#include "glTF2Exporter.h" + +#include "Exceptional.h" +#include "StringComparison.h" +#include "ByteSwapper.h" + +#include "SplitLargeMeshes.h" + +#include +#include +#include +#include +#include +#include + +// Header files, standard library. +#include +#include + +#include "glTF2AssetWriter.h" + +using namespace rapidjson; + +using namespace Assimp; +using namespace glTF2; + +namespace Assimp { + + // ------------------------------------------------------------------------------------------------ + // Worker function for exporting a scene to GLTF. Prototyped and registered in Exporter.cpp + void ExportSceneGLTF2(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties) + { + // invoke the exporter + glTF2Exporter exporter(pFile, pIOSystem, pScene, pProperties, false); + } + +} // end of namespace Assimp + +glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene, + const ExportProperties* pProperties, bool /*isBinary*/) + : mFilename(filename) + , mIOSystem(pIOSystem) + , mProperties(pProperties) +{ + aiScene* sceneCopy_tmp; + SceneCombiner::CopyScene(&sceneCopy_tmp, pScene); + std::unique_ptr sceneCopy(sceneCopy_tmp); + + SplitLargeMeshesProcess_Triangle tri_splitter; + tri_splitter.SetLimit(0xffff); + tri_splitter.Execute(sceneCopy.get()); + + SplitLargeMeshesProcess_Vertex vert_splitter; + vert_splitter.SetLimit(0xffff); + vert_splitter.Execute(sceneCopy.get()); + + mScene = sceneCopy.get(); + + mAsset.reset( new Asset( pIOSystem ) ); + + ExportMetadata(); + + ExportMaterials(); + + if (mScene->mRootNode) { + ExportNodeHierarchy(mScene->mRootNode); + } + + ExportMeshes(); + MergeMeshes(); + + ExportScene(); + + ExportAnimations(); + + AssetWriter writer(*mAsset); + + writer.WriteFile(filename); +} + +/* + * Copy a 4x4 matrix from struct aiMatrix to typedef mat4. + * Also converts from row-major to column-major storage. + */ +static void CopyValue(const aiMatrix4x4& v, mat4& o) +{ + o[ 0] = v.a1; o[ 1] = v.b1; o[ 2] = v.c1; o[ 3] = v.d1; + o[ 4] = v.a2; o[ 5] = v.b2; o[ 6] = v.c2; o[ 7] = v.d2; + o[ 8] = v.a3; o[ 9] = v.b3; o[10] = v.c3; o[11] = v.d3; + o[12] = v.a4; o[13] = v.b4; o[14] = v.c4; o[15] = v.d4; +} + +static void CopyValue(const aiMatrix4x4& v, aiMatrix4x4& o) +{ + o.a1 = v.a1; o.a2 = v.a2; o.a3 = v.a3; o.a4 = v.a4; + o.b1 = v.b1; o.b2 = v.b2; o.b3 = v.b3; o.b4 = v.b4; + o.c1 = v.c1; o.c2 = v.c2; o.c3 = v.c3; o.c4 = v.c4; + o.d1 = v.d1; o.d2 = v.d2; o.d3 = v.d3; o.d4 = v.d4; +} + +static void IdentityMatrix4(mat4& o) +{ + o[ 0] = 1; o[ 1] = 0; o[ 2] = 0; o[ 3] = 0; + o[ 4] = 0; o[ 5] = 1; o[ 6] = 0; o[ 7] = 0; + o[ 8] = 0; o[ 9] = 0; o[10] = 1; o[11] = 0; + o[12] = 0; o[13] = 0; o[14] = 0; o[15] = 1; +} + +inline Ref ExportData(Asset& a, std::string& meshName, Ref& buffer, + unsigned int count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false) +{ + if (!count || !data) return Ref(); + + unsigned int numCompsIn = AttribType::GetNumComponents(typeIn); + unsigned int numCompsOut = AttribType::GetNumComponents(typeOut); + unsigned int bytesPerComp = ComponentTypeSize(compType); + + size_t offset = buffer->byteLength; + // make sure offset is correctly byte-aligned, as required by spec + size_t padding = offset % bytesPerComp; + offset += padding; + size_t length = count * numCompsOut * bytesPerComp; + buffer->Grow(length + padding); + + // bufferView + Ref bv = a.bufferViews.Create(a.FindUniqueID(meshName, "view")); + bv->buffer = buffer; + bv->byteOffset = unsigned(offset); + bv->byteLength = length; //! The target that the WebGL buffer should be bound to. + bv->byteStride = 0; + bv->target = isIndices ? BufferViewTarget_ELEMENT_ARRAY_BUFFER : BufferViewTarget_ARRAY_BUFFER; + + // accessor + Ref acc = a.accessors.Create(a.FindUniqueID(meshName, "accessor")); + acc->bufferView = bv; + acc->byteOffset = 0; + acc->componentType = compType; + acc->count = count; + acc->type = typeOut; + + // calculate min and max values + { + // Allocate and initialize with large values. + float float_MAX = 10000000000000.0f; + for (unsigned int i = 0 ; i < numCompsOut ; i++) { + acc->min.push_back( float_MAX); + acc->max.push_back(-float_MAX); + } + + // Search and set extreme values. + float valueTmp; + for (unsigned int i = 0 ; i < count ; i++) { + for (unsigned int j = 0 ; j < numCompsOut ; j++) { + if (numCompsOut == 1) { + valueTmp = static_cast(data)[i]; + } else { + valueTmp = static_cast(data)[i][j]; + } + + if (valueTmp < acc->min[j]) { + acc->min[j] = valueTmp; + } + if (valueTmp > acc->max[j]) { + acc->max[j] = valueTmp; + } + } + } + } + + // copy the data + acc->WriteData(count, data, numCompsIn*bytesPerComp); + + return acc; +} + +inline void SetSamplerWrap(SamplerWrap& wrap, aiTextureMapMode map) +{ + switch (map) { + case aiTextureMapMode_Clamp: + wrap = SamplerWrap::Clamp_To_Edge; + break; + case aiTextureMapMode_Mirror: + wrap = SamplerWrap::Mirrored_Repeat; + break; + case aiTextureMapMode_Wrap: + case aiTextureMapMode_Decal: + default: + wrap = SamplerWrap::Repeat; + break; + }; +} + +void glTF2Exporter::GetTexSampler(const aiMaterial* mat, Ref texture, aiTextureType tt, unsigned int slot) +{ + aiString aId; + std::string id; + if (aiGetMaterialString(mat, AI_MATKEY_GLTF_MAPPINGID(tt, slot), &aId) == AI_SUCCESS) { + id = aId.C_Str(); + } + + if (Ref ref = mAsset->samplers.Get(id.c_str())) { + texture->sampler = ref; + } else { + id = mAsset->FindUniqueID(id, "sampler"); + + texture->sampler = mAsset->samplers.Create(id.c_str()); + + aiTextureMapMode mapU, mapV; + SamplerMagFilter filterMag; + SamplerMinFilter filterMin; + + if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_U(tt, slot), (int*)&mapU) == AI_SUCCESS) { + SetSamplerWrap(texture->sampler->wrapS, mapU); + } + + if (aiGetMaterialInteger(mat, AI_MATKEY_MAPPINGMODE_V(tt, slot), (int*)&mapV) == AI_SUCCESS) { + SetSamplerWrap(texture->sampler->wrapT, mapV); + } + + if (aiGetMaterialInteger(mat, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(tt, slot), (int*)&filterMag) == AI_SUCCESS) { + texture->sampler->magFilter = filterMag; + } + + if (aiGetMaterialInteger(mat, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(tt, slot), (int*)&filterMin) == AI_SUCCESS) { + texture->sampler->minFilter = filterMin; + } + + aiString name; + if (aiGetMaterialString(mat, AI_MATKEY_GLTF_MAPPINGNAME(tt, slot), &name) == AI_SUCCESS) { + texture->sampler->name = name.C_Str(); + } + } +} + +void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int slot) +{ + std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName; + + mat->Get(textureKey.c_str(), tt, slot, prop); +} + +void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int slot) +{ + std::string textureKey = std::string(_AI_MATKEY_TEXTURE_BASE) + "." + propName; + + mat->Get(textureKey.c_str(), tt, slot, prop); +} + +void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTextureType tt, unsigned int slot = 0) +{ + + if (mat->GetTextureCount(tt) > 0) { + aiString tex; + + if (mat->Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) { + std::string path = tex.C_Str(); + + if (path.size() > 0) { + if (path[0] != '*') { + std::map::iterator it = mTexturesByPath.find(path); + if (it != mTexturesByPath.end()) { + texture = mAsset->textures.Get(it->second); + } + } + + if (!texture) { + std::string texId = mAsset->FindUniqueID("", "texture"); + texture = mAsset->textures.Create(texId); + mTexturesByPath[path] = texture.GetIndex(); + + std::string imgId = mAsset->FindUniqueID("", "image"); + texture->source = mAsset->images.Create(imgId); + + if (path[0] == '*') { // embedded + aiTexture* tex = mScene->mTextures[atoi(&path[1])]; + + uint8_t* data = reinterpret_cast(tex->pcData); + texture->source->SetData(data, tex->mWidth, *mAsset); + + if (tex->achFormatHint[0]) { + std::string mimeType = "image/"; + mimeType += (memcmp(tex->achFormatHint, "jpg", 3) == 0) ? "jpeg" : tex->achFormatHint; + texture->source->mimeType = mimeType; + } + } + else { + texture->source->uri = path; + } + + GetTexSampler(mat, texture, tt, slot); + } + } + } + } +} + +void glTF2Exporter::GetMatTex(const aiMaterial* mat, TextureInfo& prop, aiTextureType tt, unsigned int slot = 0) +{ + Ref& texture = prop.texture; + + GetMatTex(mat, texture, tt, slot); + + if (texture) { + GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); + } +} + +void glTF2Exporter::GetMatTex(const aiMaterial* mat, NormalTextureInfo& prop, aiTextureType tt, unsigned int slot = 0) +{ + Ref& texture = prop.texture; + + GetMatTex(mat, texture, tt, slot); + + if (texture) { + GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); + GetMatTexProp(mat, prop.scale, "scale", tt, slot); + } +} + +void glTF2Exporter::GetMatTex(const aiMaterial* mat, OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot = 0) +{ + Ref& texture = prop.texture; + + GetMatTex(mat, texture, tt, slot); + + if (texture) { + GetMatTexProp(mat, prop.texCoord, "texCoord", tt, slot); + GetMatTexProp(mat, prop.strength, "strength", tt, slot); + } +} + +aiReturn glTF2Exporter::GetMatColor(const aiMaterial* mat, vec4& prop, const char* propName, int type, int idx) +{ + aiColor4D col; + aiReturn result = mat->Get(propName, type, idx, col); + + if (result == AI_SUCCESS) { + prop[0] = col.r; prop[1] = col.g; prop[2] = col.b; prop[3] = col.a; + } + + return result; +} + +aiReturn glTF2Exporter::GetMatColor(const aiMaterial* mat, vec3& prop, const char* propName, int type, int idx) +{ + aiColor3D col; + aiReturn result = mat->Get(propName, type, idx, col); + + if (result == AI_SUCCESS) { + prop[0] = col.r; prop[1] = col.g; prop[2] = col.b; + } + + return result; +} + +void glTF2Exporter::ExportMaterials() +{ + aiString aiName; + for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { + const aiMaterial* mat = mScene->mMaterials[i]; + + std::string id = "material_" + to_string(i); + + Ref m = mAsset->materials.Create(id); + + std::string name; + if (mat->Get(AI_MATKEY_NAME, aiName) == AI_SUCCESS) { + name = aiName.C_Str(); + } + name = mAsset->FindUniqueID(name, "material"); + + m->name = name; + + GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE); + + if (!m->pbrMetallicRoughness.baseColorTexture.texture) { + //if there wasn't a baseColorTexture defined in the source, fallback to any diffuse texture + GetMatTex(mat, m->pbrMetallicRoughness.baseColorTexture, aiTextureType_DIFFUSE); + } + + GetMatTex(mat, m->pbrMetallicRoughness.metallicRoughnessTexture, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE); + + if (GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR) != AI_SUCCESS) { + // if baseColorFactor wasn't defined, then the source is likely not a metallic roughness material. + //a fallback to any diffuse color should be used instead + GetMatColor(mat, m->pbrMetallicRoughness.baseColorFactor, AI_MATKEY_COLOR_DIFFUSE); + } + + if (mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR, m->pbrMetallicRoughness.metallicFactor) != AI_SUCCESS) { + //if metallicFactor wasn't defined, then the source is likely not a PBR file, and the metallicFactor should be 0 + m->pbrMetallicRoughness.metallicFactor = 0; + } + + // get roughness if source is gltf2 file + if (mat->Get(AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR, m->pbrMetallicRoughness.roughnessFactor) != AI_SUCCESS) { + // otherwise, try to derive and convert from specular + shininess values + aiColor4D specularColor; + ai_real shininess; + + if ( + mat->Get(AI_MATKEY_COLOR_SPECULAR, specularColor) == AI_SUCCESS && + mat->Get(AI_MATKEY_SHININESS, shininess) == AI_SUCCESS + ) { + // convert specular color to luminance + float specularIntensity = specularColor[0] * 0.2125f + specularColor[1] * 0.7154f + specularColor[2] * 0.0721f; + //normalize shininess (assuming max is 1000) with an inverse exponentional curve + float normalizedShininess = std::sqrt(shininess / 1000); + + //clamp the shininess value between 0 and 1 + normalizedShininess = std::min(std::max(normalizedShininess, 0.0f), 1.0f); + // low specular intensity values should produce a rough material even if shininess is high. + normalizedShininess = normalizedShininess * specularIntensity; + + m->pbrMetallicRoughness.roughnessFactor = 1 - normalizedShininess; + } + } + + GetMatTex(mat, m->normalTexture, aiTextureType_NORMALS); + GetMatTex(mat, m->occlusionTexture, aiTextureType_LIGHTMAP); + GetMatTex(mat, m->emissiveTexture, aiTextureType_EMISSIVE); + GetMatColor(mat, m->emissiveFactor, AI_MATKEY_COLOR_EMISSIVE); + + mat->Get(AI_MATKEY_TWOSIDED, m->doubleSided); + mat->Get(AI_MATKEY_GLTF_ALPHACUTOFF, m->alphaCutoff); + + aiString alphaMode; + + if (mat->Get(AI_MATKEY_GLTF_ALPHAMODE, alphaMode) == AI_SUCCESS) { + m->alphaMode = alphaMode.C_Str(); + } else { + float opacity; + + if (mat->Get(AI_MATKEY_OPACITY, opacity) == AI_SUCCESS) { + if (opacity < 1) { + m->alphaMode = "BLEND"; + m->pbrMetallicRoughness.baseColorFactor[3] *= opacity; + } + } + } + + bool hasPbrSpecularGlossiness = false; + mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS, hasPbrSpecularGlossiness); + + if (hasPbrSpecularGlossiness) { + + if (!mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness) { + mAsset->extensionsUsed.KHR_materials_pbrSpecularGlossiness = true; + } + + PbrSpecularGlossiness pbrSG; + + GetMatColor(mat, pbrSG.diffuseFactor, AI_MATKEY_COLOR_DIFFUSE); + GetMatColor(mat, pbrSG.specularFactor, AI_MATKEY_COLOR_SPECULAR); + + if (mat->Get(AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR, pbrSG.glossinessFactor) != AI_SUCCESS) { + float shininess; + + if (mat->Get(AI_MATKEY_SHININESS, shininess)) { + pbrSG.glossinessFactor = shininess / 1000; + } + } + + GetMatTex(mat, pbrSG.diffuseTexture, aiTextureType_DIFFUSE); + GetMatTex(mat, pbrSG.specularGlossinessTexture, aiTextureType_SPECULAR); + + m->pbrSpecularGlossiness = Nullable(pbrSG); + } + } +} + +/* + * Search through node hierarchy and find the node containing the given meshID. + * Returns true on success, and false otherwise. + */ +bool FindMeshNode(Ref& nodeIn, Ref& meshNode, std::string meshID) +{ + for (unsigned int i = 0; i < nodeIn->meshes.size(); ++i) { + if (meshID.compare(nodeIn->meshes[i]->id) == 0) { + meshNode = nodeIn; + return true; + } + } + + for (unsigned int i = 0; i < nodeIn->children.size(); ++i) { + if(FindMeshNode(nodeIn->children[i], meshNode, meshID)) { + return true; + } + } + + return false; +} + +/* + * Find the root joint of the skeleton. + * Starts will any joint node and traces up the tree, + * until a parent is found that does not have a jointName. + * Returns the first parent Ref found that does not have a jointName. + */ +Ref FindSkeletonRootJoint(Ref& skinRef) +{ + Ref startNodeRef; + Ref parentNodeRef; + + // Arbitrarily use the first joint to start the search. + startNodeRef = skinRef->jointNames[0]; + parentNodeRef = skinRef->jointNames[0]; + + do { + startNodeRef = parentNodeRef; + parentNodeRef = startNodeRef->parent; + } while (!parentNodeRef->jointName.empty()); + + return parentNodeRef; +} + +void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref& meshRef, Ref& bufferRef, Ref& skinRef, std::vector& inverseBindMatricesData) +{ + if (aimesh->mNumBones < 1) { + return; + } + + // Store the vertex joint and weight data. + const size_t NumVerts( aimesh->mNumVertices ); + vec4* vertexJointData = new vec4[ NumVerts ]; + vec4* vertexWeightData = new vec4[ NumVerts ]; + int* jointsPerVertex = new int[ NumVerts ]; + for (size_t i = 0; i < NumVerts; ++i) { + jointsPerVertex[i] = 0; + for (size_t j = 0; j < 4; ++j) { + vertexJointData[i][j] = 0; + vertexWeightData[i][j] = 0; + } + } + + for (unsigned int idx_bone = 0; idx_bone < aimesh->mNumBones; ++idx_bone) { + const aiBone* aib = aimesh->mBones[idx_bone]; + + // aib->mName =====> skinRef->jointNames + // Find the node with id = mName. + Ref nodeRef = mAsset.nodes.Get(aib->mName.C_Str()); + nodeRef->jointName = nodeRef->name; + + unsigned int jointNamesIndex = 0; + bool addJointToJointNames = true; + for ( unsigned int idx_joint = 0; idx_joint < skinRef->jointNames.size(); ++idx_joint) { + if (skinRef->jointNames[idx_joint]->jointName.compare(nodeRef->jointName) == 0) { + addJointToJointNames = false; + jointNamesIndex = idx_joint; + } + } + + if (addJointToJointNames) { + skinRef->jointNames.push_back(nodeRef); + + // aib->mOffsetMatrix =====> skinRef->inverseBindMatrices + aiMatrix4x4 tmpMatrix4; + CopyValue(aib->mOffsetMatrix, tmpMatrix4); + inverseBindMatricesData.push_back(tmpMatrix4); + jointNamesIndex = static_cast(inverseBindMatricesData.size() - 1); + } + + // aib->mWeights =====> vertexWeightData + for (unsigned int idx_weights = 0; idx_weights < aib->mNumWeights; ++idx_weights) { + unsigned int vertexId = aib->mWeights[idx_weights].mVertexId; + float vertWeight = aib->mWeights[idx_weights].mWeight; + + // A vertex can only have at most four joint weights. Ignore all others. + if (jointsPerVertex[vertexId] > 3) { + continue; + } + + vertexJointData[vertexId][jointsPerVertex[vertexId]] = static_cast(jointNamesIndex); + vertexWeightData[vertexId][jointsPerVertex[vertexId]] = vertWeight; + + jointsPerVertex[vertexId] += 1; + } + + } // End: for-loop mNumMeshes + + Mesh::Primitive& p = meshRef->primitives.back(); + Ref vertexJointAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, vertexJointData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); + if ( vertexJointAccessor ) { + p.attributes.joint.push_back( vertexJointAccessor ); + } + + Ref vertexWeightAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, vertexWeightData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); + if ( vertexWeightAccessor ) { + p.attributes.weight.push_back( vertexWeightAccessor ); + } + delete[] jointsPerVertex; + delete[] vertexWeightData; + delete[] vertexJointData; +} + +void glTF2Exporter::ExportMeshes() +{ + // Not for + // using IndicesType = decltype(aiFace::mNumIndices); + // But yes for + // using IndicesType = unsigned short; + // because "ComponentType_UNSIGNED_SHORT" used for indices. And it's a maximal type according to glTF specification. + typedef unsigned short IndicesType; + + std::string fname = std::string(mFilename); + std::string bufferIdPrefix = fname.substr(0, fname.rfind(".gltf")); + std::string bufferId = mAsset->FindUniqueID("", bufferIdPrefix.c_str()); + + Ref b = mAsset->GetBodyBuffer(); + if (!b) { + b = mAsset->buffers.Create(bufferId); + } + + //---------------------------------------- + // Initialize variables for the skin + bool createSkin = false; + for (unsigned int idx_mesh = 0; idx_mesh < mScene->mNumMeshes; ++idx_mesh) { + const aiMesh* aim = mScene->mMeshes[idx_mesh]; + if(aim->HasBones()) { + createSkin = true; + break; + } + } + + Ref skinRef; + std::string skinName = mAsset->FindUniqueID("skin", "skin"); + std::vector inverseBindMatricesData; + if(createSkin) { + skinRef = mAsset->skins.Create(skinName); + skinRef->name = skinName; + } + //---------------------------------------- + + for (unsigned int idx_mesh = 0; idx_mesh < mScene->mNumMeshes; ++idx_mesh) { + const aiMesh* aim = mScene->mMeshes[idx_mesh]; + + std::string name = aim->mName.C_Str(); + + std::string meshId = mAsset->FindUniqueID(name, "mesh"); + Ref m = mAsset->meshes.Create(meshId); + m->primitives.resize(1); + Mesh::Primitive& p = m->primitives.back(); + + m->name = name; + + p.material = mAsset->materials.Get(aim->mMaterialIndex); + + /******************* Vertices ********************/ + Ref v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + if (v) p.attributes.position.push_back(v); + + /******************** Normals ********************/ + Ref n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + if (n) p.attributes.normal.push_back(n); + + /************** Texture coordinates **************/ + for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { + // Flip UV y coords + if (aim -> mNumUVComponents[i] > 1) { + for (unsigned int j = 0; j < aim->mNumVertices; ++j) { + aim->mTextureCoords[i][j].y = 1 - aim->mTextureCoords[i][j].y; + } + } + + if (aim->mNumUVComponents[i] > 0) { + AttribType::Value type = (aim->mNumUVComponents[i] == 2) ? AttribType::VEC2 : AttribType::VEC3; + + Ref tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, false); + if (tc) p.attributes.texcoord.push_back(tc); + } + } + + /*************** Vertices indices ****************/ + if (aim->mNumFaces > 0) { + std::vector indices; + unsigned int nIndicesPerFace = aim->mFaces[0].mNumIndices; + indices.resize(aim->mNumFaces * nIndicesPerFace); + for (size_t i = 0; i < aim->mNumFaces; ++i) { + for (size_t j = 0; j < nIndicesPerFace; ++j) { + indices[i*nIndicesPerFace + j] = uint16_t(aim->mFaces[i].mIndices[j]); + } + } + + p.indices = ExportData(*mAsset, meshId, b, unsigned(indices.size()), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_SHORT, true); + } + + switch (aim->mPrimitiveTypes) { + case aiPrimitiveType_POLYGON: + p.mode = PrimitiveMode_TRIANGLES; break; // TODO implement this + case aiPrimitiveType_LINE: + p.mode = PrimitiveMode_LINES; break; + case aiPrimitiveType_POINT: + p.mode = PrimitiveMode_POINTS; break; + default: // aiPrimitiveType_TRIANGLE + p.mode = PrimitiveMode_TRIANGLES; + } + + /*************** Skins ****************/ + if(aim->HasBones()) { + ExportSkin(*mAsset, aim, m, b, skinRef, inverseBindMatricesData); + } + } + + //---------------------------------------- + // Finish the skin + // Create the Accessor for skinRef->inverseBindMatrices + if (createSkin) { + mat4* invBindMatrixData = new mat4[inverseBindMatricesData.size()]; + for ( unsigned int idx_joint = 0; idx_joint < inverseBindMatricesData.size(); ++idx_joint) { + CopyValue(inverseBindMatricesData[idx_joint], invBindMatrixData[idx_joint]); + } + + Ref invBindMatrixAccessor = ExportData(*mAsset, skinName, b, static_cast(inverseBindMatricesData.size()), invBindMatrixData, AttribType::MAT4, AttribType::MAT4, ComponentType_FLOAT); + if (invBindMatrixAccessor) skinRef->inverseBindMatrices = invBindMatrixAccessor; + + // Identity Matrix =====> skinRef->bindShapeMatrix + // Temporary. Hard-coded identity matrix here + skinRef->bindShapeMatrix.isPresent = true; + IdentityMatrix4(skinRef->bindShapeMatrix.value); + + // Find nodes that contain a mesh with bones and add "skeletons" and "skin" attributes to those nodes. + Ref rootNode = mAsset->nodes.Get(unsigned(0)); + Ref meshNode; + for (unsigned int meshIndex = 0; meshIndex < mAsset->meshes.Size(); ++meshIndex) { + Ref mesh = mAsset->meshes.Get(meshIndex); + bool hasBones = false; + for (unsigned int i = 0; i < mesh->primitives.size(); ++i) { + if (!mesh->primitives[i].attributes.weight.empty()) { + hasBones = true; + break; + } + } + if (!hasBones) { + continue; + } + std::string meshID = mesh->id; + FindMeshNode(rootNode, meshNode, meshID); + Ref rootJoint = FindSkeletonRootJoint(skinRef); + meshNode->skeletons.push_back(rootJoint); + meshNode->skin = skinRef; + } + } +} + +//merges a node's multiple meshes (with one primitive each) into one mesh with multiple primitives +void glTF2Exporter::MergeMeshes() +{ + for (unsigned int n = 0; n < mAsset->nodes.Size(); ++n) { + Ref node = mAsset->nodes.Get(n); + + unsigned int nMeshes = static_cast(node->meshes.size()); + + //skip if it's 1 or less meshes per node + if (nMeshes > 1) { + Ref firstMesh = node->meshes.at(0); + + //loop backwards to allow easy removal of a mesh from a node once it's merged + for (unsigned int m = nMeshes - 1; m >= 1; --m) { + Ref mesh = node->meshes.at(m); + + //append this mesh's primitives to the first mesh's primitives + firstMesh->primitives.insert( + firstMesh->primitives.end(), + mesh->primitives.begin(), + mesh->primitives.end() + ); + + //remove the mesh from the list of meshes + unsigned int removedIndex = mAsset->meshes.Remove(mesh->id.c_str()); + + //find the presence of the removed mesh in other nodes + for (unsigned int nn = 0; nn < mAsset->nodes.Size(); ++nn) { + Ref node = mAsset->nodes.Get(nn); + + for (unsigned int mm = 0; mm < node->meshes.size(); ++mm) { + Ref& meshRef = node->meshes.at(mm); + unsigned int meshIndex = meshRef.GetIndex(); + + if (meshIndex == removedIndex) { + node->meshes.erase(node->meshes.begin() + mm); + } else if (meshIndex > removedIndex) { + Ref newMeshRef = mAsset->meshes.Get(meshIndex - 1); + + meshRef = newMeshRef; + } + } + } + } + + //since we were looping backwards, reverse the order of merged primitives to their original order + std::reverse(firstMesh->primitives.begin() + 1, firstMesh->primitives.end()); + } + } +} + +/* + * Export the root node of the node hierarchy. + * Calls ExportNode for all children. + */ +unsigned int glTF2Exporter::ExportNodeHierarchy(const aiNode* n) +{ + Ref node = mAsset->nodes.Create(mAsset->FindUniqueID(n->mName.C_Str(), "node")); + + if (!n->mTransformation.IsIdentity()) { + node->matrix.isPresent = true; + CopyValue(n->mTransformation, node->matrix.value); + } + + for (unsigned int i = 0; i < n->mNumMeshes; ++i) { + node->meshes.push_back(mAsset->meshes.Get(n->mMeshes[i])); + } + + for (unsigned int i = 0; i < n->mNumChildren; ++i) { + unsigned int idx = ExportNode(n->mChildren[i], node); + node->children.push_back(mAsset->nodes.Get(idx)); + } + + return node.GetIndex(); +} + +/* + * Export node and recursively calls ExportNode for all children. + * Since these nodes are not the root node, we also export the parent Ref + */ +unsigned int glTF2Exporter::ExportNode(const aiNode* n, Ref& parent) +{ + std::string name = mAsset->FindUniqueID(n->mName.C_Str(), "node"); + Ref node = mAsset->nodes.Create(name); + + node->parent = parent; + node->name = name; + + if (!n->mTransformation.IsIdentity()) { + node->matrix.isPresent = true; + CopyValue(n->mTransformation, node->matrix.value); + } + + for (unsigned int i = 0; i < n->mNumMeshes; ++i) { + node->meshes.push_back(mAsset->meshes.Get(n->mMeshes[i])); + } + + for (unsigned int i = 0; i < n->mNumChildren; ++i) { + unsigned int idx = ExportNode(n->mChildren[i], node); + node->children.push_back(mAsset->nodes.Get(idx)); + } + + return node.GetIndex(); +} + + +void glTF2Exporter::ExportScene() +{ + const char* sceneName = "defaultScene"; + Ref scene = mAsset->scenes.Create(sceneName); + + // root node will be the first one exported (idx 0) + if (mAsset->nodes.Size() > 0) { + scene->nodes.push_back(mAsset->nodes.Get(0u)); + } + + // set as the default scene + mAsset->scene = scene; +} + +void glTF2Exporter::ExportMetadata() +{ + AssetMetadata& asset = mAsset->asset; + asset.version = "2.0"; + + char buffer[256]; + ai_snprintf(buffer, 256, "Open Asset Import Library (assimp v%d.%d.%d)", + aiGetVersionMajor(), aiGetVersionMinor(), aiGetVersionRevision()); + + asset.generator = buffer; +} + +inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref& animRef, Ref& buffer, const aiNodeAnim* nodeChannel, float ticksPerSecond) +{ + // Loop over the data and check to see if it exactly matches an existing buffer. + // If yes, then reference the existing corresponding accessor. + // Otherwise, add to the buffer and create a new accessor. + + size_t counts[3] = { + nodeChannel->mNumPositionKeys, + nodeChannel->mNumScalingKeys, + nodeChannel->mNumRotationKeys, + }; + size_t numKeyframes = 1; + for (int i = 0; i < 3; ++i) { + if (counts[i] > numKeyframes) { + numKeyframes = counts[i]; + } + } + + //------------------------------------------------------- + // Extract TIME parameter data. + // Check if the timeStamps are the same for mPositionKeys, mRotationKeys, and mScalingKeys. + if(nodeChannel->mNumPositionKeys > 0) { + typedef float TimeType; + std::vector timeData; + timeData.resize(numKeyframes); + for (size_t i = 0; i < numKeyframes; ++i) { + size_t frameIndex = i * nodeChannel->mNumPositionKeys / numKeyframes; + // mTime is measured in ticks, but GLTF time is measured in seconds, so convert. + // Check if we have to cast type here. e.g. uint16_t() + timeData[i] = static_cast(nodeChannel->mPositionKeys[frameIndex].mTime / ticksPerSecond); + } + + Ref timeAccessor = ExportData(mAsset, animId, buffer, static_cast(numKeyframes), &timeData[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_FLOAT); + if (timeAccessor) animRef->Parameters.TIME = timeAccessor; + } + + //------------------------------------------------------- + // Extract translation parameter data + if(nodeChannel->mNumPositionKeys > 0) { + C_STRUCT aiVector3D* translationData = new aiVector3D[numKeyframes]; + for (size_t i = 0; i < numKeyframes; ++i) { + size_t frameIndex = i * nodeChannel->mNumPositionKeys / numKeyframes; + translationData[i] = nodeChannel->mPositionKeys[frameIndex].mValue; + } + + Ref tranAccessor = ExportData(mAsset, animId, buffer, static_cast(numKeyframes), translationData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + if ( tranAccessor ) { + animRef->Parameters.translation = tranAccessor; + } + delete[] translationData; + } + + //------------------------------------------------------- + // Extract scale parameter data + if(nodeChannel->mNumScalingKeys > 0) { + C_STRUCT aiVector3D* scaleData = new aiVector3D[numKeyframes]; + for (size_t i = 0; i < numKeyframes; ++i) { + size_t frameIndex = i * nodeChannel->mNumScalingKeys / numKeyframes; + scaleData[i] = nodeChannel->mScalingKeys[frameIndex].mValue; + } + + Ref scaleAccessor = ExportData(mAsset, animId, buffer, static_cast(numKeyframes), scaleData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + if ( scaleAccessor ) { + animRef->Parameters.scale = scaleAccessor; + } + delete[] scaleData; + } + + //------------------------------------------------------- + // Extract rotation parameter data + if(nodeChannel->mNumRotationKeys > 0) { + vec4* rotationData = new vec4[numKeyframes]; + for (size_t i = 0; i < numKeyframes; ++i) { + size_t frameIndex = i * nodeChannel->mNumRotationKeys / numKeyframes; + rotationData[i][0] = nodeChannel->mRotationKeys[frameIndex].mValue.x; + rotationData[i][1] = nodeChannel->mRotationKeys[frameIndex].mValue.y; + rotationData[i][2] = nodeChannel->mRotationKeys[frameIndex].mValue.z; + rotationData[i][3] = nodeChannel->mRotationKeys[frameIndex].mValue.w; + } + + Ref rotAccessor = ExportData(mAsset, animId, buffer, static_cast(numKeyframes), rotationData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); + if ( rotAccessor ) { + animRef->Parameters.rotation = rotAccessor; + } + delete[] rotationData; + } +} + +void glTF2Exporter::ExportAnimations() +{ + Ref bufferRef = mAsset->buffers.Get(unsigned (0)); + + for (unsigned int i = 0; i < mScene->mNumAnimations; ++i) { + const aiAnimation* anim = mScene->mAnimations[i]; + + std::string nameAnim = "anim"; + if (anim->mName.length > 0) { + nameAnim = anim->mName.C_Str(); + } + + for (unsigned int channelIndex = 0; channelIndex < anim->mNumChannels; ++channelIndex) { + const aiNodeAnim* nodeChannel = anim->mChannels[channelIndex]; + + // It appears that assimp stores this type of animation as multiple animations. + // where each aiNodeAnim in mChannels animates a specific node. + std::string name = nameAnim + "_" + to_string(channelIndex); + name = mAsset->FindUniqueID(name, "animation"); + Ref animRef = mAsset->animations.Create(name); + + // Parameters + ExtractAnimationData(*mAsset, name, animRef, bufferRef, nodeChannel, static_cast(anim->mTicksPerSecond)); + + for (unsigned int j = 0; j < 3; ++j) { + std::string channelType; + int channelSize; + switch (j) { + case 0: + channelType = "rotation"; + channelSize = nodeChannel->mNumRotationKeys; + break; + case 1: + channelType = "scale"; + channelSize = nodeChannel->mNumScalingKeys; + break; + case 2: + channelType = "translation"; + channelSize = nodeChannel->mNumPositionKeys; + break; + } + + if (channelSize < 1) { continue; } + + Animation::AnimChannel tmpAnimChannel; + Animation::AnimSampler tmpAnimSampler; + + tmpAnimChannel.sampler = static_cast(animRef->Samplers.size()); + tmpAnimChannel.target.path = channelType; + tmpAnimSampler.output = channelType; + tmpAnimSampler.id = name + "_" + channelType; + + tmpAnimChannel.target.node = mAsset->nodes.Get(nodeChannel->mNodeName.C_Str()); + + tmpAnimSampler.input = "TIME"; + tmpAnimSampler.interpolation = "LINEAR"; + + animRef->Channels.push_back(tmpAnimChannel); + animRef->Samplers.push_back(tmpAnimSampler); + } + + } + + // Assimp documentation staes this is not used (not implemented) + // for (unsigned int channelIndex = 0; channelIndex < anim->mNumMeshChannels; ++channelIndex) { + // const aiMeshAnim* meshChannel = anim->mMeshChannels[channelIndex]; + // } + + } // End: for-loop mNumAnimations +} + + +#endif // ASSIMP_BUILD_NO_GLTF_EXPORTER +#endif // ASSIMP_BUILD_NO_EXPORT diff --git a/code/glTF2Exporter.h b/code/glTF2Exporter.h new file mode 100644 index 000000000..e9f7c113a --- /dev/null +++ b/code/glTF2Exporter.h @@ -0,0 +1,134 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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 GltfExporter.h +* Declares the exporter class to write a scene to a gltf/glb file +*/ +#ifndef AI_GLTF2EXPORTER_H_INC +#define AI_GLTF2EXPORTER_H_INC + +#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER + +#include +#include + +#include +#include +#include +#include + +struct aiScene; +struct aiNode; +struct aiMaterial; + +namespace glTF2 +{ + template + class Ref; + + class Asset; + struct TexProperty; + struct TextureInfo; + struct NormalTextureInfo; + struct OcclusionTextureInfo; + struct Node; + struct Texture; + + // Vec/matrix types, as raw float arrays + typedef float (vec3)[3]; + typedef float (vec4)[4]; +} + +namespace Assimp +{ + class IOSystem; + class IOStream; + class ExportProperties; + + // ------------------------------------------------------------------------------------------------ + /** Helper class to export a given scene to an glTF file. */ + // ------------------------------------------------------------------------------------------------ + class glTF2Exporter + { + public: + /// Constructor for a specific scene to export + glTF2Exporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene, + const ExportProperties* pProperties, bool binary); + + private: + + const char* mFilename; + IOSystem* mIOSystem; + const aiScene* mScene; + const ExportProperties* mProperties; + + std::map mTexturesByPath; + + std::shared_ptr mAsset; + + std::vector mBodyData; + + void WriteBinaryData(IOStream* outfile, std::size_t sceneLength); + + void GetTexSampler(const aiMaterial* mat, glTF2::Ref texture, aiTextureType tt, unsigned int slot); + void GetMatTexProp(const aiMaterial* mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int idx); + void GetMatTexProp(const aiMaterial* mat, float& prop, const char* propName, aiTextureType tt, unsigned int idx); + void GetMatTex(const aiMaterial* mat, glTF2::Ref& texture, aiTextureType tt, unsigned int slot); + void GetMatTex(const aiMaterial* mat, glTF2::TextureInfo& prop, aiTextureType tt, unsigned int slot); + void GetMatTex(const aiMaterial* mat, glTF2::NormalTextureInfo& prop, aiTextureType tt, unsigned int slot); + void GetMatTex(const aiMaterial* mat, glTF2::OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot); + aiReturn GetMatColor(const aiMaterial* mat, glTF2::vec4& prop, const char* propName, int type, int idx); + aiReturn GetMatColor(const aiMaterial* mat, glTF2::vec3& prop, const char* propName, int type, int idx); + void ExportMetadata(); + void ExportMaterials(); + void ExportMeshes(); + void MergeMeshes(); + unsigned int ExportNodeHierarchy(const aiNode* n); + unsigned int ExportNode(const aiNode* node, glTF2::Ref& parent); + void ExportScene(); + void ExportAnimations(); + }; + +} + +#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER + +#endif // AI_GLTF2EXPORTER_H_INC diff --git a/code/glTF2Importer.cpp b/code/glTF2Importer.cpp new file mode 100644 index 000000000..94e5ca3f1 --- /dev/null +++ b/code/glTF2Importer.cpp @@ -0,0 +1,694 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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. + +---------------------------------------------------------------------- +*/ + +#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER + +#include "glTF2Importer.h" +#include "StringComparison.h" +#include "StringUtils.h" + +#include +#include +#include +#include +#include + +#include + +#include "MakeVerboseFormat.h" + +#include "glTF2Asset.h" +// This is included here so WriteLazyDict's definition is found. +#include "glTF2AssetWriter.h" +#include +#include + +using namespace Assimp; +using namespace glTF2; + + +// +// glTF2Importer +// + +static const aiImporterDesc desc = { + "glTF2 Importer", + "", + "", + "", + aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental, + 0, + 0, + 0, + 0, + "gltf glb" +}; + +glTF2Importer::glTF2Importer() +: BaseImporter() +, meshOffsets() +, embeddedTexIdxs() +, mScene( NULL ) { + // empty +} + +glTF2Importer::~glTF2Importer() { + // empty +} + +const aiImporterDesc* glTF2Importer::GetInfo() const +{ + return &desc; +} + +bool glTF2Importer::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const +{ + const std::string &extension = GetExtension(pFile); + + if (extension != "gltf" && extension != "glb") + return false; + + if (checkSig && pIOHandler) { + glTF2::Asset asset(pIOHandler); + try { + asset.Load(pFile, extension == "glb"); + std::string version = asset.asset.version; + return !version.empty() && version[0] == '2'; + } catch (...) { + return false; + } + } + + return false; +} + + +//static void CopyValue(const glTF2::vec3& v, aiColor3D& out) +//{ +// out.r = v[0]; out.g = v[1]; out.b = v[2]; +//} + +static void CopyValue(const glTF2::vec4& v, aiColor4D& out) +{ + out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = v[3]; +} + +/*static void CopyValue(const glTF2::vec4& v, aiColor3D& out) +{ + out.r = v[0]; out.g = v[1]; out.b = v[2]; +}*/ + +static void CopyValue(const glTF2::vec3& v, aiColor4D& out) +{ + out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = 1.0; +} + +static void CopyValue(const glTF2::vec3& v, aiVector3D& out) +{ + out.x = v[0]; out.y = v[1]; out.z = v[2]; +} + +static void CopyValue(const glTF2::vec4& v, aiQuaternion& out) +{ + out.x = v[0]; out.y = v[1]; out.z = v[2]; out.w = v[3]; +} + +static void CopyValue(const glTF2::mat4& v, aiMatrix4x4& o) +{ + o.a1 = v[ 0]; o.b1 = v[ 1]; o.c1 = v[ 2]; o.d1 = v[ 3]; + o.a2 = v[ 4]; o.b2 = v[ 5]; o.c2 = v[ 6]; o.d2 = v[ 7]; + o.a3 = v[ 8]; o.b3 = v[ 9]; o.c3 = v[10]; o.d3 = v[11]; + o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15]; +} + +inline void SetMaterialColorProperty(Asset& /*r*/, vec4& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx) +{ + aiColor4D col; + CopyValue(prop, col); + mat->AddProperty(&col, 1, pKey, type, idx); +} + +inline void SetMaterialColorProperty(Asset& /*r*/, vec3& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx) +{ + aiColor4D col; + CopyValue(prop, col); + mat->AddProperty(&col, 1, pKey, type, idx); +} + +inline void SetMaterialTextureProperty(std::vector& embeddedTexIdxs, Asset& /*r*/, glTF2::TextureInfo prop, aiMaterial* mat, aiTextureType texType, unsigned int texSlot = 0) +{ + if (prop.texture && prop.texture->source) { + aiString uri(prop.texture->source->uri); + + int texIdx = embeddedTexIdxs[prop.texture->source.GetIndex()]; + if (texIdx != -1) { // embedded + // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture) + uri.data[0] = '*'; + uri.length = 1 + ASSIMP_itoa10(uri.data + 1, MAXLEN - 1, texIdx); + } + + mat->AddProperty(&uri, AI_MATKEY_TEXTURE(texType, texSlot)); + mat->AddProperty(&prop.texCoord, 1, _AI_MATKEY_GLTF_TEXTURE_TEXCOORD_BASE, texType, texSlot); + + if (prop.texture->sampler) { + Ref sampler = prop.texture->sampler; + + aiString name(sampler->name); + aiString id(sampler->id); + + mat->AddProperty(&name, AI_MATKEY_GLTF_MAPPINGNAME(texType, texSlot)); + mat->AddProperty(&id, AI_MATKEY_GLTF_MAPPINGID(texType, texSlot)); + + mat->AddProperty(&sampler->wrapS, 1, AI_MATKEY_MAPPINGMODE_U(texType, texSlot)); + mat->AddProperty(&sampler->wrapT, 1, AI_MATKEY_MAPPINGMODE_V(texType, texSlot)); + + if (sampler->magFilter != SamplerMagFilter::UNSET) { + mat->AddProperty(&sampler->magFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MAG(texType, texSlot)); + } + + if (sampler->minFilter != SamplerMinFilter::UNSET) { + mat->AddProperty(&sampler->minFilter, 1, AI_MATKEY_GLTF_MAPPINGFILTER_MIN(texType, texSlot)); + } + } + } +} + +void glTF2Importer::ImportMaterials(glTF2::Asset& r) +{ + mScene->mNumMaterials = unsigned(r.materials.Size()); + mScene->mMaterials = new aiMaterial*[mScene->mNumMaterials]; + + for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) { + aiMaterial* aimat = mScene->mMaterials[i] = new aiMaterial(); + + Material& mat = r.materials[i]; + + if (!mat.name.empty()) { + aiString str(mat.name); + + aimat->AddProperty(&str, AI_MATKEY_NAME); + } + + SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_COLOR_DIFFUSE); + SetMaterialColorProperty(r, mat.pbrMetallicRoughness.baseColorFactor, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_FACTOR); + + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_DIFFUSE); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_BASE_COLOR_TEXTURE); + + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE); + + aimat->AddProperty(&mat.pbrMetallicRoughness.metallicFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR); + aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR); + + float roughnessAsShininess = (1 - mat.pbrMetallicRoughness.roughnessFactor) * 1000; + aimat->AddProperty(&roughnessAsShininess, 1, AI_MATKEY_SHININESS); + + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.normalTexture, aimat, aiTextureType_NORMALS); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.occlusionTexture, aimat, aiTextureType_LIGHTMAP); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.emissiveTexture, aimat, aiTextureType_EMISSIVE); + SetMaterialColorProperty(r, mat.emissiveFactor, aimat, AI_MATKEY_COLOR_EMISSIVE); + + aimat->AddProperty(&mat.doubleSided, 1, AI_MATKEY_TWOSIDED); + + aiString alphaMode(mat.alphaMode); + aimat->AddProperty(&alphaMode, AI_MATKEY_GLTF_ALPHAMODE); + aimat->AddProperty(&mat.alphaCutoff, 1, AI_MATKEY_GLTF_ALPHACUTOFF); + + //pbrSpecularGlossiness + if (mat.pbrSpecularGlossiness.isPresent) { + PbrSpecularGlossiness &pbrSG = mat.pbrSpecularGlossiness.value; + + aimat->AddProperty(&mat.pbrSpecularGlossiness.isPresent, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS); + SetMaterialColorProperty(r, pbrSG.diffuseFactor, aimat, AI_MATKEY_COLOR_DIFFUSE); + SetMaterialColorProperty(r, pbrSG.specularFactor, aimat, AI_MATKEY_COLOR_SPECULAR); + + float glossinessAsShininess = pbrSG.glossinessFactor * 1000.0f; + aimat->AddProperty(&glossinessAsShininess, 1, AI_MATKEY_SHININESS); + aimat->AddProperty(&pbrSG.glossinessFactor, 1, AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR); + + SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.diffuseTexture, aimat, aiTextureType_DIFFUSE); + + SetMaterialTextureProperty(embeddedTexIdxs, r, pbrSG.specularGlossinessTexture, aimat, aiTextureType_SPECULAR); + } + } +} + + +static inline void SetFace(aiFace& face, int a) +{ + face.mNumIndices = 1; + face.mIndices = new unsigned int[1]; + face.mIndices[0] = a; +} + +static inline void SetFace(aiFace& face, int a, int b) +{ + face.mNumIndices = 2; + face.mIndices = new unsigned int[2]; + face.mIndices[0] = a; + face.mIndices[1] = b; +} + +static inline void SetFace(aiFace& face, int a, int b, int c) +{ + face.mNumIndices = 3; + face.mIndices = new unsigned int[3]; + face.mIndices[0] = a; + face.mIndices[1] = b; + face.mIndices[2] = c; +} + +#ifdef ASSIMP_BUILD_DEBUG +static inline bool CheckValidFacesIndices(aiFace* faces, unsigned nFaces, unsigned nVerts) +{ + for (unsigned i = 0; i < nFaces; ++i) { + for (unsigned j = 0; j < faces[i].mNumIndices; ++j) { + unsigned idx = faces[i].mIndices[j]; + if (idx >= nVerts) + return false; + } + } + return true; +} +#endif // ASSIMP_BUILD_DEBUG + +void glTF2Importer::ImportMeshes(glTF2::Asset& r) +{ + std::vector meshes; + + unsigned int k = 0; + + for (unsigned int m = 0; m < r.meshes.Size(); ++m) { + Mesh& mesh = r.meshes[m]; + + meshOffsets.push_back(k); + k += unsigned(mesh.primitives.size()); + + for (unsigned int p = 0; p < mesh.primitives.size(); ++p) { + Mesh::Primitive& prim = mesh.primitives[p]; + + aiMesh* aim = new aiMesh(); + meshes.push_back(aim); + + aim->mName = mesh.name.empty() ? mesh.id : mesh.name; + + if (mesh.primitives.size() > 1) { + size_t& len = aim->mName.length; + aim->mName.data[len] = '-'; + len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p); + } + + switch (prim.mode) { + case PrimitiveMode_POINTS: + aim->mPrimitiveTypes |= aiPrimitiveType_POINT; + break; + + case PrimitiveMode_LINES: + case PrimitiveMode_LINE_LOOP: + case PrimitiveMode_LINE_STRIP: + aim->mPrimitiveTypes |= aiPrimitiveType_LINE; + break; + + case PrimitiveMode_TRIANGLES: + case PrimitiveMode_TRIANGLE_STRIP: + case PrimitiveMode_TRIANGLE_FAN: + aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; + break; + + } + + Mesh::Primitive::Attributes& attr = prim.attributes; + + if (attr.position.size() > 0 && attr.position[0]) { + aim->mNumVertices = attr.position[0]->count; + attr.position[0]->ExtractData(aim->mVertices); + } + + if (attr.normal.size() > 0 && attr.normal[0]) { + attr.normal[0]->ExtractData(aim->mNormals); + + // only extract tangents if normals are present + if (attr.tangent.size() > 0 && attr.tangent[0]) { + // generate bitangents from normals and tangents according to spec + struct Tangent + { + aiVector3D xyz; + ai_real w; + } *tangents = nullptr; + + attr.tangent[0]->ExtractData(tangents); + + aim->mTangents = new aiVector3D[aim->mNumVertices]; + aim->mBitangents = new aiVector3D[aim->mNumVertices]; + + for (unsigned int i = 0; i < aim->mNumVertices; ++i) { + aim->mTangents[i] = tangents[i].xyz; + aim->mBitangents[i] = (aim->mNormals[i] ^ tangents[i].xyz) * tangents[i].w; + } + + delete tangents; + } + } + + for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) { + attr.texcoord[tc]->ExtractData(aim->mTextureCoords[tc]); + aim->mNumUVComponents[tc] = attr.texcoord[tc]->GetNumComponents(); + + aiVector3D* values = aim->mTextureCoords[tc]; + for (unsigned int i = 0; i < aim->mNumVertices; ++i) { + values[i].y = 1 - values[i].y; // Flip Y coords + } + } + + + if (prim.indices) { + aiFace* faces = 0; + unsigned int nFaces = 0; + + unsigned int count = prim.indices->count; + + Accessor::Indexer data = prim.indices->GetIndexer(); + ai_assert(data.IsValid()); + + switch (prim.mode) { + case PrimitiveMode_POINTS: { + nFaces = count; + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; ++i) { + SetFace(faces[i], data.GetUInt(i)); + } + break; + } + + case PrimitiveMode_LINES: { + nFaces = count / 2; + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; i += 2) { + SetFace(faces[i / 2], data.GetUInt(i), data.GetUInt(i + 1)); + } + break; + } + + case PrimitiveMode_LINE_LOOP: + case PrimitiveMode_LINE_STRIP: { + nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); + faces = new aiFace[nFaces]; + SetFace(faces[0], data.GetUInt(0), data.GetUInt(1)); + for (unsigned int i = 2; i < count; ++i) { + SetFace(faces[i - 1], faces[i - 2].mIndices[1], data.GetUInt(i)); + } + if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop + SetFace(faces[count - 1], faces[count - 2].mIndices[1], faces[0].mIndices[0]); + } + break; + } + + case PrimitiveMode_TRIANGLES: { + nFaces = count / 3; + faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; i += 3) { + SetFace(faces[i / 3], data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); + } + break; + } + case PrimitiveMode_TRIANGLE_STRIP: { + nFaces = count - 2; + faces = new aiFace[nFaces]; + SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); + for (unsigned int i = 3; i < count; ++i) { + SetFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], data.GetUInt(i)); + } + break; + } + case PrimitiveMode_TRIANGLE_FAN: + nFaces = count - 2; + faces = new aiFace[nFaces]; + SetFace(faces[0], data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); + for (unsigned int i = 3; i < count; ++i) { + SetFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], data.GetUInt(i)); + } + break; + } + + if (faces) { + aim->mFaces = faces; + aim->mNumFaces = nFaces; + ai_assert(CheckValidFacesIndices(faces, nFaces, aim->mNumVertices)); + } + } + + + if (prim.material) { + aim->mMaterialIndex = prim.material.GetIndex(); + } + } + } + + meshOffsets.push_back(k); + + CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes); +} + +void glTF2Importer::ImportCameras(glTF2::Asset& r) +{ + if (!r.cameras.Size()) return; + + mScene->mNumCameras = r.cameras.Size(); + mScene->mCameras = new aiCamera*[r.cameras.Size()]; + + for (size_t i = 0; i < r.cameras.Size(); ++i) { + Camera& cam = r.cameras[i]; + + aiCamera* aicam = mScene->mCameras[i] = new aiCamera(); + + if (cam.type == Camera::Perspective) { + + aicam->mAspect = cam.cameraProperties.perspective.aspectRatio; + aicam->mHorizontalFOV = cam.cameraProperties.perspective.yfov * aicam->mAspect; + aicam->mClipPlaneFar = cam.cameraProperties.perspective.zfar; + aicam->mClipPlaneNear = cam.cameraProperties.perspective.znear; + } + else { + // assimp does not support orthographic cameras + } + } +} + +aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector& meshOffsets, glTF2::Ref& ptr) +{ + Node& node = *ptr; + + std::string nameOrId = node.name.empty() ? node.id : node.name; + + aiNode* ainode = new aiNode(nameOrId); + + if (!node.children.empty()) { + ainode->mNumChildren = unsigned(node.children.size()); + ainode->mChildren = new aiNode*[ainode->mNumChildren]; + + for (unsigned int i = 0; i < ainode->mNumChildren; ++i) { + aiNode* child = ImportNode(pScene, r, meshOffsets, node.children[i]); + child->mParent = ainode; + ainode->mChildren[i] = child; + } + } + + aiMatrix4x4& matrix = ainode->mTransformation; + if (node.matrix.isPresent) { + CopyValue(node.matrix.value, matrix); + } + else { + if (node.translation.isPresent) { + aiVector3D trans; + CopyValue(node.translation.value, trans); + aiMatrix4x4 t; + aiMatrix4x4::Translation(trans, t); + matrix = matrix * t; + } + + if (node.rotation.isPresent) { + aiQuaternion rot; + CopyValue(node.rotation.value, rot); + matrix = matrix * aiMatrix4x4(rot.GetMatrix()); + } + + if (node.scale.isPresent) { + aiVector3D scal(1.f); + CopyValue(node.scale.value, scal); + aiMatrix4x4 s; + aiMatrix4x4::Scaling(scal, s); + matrix = matrix * s; + } + } + + if (!node.meshes.empty()) { + int count = 0; + for (size_t i = 0; i < node.meshes.size(); ++i) { + int idx = node.meshes[i].GetIndex(); + count += meshOffsets[idx + 1] - meshOffsets[idx]; + } + ainode->mNumMeshes = count; + + ainode->mMeshes = new unsigned int[count]; + + int k = 0; + for (size_t i = 0; i < node.meshes.size(); ++i) { + int idx = node.meshes[i].GetIndex(); + for (unsigned int j = meshOffsets[idx]; j < meshOffsets[idx + 1]; ++j, ++k) { + ainode->mMeshes[k] = j; + } + } + } + + if (node.camera) { + pScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName; + } + + return ainode; +} + +void glTF2Importer::ImportNodes(glTF2::Asset& r) +{ + if (!r.scene) return; + + std::vector< Ref > rootNodes = r.scene->nodes; + + // The root nodes + unsigned int numRootNodes = unsigned(rootNodes.size()); + if (numRootNodes == 1) { // a single root node: use it + mScene->mRootNode = ImportNode(mScene, r, meshOffsets, rootNodes[0]); + } + else if (numRootNodes > 1) { // more than one root node: create a fake root + aiNode* root = new aiNode("ROOT"); + root->mChildren = new aiNode*[numRootNodes]; + for (unsigned int i = 0; i < numRootNodes; ++i) { + aiNode* node = ImportNode(mScene, r, meshOffsets, rootNodes[i]); + node->mParent = root; + root->mChildren[root->mNumChildren++] = node; + } + mScene->mRootNode = root; + } + + //if (!mScene->mRootNode) { + // mScene->mRootNode = new aiNode("EMPTY"); + //} +} + +void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset& r) +{ + embeddedTexIdxs.resize(r.images.Size(), -1); + + int numEmbeddedTexs = 0; + for (size_t i = 0; i < r.images.Size(); ++i) { + if (r.images[i].HasData()) + numEmbeddedTexs += 1; + } + + if (numEmbeddedTexs == 0) + return; + + mScene->mTextures = new aiTexture*[numEmbeddedTexs]; + + // Add the embedded textures + for (size_t i = 0; i < r.images.Size(); ++i) { + Image img = r.images[i]; + if (!img.HasData()) continue; + + int idx = mScene->mNumTextures++; + embeddedTexIdxs[i] = idx; + + aiTexture* tex = mScene->mTextures[idx] = new aiTexture(); + + size_t length = img.GetDataLength(); + void* data = img.StealData(); + + tex->mWidth = static_cast(length); + tex->mHeight = 0; + tex->pcData = reinterpret_cast(data); + + if (!img.mimeType.empty()) { + const char* ext = strchr(img.mimeType.c_str(), '/') + 1; + if (ext) { + if (strcmp(ext, "jpeg") == 0) ext = "jpg"; + + size_t len = strlen(ext); + if (len <= 3) { + strcpy(tex->achFormatHint, ext); + } + } + } + } +} + +void glTF2Importer::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { + + this->mScene = pScene; + + // read the asset file + glTF2::Asset asset(pIOHandler); + asset.Load(pFile, GetExtension(pFile) == "glb"); + + // + // Copy the data out + // + + ImportEmbeddedTextures(asset); + ImportMaterials(asset); + + ImportMeshes(asset); + + ImportCameras(asset); + + ImportNodes(asset); + + // TODO: it does not split the loaded vertices, should it? + //pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT; + MakeVerboseFormatProcess process; + process.Execute(pScene); + + + if (pScene->mNumMeshes == 0) { + pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; + } +} + +#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER + diff --git a/code/glTF2Importer.h b/code/glTF2Importer.h new file mode 100644 index 000000000..6be7131d1 --- /dev/null +++ b/code/glTF2Importer.h @@ -0,0 +1,91 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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. + +---------------------------------------------------------------------- +*/ +#ifndef AI_GLTF2IMPORTER_H_INC +#define AI_GLTF2IMPORTER_H_INC + +#include "BaseImporter.h" +#include + +struct aiNode; + + +namespace glTF2 +{ + class Asset; +} + +namespace Assimp { + +/** + * Load the glTF2 format. + * https://github.com/KhronosGroup/glTF/tree/master/specification + */ +class glTF2Importer : public BaseImporter{ +public: + glTF2Importer(); + virtual ~glTF2Importer(); + virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const; + +protected: + virtual const aiImporterDesc* GetInfo() const; + virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler ); + +private: + + std::vector meshOffsets; + + std::vector embeddedTexIdxs; + + aiScene* mScene; + + void ImportEmbeddedTextures(glTF2::Asset& a); + void ImportMaterials(glTF2::Asset& a); + void ImportMeshes(glTF2::Asset& a); + void ImportCameras(glTF2::Asset& a); + void ImportLights(glTF2::Asset& a); + void ImportNodes(glTF2::Asset& a); + +}; + +} // Namespace assimp + +#endif // AI_GLTF2IMPORTER_H_INC + diff --git a/code/glTFAsset.h b/code/glTFAsset.h index 2a0de7bf3..0c3de16a5 100644 --- a/code/glTFAsset.h +++ b/code/glTFAsset.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -45,8 +46,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * KHR_binary_glTF: full * KHR_materials_common: full */ -#ifndef glTFAsset_H_INC -#define glTFAsset_H_INC +#ifndef GLTFASSET_H_INC +#define GLTFASSET_H_INC + +#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER #include #include @@ -62,7 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef ASSIMP_API # include -# include "DefaultIOSystem.h" +# include # include "ByteSwapper.h" #else # include @@ -210,6 +213,7 @@ namespace glTF ComponentType_UNSIGNED_BYTE = 5121, ComponentType_SHORT = 5122, ComponentType_UNSIGNED_SHORT = 5123, + ComponentType_UNSIGNED_INT = 5125, ComponentType_FLOAT = 5126 }; @@ -220,13 +224,17 @@ namespace glTF case ComponentType_UNSIGNED_SHORT: return 2; + case ComponentType_UNSIGNED_INT: case ComponentType_FLOAT: return 4; - //case Accessor::ComponentType_BYTE: - //case Accessor::ComponentType_UNSIGNED_BYTE: - default: + case ComponentType_BYTE: + case ComponentType_UNSIGNED_BYTE: return 1; + default: + std::string err = "GLTF: Unsupported Component Type "; + err += t; + throw DeadlyImportError(err); } } @@ -385,7 +393,7 @@ namespace glTF virtual ~Object() {} //! Maps special IDs to another ID, where needed. Subclasses may override it (statically) - static const char* TranslateId(Asset& r, const char* id) + static const char* TranslateId(Asset& /*r*/, const char* id) { return id; } }; @@ -1052,13 +1060,13 @@ namespace glTF std::string version; //!< Specifies the target rendering API (default: "1.0.3") } profile; //!< Specifies the target rendering API and version, e.g., WebGL 1.0.3. (default: {}) - int version; //!< The glTF format version (should be 1) + std::string version; //!< The glTF format version (should be 1.0) void Read(Document& doc); AssetMetadata() : premultipliedAlpha(false) - , version(0) + , version("") { } }; @@ -1183,4 +1191,6 @@ namespace glTF // Include the implementation of the methods #include "glTFAsset.inl" -#endif +#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER + +#endif // GLTFASSET_H_INC diff --git a/code/glTFAsset.inl b/code/glTFAsset.inl index 4ec8c2ffe..a5d74f5a0 100644 --- a/code/glTFAsset.inl +++ b/code/glTFAsset.inl @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -39,6 +40,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "StringUtils.h" +#include // Header files, Assimp #include @@ -127,6 +129,12 @@ namespace { return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0; } + inline Value* FindNumber(Value& val, const char* id) + { + Value::MemberIterator it = val.FindMember(id); + return (it != val.MemberEnd() && it->value.IsNumber()) ? &it->value : 0; + } + inline Value* FindArray(Value& val, const char* id) { Value::MemberIterator it = val.FindMember(id); @@ -308,7 +316,9 @@ inline void Buffer::Read(Value& obj, Asset& r) } else { // Local file if (byteLength > 0) { - IOStream* file = r.OpenFile(uri, "rb"); + std::string dir = !r.mCurrentAssetDir.empty() ? (r.mCurrentAssetDir + "/") : ""; + + IOStream* file = r.OpenFile(dir + uri, "rb"); if (file) { bool ok = LoadFromStream(*file, byteLength); delete file; @@ -331,7 +341,7 @@ inline bool Buffer::LoadFromStream(IOStream& stream, size_t length, size_t baseO stream.Seek(baseOffset, aiOrigin_SET); } - mData.reset(new uint8_t[byteLength]); + mData.reset(new uint8_t[byteLength], std::default_delete()); if (stream.Read(mData.get(), byteLength, 1) != 1) { return false; @@ -665,7 +675,7 @@ inline void Image::SetData(uint8_t* data, size_t length, Asset& r) } } -inline void Sampler::Read(Value& obj, Asset& r) +inline void Sampler::Read(Value& obj, Asset& /*r*/) { SetDefaults(); @@ -1083,7 +1093,7 @@ Ref buf = pAsset_Root.buffers.Get(pCompression_Open3DGC.Buffer); } #endif -inline void Camera::Read(Value& obj, Asset& r) +inline void Camera::Read(Value& obj, Asset& /*r*/) { type = MemberOrDefault(obj, "type", Camera::Perspective); @@ -1106,7 +1116,7 @@ inline void Camera::Read(Value& obj, Asset& r) } } -inline void Light::Read(Value& obj, Asset& r) +inline void Light::Read(Value& obj, Asset& /*r*/) { SetDefaults(); @@ -1227,13 +1237,21 @@ inline void Scene::Read(Value& obj, Asset& r) inline void AssetMetadata::Read(Document& doc) { // read the version, etc. - int statedVersion = 0; if (Value* obj = FindObject(doc, "asset")) { ReadMember(*obj, "copyright", copyright); ReadMember(*obj, "generator", generator); premultipliedAlpha = MemberOrDefault(*obj, "premultipliedAlpha", false); - statedVersion = MemberOrDefault(*obj, "version", 0); + + if (Value* versionString = FindString(*obj, "version")) { + version = versionString->GetString(); + } else if (Value* versionNumber = FindNumber (*obj, "version")) { + char buf[4]; + + ai_snprintf(buf, 4, "%.1f", versionNumber->GetDouble()); + + version = buf; + } if (Value* profile = FindObject(*obj, "profile")) { ReadMember(*profile, "api", this->profile.api); @@ -1241,16 +1259,8 @@ inline void AssetMetadata::Read(Document& doc) } } - version = std::max(statedVersion, version); - if (version == 0) { - // if missing version, we'll assume version 1... - version = 1; - } - - if (version != 1) { - char msg[128]; - ai_snprintf(msg, 128, "GLTF: Unsupported glTF version: %d", version); - throw DeadlyImportError(msg); + if (version.empty() || version[0] != '1') { + throw DeadlyImportError("GLTF: Unsupported glTF version: " + version); } } @@ -1272,7 +1282,7 @@ inline void Asset::ReadBinaryHeader(IOStream& stream) } AI_SWAP4(header.version); - asset.version = header.version; + asset.version = to_string(header.version); if (header.version != 1) { throw DeadlyImportError("GLTF: Unsupported binary glTF version"); } @@ -1404,7 +1414,7 @@ inline void Asset::ReadExtensionsUsed(Document& doc) #undef CHECK_EXT } -inline IOStream* Asset::OpenFile(std::string path, const char* mode, bool absolute) +inline IOStream* Asset::OpenFile(std::string path, const char* mode, bool /*absolute*/) { #ifdef ASSIMP_API return mIOSystem->Open(path, mode); diff --git a/code/glTFAssetWriter.h b/code/glTFAssetWriter.h index 4d2d3c919..186d32a15 100644 --- a/code/glTFAssetWriter.h +++ b/code/glTFAssetWriter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -45,8 +46,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * KHR_binary_glTF: full * KHR_materials_common: full */ -#ifndef glTFAssetWriter_H_INC -#define glTFAssetWriter_H_INC +#ifndef GLTFASSETWRITER_H_INC +#define GLTFASSETWRITER_H_INC + +#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER #include "glTFAsset.h" @@ -87,4 +90,6 @@ public: // Include the implementation of the methods #include "glTFAssetWriter.inl" -#endif +#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER + +#endif // GLTFASSETWRITER_H_INC diff --git a/code/glTFAssetWriter.inl b/code/glTFAssetWriter.inl index 1e545b497..485abc4f6 100644 --- a/code/glTFAssetWriter.inl +++ b/code/glTFAssetWriter.inl @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -186,7 +187,7 @@ namespace glTF { obj.AddMember("target", int(bv.target), w.mAl); } - inline void Write(Value& obj, Camera& c, AssetWriter& w) + inline void Write(Value& /*obj*/, Camera& /*c*/, AssetWriter& /*w*/) { } @@ -397,7 +398,7 @@ namespace glTF { } } - inline void Write(Value& obj, Program& b, AssetWriter& w) + inline void Write(Value& /*obj*/, Program& /*b*/, AssetWriter& /*w*/) { } @@ -423,7 +424,7 @@ namespace glTF { AddRefsVector(scene, "nodes", s.nodes, w.mAl); } - inline void Write(Value& obj, Shader& b, AssetWriter& w) + inline void Write(Value& /*obj*/, Shader& /*b*/, AssetWriter& /*w*/) { } @@ -451,7 +452,7 @@ namespace glTF { } - inline void Write(Value& obj, Technique& b, AssetWriter& w) + inline void Write(Value& /*obj*/, Technique& /*b*/, AssetWriter& /*w*/) { } @@ -466,7 +467,7 @@ namespace glTF { } } - inline void Write(Value& obj, Light& b, AssetWriter& w) + inline void Write(Value& /*obj*/, Light& /*b*/, AssetWriter& /*w*/) { } @@ -605,13 +606,8 @@ namespace glTF { { Value asset; asset.SetObject(); - { - char versionChar[10]; - ai_snprintf(versionChar, sizeof(versionChar), "%d", mAsset.asset.version); - asset.AddMember("version", Value(versionChar, mAl).Move(), mAl); - - asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl); - } + asset.AddMember("version", Value(mAsset.asset.version, mAl).Move(), mAl); + asset.AddMember("generator", Value(mAsset.asset.generator, mAl).Move(), mAl); mDoc.AddMember("asset", asset, mAl); } diff --git a/code/glTFExporter.cpp b/code/glTFExporter.cpp index 203a46040..d88081884 100644 --- a/code/glTFExporter.cpp +++ b/code/glTFExporter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -47,15 +48,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ByteSwapper.h" #include "SplitLargeMeshes.h" -#include "SceneCombiner.h" +#include #include #include #include #include #include -// Header files, standart library. +// Header files, standard library. #include #include @@ -184,8 +185,11 @@ inline Ref ExportData(Asset& a, std::string& meshName, Ref& bu unsigned int bytesPerComp = ComponentTypeSize(compType); size_t offset = buffer->byteLength; + // make sure offset is correctly byte-aligned, as required by spec + size_t padding = offset % bytesPerComp; + offset += padding; size_t length = count * numCompsOut * bytesPerComp; - buffer->Grow(length); + buffer->Grow(length + padding); // bufferView Ref bv = a.bufferViews.Create(a.FindUniqueID(meshName, "view")); @@ -440,7 +444,7 @@ void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref& meshRef, Ref nodeRef = mAsset.nodes.Get(aib->mName.C_Str()); nodeRef->jointName = nodeRef->id; - unsigned int jointNamesIndex; + unsigned int jointNamesIndex = 0; bool addJointToJointNames = true; for ( unsigned int idx_joint = 0; idx_joint < skinRef->jointNames.size(); ++idx_joint) { if (skinRef->jointNames[idx_joint]->jointName.compare(nodeRef->jointName) == 0) { @@ -465,11 +469,11 @@ void ExportSkin(Asset& mAsset, const aiMesh* aimesh, Ref& meshRef, RefmWeights[idx_weights].mWeight; // A vertex can only have at most four joint weights. Ignore all others. - if (jointsPerVertex[vertexId] > 3) { - continue; + if (jointsPerVertex[vertexId] > 3) { + continue; } - vertexJointData[vertexId][jointsPerVertex[vertexId]] = jointNamesIndex; + vertexJointData[vertexId][jointsPerVertex[vertexId]] = static_cast(jointNamesIndex); vertexWeightData[vertexId][jointsPerVertex[vertexId]] = vertWeight; jointsPerVertex[vertexId] += 1; @@ -503,7 +507,7 @@ void glTFExporter::ExportMeshes() // Variables needed for compression. BEGIN. // Indices, not pointers - because pointer to buffer is changing while writing to it. - size_t idx_srcdata_begin;// Index of buffer before writing mesh data. Also, index of begin of coordinates array in buffer. + size_t idx_srcdata_begin = 0; // Index of buffer before writing mesh data. Also, index of begin of coordinates array in buffer. size_t idx_srcdata_normal = SIZE_MAX;// Index of begin of normals array in buffer. SIZE_MAX - mean that mesh has no normals. std::vector idx_srcdata_tc;// Array of indices. Every index point to begin of texture coordinates array in buffer. size_t idx_srcdata_ind;// Index of begin of coordinates indices array in buffer. @@ -511,7 +515,7 @@ void glTFExporter::ExportMeshes() // Variables needed for compression. END. std::string fname = std::string(mFilename); - std::string bufferIdPrefix = fname.substr(0, fname.find(".")); + std::string bufferIdPrefix = fname.substr(0, fname.rfind(".gltf")); std::string bufferId = mAsset->FindUniqueID("", bufferIdPrefix.c_str()); Ref b = mAsset->GetBodyBuffer(); @@ -582,7 +586,7 @@ void glTFExporter::ExportMeshes() if (v) p.attributes.position.push_back(v); /******************** Normals ********************/ - if(comp_allow && (aim->mNormals > 0)) idx_srcdata_normal = b->byteLength;// Store index of normals array. + if(comp_allow && (aim->mNormals != 0)) idx_srcdata_normal = b->byteLength;// Store index of normals array. Ref n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); if (n) p.attributes.normal.push_back(n); @@ -830,7 +834,7 @@ void glTFExporter::ExportScene() void glTFExporter::ExportMetadata() { glTF::AssetMetadata& asset = mAsset->asset; - asset.version = 1; + asset.version = "1.0"; char buffer[256]; ai_snprintf(buffer, 256, "Open Asset Import Library (assimp v%d.%d.%d)", @@ -839,36 +843,52 @@ void glTFExporter::ExportMetadata() asset.generator = buffer; } -inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref& animRef, Ref& buffer, const aiNodeAnim* nodeChannel) +inline void ExtractAnimationData(Asset& mAsset, std::string& animId, Ref& animRef, Ref& buffer, const aiNodeAnim* nodeChannel, float ticksPerSecond) { // Loop over the data and check to see if it exactly matches an existing buffer. // If yes, then reference the existing corresponding accessor. // Otherwise, add to the buffer and create a new accessor. + size_t counts[3] = { + nodeChannel->mNumPositionKeys, + nodeChannel->mNumScalingKeys, + nodeChannel->mNumRotationKeys, + }; + size_t numKeyframes = 1; + for (int i = 0; i < 3; ++i) { + if (counts[i] > numKeyframes) { + numKeyframes = counts[i]; + } + } + //------------------------------------------------------- // Extract TIME parameter data. // Check if the timeStamps are the same for mPositionKeys, mRotationKeys, and mScalingKeys. if(nodeChannel->mNumPositionKeys > 0) { typedef float TimeType; std::vector timeData; - timeData.resize(nodeChannel->mNumPositionKeys); - for (size_t i = 0; i < nodeChannel->mNumPositionKeys; ++i) { - timeData[i] = nodeChannel->mPositionKeys[i].mTime; // Check if we have to cast type here. e.g. uint16_t() + timeData.resize(numKeyframes); + for (size_t i = 0; i < numKeyframes; ++i) { + size_t frameIndex = i * nodeChannel->mNumPositionKeys / numKeyframes; + // mTime is measured in ticks, but GLTF time is measured in seconds, so convert. + // Check if we have to cast type here. e.g. uint16_t() + timeData[i] = static_cast(nodeChannel->mPositionKeys[frameIndex].mTime / ticksPerSecond); } - Ref timeAccessor = ExportData(mAsset, animId, buffer, nodeChannel->mNumPositionKeys, &timeData[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_FLOAT); + Ref timeAccessor = ExportData(mAsset, animId, buffer, static_cast(numKeyframes), &timeData[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_FLOAT); if (timeAccessor) animRef->Parameters.TIME = timeAccessor; } //------------------------------------------------------- // Extract translation parameter data if(nodeChannel->mNumPositionKeys > 0) { - C_STRUCT aiVector3D* translationData = new aiVector3D[nodeChannel->mNumPositionKeys]; - for (size_t i = 0; i < nodeChannel->mNumPositionKeys; ++i) { - translationData[i] = nodeChannel->mPositionKeys[i].mValue; + C_STRUCT aiVector3D* translationData = new aiVector3D[numKeyframes]; + for (size_t i = 0; i < numKeyframes; ++i) { + size_t frameIndex = i * nodeChannel->mNumPositionKeys / numKeyframes; + translationData[i] = nodeChannel->mPositionKeys[frameIndex].mValue; } - Ref tranAccessor = ExportData(mAsset, animId, buffer, nodeChannel->mNumPositionKeys, translationData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + Ref tranAccessor = ExportData(mAsset, animId, buffer, static_cast(numKeyframes), translationData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); if ( tranAccessor ) { animRef->Parameters.translation = tranAccessor; } @@ -878,12 +898,13 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, RefmNumScalingKeys > 0) { - C_STRUCT aiVector3D* scaleData = new aiVector3D[nodeChannel->mNumScalingKeys]; - for (size_t i = 0; i < nodeChannel->mNumScalingKeys; ++i) { - scaleData[i] = nodeChannel->mScalingKeys[i].mValue; + C_STRUCT aiVector3D* scaleData = new aiVector3D[numKeyframes]; + for (size_t i = 0; i < numKeyframes; ++i) { + size_t frameIndex = i * nodeChannel->mNumScalingKeys / numKeyframes; + scaleData[i] = nodeChannel->mScalingKeys[frameIndex].mValue; } - Ref scaleAccessor = ExportData(mAsset, animId, buffer, nodeChannel->mNumScalingKeys, scaleData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); + Ref scaleAccessor = ExportData(mAsset, animId, buffer, static_cast(numKeyframes), scaleData, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT); if ( scaleAccessor ) { animRef->Parameters.scale = scaleAccessor; } @@ -893,15 +914,16 @@ inline void ExtractAnimationData(Asset& mAsset, std::string& animId, RefmNumRotationKeys > 0) { - vec4* rotationData = new vec4[nodeChannel->mNumRotationKeys]; - for (size_t i = 0; i < nodeChannel->mNumRotationKeys; ++i) { - rotationData[i][0] = nodeChannel->mRotationKeys[i].mValue.x; - rotationData[i][1] = nodeChannel->mRotationKeys[i].mValue.y; - rotationData[i][2] = nodeChannel->mRotationKeys[i].mValue.z; - rotationData[i][3] = nodeChannel->mRotationKeys[i].mValue.w; + vec4* rotationData = new vec4[numKeyframes]; + for (size_t i = 0; i < numKeyframes; ++i) { + size_t frameIndex = i * nodeChannel->mNumRotationKeys / numKeyframes; + rotationData[i][0] = nodeChannel->mRotationKeys[frameIndex].mValue.x; + rotationData[i][1] = nodeChannel->mRotationKeys[frameIndex].mValue.y; + rotationData[i][2] = nodeChannel->mRotationKeys[frameIndex].mValue.z; + rotationData[i][3] = nodeChannel->mRotationKeys[frameIndex].mValue.w; } - Ref rotAccessor = ExportData(mAsset, animId, buffer, nodeChannel->mNumRotationKeys, rotationData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); + Ref rotAccessor = ExportData(mAsset, animId, buffer, static_cast(numKeyframes), rotationData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); if ( rotAccessor ) { animRef->Parameters.rotation = rotAccessor; } @@ -931,7 +953,7 @@ void glTFExporter::ExportAnimations() Ref animRef = mAsset->animations.Create(name); /******************* Parameters ********************/ - ExtractAnimationData(*mAsset, name, animRef, bufferRef, nodeChannel); + ExtractAnimationData(*mAsset, name, animRef, bufferRef, nodeChannel, static_cast(anim->mTicksPerSecond)); for (unsigned int j = 0; j < 3; ++j) { std::string channelType; diff --git a/code/glTFExporter.h b/code/glTFExporter.h index 49df9193e..c813fff44 100644 --- a/code/glTFExporter.h +++ b/code/glTFExporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -44,6 +45,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_GLTFEXPORTER_H_INC #define AI_GLTFEXPORTER_H_INC +#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER + #include #include @@ -110,4 +113,6 @@ namespace Assimp } -#endif +#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER + +#endif // AI_GLTFEXPORTER_H_INC diff --git a/code/glTFImporter.cpp b/code/glTFImporter.cpp index 65a600f83..5d1b5afab 100644 --- a/code/glTFImporter.cpp +++ b/code/glTFImporter.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -48,6 +49,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include + #include #include "MakeVerboseFormat.h" @@ -97,24 +100,19 @@ const aiImporterDesc* glTFImporter::GetInfo() const bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { - const std::string& extension = GetExtension(pFile); + const std::string &extension = GetExtension(pFile); - if (extension == "gltf" || extension == "glb") - return true; + if (extension != "gltf" && extension != "glb") + return false; - if ((checkSig || !extension.length()) && pIOHandler) { - char buffer[4]; - - std::unique_ptr pStream(pIOHandler->Open(pFile)); - if (pStream && pStream->Read(buffer, sizeof(buffer), 1) == 1) { - if (memcmp(buffer, AI_GLB_MAGIC_NUMBER, sizeof(buffer)) == 0) { - return true; // Has GLB header - } - else if (memcmp(buffer, "{\r\n ", sizeof(buffer)) == 0 - || memcmp(buffer, "{\n ", sizeof(buffer)) == 0) { - // seems a JSON file, and we're the only format that can read them - return true; - } + if (checkSig && pIOHandler) { + glTF::Asset asset(pIOHandler); + try { + asset.Load(pFile, extension == "glb"); + std::string version = asset.asset.version; + return !version.empty() && version[0] == '1'; + } catch (...) { + return false; } } @@ -156,7 +154,7 @@ static void CopyValue(const glTF::mat4& v, aiMatrix4x4& o) o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15]; } -inline void SetMaterialColorProperty(std::vector& embeddedTexIdxs, Asset& r, glTF::TexProperty prop, aiMaterial* mat, +inline void SetMaterialColorProperty(std::vector& embeddedTexIdxs, Asset& /*r*/, glTF::TexProperty prop, aiMaterial* mat, aiTextureType texType, const char* pKey, unsigned int type, unsigned int idx) { if (prop.texture) { @@ -176,9 +174,7 @@ inline void SetMaterialColorProperty(std::vector& embeddedTexIdxs, Asset& r else { aiColor4D col; CopyValue(prop.color, col); - if (col.r != 1.f || col.g != 1.f || col.b != 1.f || col.a != 1.f) { - mat->AddProperty(&col, 1, pKey, type, idx); - } + mat->AddProperty(&col, 1, pKey, type, idx); } } @@ -238,6 +234,7 @@ static inline void SetFace(aiFace& face, int a, int b, int c) face.mIndices[2] = c; } +#ifdef ASSIMP_BUILD_DEBUG static inline bool CheckValidFacesIndices(aiFace* faces, unsigned nFaces, unsigned nVerts) { for (unsigned i = 0; i < nFaces; ++i) { @@ -249,6 +246,7 @@ static inline bool CheckValidFacesIndices(aiFace* faces, unsigned nFaces, unsign } return true; } +#endif // ASSIMP_BUILD_DEBUG void glTFImporter::ImportMeshes(glTF::Asset& r) { @@ -674,7 +672,7 @@ void glTFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOS //pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT; MakeVerboseFormatProcess process; process.Execute(pScene); - + if (pScene->mNumMeshes == 0) { pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; diff --git a/code/glTFImporter.h b/code/glTFImporter.h index 5d06730a5..46f450f86 100644 --- a/code/glTFImporter.h +++ b/code/glTFImporter.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -41,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_GLTFIMPORTER_H_INC #include "BaseImporter.h" -#include "DefaultIOSystem.h" +#include struct aiNode; diff --git a/code/irrXMLWrapper.h b/code/irrXMLWrapper.h index 5b47faefe..bbda7c0f0 100644 --- a/code/irrXMLWrapper.h +++ b/code/irrXMLWrapper.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -42,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_IRRXML_WRAPPER // some long includes .... -#include "./../contrib/irrXML/irrXML.h" +#include #include "./../include/assimp/IOStream.hpp" #include "BaseImporter.h" #include @@ -69,9 +70,7 @@ namespace Assimp { * } * @endcode **/ -class CIrrXML_IOStreamReader - : public irr::io::IFileReadCallBack -{ +class CIrrXML_IOStreamReader : public irr::io::IFileReadCallBack { public: // ---------------------------------------------------------------------------------- diff --git a/code/qnan.h b/code/qnan.h index 80d6229f9..fcff16b74 100644 --- a/code/qnan.h +++ b/code/qnan.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/code/res/assimp.rc b/code/res/assimp.rc index 78f9d852b..0fe98c05d 100644 --- a/code/res/assimp.rc +++ b/code/res/assimp.rc @@ -1,80 +1,80 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" -#include "..\..\revision.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#define APSTUDIO_HIDDEN_SYMBOLS -#include "windows.h" -#undef APSTUDIO_HIDDEN_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// Deutsch (Deutschland) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) -#ifdef _WIN32 -LANGUAGE LANG_GERMAN, SUBLANG_GERMAN -#pragma code_page(1252) -#endif //_WIN32 - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,1,SVNRevision, 0 - PRODUCTVERSION 1,1,SVNRevision,0 - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x7L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040704b0" - BEGIN - VALUE "Comments", "Licensed under a 3-clause BSD license" - VALUE "CompanyName", "assimp team" - VALUE "FileDescription", "Open Asset Import Library" - VALUE "FileVersion", 1,1,SVNRevision,0 - VALUE "InternalName", "assimp " - VALUE "LegalCopyright", "Copyright (C) 2006-2010" - VALUE "OriginalFilename", "assimpNN.dll" - VALUE "ProductName", "Open Asset Import Library" - VALUE "ProductVersion", 1,1,SVNRevision,0 - ,0 - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x407, 1200 - END -END - -#endif // Deutsch (Deutschland) resources -///////////////////////////////////////////////////////////////////////////// - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" +#include "..\..\revision.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Deutschland) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,1,SVNRevision, 0 + PRODUCTVERSION 1,1,SVNRevision,0 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x7L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040704b0" + BEGIN + VALUE "Comments", "Licensed under a 3-clause BSD license" + VALUE "CompanyName", "assimp team" + VALUE "FileDescription", "Open Asset Import Library" + VALUE "FileVersion", 1,1,SVNRevision,0 + VALUE "InternalName", "assimp " + VALUE "LegalCopyright", "Copyright (C) 2006-2010" + VALUE "OriginalFilename", "assimpNN.dll" + VALUE "ProductName", "Open Asset Import Library" + VALUE "ProductVersion", 1,1,SVNRevision,0 + ,0 + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x407, 1200 + END +END + +#endif // Deutsch (Deutschland) resources +///////////////////////////////////////////////////////////////////////////// + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/code/scene.cpp b/code/scene.cpp new file mode 100644 index 000000000..467a2895d --- /dev/null +++ b/code/scene.cpp @@ -0,0 +1,139 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include + +aiNode::aiNode() +: mName("") +, mParent(NULL) +, mNumChildren(0) +, mChildren(NULL) +, mNumMeshes(0) +, mMeshes(NULL) +, mMetaData(NULL) { + // empty +} + +aiNode::aiNode(const std::string& name) +: mName(name) +, mParent(NULL) +, mNumChildren(0) +, mChildren(NULL) +, mNumMeshes(0) +, mMeshes(NULL) +, mMetaData(NULL) { + // empty +} + +/** Destructor */ +aiNode::~aiNode() { + // delete all children recursively + // to make sure we won't crash if the data is invalid ... + if (mChildren && mNumChildren) + { + for (unsigned int a = 0; a < mNumChildren; a++) + delete mChildren[a]; + } + delete[] mChildren; + delete[] mMeshes; + delete mMetaData; +} + +const aiNode *aiNode::FindNode(const char* name) const { + if (nullptr == name) { + return nullptr; + } + if (!::strcmp(mName.data, name)) { + return this; + } + for (unsigned int i = 0; i < mNumChildren; ++i) { + const aiNode* const p = mChildren[i]->FindNode(name); + if (p) { + return p; + } + } + // there is definitely no sub-node with this name + return nullptr; +} + +aiNode *aiNode::FindNode(const char* name) { + if (!::strcmp(mName.data, name))return this; + for (unsigned int i = 0; i < mNumChildren; ++i) + { + aiNode* const p = mChildren[i]->FindNode(name); + if (p) { + return p; + } + } + // there is definitely no sub-node with this name + return nullptr; +} + +void aiNode::addChildren(unsigned int numChildren, aiNode **children) { + if (nullptr == children || 0 == numChildren) { + return; + } + + for (unsigned int i = 0; i < numChildren; i++) { + aiNode *child = children[i]; + if (nullptr != child) { + child->mParent = this; + } + } + + if (mNumChildren > 0) { + aiNode **tmp = new aiNode*[mNumChildren]; + ::memcpy(tmp, mChildren, sizeof(aiNode*) * mNumChildren); + delete[] mChildren; + mChildren = new aiNode*[mNumChildren + numChildren]; + ::memcpy(mChildren, tmp, sizeof(aiNode*) * mNumChildren); + ::memcpy(&mChildren[mNumChildren], children, sizeof(aiNode*)* numChildren); + mNumChildren += numChildren; + delete[] tmp; + } + else { + mChildren = new aiNode*[numChildren]; + for (unsigned int i = 0; i < numChildren; i++) { + mChildren[i] = children[i]; + } + mNumChildren = numChildren; + } +} diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt new file mode 100644 index 000000000..362f1653d --- /dev/null +++ b/contrib/CMakeLists.txt @@ -0,0 +1,4 @@ +# Compile internal irrXML only if system is not requested +if( NOT SYSTEM_IRRXML ) + add_subdirectory(irrXML) +endif( NOT SYSTEM_IRRXML ) diff --git a/contrib/ConvertUTF/ConvertUTF.c b/contrib/ConvertUTF/ConvertUTF.c deleted file mode 100644 index 9b3deebd6..000000000 --- a/contrib/ConvertUTF/ConvertUTF.c +++ /dev/null @@ -1,539 +0,0 @@ -/* - * Copyright 2001-2004 Unicode, Inc. - * - * Disclaimer - * - * This source code is provided as is by Unicode, Inc. No claims are - * made as to fitness for any particular purpose. No warranties of any - * kind are expressed or implied. The recipient agrees to determine - * applicability of information provided. If this file has been - * purchased on magnetic or optical media from Unicode, Inc., the - * sole remedy for any claim will be exchange of defective media - * within 90 days of receipt. - * - * Limitations on Rights to Redistribute This Code - * - * Unicode, Inc. hereby grants the right to freely use the information - * supplied in this file in the creation of products supporting the - * Unicode Standard, and to make copies of this file in any form - * for internal or external distribution as long as this notice - * remains attached. - */ - -/* --------------------------------------------------------------------- - - Conversions between UTF32, UTF-16, and UTF-8. Source code file. - Author: Mark E. Davis, 1994. - Rev History: Rick McGowan, fixes & updates May 2001. - Sept 2001: fixed const & error conditions per - mods suggested by S. Parent & A. Lillich. - June 2002: Tim Dodd added detection and handling of incomplete - source sequences, enhanced error detection, added casts - to eliminate compiler warnings. - July 2003: slight mods to back out aggressive FFFE detection. - Jan 2004: updated switches in from-UTF8 conversions. - Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions. - - See the header file "ConvertUTF.h" for complete documentation. - ------------------------------------------------------------------------- */ - - -#include "ConvertUTF.h" -#ifdef CVTUTF_DEBUG -#include -#endif - -static const int halfShift = 10; /* used for shifting by 10 bits */ - -static const UTF32 halfBase = 0x0010000UL; -static const UTF32 halfMask = 0x3FFUL; - -#define UNI_SUR_HIGH_START (UTF32)0xD800 -#define UNI_SUR_HIGH_END (UTF32)0xDBFF -#define UNI_SUR_LOW_START (UTF32)0xDC00 -#define UNI_SUR_LOW_END (UTF32)0xDFFF -#define false 0 -#define true 1 - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF32toUTF16 ( - const UTF32** sourceStart, const UTF32* sourceEnd, - UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF32* source = *sourceStart; - UTF16* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch; - if (target >= targetEnd) { - result = targetExhausted; break; - } - ch = *source++; - if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ - /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - if (flags == strictConversion) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - *target++ = (UTF16)ch; /* normal case */ - } - } else if (ch > UNI_MAX_LEGAL_UTF32) { - if (flags == strictConversion) { - result = sourceIllegal; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - /* target is a character in range 0xFFFF - 0x10FFFF. */ - if (target + 1 >= targetEnd) { - --source; /* Back up source pointer! */ - result = targetExhausted; break; - } - ch -= halfBase; - *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); - *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); - } - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF16toUTF32 ( - const UTF16** sourceStart, const UTF16* sourceEnd, - UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF16* source = *sourceStart; - UTF32* target = *targetStart; - UTF32 ch, ch2; - while (source < sourceEnd) { - const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ - ch = *source++; - /* If we have a surrogate pair, convert to UTF32 first. */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { - /* If the 16 bits following the high surrogate are in the source buffer... */ - if (source < sourceEnd) { - ch2 = *source; - /* If it's a low surrogate, convert to UTF32. */ - if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { - ch = ((ch - UNI_SUR_HIGH_START) << halfShift) - + (ch2 - UNI_SUR_LOW_START) + halfBase; - ++source; - } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } else { /* We don't have the 16 bits following the high surrogate. */ - --source; /* return to the high surrogate */ - result = sourceExhausted; - break; - } - } else if (flags == strictConversion) { - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - if (target >= targetEnd) { - source = oldSource; /* Back up source pointer! */ - result = targetExhausted; break; - } - *target++ = ch; - } - *sourceStart = source; - *targetStart = target; -#ifdef CVTUTF_DEBUG -if (result == sourceIllegal) { - fprintf(stderr, "ConvertUTF16toUTF32 illegal seq 0x%04x,%04x\n", ch, ch2); - fflush(stderr); -} -#endif - return result; -} - -/* --------------------------------------------------------------------- */ - -/* - * Index into the table below with the first byte of a UTF-8 sequence to - * get the number of trailing bytes that are supposed to follow it. - * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is - * left as-is for anyone who may want to do such conversion, which was - * allowed in earlier algorithms. - */ -static const char trailingBytesForUTF8[256] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 -}; - -/* - * Magic values subtracted from a buffer value during UTF8 conversion. - * This table contains as many values as there might be trailing bytes - * in a UTF-8 sequence. - */ -static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, - 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; - -/* - * Once the bits are split out into bytes of UTF-8, this is a mask OR-ed - * into the first byte, depending on how many bytes follow. There are - * as many entries in this table as there are UTF-8 sequence types. - * (I.e., one byte sequence, two byte... etc.). Remember that sequencs - * for *legal* UTF-8 will be 4 or fewer bytes total. - */ -static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - -/* --------------------------------------------------------------------- */ - -/* The interface converts a whole buffer to avoid function-call overhead. - * Constants have been gathered. Loops & conditionals have been removed as - * much as possible for efficiency, in favor of drop-through switches. - * (See "Note A" at the bottom of the file for equivalent code.) - * If your compiler supports it, the "isLegalUTF8" call can be turned - * into an inline function. - */ - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF16toUTF8 ( - const UTF16** sourceStart, const UTF16* sourceEnd, - UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF16* source = *sourceStart; - UTF8* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch; - unsigned short bytesToWrite = 0; - const UTF32 byteMask = 0xBF; - const UTF32 byteMark = 0x80; - const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */ - ch = *source++; - /* If we have a surrogate pair, convert to UTF32 first. */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) { - /* If the 16 bits following the high surrogate are in the source buffer... */ - if (source < sourceEnd) { - UTF32 ch2 = *source; - /* If it's a low surrogate, convert to UTF32. */ - if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) { - ch = ((ch - UNI_SUR_HIGH_START) << halfShift) - + (ch2 - UNI_SUR_LOW_START) + halfBase; - ++source; - } else if (flags == strictConversion) { /* it's an unpaired high surrogate */ - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } else { /* We don't have the 16 bits following the high surrogate. */ - --source; /* return to the high surrogate */ - result = sourceExhausted; - break; - } - } else if (flags == strictConversion) { - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - /* Figure out how many bytes the result will require */ - if (ch < (UTF32)0x80) { bytesToWrite = 1; - } else if (ch < (UTF32)0x800) { bytesToWrite = 2; - } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; - } else if (ch < (UTF32)0x110000) { bytesToWrite = 4; - } else { bytesToWrite = 3; - ch = UNI_REPLACEMENT_CHAR; - } - - target += bytesToWrite; - if (target > targetEnd) { - source = oldSource; /* Back up source pointer! */ - target -= bytesToWrite; result = targetExhausted; break; - } - switch (bytesToWrite) { /* note: everything falls through. */ - case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]); - } - target += bytesToWrite; - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- */ - -/* - * Utility routine to tell whether a sequence of bytes is legal UTF-8. - * This must be called with the length pre-determined by the first byte. - * If not calling this from ConvertUTF8to*, then the length can be set by: - * length = trailingBytesForUTF8[*source]+1; - * and the sequence is illegal right away if there aren't that many bytes - * available. - * If presented with a length > 4, this returns false. The Unicode - * definition of UTF-8 goes up to 4-byte sequences. - */ - -static Boolean isLegalUTF8(const UTF8 *source, int length) { - UTF8 a; - const UTF8 *srcptr = source+length; - switch (length) { - default: return false; - /* Everything else falls through when "true"... */ - case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; - case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; - case 2: if ((a = (*--srcptr)) > 0xBF) return false; - - switch (*source) { - /* no fall-through in this inner switch */ - case 0xE0: if (a < 0xA0) return false; break; - case 0xED: if (a > 0x9F) return false; break; - case 0xF0: if (a < 0x90) return false; break; - case 0xF4: if (a > 0x8F) return false; break; - default: if (a < 0x80) return false; - } - - case 1: if (*source >= 0x80 && *source < 0xC2) return false; - } - if (*source > 0xF4) return false; - return true; -} - -/* --------------------------------------------------------------------- */ - -/* - * Exported function to return whether a UTF-8 sequence is legal or not. - * This is not used here; it's just exported. - */ -Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) { - int length = trailingBytesForUTF8[*source]+1; - if (source+length > sourceEnd) { - return false; - } - return isLegalUTF8(source, length); -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF8toUTF16 ( - const UTF8** sourceStart, const UTF8* sourceEnd, - UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF8* source = *sourceStart; - UTF16* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch = 0; - unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; - if (source + extraBytesToRead >= sourceEnd) { - result = sourceExhausted; break; - } - /* Do this check whether lenient or strict */ - if (! isLegalUTF8(source, extraBytesToRead+1)) { - result = sourceIllegal; - break; - } - /* - * The cases all fall through. See "Note A" below. - */ - switch (extraBytesToRead) { - case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ - case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ - case 3: ch += *source++; ch <<= 6; - case 2: ch += *source++; ch <<= 6; - case 1: ch += *source++; ch <<= 6; - case 0: ch += *source++; - } - ch -= offsetsFromUTF8[extraBytesToRead]; - - if (target >= targetEnd) { - source -= (extraBytesToRead+1); /* Back up source pointer! */ - result = targetExhausted; break; - } - if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - if (flags == strictConversion) { - source -= (extraBytesToRead+1); /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - *target++ = (UTF16)ch; /* normal case */ - } - } else if (ch > UNI_MAX_UTF16) { - if (flags == strictConversion) { - result = sourceIllegal; - source -= (extraBytesToRead+1); /* return to the start */ - break; /* Bail out; shouldn't continue */ - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - /* target is a character in range 0xFFFF - 0x10FFFF. */ - if (target + 1 >= targetEnd) { - source -= (extraBytesToRead+1); /* Back up source pointer! */ - result = targetExhausted; break; - } - ch -= halfBase; - *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START); - *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START); - } - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF32toUTF8 ( - const UTF32** sourceStart, const UTF32* sourceEnd, - UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF32* source = *sourceStart; - UTF8* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch; - unsigned short bytesToWrite = 0; - const UTF32 byteMask = 0xBF; - const UTF32 byteMark = 0x80; - ch = *source++; - if (flags == strictConversion ) { - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - --source; /* return to the illegal value itself */ - result = sourceIllegal; - break; - } - } - /* - * Figure out how many bytes the result will require. Turn any - * illegally large UTF32 things (> Plane 17) into replacement chars. - */ - if (ch < (UTF32)0x80) { bytesToWrite = 1; - } else if (ch < (UTF32)0x800) { bytesToWrite = 2; - } else if (ch < (UTF32)0x10000) { bytesToWrite = 3; - } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4; - } else { bytesToWrite = 3; - ch = UNI_REPLACEMENT_CHAR; - result = sourceIllegal; - } - - target += bytesToWrite; - if (target > targetEnd) { - --source; /* Back up source pointer! */ - target -= bytesToWrite; result = targetExhausted; break; - } - switch (bytesToWrite) { /* note: everything falls through. */ - case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6; - case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]); - } - target += bytesToWrite; - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- */ - -ConversionResult ConvertUTF8toUTF32 ( - const UTF8** sourceStart, const UTF8* sourceEnd, - UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) { - ConversionResult result = conversionOK; - const UTF8* source = *sourceStart; - UTF32* target = *targetStart; - while (source < sourceEnd) { - UTF32 ch = 0; - unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; - if (source + extraBytesToRead >= sourceEnd) { - result = sourceExhausted; break; - } - /* Do this check whether lenient or strict */ - if (! isLegalUTF8(source, extraBytesToRead+1)) { - result = sourceIllegal; - break; - } - /* - * The cases all fall through. See "Note A" below. - */ - switch (extraBytesToRead) { - case 5: ch += *source++; ch <<= 6; - case 4: ch += *source++; ch <<= 6; - case 3: ch += *source++; ch <<= 6; - case 2: ch += *source++; ch <<= 6; - case 1: ch += *source++; ch <<= 6; - case 0: ch += *source++; - } - ch -= offsetsFromUTF8[extraBytesToRead]; - - if (target >= targetEnd) { - source -= (extraBytesToRead+1); /* Back up the source pointer! */ - result = targetExhausted; break; - } - if (ch <= UNI_MAX_LEGAL_UTF32) { - /* - * UTF-16 surrogate values are illegal in UTF-32, and anything - * over Plane 17 (> 0x10FFFF) is illegal. - */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { - if (flags == strictConversion) { - source -= (extraBytesToRead+1); /* return to the illegal value itself */ - result = sourceIllegal; - break; - } else { - *target++ = UNI_REPLACEMENT_CHAR; - } - } else { - *target++ = ch; - } - } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */ - result = sourceIllegal; - *target++ = UNI_REPLACEMENT_CHAR; - } - } - *sourceStart = source; - *targetStart = target; - return result; -} - -/* --------------------------------------------------------------------- - - Note A. - The fall-through switches in UTF-8 reading code save a - temp variable, some decrements & conditionals. The switches - are equivalent to the following loop: - { - int tmpBytesToRead = extraBytesToRead+1; - do { - ch += *source++; - --tmpBytesToRead; - if (tmpBytesToRead) ch <<= 6; - } while (tmpBytesToRead > 0); - } - In UTF-8 writing code, the switches on "bytesToWrite" are - similarly unrolled loops. - - --------------------------------------------------------------------- */ diff --git a/contrib/ConvertUTF/ConvertUTF.h b/contrib/ConvertUTF/ConvertUTF.h deleted file mode 100644 index 05e800ad8..000000000 --- a/contrib/ConvertUTF/ConvertUTF.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2001-2004 Unicode, Inc. - * - * Disclaimer - * - * This source code is provided as is by Unicode, Inc. No claims are - * made as to fitness for any particular purpose. No warranties of any - * kind are expressed or implied. The recipient agrees to determine - * applicability of information provided. If this file has been - * purchased on magnetic or optical media from Unicode, Inc., the - * sole remedy for any claim will be exchange of defective media - * within 90 days of receipt. - * - * Limitations on Rights to Redistribute This Code - * - * Unicode, Inc. hereby grants the right to freely use the information - * supplied in this file in the creation of products supporting the - * Unicode Standard, and to make copies of this file in any form - * for internal or external distribution as long as this notice - * remains attached. - */ -#ifndef CONVERTUTF_H -#define CONVERTUTF_H -/* --------------------------------------------------------------------- - - Conversions between UTF32, UTF-16, and UTF-8. Header file. - - Several funtions are included here, forming a complete set of - conversions between the three formats. UTF-7 is not included - here, but is handled in a separate source file. - - Each of these routines takes pointers to input buffers and output - buffers. The input buffers are const. - - Each routine converts the text between *sourceStart and sourceEnd, - putting the result into the buffer between *targetStart and - targetEnd. Note: the end pointers are *after* the last item: e.g. - *(sourceEnd - 1) is the last item. - - The return result indicates whether the conversion was successful, - and if not, whether the problem was in the source or target buffers. - (Only the first encountered problem is indicated.) - - After the conversion, *sourceStart and *targetStart are both - updated to point to the end of last text successfully converted in - the respective buffers. - - Input parameters: - sourceStart - pointer to a pointer to the source buffer. - The contents of this are modified on return so that - it points at the next thing to be converted. - targetStart - similarly, pointer to pointer to the target buffer. - sourceEnd, targetEnd - respectively pointers to the ends of the - two buffers, for overflow checking only. - - These conversion functions take a ConversionFlags argument. When this - flag is set to strict, both irregular sequences and isolated surrogates - will cause an error. When the flag is set to lenient, both irregular - sequences and isolated surrogates are converted. - - Whether the flag is strict or lenient, all illegal sequences will cause - an error return. This includes sequences such as: , , - or in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code - must check for illegal sequences. - - When the flag is set to lenient, characters over 0x10FFFF are converted - to the replacement character; otherwise (when the flag is set to strict) - they constitute an error. - - Output parameters: - The value "sourceIllegal" is returned from some routines if the input - sequence is malformed. When "sourceIllegal" is returned, the source - value will point to the illegal value that caused the problem. E.g., - in UTF-8 when a sequence is malformed, it points to the start of the - malformed sequence. - - Author: Mark E. Davis, 1994. - Rev History: Rick McGowan, fixes & updates May 2001. - Fixes & updates, Sept 2001. - ------------------------------------------------------------------------- */ - -/* --------------------------------------------------------------------- - The following 4 definitions are compiler-specific. - The C standard does not guarantee that wchar_t has at least - 16 bits, so wchar_t is no less portable than unsigned short! - All should be unsigned values to avoid sign extension during - bit mask & shift operations. ------------------------------------------------------------------------- */ - -typedef unsigned long UTF32; /* at least 32 bits */ -typedef unsigned short UTF16; /* at least 16 bits */ -typedef unsigned char UTF8; /* typically 8 bits */ -typedef unsigned char Boolean; /* 0 or 1 */ - -/* Some fundamental constants */ -#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD -#define UNI_MAX_BMP (UTF32)0x0000FFFF -#define UNI_MAX_UTF16 (UTF32)0x0010FFFF -#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF -#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF - -typedef enum { - conversionOK, /* conversion successful */ - sourceExhausted, /* partial character in source, but hit end */ - targetExhausted, /* insuff. room in target for conversion */ - sourceIllegal /* source sequence is illegal/malformed */ -} ConversionResult; - -typedef enum { - strictConversion = 0, - lenientConversion -} ConversionFlags; - -/* This is for C++ and does no harm in C */ -#ifdef __cplusplus -extern "C" { -#endif - -ConversionResult ConvertUTF8toUTF16 ( - const UTF8** sourceStart, const UTF8* sourceEnd, - UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); - -ConversionResult ConvertUTF16toUTF8 ( - const UTF16** sourceStart, const UTF16* sourceEnd, - UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); - -ConversionResult ConvertUTF8toUTF32 ( - const UTF8** sourceStart, const UTF8* sourceEnd, - UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); - -ConversionResult ConvertUTF32toUTF8 ( - const UTF32** sourceStart, const UTF32* sourceEnd, - UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); - -ConversionResult ConvertUTF16toUTF32 ( - const UTF16** sourceStart, const UTF16* sourceEnd, - UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags); - -ConversionResult ConvertUTF32toUTF16 ( - const UTF32** sourceStart, const UTF32* sourceEnd, - UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags); - -Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); - -#ifdef __cplusplus -} -#endif - -/* --------------------------------------------------------------------- */ -#endif // CONVERTUTF_H diff --git a/contrib/ConvertUTF/readme.txt b/contrib/ConvertUTF/readme.txt deleted file mode 100644 index b9f17fb81..000000000 --- a/contrib/ConvertUTF/readme.txt +++ /dev/null @@ -1,43 +0,0 @@ - -The accompanying C source code file "ConvertUTF.c" and the associated header -file "ConvertUTF.h" provide for conversion between various transformation -formats of Unicode characters. The following conversions are supported: - - UTF-32 to UTF-16 - UTF-32 to UTF-8 - UTF-16 to UTF-32 - UTF-16 to UTF-8 - UTF-8 to UTF-16 - UTF-8 to UTF-32 - -In addition, there is a test harness which runs various tests. - -The files "CVTUTF7.C" and "CVTUTF7.H" are for archival and historical purposes -only. They have not been updated to Unicode 3.0 or later and should be -considered obsolescent. "CVTUTF7.C" contains two functions that can convert -between UCS2 (i.e., the BMP characters only) and UTF-7. Surrogates are -not supported, the code has not been tested, and should be considered -unsuitable for general purpose use. - -Please submit any bug reports about these programs here: - - http://www.unicode.org/unicode/reporting.html - -Version 1.0: initial version. - -Version 1.1: corrected some minor problems; added stricter checks. - -Version 1.2: corrected switch statements associated with "extraBytesToRead" - in 4 & 5 byte cases, in functions for conversion from UTF8. - Note: formally, the 4 & 5 byte cases are illegal in the latest - UTF8, but the table and this code has always catered for those, - cases since at one time they were legal. - -Version 1.3: Updated UTF-8 legality check; - updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions - Updated UTF-8 legality tests in harness.c - - -Last update: October 19, 2004 - - diff --git a/contrib/Open3DGC/o3dgcAdjacencyInfo.h b/contrib/Open3DGC/o3dgcAdjacencyInfo.h index 6b53a242d..72fe3d4c6 100644 --- a/contrib/Open3DGC/o3dgcAdjacencyInfo.h +++ b/contrib/Open3DGC/o3dgcAdjacencyInfo.h @@ -140,8 +140,8 @@ namespace o3dgc { return End(element) - Begin(element); } - long * const GetNumNeighborsBuffer() { return m_numNeighbors;} - long * const GetNeighborsBuffer() { return m_neighbors;} + long * GetNumNeighborsBuffer() { return m_numNeighbors;} + long * GetNeighborsBuffer() { return m_neighbors;} private: long m_neighborsSize; // actual allocated size for m_neighbors diff --git a/contrib/Open3DGC/o3dgcArithmeticCodec.cpp b/contrib/Open3DGC/o3dgcArithmeticCodec.cpp index 1d160ba95..3597ec39a 100644 --- a/contrib/Open3DGC/o3dgcArithmeticCodec.cpp +++ b/contrib/Open3DGC/o3dgcArithmeticCodec.cpp @@ -820,6 +820,7 @@ namespace o3dgc for (unsigned n = 0; n < data_symbols; n++) total_count += (symbol_count[n] = (symbol_count[n] + 1) >> 1); } + assert(total_count > 0); // compute cumulative distribution, decoder table unsigned k, sum = 0, s = 0; unsigned scale = 0x80000000U / total_count; @@ -830,6 +831,7 @@ namespace o3dgc sum += symbol_count[k]; } else { + assert(decoder_table); for (k = 0; k < data_symbols; k++) { distribution[k] = (scale * sum) >> (31 - DM__LengthShift); sum += symbol_count[k]; diff --git a/contrib/Open3DGC/o3dgcBinaryStream.h b/contrib/Open3DGC/o3dgcBinaryStream.h index 9f4aefe55..b7b7678b7 100644 --- a/contrib/Open3DGC/o3dgcBinaryStream.h +++ b/contrib/Open3DGC/o3dgcBinaryStream.h @@ -231,7 +231,8 @@ namespace o3dgc float ReadFloat32Bin(unsigned long & position) const { unsigned long value = ReadUInt32Bin(position); - float fvalue = *((float *)(&value)); + float fvalue; + memcpy(&fvalue, &value, 4); return fvalue; } unsigned long ReadUInt32Bin(unsigned long & position) const @@ -261,7 +262,8 @@ namespace o3dgc void WriteFloat32ASCII(float value) { - unsigned long uiValue = *((unsigned long *)(&value)); + unsigned long uiValue; + memcpy(&uiValue, &value, 4); WriteUInt32ASCII(uiValue); } void WriteUInt32ASCII(unsigned long position, unsigned long value) @@ -314,7 +316,8 @@ namespace o3dgc float ReadFloat32ASCII(unsigned long & position) const { unsigned long value = ReadUInt32ASCII(position); - float fvalue = *((float *)(&value)); + float fvalue; + memcpy(&fvalue, &value, 4); return fvalue; } unsigned long ReadUInt32ASCII(unsigned long & position) const @@ -395,15 +398,15 @@ namespace o3dgc { return m_stream.GetSize(); } - const unsigned char * const GetBuffer(unsigned long position) const + const unsigned char * GetBuffer(unsigned long position) const { return m_stream.GetBuffer() + position; } - unsigned char * const GetBuffer(unsigned long position) + unsigned char * GetBuffer(unsigned long position) { return (m_stream.GetBuffer() + position); } - unsigned char * const GetBuffer() + unsigned char * GetBuffer() { return m_stream.GetBuffer(); } diff --git a/contrib/Open3DGC/o3dgcDynamicVector.h b/contrib/Open3DGC/o3dgcDynamicVector.h index edc97d83c..aa7fb3142 100644 --- a/contrib/Open3DGC/o3dgcDynamicVector.h +++ b/contrib/Open3DGC/o3dgcDynamicVector.h @@ -48,10 +48,10 @@ namespace o3dgc unsigned long GetNVector() const { return m_num;} unsigned long GetDimVector() const { return m_dim;} unsigned long GetStride() const { return m_stride;} - const Real * const GetMin() const { return m_min;} - const Real * const GetMax() const { return m_max;} - const Real * const GetVectors() const { return m_vectors;} - Real * const GetVectors() { return m_vectors;} + const Real * GetMin() const { return m_min;} + const Real * GetMax() const { return m_max;} + const Real * GetVectors() const { return m_vectors;} + Real * GetVectors() { return m_vectors;} Real GetMin(unsigned long j) const { return m_min[j];} Real GetMax(unsigned long j) const { return m_max[j];} diff --git a/contrib/Open3DGC/o3dgcFIFO.h b/contrib/Open3DGC/o3dgcFIFO.h index 874c26475..4a5555f2a 100644 --- a/contrib/Open3DGC/o3dgcFIFO.h +++ b/contrib/Open3DGC/o3dgcFIFO.h @@ -81,8 +81,8 @@ namespace o3dgc m_end = 0; } } - const unsigned long GetSize() const { return m_size;}; - const unsigned long GetAllocatedSize() const { return m_allocated;}; + unsigned long GetSize() const { return m_size;}; + unsigned long GetAllocatedSize() const { return m_allocated;}; void Clear() { m_start = m_end = m_size = 0;}; private: diff --git a/contrib/Open3DGC/o3dgcIndexedFaceSet.h b/contrib/Open3DGC/o3dgcIndexedFaceSet.h index 4af9de437..adb8cb001 100644 --- a/contrib/Open3DGC/o3dgcIndexedFaceSet.h +++ b/contrib/Open3DGC/o3dgcIndexedFaceSet.h @@ -62,26 +62,26 @@ namespace o3dgc } unsigned long GetNumFloatAttributes() const { return m_numFloatAttributes;} unsigned long GetNumIntAttributes() const { return m_numIntAttributes ;} - const Real * const GetCoordMin () const { return m_coordMin;} - const Real * const GetCoordMax () const { return m_coordMax;} - const Real * const GetNormalMin () const { return m_normalMin;} - const Real * const GetNormalMax () const { return m_normalMax;} + const Real * GetCoordMin () const { return m_coordMin;} + const Real * GetCoordMax () const { return m_coordMax;} + const Real * GetNormalMin () const { return m_normalMin;} + const Real * GetNormalMax () const { return m_normalMax;} Real GetCoordMin (int j) const { return m_coordMin[j] ;} Real GetCoordMax (int j) const { return m_coordMax[j] ;} Real GetNormalMin (int j) const { return m_normalMin[j] ;} Real GetNormalMax (int j) const { return m_normalMax[j] ;} - const O3DGCIFSFloatAttributeType GetFloatAttributeType(unsigned long a) const + O3DGCIFSFloatAttributeType GetFloatAttributeType(unsigned long a) const { assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES); return m_typeFloatAttribute[a]; } - const O3DGCIFSIntAttributeType GetIntAttributeType(unsigned long a) const + O3DGCIFSIntAttributeType GetIntAttributeType(unsigned long a) const { assert(a < O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES); return m_typeIntAttribute[a]; } - const unsigned long GetFloatAttributeDim(unsigned long a) const + unsigned long GetFloatAttributeDim(unsigned long a) const { assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES); return m_dimFloatAttribute[a]; @@ -91,12 +91,12 @@ namespace o3dgc assert(a < O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES); return m_dimIntAttribute[a]; } - const Real * const GetFloatAttributeMin(unsigned long a) const + const Real * GetFloatAttributeMin(unsigned long a) const { assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES); return &(m_minFloatAttribute[a * O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES]); } - const Real * const GetFloatAttributeMax(unsigned long a) const + const Real * GetFloatAttributeMax(unsigned long a) const { assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES); return &(m_maxFloatAttribute[a * O3DGC_SC3DMC_MAX_DIM_ATTRIBUTES]); @@ -118,17 +118,17 @@ namespace o3dgc bool GetSolid() const { return m_solid ;} bool GetConvex() const { return m_convex ;} bool GetIsTriangularMesh() const { return m_isTriangularMesh;} - const unsigned long * const GetIndexBufferID() const { return m_indexBufferID ;} - const T * const GetCoordIndex() const { return m_coordIndex;} - T * const GetCoordIndex() { return m_coordIndex;} - Real * const GetCoord() const { return m_coord ;} - Real * const GetNormal() const { return m_normal ;} - Real * const GetFloatAttribute(unsigned long a) const + const unsigned long * GetIndexBufferID() const { return m_indexBufferID ;} + const T * GetCoordIndex() const { return m_coordIndex;} + T * GetCoordIndex() { return m_coordIndex;} + Real * GetCoord() const { return m_coord ;} + Real * GetNormal() const { return m_normal ;} + Real * GetFloatAttribute(unsigned long a) const { assert(a < O3DGC_SC3DMC_MAX_NUM_FLOAT_ATTRIBUTES); return m_floatAttribute[a]; } - long * const GetIntAttribute(unsigned long a) const + long * GetIntAttribute(unsigned long a) const { assert(a < O3DGC_SC3DMC_MAX_NUM_INT_ATTRIBUTES); return m_intAttribute[a] ; diff --git a/contrib/Open3DGC/o3dgcSC3DMCDecoder.inl b/contrib/Open3DGC/o3dgcSC3DMCDecoder.inl index d36b62f2b..aa6f24b73 100644 --- a/contrib/Open3DGC/o3dgcSC3DMCDecoder.inl +++ b/contrib/Open3DGC/o3dgcSC3DMCDecoder.inl @@ -425,7 +425,7 @@ namespace o3dgc const AdjacencyInfo & v2T = m_triangleListDecoder.GetVertexToTriangle(); const T * const triangles = ifs.GetCoordIndex(); Vec3 p1, p2, p3, n0, nt; - long na0, nb0; + long na0 = 0, nb0 = 0; Real rna0, rnb0, norm0; char ni0 = 0, ni1 = 0; long a, b, c; diff --git a/contrib/Open3DGC/o3dgcSC3DMCEncoder.inl b/contrib/Open3DGC/o3dgcSC3DMCEncoder.inl index b2c438814..2d30b05a2 100644 --- a/contrib/Open3DGC/o3dgcSC3DMCEncoder.inl +++ b/contrib/Open3DGC/o3dgcSC3DMCEncoder.inl @@ -762,8 +762,8 @@ namespace o3dgc const Real * const originalNormals = ifs.GetNormal(); Vec3 p1, p2, p3, n0, nt; Vec3 n1; - long na0, nb0; - Real rna0, rnb0, na1, nb1, norm0, norm1; + long na0 = 0, nb0 = 0; + Real rna0, rnb0, na1 = 0, nb1 = 0, norm0, norm1; char ni0 = 0, ni1 = 0; long a, b, c, v; m_predictors.Clear(); diff --git a/contrib/Open3DGC/o3dgcTriangleListEncoder.h b/contrib/Open3DGC/o3dgcTriangleListEncoder.h index cf790ecc3..c09172273 100644 --- a/contrib/Open3DGC/o3dgcTriangleListEncoder.h +++ b/contrib/Open3DGC/o3dgcTriangleListEncoder.h @@ -50,10 +50,10 @@ namespace o3dgc BinaryStream & bstream); O3DGCStreamType GetStreamType() const { return m_streamType; } void SetStreamType(O3DGCStreamType streamType) { m_streamType = streamType; } - const long * const GetInvVMap() const { return m_invVMap;} - const long * const GetInvTMap() const { return m_invTMap;} - const long * const GetVMap() const { return m_vmap;} - const long * const GetTMap() const { return m_tmap;} + const long * GetInvVMap() const { return m_invVMap;} + const long * GetInvTMap() const { return m_invTMap;} + const long * GetVMap() const { return m_vmap;} + const long * GetTMap() const { return m_tmap;} const AdjacencyInfo & GetVertexToTriangle() const { return m_vertexToTriangle;} private: diff --git a/contrib/Open3DGC/o3dgcTriangleListEncoder.inl b/contrib/Open3DGC/o3dgcTriangleListEncoder.inl index d499f6dc9..017dd86bf 100644 --- a/contrib/Open3DGC/o3dgcTriangleListEncoder.inl +++ b/contrib/Open3DGC/o3dgcTriangleListEncoder.inl @@ -125,7 +125,7 @@ namespace o3dgc } return true; } - inline bool IsCase6(long degree, long numIndices, const long * const ops, const long * const indices) + inline bool IsCase6(long degree, long numIndices, const long * const ops, const long * const /*indices*/) { // ops: 0000000 indices: if (numIndices!= 0) diff --git a/contrib/Open3DGC/o3dgcVector.h b/contrib/Open3DGC/o3dgcVector.h index e766e2b7f..08d3ed564 100644 --- a/contrib/Open3DGC/o3dgcVector.h +++ b/contrib/Open3DGC/o3dgcVector.h @@ -88,8 +88,8 @@ namespace o3dgc assert(m_size < m_allocated); m_buffer[m_size++] = value; } - const T * const GetBuffer() const { return m_buffer;}; - T * const GetBuffer() { return m_buffer;}; + const T * GetBuffer() const { return m_buffer;}; + T * GetBuffer() { return m_buffer;}; unsigned long GetSize() const { return m_size;}; void SetSize(unsigned long size) { diff --git a/contrib/android-cmake/AndroidNdkGdb.cmake b/contrib/android-cmake/AndroidNdkGdb.cmake new file mode 100644 index 000000000..0677dcda9 --- /dev/null +++ b/contrib/android-cmake/AndroidNdkGdb.cmake @@ -0,0 +1,96 @@ +# Copyright (c) 2014, Pavel Rojtberg +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. 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. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# 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 HOLDER 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. + +# ------------------------------------------------------------------------------ +# Usage: +# 1. place AndroidNdkGdb.cmake somewhere inside ${CMAKE_MODULE_PATH} +# 2. inside your project add +# +# include(AndroidNdkGdb) +# android_ndk_gdb_enable() +# # for each target +# add_library(MyLibrary ...) +# android_ndk_gdb_debuggable(MyLibrary) + + +# add gdbserver and general gdb configuration to project +# also create a mininal NDK skeleton so ndk-gdb finds the paths +# +# the optional parameter defines the path to the android project. +# uses PROJECT_SOURCE_DIR by default. +macro(android_ndk_gdb_enable) + if(ANDROID) + # create custom target that depends on the real target so it gets executed afterwards + add_custom_target(NDK_GDB ALL) + + if(${ARGC}) + set(ANDROID_PROJECT_DIR ${ARGV0}) + else() + set(ANDROID_PROJECT_DIR ${PROJECT_SOURCE_DIR}) + endif() + + set(NDK_GDB_SOLIB_PATH ${ANDROID_PROJECT_DIR}/obj/local/${ANDROID_NDK_ABI_NAME}/) + file(MAKE_DIRECTORY ${NDK_GDB_SOLIB_PATH}) + + # 1. generate essential Android Makefiles + file(MAKE_DIRECTORY ${ANDROID_PROJECT_DIR}/jni) + if(NOT EXISTS ${ANDROID_PROJECT_DIR}/jni/Android.mk) + file(WRITE ${ANDROID_PROJECT_DIR}/jni/Android.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n") + endif() + if(NOT EXISTS ${ANDROID_PROJECT_DIR}/jni/Application.mk) + file(WRITE ${ANDROID_PROJECT_DIR}/jni/Application.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n") + endif() + + # 2. generate gdb.setup + get_directory_property(PROJECT_INCLUDES DIRECTORY ${PROJECT_SOURCE_DIR} INCLUDE_DIRECTORIES) + string(REGEX REPLACE ";" " " PROJECT_INCLUDES "${PROJECT_INCLUDES}") + file(WRITE ${LIBRARY_OUTPUT_PATH}/gdb.setup "set solib-search-path ${NDK_GDB_SOLIB_PATH}\n") + file(APPEND ${LIBRARY_OUTPUT_PATH}/gdb.setup "directory ${PROJECT_INCLUDES}\n") + + # 3. copy gdbserver executable + file(COPY ${ANDROID_NDK}/prebuilt/android-${ANDROID_ARCH_NAME}/gdbserver/gdbserver DESTINATION ${LIBRARY_OUTPUT_PATH}) + endif() +endmacro() + +# register a target for remote debugging +# copies the debug version to NDK_GDB_SOLIB_PATH then strips symbols of original +macro(android_ndk_gdb_debuggable TARGET_NAME) + if(ANDROID) + get_property(TARGET_LOCATION TARGET ${TARGET_NAME} PROPERTY LOCATION) + + # create custom target that depends on the real target so it gets executed afterwards + add_dependencies(NDK_GDB ${TARGET_NAME}) + + # 4. copy lib to obj + add_custom_command(TARGET NDK_GDB POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${TARGET_LOCATION} ${NDK_GDB_SOLIB_PATH}) + + # 5. strip symbols + add_custom_command(TARGET NDK_GDB POST_BUILD COMMAND ${CMAKE_STRIP} ${TARGET_LOCATION}) + endif() +endmacro() diff --git a/contrib/android-cmake/AndroidNdkModules.cmake b/contrib/android-cmake/AndroidNdkModules.cmake new file mode 100644 index 000000000..64f37fdee --- /dev/null +++ b/contrib/android-cmake/AndroidNdkModules.cmake @@ -0,0 +1,58 @@ +# Copyright (c) 2014, Pavel Rojtberg +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. 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. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# 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 HOLDER 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. + +macro(android_ndk_import_module_cpufeatures) + if(ANDROID) + include_directories(${ANDROID_NDK}/sources/android/cpufeatures) + add_library(cpufeatures ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c) + target_link_libraries(cpufeatures dl) + endif() +endmacro() + +macro(android_ndk_import_module_native_app_glue) + if(ANDROID) + include_directories(${ANDROID_NDK}/sources/android/native_app_glue) + add_library(native_app_glue ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c) + target_link_libraries(native_app_glue log) + endif() +endmacro() + +macro(android_ndk_import_module_ndk_helper) + if(ANDROID) + android_ndk_import_module_cpufeatures() + android_ndk_import_module_native_app_glue() + + include_directories(${ANDROID_NDK}/sources/android/ndk_helper) + file(GLOB _NDK_HELPER_SRCS ${ANDROID_NDK}/sources/android/ndk_helper/*.cpp ${ANDROID_NDK}/sources/android/ndk_helper/gl3stub.c) + add_library(ndk_helper ${_NDK_HELPER_SRCS}) + target_link_libraries(ndk_helper log android EGL GLESv2 cpufeatures native_app_glue) + + unset(_NDK_HELPER_SRCS) + endif() +endmacro() \ No newline at end of file diff --git a/contrib/android-cmake/README.md b/contrib/android-cmake/README.md new file mode 100644 index 000000000..ee6302128 --- /dev/null +++ b/contrib/android-cmake/README.md @@ -0,0 +1,240 @@ +# android-cmake + +CMake is great, and so is Android. This is a collection of CMake scripts that may be useful to the Android NDK community. It is based on experience from porting OpenCV library to Android: http://opencv.org/platforms/android.html + +Main goal is to share these scripts so that devs that use CMake as their build system may easily compile native code for Android. + +## TL;DR + + cmake -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake \ + -DANDROID_NDK= \ + -DCMAKE_BUILD_TYPE=Release \ + -DANDROID_ABI="armeabi-v7a with NEON" \ + + cmake --build . + +One-liner: + + cmake -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake -DANDROID_NDK= -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="armeabi-v7a with NEON" && cmake --build . + +_android-cmake_ will search for your NDK install in the following order: + +1. Value of `ANDROID_NDK` CMake variable; +1. Value of `ANDROID_NDK` environment variable; +1. Search under paths from `ANDROID_NDK_SEARCH_PATHS` CMake variable; +1. Search platform specific locations (home folder, Windows "Program Files", etc). + +So if you have installed the NDK as `~/android-ndk-r10d` then _android-cmake_ will locate it automatically. + +## Getting started + +To build a cmake-based C/C++ project for Android you need: + +* Android NDK (>= r5) http://developer.android.com/tools/sdk/ndk/index.html +* CMake (>= v2.6.3, >= v2.8.9 recommended) http://www.cmake.org/download + +The _android-cmake_ is also capable to build with NDK from AOSP or Linaro Android source tree, but you may be required to manually specify path to `libm` binary to link with. + +## Difference from traditional CMake + +Folowing the _ndk-build_ the _android-cmake_ supports **only two build targets**: + +* `-DCMAKE_BUILD_TYPE=Release` +* `-DCMAKE_BUILD_TYPE=Debug` + +So don't even try other targets that can be found in CMake documentation and don't forget to explicitly specify `Release` or `Debug` because CMake builds without a build configuration by default. + +## Difference from _ndk-build_ + +* Latest GCC available in NDK is used as the default compiler; +* `Release` builds with `-O3` instead of `-Os`; +* `Release` builds without debug info (without `-g`) (because _ndk-build_ always creates a stripped version but cmake delays this for `install/strip` target); +* `-fsigned-char` is added to compiler flags to make `char` signed by default as it is on x86/x86_64; +* GCC's stack protector is not used neither in `Debug` nor `Release` configurations; +* No builds for multiple platforms (e.g. building for both arm and x86 require to run cmake twice with different parameters); +* No file level Neon via `.neon` suffix; + +The following features of _ndk-build_ are not supported by the _android-cmake_ yet: + +* `armeabi-v7a-hard` ABI +* `libc++_static`/`libc++_shared` STL runtime + +## Basic options + +Similarly to the NDK build system _android-cmake_ allows to select between several compiler toolchains and target platforms. Most of the options can be set either as cmake arguments: `-D=` or as environment variables: + +* **ANDROID_NDK** - path to the Android NDK. If not set then _android-cmake_ will search for the most recent version of supported NDK in commonly used locations; +* **ANDROID_ABI** - specifies the target Application Binary Interface (ABI). This option nearly matches to the APP_ABI variable used by ndk-build tool from Android NDK. If not specified then set to `armeabi-v7a`. Possible target names are: + * `armeabi` - ARMv5TE based CPU with software floating point operations; + * **`armeabi-v7a`** - ARMv7 based devices with hardware FPU instructions (VFPv3_D16); + * `armeabi-v7a with NEON` - same as armeabi-v7a, but sets NEON as floating-point unit; + * `armeabi-v7a with VFPV3` - same as armeabi-v7a, but sets VFPv3_D32 as floating-point unit; + * `armeabi-v6 with VFP` - tuned for ARMv6 processors having VFP; + * `x86` - IA-32 instruction set + * `mips` - MIPS32 instruction set + * `arm64-v8a` - ARMv8 AArch64 instruction set - only for NDK r10 and newer + * `x86_64` - Intel64 instruction set (r1) - only for NDK r10 and newer + * `mips64` - MIPS64 instruction set (r6) - only for NDK r10 and newer +* **ANDROID_NATIVE_API_LEVEL** - level of android API to build for. Can be set either to full name (example: `android-8`) or a numeric value (example: `17`). The default API level depends on the target ABI: + * `android-8` for ARM; + * `android-9` for x86 and MIPS; + * `android-21` for 64-bit ABIs. + + Building for `android-L` is possible only when it is explicitly selected. +* **ANDROID_TOOLCHAIN_NAME** - the name of compiler toolchain to be used. This option allows to select between different GCC and Clang versions. The list of possible values depends on the NDK version and will be printed by toolchain file if an invalid value is set. By default _android-cmake_ selects the most recent version of GCC which can build for specified `ANDROID_ABI`. + + Example values are: + * `aarch64-linux-android-4.9` + * `aarch64-linux-android-clang3.5` + * `arm-linux-androideabi-4.8` + * `arm-linux-androideabi-4.9` + * `arm-linux-androideabi-clang3.5` + * `mips64el-linux-android-4.9` + * `mipsel-linux-android-4.8` + * `x86-4.9` + * `x86_64-4.9` + * etc. +* **ANDROID_STL** - the name of C++ runtime to use. The default is `gnustl_static`. + * `none` - do not configure the runtime. + * `system` - use the default minimal system C++ runtime library. + * Implies `-fno-rtti -fno-exceptions`. + * `system_re` - use the default minimal system C++ runtime library. + * Implies `-frtti -fexceptions`. + * `gabi++_static` - use the GAbi++ runtime as a static library. + * Implies `-frtti -fno-exceptions`. + * Available for NDK r7 and newer. + * `gabi++_shared` - use the GAbi++ runtime as a shared library. + * Implies `-frtti -fno-exceptions`. + * Available for NDK r7 and newer. + * `stlport_static` - use the STLport runtime as a static library. + * Implies `-fno-rtti -fno-exceptions` for NDK before r7. + * Implies `-frtti -fno-exceptions` for NDK r7 and newer. + * `stlport_shared` - use the STLport runtime as a shared library. + * Implies `-fno-rtti -fno-exceptions` for NDK before r7. + * Implies `-frtti -fno-exceptions` for NDK r7 and newer. + * **`gnustl_static`** - use the GNU STL as a static library. + * Implies `-frtti -fexceptions`. + * `gnustl_shared` - use the GNU STL as a shared library. + * Implies `-frtti -fno-exceptions`. + * Available for NDK r7b and newer. + * Silently degrades to `gnustl_static` if not available. +* **NDK_CCACHE** - path to `ccache` executable. If not set then initialized from `NDK_CCACHE` environment variable. + +## Advanced _android-cmake_ options + +Normally _android-cmake_ users are not supposed to touch these variables but they might be useful to workaround some build issues: + +* **ANDROID_FORCE_ARM_BUILD** = `OFF` - generate 32-bit ARM instructions instead of Thumb. Applicable only for arm ABIs and is forced to be `ON` for `armeabi-v6 with VFP`; +* **ANDROID_NO_UNDEFINED** = `ON` - show all undefined symbols as linker errors; +* **ANDROID_SO_UNDEFINED** = `OFF` - allow undefined symbols in shared libraries; + * actually it is turned `ON` by default for NDK older than `r7` +* **ANDROID_STL_FORCE_FEATURES** = `ON` - automatically configure rtti and exceptions support based on C++ runtime; +* **ANDROID_NDK_LAYOUT** = `RELEASE` - inner layout of Android NDK, should be detected automatically. Possible values are: + * `RELEASE` - public releases from Google; + * `LINARO` - NDK from Linaro project; + * `ANDROID` - NDK from AOSP. +* **ANDROID_FUNCTION_LEVEL_LINKING** = `ON` - enables saparate putting each function and data items into separate sections and enable garbage collection of unused input sections at link time (`-fdata-sections -ffunction-sections -Wl,--gc-sections`); +* **ANDROID_GOLD_LINKER** = `ON` - use gold linker with GCC 4.6 for NDK r8b and newer (only for ARM and x86); +* **ANDROID_NOEXECSTACK** = `ON` - enables or disables stack execution protection code (`-Wl,-z,noexecstack`); +* **ANDROID_RELRO** = `ON` - Enables RELRO - a memory corruption mitigation technique (`-Wl,-z,relro -Wl,-z,now`); +* **ANDROID_LIBM_PATH** - path to `libm.so` (set to something like `$(TOP)/out/target/product//obj/lib/libm.so`) to workaround unresolved `sincos`. + +## Fine-tuning `CMakeLists.txt` for _android-cmake_ + +### Recognizing Android build + +_android-cmake_ defines `ANDROID` CMake variable which can be used to add Android-specific stuff: + + if (ANDROID) + message(STATUS "Hello from Android build!") + endif() + +The recommended way to identify ARM/MIPS/x86 architecture is examining `CMAKE_SYSTEM_PROCESSOR` which is set to the appropriate value: + +* `armv5te` - for `armeabi` ABI +* `armv6` - for `armeabi-v6 with VFP` ABI +* `armv7-a` - for `armeabi-v7a`, `armeabi-v7a with VFPV3` and `armeabi-v7a with NEON` ABIs +* `aarch64` - for `arm64-v8a` ABI +* `i686` - for `x86` ABI +* `x86_64` - for `x86_64` ABI +* `mips` - for `mips` ABI +* `mips64` - for `mips64` ABI + +Other variables that are set by _android-cmake_ and can be used for the fine-grained build configuration are: + +* `NEON` - set if target ABI supports Neon; +* `ANDROID_NATIVE_API_LEVEL` - native Android API level we are building for (note: Java part of Andoid application can be built for another API level) +* `ANDROID_NDK_RELEASE` - version of the Android NDK +* `ANDROID_NDK_HOST_SYSTEM_NAME` - "windows", "linux-x86" or "darwin-x86" depending on the host platform +* `ANDROID_RTTI` - set if rtti is enabled by the runtime +* `ANDROID_EXCEPTIONS` - set if exceptions are enabled by the runtime + +### Finding packages + +When crosscompiling CMake `find_*` commands are normally expected to find libraries and packages belonging to the same build target. So _android-cmake_ configures CMake to search in Android-specific paths only and ignore your host system locations. So + + find_package(ZLIB) + +will surely find libz.so within the Android NDK. + +However sometimes you need to locate a host package even when cross-compiling. For example you can be searching for your documentation generator. The _android-cmake_ recommends you to use `find_host_package` and `find_host_program` macro defined in the `android.toolchain.cmake`: + + find_host_package(Doxygen) + find_host_program(PDFLATEX pdflatex) + +However this will break regular builds so instead of wrapping package search into platform-specific logic you can copy the following snippet into your project (put it after your top-level `project()` command): + + # Search packages for host system instead of packages for target system + # in case of cross compilation these macro should be defined by toolchain file + if(NOT COMMAND find_host_package) + macro(find_host_package) + find_package(${ARGN}) + endmacro() + endif() + if(NOT COMMAND find_host_program) + macro(find_host_program) + find_program(${ARGN}) + endmacro() + endif() + +### Compiler flags recycling + +Make sure to do the following in your scripts: + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}") + +The flags will be prepopulated with critical flags, so don't loose them. Also be aware that _android-cmake_ also sets configuration-specific compiler and linker flags. + +## Troubleshooting + +### Building on Windows + +First of all `cygwin` builds are **NOT supported** and will not be supported by _android-cmake_. To build natively on Windows you need a port of make but I recommend http://martine.github.io/ninja/ instead. + +To build with Ninja you need: + +* Ensure you are using CMake newer than 2.8.9; +* Download the latest Ninja from https://github.com/martine/ninja/releases; +* Put the `ninja.exe` into your PATH (or add path to `ninja.exe` to your PATH environment variable); +* Pass `-GNinja` to `cmake` alongside with other arguments (or choose Ninja generator in `cmake-gui`). +* Enjoy the fast native multithreaded build :) + +But if you still want to stick to old make then: + +* Get a Windows port of GNU Make: + * Android NDK r7 (and newer) already has `make.exe` on board; + * `mingw-make` should work as fine; + * Download some other port. For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm. +* Add path to your `make.exe` to system PATH or always use full path; +* Pass `-G"MinGW Makefiles"` and `-DCMAKE_MAKE_PROGRAM="make.exe"` + * It must be `MinGW Makefiles` and not `Unix Makefiles` even if your `make.exe` is not a MinGW's make. +* Run `make.exe` or `cmake --build .` for single-threaded build. + +### Projects with assembler files + +The _android-cmake_ should correctly handle projects with assembler sources (`*.s` or `*.S`). But if you still facing problems with assembler then try to upgrade your CMake to version newer than 2.8.5 + +## Copying + +_android-cmake_ is distributed under the terms of [BSD 3-Clause License](http://opensource.org/licenses/BSD-3-Clause) \ No newline at end of file diff --git a/contrib/android-cmake/android.toolchain.cmake b/contrib/android-cmake/android.toolchain.cmake new file mode 100644 index 000000000..ffa26126a --- /dev/null +++ b/contrib/android-cmake/android.toolchain.cmake @@ -0,0 +1,1693 @@ +# Copyright (c) 2010-2011, Ethan Rublee +# Copyright (c) 2011-2014, Andrey Kamaev +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. 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. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# +# 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 HOLDER 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. + +# ------------------------------------------------------------------------------ +# Android CMake toolchain file, for use with the Android NDK r5-r10d +# Requires cmake 2.6.3 or newer (2.8.9 or newer is recommended). +# See home page: https://github.com/taka-no-me/android-cmake +# +# Usage Linux: +# $ export ANDROID_NDK=/absolute/path/to/the/android-ndk +# $ mkdir build && cd build +# $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake .. +# $ make -j8 +# +# Usage Windows: +# You need native port of make to build your project. +# Android NDK r7 (and newer) already has make.exe on board. +# For older NDK you have to install it separately. +# For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm +# +# $ SET ANDROID_NDK=C:\absolute\path\to\the\android-ndk +# $ mkdir build && cd build +# $ cmake.exe -G"MinGW Makefiles" +# -DCMAKE_TOOLCHAIN_FILE=path\to\the\android.toolchain.cmake +# -DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%\prebuilt\windows\bin\make.exe" .. +# $ cmake.exe --build . +# +# +# Options (can be set as cmake parameters: -D=): +# ANDROID_NDK=/opt/android-ndk - path to the NDK root. +# Can be set as environment variable. Can be set only at first cmake run. +# +# ANDROID_ABI=armeabi-v7a - specifies the target Application Binary +# Interface (ABI). This option nearly matches to the APP_ABI variable +# used by ndk-build tool from Android NDK. +# +# Possible targets are: +# "armeabi" - ARMv5TE based CPU with software floating point operations +# "armeabi-v7a" - ARMv7 based devices with hardware FPU instructions +# this ABI target is used by default +# "armeabi-v7a with NEON" - same as armeabi-v7a, but +# sets NEON as floating-point unit +# "armeabi-v7a with VFPV3" - same as armeabi-v7a, but +# sets VFPV3 as floating-point unit (has 32 registers instead of 16) +# "armeabi-v6 with VFP" - tuned for ARMv6 processors having VFP +# "x86" - IA-32 instruction set +# "mips" - MIPS32 instruction set +# +# 64-bit ABIs for NDK r10 and newer: +# "arm64-v8a" - ARMv8 AArch64 instruction set +# "x86_64" - Intel64 instruction set (r1) +# "mips64" - MIPS64 instruction set (r6) +# +# ANDROID_NATIVE_API_LEVEL=android-8 - level of Android API compile for. +# Option is read-only when standalone toolchain is used. +# Note: building for "android-L" requires explicit configuration. +# +# ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 - the name of compiler +# toolchain to be used. The list of possible values depends on the NDK +# version. For NDK r10c the possible values are: +# +# * aarch64-linux-android-4.9 +# * aarch64-linux-android-clang3.4 +# * aarch64-linux-android-clang3.5 +# * arm-linux-androideabi-4.6 +# * arm-linux-androideabi-4.8 +# * arm-linux-androideabi-4.9 (default) +# * arm-linux-androideabi-clang3.4 +# * arm-linux-androideabi-clang3.5 +# * mips64el-linux-android-4.9 +# * mips64el-linux-android-clang3.4 +# * mips64el-linux-android-clang3.5 +# * mipsel-linux-android-4.6 +# * mipsel-linux-android-4.8 +# * mipsel-linux-android-4.9 +# * mipsel-linux-android-clang3.4 +# * mipsel-linux-android-clang3.5 +# * x86-4.6 +# * x86-4.8 +# * x86-4.9 +# * x86-clang3.4 +# * x86-clang3.5 +# * x86_64-4.9 +# * x86_64-clang3.4 +# * x86_64-clang3.5 +# +# ANDROID_FORCE_ARM_BUILD=OFF - set ON to generate 32-bit ARM instructions +# instead of Thumb. Is not available for "armeabi-v6 with VFP" +# (is forced to be ON) ABI. +# +# ANDROID_NO_UNDEFINED=ON - set ON to show all undefined symbols as linker +# errors even if they are not used. +# +# ANDROID_SO_UNDEFINED=OFF - set ON to allow undefined symbols in shared +# libraries. Automatically turned for NDK r5x and r6x due to GLESv2 +# problems. +# +# ANDROID_STL=gnustl_static - specify the runtime to use. +# +# Possible values are: +# none -> Do not configure the runtime. +# system -> Use the default minimal system C++ runtime library. +# Implies -fno-rtti -fno-exceptions. +# Is not available for standalone toolchain. +# system_re -> Use the default minimal system C++ runtime library. +# Implies -frtti -fexceptions. +# Is not available for standalone toolchain. +# gabi++_static -> Use the GAbi++ runtime as a static library. +# Implies -frtti -fno-exceptions. +# Available for NDK r7 and newer. +# Is not available for standalone toolchain. +# gabi++_shared -> Use the GAbi++ runtime as a shared library. +# Implies -frtti -fno-exceptions. +# Available for NDK r7 and newer. +# Is not available for standalone toolchain. +# stlport_static -> Use the STLport runtime as a static library. +# Implies -fno-rtti -fno-exceptions for NDK before r7. +# Implies -frtti -fno-exceptions for NDK r7 and newer. +# Is not available for standalone toolchain. +# stlport_shared -> Use the STLport runtime as a shared library. +# Implies -fno-rtti -fno-exceptions for NDK before r7. +# Implies -frtti -fno-exceptions for NDK r7 and newer. +# Is not available for standalone toolchain. +# gnustl_static -> Use the GNU STL as a static library. +# Implies -frtti -fexceptions. +# gnustl_shared -> Use the GNU STL as a shared library. +# Implies -frtti -fno-exceptions. +# Available for NDK r7b and newer. +# Silently degrades to gnustl_static if not available. +# +# ANDROID_STL_FORCE_FEATURES=ON - turn rtti and exceptions support based on +# chosen runtime. If disabled, then the user is responsible for settings +# these options. +# +# What?: +# android-cmake toolchain searches for NDK/toolchain in the following order: +# ANDROID_NDK - cmake parameter +# ANDROID_NDK - environment variable +# ANDROID_STANDALONE_TOOLCHAIN - cmake parameter +# ANDROID_STANDALONE_TOOLCHAIN - environment variable +# ANDROID_NDK - default locations +# ANDROID_STANDALONE_TOOLCHAIN - default locations +# +# Make sure to do the following in your scripts: +# SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}" ) +# SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}" ) +# The flags will be prepopulated with critical flags, so don't loose them. +# Also be aware that toolchain also sets configuration-specific compiler +# flags and linker flags. +# +# ANDROID and BUILD_ANDROID will be set to true, you may test any of these +# variables to make necessary Android-specific configuration changes. +# +# Also ARMEABI or ARMEABI_V7A or X86 or MIPS or ARM64_V8A or X86_64 or MIPS64 +# will be set true, mutually exclusive. NEON option will be set true +# if VFP is set to NEON. +# +# ------------------------------------------------------------------------------ + +cmake_minimum_required( VERSION 2.6.3 ) + +if( DEFINED CMAKE_CROSSCOMPILING ) + # subsequent toolchain loading is not really needed + return() +endif() + +if( CMAKE_TOOLCHAIN_FILE ) + # touch toolchain variable to suppress "unused variable" warning +endif() + +# inherit settings in recursive loads +get_property( _CMAKE_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE ) +if( _CMAKE_IN_TRY_COMPILE ) + include( "${CMAKE_CURRENT_SOURCE_DIR}/../android.toolchain.config.cmake" OPTIONAL ) +endif() + +# this one is important +if( CMAKE_VERSION VERSION_GREATER "3.0.99" ) + set( CMAKE_SYSTEM_NAME Android ) +else() + set( CMAKE_SYSTEM_NAME Linux ) +endif() + +# this one not so much +set( CMAKE_SYSTEM_VERSION 1 ) + +# rpath makes low sense for Android +set( CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "" ) +set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." ) + +# NDK search paths +set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r10d -r10c -r10b -r10 -r9d -r9c -r9b -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" ) +if( NOT DEFINED ANDROID_NDK_SEARCH_PATHS ) + if( CMAKE_HOST_WIN32 ) + file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS ) + set( ANDROID_NDK_SEARCH_PATHS "${ANDROID_NDK_SEARCH_PATHS}" "$ENV{SystemDrive}/NVPACK" ) + else() + file( TO_CMAKE_PATH "$ENV{HOME}" ANDROID_NDK_SEARCH_PATHS ) + set( ANDROID_NDK_SEARCH_PATHS /opt "${ANDROID_NDK_SEARCH_PATHS}/NVPACK" ) + endif() +endif() +if( NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH ) + set( ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH /opt/android-toolchain ) +endif() + +# known ABIs +set( ANDROID_SUPPORTED_ABIS_arm "armeabi-v7a;armeabi;armeabi-v7a with NEON;armeabi-v7a with VFPV3;armeabi-v6 with VFP" ) +set( ANDROID_SUPPORTED_ABIS_arm64 "arm64-v8a" ) +set( ANDROID_SUPPORTED_ABIS_x86 "x86" ) +set( ANDROID_SUPPORTED_ABIS_x86_64 "x86_64" ) +set( ANDROID_SUPPORTED_ABIS_mips "mips" ) +set( ANDROID_SUPPORTED_ABIS_mips64 "mips64" ) + +# API level defaults +set( ANDROID_DEFAULT_NDK_API_LEVEL 8 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_arm64 21 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_x86 9 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_x86_64 21 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_mips 9 ) +set( ANDROID_DEFAULT_NDK_API_LEVEL_mips64 21 ) + + +macro( __LIST_FILTER listvar regex ) + if( ${listvar} ) + foreach( __val ${${listvar}} ) + if( __val MATCHES "${regex}" ) + list( REMOVE_ITEM ${listvar} "${__val}" ) + endif() + endforeach() + endif() +endmacro() + +macro( __INIT_VARIABLE var_name ) + set( __test_path 0 ) + foreach( __var ${ARGN} ) + if( __var STREQUAL "PATH" ) + set( __test_path 1 ) + break() + endif() + endforeach() + + if( __test_path AND NOT EXISTS "${${var_name}}" ) + unset( ${var_name} CACHE ) + endif() + + if( " ${${var_name}}" STREQUAL " " ) + set( __values 0 ) + foreach( __var ${ARGN} ) + if( __var STREQUAL "VALUES" ) + set( __values 1 ) + elseif( NOT __var STREQUAL "PATH" ) + if( __var MATCHES "^ENV_.*$" ) + string( REPLACE "ENV_" "" __var "${__var}" ) + set( __value "$ENV{${__var}}" ) + elseif( DEFINED ${__var} ) + set( __value "${${__var}}" ) + elseif( __values ) + set( __value "${__var}" ) + else() + set( __value "" ) + endif() + + if( NOT " ${__value}" STREQUAL " " AND (NOT __test_path OR EXISTS "${__value}") ) + set( ${var_name} "${__value}" ) + break() + endif() + endif() + endforeach() + unset( __value ) + unset( __values ) + endif() + + if( __test_path ) + file( TO_CMAKE_PATH "${${var_name}}" ${var_name} ) + endif() + unset( __test_path ) +endmacro() + +macro( __DETECT_NATIVE_API_LEVEL _var _path ) + set( __ndkApiLevelRegex "^[\t ]*#define[\t ]+__ANDROID_API__[\t ]+([0-9]+)[\t ]*.*$" ) + file( STRINGS ${_path} __apiFileContent REGEX "${__ndkApiLevelRegex}" ) + if( NOT __apiFileContent ) + message( SEND_ERROR "Could not get Android native API level. Probably you have specified invalid level value, or your copy of NDK/toolchain is broken." ) + endif() + string( REGEX REPLACE "${__ndkApiLevelRegex}" "\\1" ${_var} "${__apiFileContent}" ) + unset( __apiFileContent ) + unset( __ndkApiLevelRegex ) +endmacro() + +macro( __DETECT_TOOLCHAIN_MACHINE_NAME _var _root ) + if( EXISTS "${_root}" ) + file( GLOB __gccExePath RELATIVE "${_root}/bin/" "${_root}/bin/*-gcc${TOOL_OS_SUFFIX}" ) + __LIST_FILTER( __gccExePath "^[.].*" ) + list( LENGTH __gccExePath __gccExePathsCount ) + if( NOT __gccExePathsCount EQUAL 1 AND NOT _CMAKE_IN_TRY_COMPILE ) + message( WARNING "Could not determine machine name for compiler from ${_root}" ) + set( ${_var} "" ) + else() + get_filename_component( __gccExeName "${__gccExePath}" NAME_WE ) + string( REPLACE "-gcc" "" ${_var} "${__gccExeName}" ) + endif() + unset( __gccExePath ) + unset( __gccExePathsCount ) + unset( __gccExeName ) + else() + set( ${_var} "" ) + endif() +endmacro() + + +# fight against cygwin +set( ANDROID_FORBID_SYGWIN TRUE CACHE BOOL "Prevent cmake from working under cygwin and using cygwin tools") +mark_as_advanced( ANDROID_FORBID_SYGWIN ) +if( ANDROID_FORBID_SYGWIN ) + if( CYGWIN ) + message( FATAL_ERROR "Android NDK and android-cmake toolchain are not welcome Cygwin. It is unlikely that this cmake toolchain will work under cygwin. But if you want to try then you can set cmake variable ANDROID_FORBID_SYGWIN to FALSE and rerun cmake." ) + endif() + + if( CMAKE_HOST_WIN32 ) + # remove cygwin from PATH + set( __new_path "$ENV{PATH}") + __LIST_FILTER( __new_path "cygwin" ) + set(ENV{PATH} "${__new_path}") + unset(__new_path) + endif() +endif() + + +# detect current host platform +if( NOT DEFINED ANDROID_NDK_HOST_X64 AND (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64" OR CMAKE_HOST_APPLE) ) + set( ANDROID_NDK_HOST_X64 1 CACHE BOOL "Try to use 64-bit compiler toolchain" ) + mark_as_advanced( ANDROID_NDK_HOST_X64 ) +endif() + +set( TOOL_OS_SUFFIX "" ) +if( CMAKE_HOST_APPLE ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME2 "darwin-x86" ) +elseif( CMAKE_HOST_WIN32 ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "windows-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME2 "windows" ) + set( TOOL_OS_SUFFIX ".exe" ) +elseif( CMAKE_HOST_UNIX ) + set( ANDROID_NDK_HOST_SYSTEM_NAME "linux-x86_64" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME2 "linux-x86" ) +else() + message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" ) +endif() + +if( NOT ANDROID_NDK_HOST_X64 ) + set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) +endif() + +# see if we have path to Android NDK +if( NOT ANDROID_NDK AND NOT ANDROID_STANDALONE_TOOLCHAIN ) + __INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK ) +endif() +if( NOT ANDROID_NDK ) + # see if we have path to Android standalone toolchain + __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ENV_ANDROID_STANDALONE_TOOLCHAIN ) + + if( NOT ANDROID_STANDALONE_TOOLCHAIN ) + #try to find Android NDK in one of the the default locations + set( __ndkSearchPaths ) + foreach( __ndkSearchPath ${ANDROID_NDK_SEARCH_PATHS} ) + foreach( suffix ${ANDROID_SUPPORTED_NDK_VERSIONS} ) + list( APPEND __ndkSearchPaths "${__ndkSearchPath}/android-ndk${suffix}" ) + endforeach() + endforeach() + __INIT_VARIABLE( ANDROID_NDK PATH VALUES ${__ndkSearchPaths} ) + unset( __ndkSearchPaths ) + + if( ANDROID_NDK ) + message( STATUS "Using default path for Android NDK: ${ANDROID_NDK}" ) + message( STATUS " If you prefer to use a different location, please define a cmake or environment variable: ANDROID_NDK" ) + else() + #try to find Android standalone toolchain in one of the the default locations + __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH ) + + if( ANDROID_STANDALONE_TOOLCHAIN ) + message( STATUS "Using default path for standalone toolchain ${ANDROID_STANDALONE_TOOLCHAIN}" ) + message( STATUS " If you prefer to use a different location, please define the variable: ANDROID_STANDALONE_TOOLCHAIN" ) + endif( ANDROID_STANDALONE_TOOLCHAIN ) + endif( ANDROID_NDK ) + endif( NOT ANDROID_STANDALONE_TOOLCHAIN ) +endif( NOT ANDROID_NDK ) + +# remember found paths +if( ANDROID_NDK ) + get_filename_component( ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE ) + set( ANDROID_NDK "${ANDROID_NDK}" CACHE INTERNAL "Path of the Android NDK" FORCE ) + set( BUILD_WITH_ANDROID_NDK True ) + if( EXISTS "${ANDROID_NDK}/RELEASE.TXT" ) + file( STRINGS "${ANDROID_NDK}/RELEASE.TXT" ANDROID_NDK_RELEASE_FULL LIMIT_COUNT 1 REGEX "r[0-9]+[a-z]?" ) + string( REGEX MATCH "r([0-9]+)([a-z]?)" ANDROID_NDK_RELEASE "${ANDROID_NDK_RELEASE_FULL}" ) + else() + set( ANDROID_NDK_RELEASE "r1x" ) + set( ANDROID_NDK_RELEASE_FULL "unreleased" ) + endif() + string( REGEX REPLACE "r([0-9]+)([a-z]?)" "\\1*1000" ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE}" ) + string( FIND " abcdefghijklmnopqastuvwxyz" "${CMAKE_MATCH_2}" __ndkReleaseLetterNum ) + math( EXPR ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE_NUM}+${__ndkReleaseLetterNum}" ) +elseif( ANDROID_STANDALONE_TOOLCHAIN ) + get_filename_component( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" ABSOLUTE ) + # try to detect change + if( CMAKE_AR ) + string( LENGTH "${ANDROID_STANDALONE_TOOLCHAIN}" __length ) + string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidStandaloneToolchainPreviousPath ) + if( NOT __androidStandaloneToolchainPreviousPath STREQUAL ANDROID_STANDALONE_TOOLCHAIN ) + message( FATAL_ERROR "It is not possible to change path to the Android standalone toolchain on subsequent run." ) + endif() + unset( __androidStandaloneToolchainPreviousPath ) + unset( __length ) + endif() + set( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" CACHE INTERNAL "Path of the Android standalone toolchain" FORCE ) + set( BUILD_WITH_STANDALONE_TOOLCHAIN True ) +else() + list(GET ANDROID_NDK_SEARCH_PATHS 0 ANDROID_NDK_SEARCH_PATH) + message( FATAL_ERROR "Could not find neither Android NDK nor Android standalone toolchain. + You should either set an environment variable: + export ANDROID_NDK=~/my-android-ndk + or + export ANDROID_STANDALONE_TOOLCHAIN=~/my-android-toolchain + or put the toolchain or NDK in the default path: + sudo ln -s ~/my-android-ndk ${ANDROID_NDK_SEARCH_PATH}/android-ndk + sudo ln -s ~/my-android-toolchain ${ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH}" ) +endif() + +# android NDK layout +if( BUILD_WITH_ANDROID_NDK ) + if( NOT DEFINED ANDROID_NDK_LAYOUT ) + # try to automatically detect the layout + if( EXISTS "${ANDROID_NDK}/RELEASE.TXT") + set( ANDROID_NDK_LAYOUT "RELEASE" ) + elseif( EXISTS "${ANDROID_NDK}/../../linux-x86/toolchain/" ) + set( ANDROID_NDK_LAYOUT "LINARO" ) + elseif( EXISTS "${ANDROID_NDK}/../../gcc/" ) + set( ANDROID_NDK_LAYOUT "ANDROID" ) + endif() + endif() + set( ANDROID_NDK_LAYOUT "${ANDROID_NDK_LAYOUT}" CACHE STRING "The inner layout of NDK" ) + mark_as_advanced( ANDROID_NDK_LAYOUT ) + if( ANDROID_NDK_LAYOUT STREQUAL "LINARO" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment + set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../${ANDROID_NDK_HOST_SYSTEM_NAME}/toolchain" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" ) + elseif( ANDROID_NDK_LAYOUT STREQUAL "ANDROID" ) + set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment + set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../gcc/${ANDROID_NDK_HOST_SYSTEM_NAME}/arm" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH "" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" ) + else() # ANDROID_NDK_LAYOUT STREQUAL "RELEASE" + set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/toolchains" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME2}" ) + endif() + get_filename_component( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK_TOOLCHAINS_PATH}" ABSOLUTE ) + + # try to detect change of NDK + if( CMAKE_AR ) + string( LENGTH "${ANDROID_NDK_TOOLCHAINS_PATH}" __length ) + string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidNdkPreviousPath ) + if( NOT __androidNdkPreviousPath STREQUAL ANDROID_NDK_TOOLCHAINS_PATH ) + message( FATAL_ERROR "It is not possible to change the path to the NDK on subsequent CMake run. You must remove all generated files from your build folder first. + " ) + endif() + unset( __androidNdkPreviousPath ) + unset( __length ) + endif() +endif() + + +# get all the details about standalone toolchain +if( BUILD_WITH_STANDALONE_TOOLCHAIN ) + __DETECT_NATIVE_API_LEVEL( ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h" ) + set( ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) + set( __availableToolchains "standalone" ) + __DETECT_TOOLCHAIN_MACHINE_NAME( __availableToolchainMachines "${ANDROID_STANDALONE_TOOLCHAIN}" ) + if( NOT __availableToolchainMachines ) + message( FATAL_ERROR "Could not determine machine name of your toolchain. Probably your Android standalone toolchain is broken." ) + endif() + if( __availableToolchainMachines MATCHES x86_64 ) + set( __availableToolchainArchs "x86_64" ) + elseif( __availableToolchainMachines MATCHES i686 ) + set( __availableToolchainArchs "x86" ) + elseif( __availableToolchainMachines MATCHES aarch64 ) + set( __availableToolchainArchs "arm64" ) + elseif( __availableToolchainMachines MATCHES arm ) + set( __availableToolchainArchs "arm" ) + elseif( __availableToolchainMachines MATCHES mips64el ) + set( __availableToolchainArchs "mips64" ) + elseif( __availableToolchainMachines MATCHES mipsel ) + set( __availableToolchainArchs "mips" ) + endif() + execute_process( COMMAND "${ANDROID_STANDALONE_TOOLCHAIN}/bin/${__availableToolchainMachines}-gcc${TOOL_OS_SUFFIX}" -dumpversion + OUTPUT_VARIABLE __availableToolchainCompilerVersions OUTPUT_STRIP_TRAILING_WHITESPACE ) + string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9]+)?" __availableToolchainCompilerVersions "${__availableToolchainCompilerVersions}" ) + if( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/bin/clang${TOOL_OS_SUFFIX}" ) + list( APPEND __availableToolchains "standalone-clang" ) + list( APPEND __availableToolchainMachines ${__availableToolchainMachines} ) + list( APPEND __availableToolchainArchs ${__availableToolchainArchs} ) + list( APPEND __availableToolchainCompilerVersions ${__availableToolchainCompilerVersions} ) + endif() +endif() + +macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar __availableToolchainsLst __toolchain_subpath ) + foreach( __toolchain ${${__availableToolchainsLst}} ) + if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" ) + SET( __toolchainVersionRegex "^TOOLCHAIN_VERSION[\t ]+:=[\t ]+(.*)$" ) + FILE( STRINGS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}/setup.mk" __toolchainVersionStr REGEX "${__toolchainVersionRegex}" ) + if( __toolchainVersionStr ) + string( REGEX REPLACE "${__toolchainVersionRegex}" "\\1" __toolchainVersionStr "${__toolchainVersionStr}" ) + string( REGEX REPLACE "-clang3[.][0-9]$" "-${__toolchainVersionStr}" __gcc_toolchain "${__toolchain}" ) + else() + string( REGEX REPLACE "-clang3[.][0-9]$" "-4.6" __gcc_toolchain "${__toolchain}" ) + endif() + unset( __toolchainVersionStr ) + unset( __toolchainVersionRegex ) + else() + set( __gcc_toolchain "${__toolchain}" ) + endif() + __DETECT_TOOLCHAIN_MACHINE_NAME( __machine "${ANDROID_NDK_TOOLCHAINS_PATH}/${__gcc_toolchain}${__toolchain_subpath}" ) + if( __machine ) + string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9x]+)?$" __version "${__gcc_toolchain}" ) + if( __machine MATCHES x86_64 ) + set( __arch "x86_64" ) + elseif( __machine MATCHES i686 ) + set( __arch "x86" ) + elseif( __machine MATCHES aarch64 ) + set( __arch "arm64" ) + elseif( __machine MATCHES arm ) + set( __arch "arm" ) + elseif( __machine MATCHES mips64el ) + set( __arch "mips64" ) + elseif( __machine MATCHES mipsel ) + set( __arch "mips" ) + else() + set( __arch "" ) + endif() + #message("machine: !${__machine}!\narch: !${__arch}!\nversion: !${__version}!\ntoolchain: !${__toolchain}!\n") + if (__arch) + list( APPEND __availableToolchainMachines "${__machine}" ) + list( APPEND __availableToolchainArchs "${__arch}" ) + list( APPEND __availableToolchainCompilerVersions "${__version}" ) + list( APPEND ${__availableToolchainsVar} "${__toolchain}" ) + endif() + endif() + unset( __gcc_toolchain ) + endforeach() +endmacro() + +# get all the details about NDK +if( BUILD_WITH_ANDROID_NDK ) + file( GLOB ANDROID_SUPPORTED_NATIVE_API_LEVELS RELATIVE "${ANDROID_NDK}/platforms" "${ANDROID_NDK}/platforms/android-*" ) + string( REPLACE "android-" "" ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_SUPPORTED_NATIVE_API_LEVELS}" ) + set( __availableToolchains "" ) + set( __availableToolchainMachines "" ) + set( __availableToolchainArchs "" ) + set( __availableToolchainCompilerVersions "" ) + if( ANDROID_TOOLCHAIN_NAME AND EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_TOOLCHAIN_NAME}/" ) + # do not go through all toolchains if we know the name + set( __availableToolchainsLst "${ANDROID_TOOLCHAIN_NAME}" ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) + if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" ) + if( __availableToolchains ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} ) + endif() + endif() + endif() + if( NOT __availableToolchains ) + file( GLOB __availableToolchainsLst RELATIVE "${ANDROID_NDK_TOOLCHAINS_PATH}" "${ANDROID_NDK_TOOLCHAINS_PATH}/*" ) + if( __availableToolchainsLst ) + list(SORT __availableToolchainsLst) # we need clang to go after gcc + endif() + __LIST_FILTER( __availableToolchainsLst "^[.]" ) + __LIST_FILTER( __availableToolchainsLst "llvm" ) + __LIST_FILTER( __availableToolchainsLst "renderscript" ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) + if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 ) + __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" ) + if( __availableToolchains ) + set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} ) + endif() + endif() + endif() + if( NOT __availableToolchains ) + message( FATAL_ERROR "Could not find any working toolchain in the NDK. Probably your Android NDK is broken." ) + endif() +endif() + +# build list of available ABIs +set( ANDROID_SUPPORTED_ABIS "" ) +set( __uniqToolchainArchNames ${__availableToolchainArchs} ) +list( REMOVE_DUPLICATES __uniqToolchainArchNames ) +list( SORT __uniqToolchainArchNames ) +foreach( __arch ${__uniqToolchainArchNames} ) + list( APPEND ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${__arch}} ) +endforeach() +unset( __uniqToolchainArchNames ) +if( NOT ANDROID_SUPPORTED_ABIS ) + message( FATAL_ERROR "No one of known Android ABIs is supported by this cmake toolchain." ) +endif() + +# choose target ABI +__INIT_VARIABLE( ANDROID_ABI VALUES ${ANDROID_SUPPORTED_ABIS} ) +# verify that target ABI is supported +list( FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI}" __androidAbiIdx ) +if( __androidAbiIdx EQUAL -1 ) + string( REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_ABIS "${ANDROID_SUPPORTED_ABIS}" ) + message( FATAL_ERROR "Specified ANDROID_ABI = \"${ANDROID_ABI}\" is not supported by this cmake toolchain or your NDK/toolchain. + Supported values are: \"${PRINTABLE_ANDROID_SUPPORTED_ABIS}\" + " ) +endif() +unset( __androidAbiIdx ) + +# set target ABI options +if( ANDROID_ABI STREQUAL "x86" ) + set( X86 true ) + set( ANDROID_NDK_ABI_NAME "x86" ) + set( ANDROID_ARCH_NAME "x86" ) + set( ANDROID_LLVM_TRIPLE "i686-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "i686" ) +elseif( ANDROID_ABI STREQUAL "x86_64" ) + set( X86 true ) + set( X86_64 true ) + set( ANDROID_NDK_ABI_NAME "x86_64" ) + set( ANDROID_ARCH_NAME "x86_64" ) + set( CMAKE_SYSTEM_PROCESSOR "x86_64" ) + set( ANDROID_LLVM_TRIPLE "x86_64-none-linux-android" ) +elseif( ANDROID_ABI STREQUAL "mips64" ) + set( MIPS64 true ) + set( ANDROID_NDK_ABI_NAME "mips64" ) + set( ANDROID_ARCH_NAME "mips64" ) + set( ANDROID_LLVM_TRIPLE "mips64el-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "mips64" ) +elseif( ANDROID_ABI STREQUAL "mips" ) + set( MIPS true ) + set( ANDROID_NDK_ABI_NAME "mips" ) + set( ANDROID_ARCH_NAME "mips" ) + set( ANDROID_LLVM_TRIPLE "mipsel-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "mips" ) +elseif( ANDROID_ABI STREQUAL "arm64-v8a" ) + set( ARM64_V8A true ) + set( ANDROID_NDK_ABI_NAME "arm64-v8a" ) + set( ANDROID_ARCH_NAME "arm64" ) + set( ANDROID_LLVM_TRIPLE "aarch64-none-linux-android" ) + set( CMAKE_SYSTEM_PROCESSOR "aarch64" ) + set( VFPV3 true ) + set( NEON true ) +elseif( ANDROID_ABI STREQUAL "armeabi" ) + set( ARMEABI true ) + set( ANDROID_NDK_ABI_NAME "armeabi" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv5te" ) +elseif( ANDROID_ABI STREQUAL "armeabi-v6 with VFP" ) + set( ARMEABI_V6 true ) + set( ANDROID_NDK_ABI_NAME "armeabi" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv6" ) + # need always fallback to older platform + set( ARMEABI true ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a") + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a with VFPV3" ) + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) + set( VFPV3 true ) +elseif( ANDROID_ABI STREQUAL "armeabi-v7a with NEON" ) + set( ARMEABI_V7A true ) + set( ANDROID_NDK_ABI_NAME "armeabi-v7a" ) + set( ANDROID_ARCH_NAME "arm" ) + set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" ) + set( CMAKE_SYSTEM_PROCESSOR "armv7-a" ) + set( VFPV3 true ) + set( NEON true ) +else() + message( SEND_ERROR "Unknown ANDROID_ABI=\"${ANDROID_ABI}\" is specified." ) +endif() + +if( CMAKE_BINARY_DIR AND EXISTS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" ) + # really dirty hack + # it is not possible to change CMAKE_SYSTEM_PROCESSOR after the first run... + file( APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" "SET(CMAKE_SYSTEM_PROCESSOR \"${CMAKE_SYSTEM_PROCESSOR}\")\n" ) +endif() + +if( ANDROID_ARCH_NAME STREQUAL "arm" AND NOT ARMEABI_V6 ) + __INIT_VARIABLE( ANDROID_FORCE_ARM_BUILD VALUES OFF ) + set( ANDROID_FORCE_ARM_BUILD ${ANDROID_FORCE_ARM_BUILD} CACHE BOOL "Use 32-bit ARM instructions instead of Thumb-1" FORCE ) + mark_as_advanced( ANDROID_FORCE_ARM_BUILD ) +else() + unset( ANDROID_FORCE_ARM_BUILD CACHE ) +endif() + +# choose toolchain +if( ANDROID_TOOLCHAIN_NAME ) + list( FIND __availableToolchains "${ANDROID_TOOLCHAIN_NAME}" __toolchainIdx ) + if( __toolchainIdx EQUAL -1 ) + list( SORT __availableToolchains ) + string( REPLACE ";" "\n * " toolchains_list "${__availableToolchains}" ) + set( toolchains_list " * ${toolchains_list}") + message( FATAL_ERROR "Specified toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is missing in your NDK or broken. Please verify that your NDK is working or select another compiler toolchain. +To configure the toolchain set CMake variable ANDROID_TOOLCHAIN_NAME to one of the following values:\n${toolchains_list}\n" ) + endif() + list( GET __availableToolchainArchs ${__toolchainIdx} __toolchainArch ) + if( NOT __toolchainArch STREQUAL ANDROID_ARCH_NAME ) + message( SEND_ERROR "Selected toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is not able to compile binaries for the \"${ANDROID_ARCH_NAME}\" platform." ) + endif() +else() + set( __toolchainIdx -1 ) + set( __applicableToolchains "" ) + set( __toolchainMaxVersion "0.0.0" ) + list( LENGTH __availableToolchains __availableToolchainsCount ) + math( EXPR __availableToolchainsCount "${__availableToolchainsCount}-1" ) + foreach( __idx RANGE ${__availableToolchainsCount} ) + list( GET __availableToolchainArchs ${__idx} __toolchainArch ) + if( __toolchainArch STREQUAL ANDROID_ARCH_NAME ) + list( GET __availableToolchainCompilerVersions ${__idx} __toolchainVersion ) + string( REPLACE "x" "99" __toolchainVersion "${__toolchainVersion}") + if( __toolchainVersion VERSION_GREATER __toolchainMaxVersion ) + set( __toolchainMaxVersion "${__toolchainVersion}" ) + set( __toolchainIdx ${__idx} ) + endif() + endif() + endforeach() + unset( __availableToolchainsCount ) + unset( __toolchainMaxVersion ) + unset( __toolchainVersion ) +endif() +unset( __toolchainArch ) +if( __toolchainIdx EQUAL -1 ) + message( FATAL_ERROR "No one of available compiler toolchains is able to compile for ${ANDROID_ARCH_NAME} platform." ) +endif() +list( GET __availableToolchains ${__toolchainIdx} ANDROID_TOOLCHAIN_NAME ) +list( GET __availableToolchainMachines ${__toolchainIdx} ANDROID_TOOLCHAIN_MACHINE_NAME ) +list( GET __availableToolchainCompilerVersions ${__toolchainIdx} ANDROID_COMPILER_VERSION ) + +unset( __toolchainIdx ) +unset( __availableToolchains ) +unset( __availableToolchainMachines ) +unset( __availableToolchainArchs ) +unset( __availableToolchainCompilerVersions ) + +# choose native API level +__INIT_VARIABLE( ANDROID_NATIVE_API_LEVEL ENV_ANDROID_NATIVE_API_LEVEL ANDROID_API_LEVEL ENV_ANDROID_API_LEVEL ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME} ANDROID_DEFAULT_NDK_API_LEVEL ) +string( REPLACE "android-" "" ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" ) +string( STRIP "${ANDROID_NATIVE_API_LEVEL}" ANDROID_NATIVE_API_LEVEL ) +# adjust API level +set( __real_api_level ${ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME}} ) +foreach( __level ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) + if( (__level LESS ANDROID_NATIVE_API_LEVEL OR __level STREQUAL ANDROID_NATIVE_API_LEVEL) AND NOT __level LESS __real_api_level ) + set( __real_api_level ${__level} ) + endif() +endforeach() +if( __real_api_level AND NOT ANDROID_NATIVE_API_LEVEL STREQUAL __real_api_level ) + message( STATUS "Adjusting Android API level 'android-${ANDROID_NATIVE_API_LEVEL}' to 'android-${__real_api_level}'") + set( ANDROID_NATIVE_API_LEVEL ${__real_api_level} ) +endif() +unset(__real_api_level) +# validate +list( FIND ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_NATIVE_API_LEVEL}" __levelIdx ) +if( __levelIdx EQUAL -1 ) + message( SEND_ERROR "Specified Android native API level 'android-${ANDROID_NATIVE_API_LEVEL}' is not supported by your NDK/toolchain." ) +else() + if( BUILD_WITH_ANDROID_NDK ) + __DETECT_NATIVE_API_LEVEL( __realApiLevel "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}/usr/include/android/api-level.h" ) + if( NOT __realApiLevel EQUAL ANDROID_NATIVE_API_LEVEL AND NOT __realApiLevel GREATER 9000 ) + message( SEND_ERROR "Specified Android API level (${ANDROID_NATIVE_API_LEVEL}) does not match to the level found (${__realApiLevel}). Probably your copy of NDK is broken." ) + endif() + unset( __realApiLevel ) + endif() + set( ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" CACHE STRING "Android API level for native code" FORCE ) + set( CMAKE_ANDROID_API ${ANDROID_NATIVE_API_LEVEL} ) + if( CMAKE_VERSION VERSION_GREATER "2.8" ) + list( SORT ANDROID_SUPPORTED_NATIVE_API_LEVELS ) + set_property( CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} ) + endif() +endif() +unset( __levelIdx ) + + +# remember target ABI +set( ANDROID_ABI "${ANDROID_ABI}" CACHE STRING "The target ABI for Android. If arm, then armeabi-v7a is recommended for hardware floating point." FORCE ) +if( CMAKE_VERSION VERSION_GREATER "2.8" ) + list( SORT ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME} ) + set_property( CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME}} ) +endif() + + +# runtime choice (STL, rtti, exceptions) +if( NOT ANDROID_STL ) + set( ANDROID_STL gnustl_static ) +endif() +set( ANDROID_STL "${ANDROID_STL}" CACHE STRING "C++ runtime" ) +set( ANDROID_STL_FORCE_FEATURES ON CACHE BOOL "automatically configure rtti and exceptions support based on C++ runtime" ) +mark_as_advanced( ANDROID_STL ANDROID_STL_FORCE_FEATURES ) + +if( BUILD_WITH_ANDROID_NDK ) + if( NOT "${ANDROID_STL}" MATCHES "^(none|system|system_re|gabi\\+\\+_static|gabi\\+\\+_shared|stlport_static|stlport_shared|gnustl_static|gnustl_shared)$") + message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\". +The possible values are: + none -> Do not configure the runtime. + system -> Use the default minimal system C++ runtime library. + system_re -> Same as system but with rtti and exceptions. + gabi++_static -> Use the GAbi++ runtime as a static library. + gabi++_shared -> Use the GAbi++ runtime as a shared library. + stlport_static -> Use the STLport runtime as a static library. + stlport_shared -> Use the STLport runtime as a shared library. + gnustl_static -> (default) Use the GNU STL as a static library. + gnustl_shared -> Use the GNU STL as a shared library. +" ) + endif() +elseif( BUILD_WITH_STANDALONE_TOOLCHAIN ) + if( NOT "${ANDROID_STL}" MATCHES "^(none|gnustl_static|gnustl_shared)$") + message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\". +The possible values are: + none -> Do not configure the runtime. + gnustl_static -> (default) Use the GNU STL as a static library. + gnustl_shared -> Use the GNU STL as a shared library. +" ) + endif() +endif() + +unset( ANDROID_RTTI ) +unset( ANDROID_EXCEPTIONS ) +unset( ANDROID_STL_INCLUDE_DIRS ) +unset( __libstl ) +unset( __libsupcxx ) + +if( NOT _CMAKE_IN_TRY_COMPILE AND ANDROID_NDK_RELEASE STREQUAL "r7b" AND ARMEABI_V7A AND NOT VFPV3 AND ANDROID_STL MATCHES "gnustl" ) + message( WARNING "The GNU STL armeabi-v7a binaries from NDK r7b can crash non-NEON devices. The files provided with NDK r7b were not configured properly, resulting in crashes on Tegra2-based devices and others when trying to use certain floating-point functions (e.g., cosf, sinf, expf). +You are strongly recommended to switch to another NDK release. +" ) +endif() + +if( NOT _CMAKE_IN_TRY_COMPILE AND X86 AND ANDROID_STL MATCHES "gnustl" AND ANDROID_NDK_RELEASE STREQUAL "r6" ) + message( WARNING "The x86 system header file from NDK r6 has incorrect definition for ptrdiff_t. You are recommended to upgrade to a newer NDK release or manually patch the header: +See https://android.googlesource.com/platform/development.git f907f4f9d4e56ccc8093df6fee54454b8bcab6c2 + diff --git a/ndk/platforms/android-9/arch-x86/include/machine/_types.h b/ndk/platforms/android-9/arch-x86/include/machine/_types.h + index 5e28c64..65892a1 100644 + --- a/ndk/platforms/android-9/arch-x86/include/machine/_types.h + +++ b/ndk/platforms/android-9/arch-x86/include/machine/_types.h + @@ -51,7 +51,11 @@ typedef long int ssize_t; + #endif + #ifndef _PTRDIFF_T + #define _PTRDIFF_T + -typedef long ptrdiff_t; + +# ifdef __ANDROID__ + + typedef int ptrdiff_t; + +# else + + typedef long ptrdiff_t; + +# endif + #endif +" ) +endif() + + +# setup paths and STL for standalone toolchain +if( BUILD_WITH_STANDALONE_TOOLCHAIN ) + set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" ) + set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" ) + set( ANDROID_SYSROOT "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot" ) + + if( NOT ANDROID_STL STREQUAL "none" ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/include/c++/${ANDROID_COMPILER_VERSION}" ) + if( NOT EXISTS "${ANDROID_STL_INCLUDE_DIRS}" ) + # old location ( pre r8c ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}" ) + endif() + if( ARMEABI_V7A AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/bits" ) + list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}" ) + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb/bits" ) + list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb" ) + else() + list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" ) + endif() + # always search static GNU STL to get the location of libsupc++.a + if( ARMEABI_V7A AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb" ) + elseif( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}" ) + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb" ) + elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libstdc++.a" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib" ) + endif() + if( __libstl ) + set( __libsupcxx "${__libstl}/libsupc++.a" ) + set( __libstl "${__libstl}/libstdc++.a" ) + endif() + if( NOT EXISTS "${__libsupcxx}" ) + message( FATAL_ERROR "The required libstdsupc++.a is missing in your standalone toolchain. + Usually it happens because of bug in make-standalone-toolchain.sh script from NDK r7, r7b and r7c. + You need to either upgrade to newer NDK or manually copy + $ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a + to + ${__libsupcxx} + " ) + endif() + if( ANDROID_STL STREQUAL "gnustl_shared" ) + if( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" ) + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" ) + elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" ) + set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" ) + endif() + endif() + endif() +endif() + +# clang +if( "${ANDROID_TOOLCHAIN_NAME}" STREQUAL "standalone-clang" ) + set( ANDROID_COMPILER_IS_CLANG 1 ) + execute_process( COMMAND "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/clang${TOOL_OS_SUFFIX}" --version OUTPUT_VARIABLE ANDROID_CLANG_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE ) + string( REGEX MATCH "[0-9]+[.][0-9]+" ANDROID_CLANG_VERSION "${ANDROID_CLANG_VERSION}") +elseif( "${ANDROID_TOOLCHAIN_NAME}" MATCHES "-clang3[.][0-9]?$" ) + string( REGEX MATCH "3[.][0-9]$" ANDROID_CLANG_VERSION "${ANDROID_TOOLCHAIN_NAME}") + string( REGEX REPLACE "-clang${ANDROID_CLANG_VERSION}$" "-${ANDROID_COMPILER_VERSION}" ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" ) + if( NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}/bin/clang${TOOL_OS_SUFFIX}" ) + message( FATAL_ERROR "Could not find the Clang compiler driver" ) + endif() + set( ANDROID_COMPILER_IS_CLANG 1 ) + set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) +else() + set( ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" ) + unset( ANDROID_COMPILER_IS_CLANG CACHE ) +endif() + +string( REPLACE "." "" _clang_name "clang${ANDROID_CLANG_VERSION}" ) +if( NOT EXISTS "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" ) + set( _clang_name "clang" ) +endif() + + +# setup paths and STL for NDK +if( BUILD_WITH_ANDROID_NDK ) + set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" ) + set( ANDROID_SYSROOT "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}" ) + + if( ANDROID_STL STREQUAL "none" ) + # do nothing + elseif( ANDROID_STL STREQUAL "system" ) + set( ANDROID_RTTI OFF ) + set( ANDROID_EXCEPTIONS OFF ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" ) + elseif( ANDROID_STL STREQUAL "system_re" ) + set( ANDROID_RTTI ON ) + set( ANDROID_EXCEPTIONS ON ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" ) + elseif( ANDROID_STL MATCHES "gabi" ) + if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7 + message( FATAL_ERROR "gabi++ is not available in your NDK. You have to upgrade to NDK r7 or newer to use gabi++.") + endif() + set( ANDROID_RTTI ON ) + set( ANDROID_EXCEPTIONS OFF ) + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/gabi++/include" ) + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gabi++/libs/${ANDROID_NDK_ABI_NAME}/libgabi++_static.a" ) + elseif( ANDROID_STL MATCHES "stlport" ) + if( NOT ANDROID_NDK_RELEASE_NUM LESS 8004 ) # before r8d + set( ANDROID_EXCEPTIONS ON ) + else() + set( ANDROID_EXCEPTIONS OFF ) + endif() + if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7 + set( ANDROID_RTTI OFF ) + else() + set( ANDROID_RTTI ON ) + endif() + set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/stlport/stlport" ) + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/stlport/libs/${ANDROID_NDK_ABI_NAME}/libstlport_static.a" ) + elseif( ANDROID_STL MATCHES "gnustl" ) + set( ANDROID_EXCEPTIONS ON ) + set( ANDROID_RTTI ON ) + if( EXISTS "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) + if( ARMEABI_V7A AND ANDROID_COMPILER_VERSION VERSION_EQUAL "4.7" AND ANDROID_NDK_RELEASE STREQUAL "r8d" ) + # gnustl binary for 4.7 compiler is buggy :( + # TODO: look for right fix + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.6" ) + else() + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" ) + endif() + else() + set( __libstl "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++" ) + endif() + set( ANDROID_STL_INCLUDE_DIRS "${__libstl}/include" "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/include" "${__libstl}/include/backward" ) + if( EXISTS "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" ) + set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" ) + else() + set( __libstl "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" ) + endif() + else() + message( FATAL_ERROR "Unknown runtime: ${ANDROID_STL}" ) + endif() + # find libsupc++.a - rtti & exceptions + if( ANDROID_STL STREQUAL "system_re" OR ANDROID_STL MATCHES "gnustl" ) + set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r8b or newer + if( NOT EXISTS "${__libsupcxx}" ) + set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r7-r8 + endif() + if( NOT EXISTS "${__libsupcxx}" ) # before r7 + if( ARMEABI_V7A ) + if( ANDROID_FORCE_ARM_BUILD ) + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" ) + else() + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" ) + endif() + elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD ) + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" ) + else() + set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" ) + endif() + endif() + if( NOT EXISTS "${__libsupcxx}") + message( ERROR "Could not find libsupc++.a for a chosen platform. Either your NDK is not supported or is broken.") + endif() + endif() +endif() + + +# case of shared STL linkage +if( ANDROID_STL MATCHES "shared" AND DEFINED __libstl ) + string( REPLACE "_static.a" "_shared.so" __libstl "${__libstl}" ) + # TODO: check if .so file exists before the renaming +endif() + + +# ccache support +__INIT_VARIABLE( _ndk_ccache NDK_CCACHE ENV_NDK_CCACHE ) +if( _ndk_ccache ) + if( DEFINED NDK_CCACHE AND NOT EXISTS NDK_CCACHE ) + unset( NDK_CCACHE CACHE ) + endif() + find_program( NDK_CCACHE "${_ndk_ccache}" DOC "The path to ccache binary") +else() + unset( NDK_CCACHE CACHE ) +endif() +unset( _ndk_ccache ) + + +# setup the cross-compiler +if( NOT CMAKE_C_COMPILER ) + if( NDK_CCACHE AND NOT ANDROID_SYSROOT MATCHES "[ ;\"]" ) + set( CMAKE_C_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C compiler" ) + set( CMAKE_CXX_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C++ compiler" ) + if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_C_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") + set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") + else() + set( CMAKE_C_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") + set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") + endif() + else() + if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_C_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" CACHE PATH "C compiler") + set( CMAKE_CXX_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler") + else() + set( CMAKE_C_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler" ) + set( CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler" ) + endif() + endif() + set( CMAKE_ASM_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "assembler" ) + set( CMAKE_STRIP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip" ) + if( EXISTS "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}" ) + # Use gcc-ar if we have it for better LTO support. + set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" ) + else() + set( CMAKE_AR "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" ) + endif() + set( CMAKE_LINKER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker" ) + set( CMAKE_NM "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm" ) + set( CMAKE_OBJCOPY "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" ) + set( CMAKE_OBJDUMP "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump" ) + set( CMAKE_RANLIB "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ranlib${TOOL_OS_SUFFIX}" CACHE PATH "ranlib" ) +endif() + +set( _CMAKE_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_MACHINE_NAME}-" ) +if( CMAKE_VERSION VERSION_LESS 2.8.5 ) + set( CMAKE_ASM_COMPILER_ARG1 "-c" ) +endif() +if( APPLE ) + find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool ) + if( NOT CMAKE_INSTALL_NAME_TOOL ) + message( FATAL_ERROR "Could not find install_name_tool, please check your installation." ) + endif() + mark_as_advanced( CMAKE_INSTALL_NAME_TOOL ) +endif() + +# Force set compilers because standard identification works badly for us +include( CMakeForceCompiler ) +CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU ) +if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_C_COMPILER_ID Clang ) +endif() +set( CMAKE_C_PLATFORM_ID Linux ) +if( X86_64 OR MIPS64 OR ARM64_V8A ) + set( CMAKE_C_SIZEOF_DATA_PTR 8 ) +else() + set( CMAKE_C_SIZEOF_DATA_PTR 4 ) +endif() +set( CMAKE_C_HAS_ISYSROOT 1 ) +set( CMAKE_C_COMPILER_ABI ELF ) +CMAKE_FORCE_CXX_COMPILER( "${CMAKE_CXX_COMPILER}" GNU ) +if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_CXX_COMPILER_ID Clang) +endif() +set( CMAKE_CXX_PLATFORM_ID Linux ) +set( CMAKE_CXX_SIZEOF_DATA_PTR ${CMAKE_C_SIZEOF_DATA_PTR} ) +set( CMAKE_CXX_HAS_ISYSROOT 1 ) +set( CMAKE_CXX_COMPILER_ABI ELF ) +set( CMAKE_CXX_SOURCE_FILE_EXTENSIONS cc cp cxx cpp CPP c++ C ) +# force ASM compiler (required for CMake < 2.8.5) +set( CMAKE_ASM_COMPILER_ID_RUN TRUE ) +set( CMAKE_ASM_COMPILER_ID GNU ) +set( CMAKE_ASM_COMPILER_WORKS TRUE ) +set( CMAKE_ASM_COMPILER_FORCED TRUE ) +set( CMAKE_COMPILER_IS_GNUASM 1) +set( CMAKE_ASM_SOURCE_FILE_EXTENSIONS s S asm ) + +foreach( lang C CXX ASM ) + if( ANDROID_COMPILER_IS_CLANG ) + set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_CLANG_VERSION} ) + else() + set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_COMPILER_VERSION} ) + endif() +endforeach() + +# flags and definitions +remove_definitions( -DANDROID ) +add_definitions( -DANDROID ) + +if( ANDROID_SYSROOT MATCHES "[ ;\"]" ) + if( CMAKE_HOST_WIN32 ) + # try to convert path to 8.3 form + file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "@echo %~s1" ) + execute_process( COMMAND "$ENV{ComSpec}" /c "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "${ANDROID_SYSROOT}" + OUTPUT_VARIABLE __path OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE __result ERROR_QUIET ) + if( __result EQUAL 0 ) + file( TO_CMAKE_PATH "${__path}" ANDROID_SYSROOT ) + set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" ) + else() + set( ANDROID_CXX_FLAGS "--sysroot=\"${ANDROID_SYSROOT}\"" ) + endif() + else() + set( ANDROID_CXX_FLAGS "'--sysroot=${ANDROID_SYSROOT}'" ) + endif() + if( NOT _CMAKE_IN_TRY_COMPILE ) + # quotes can break try_compile and compiler identification + message(WARNING "Path to your Android NDK (or toolchain) has non-alphanumeric symbols.\nThe build might be broken.\n") + endif() +else() + set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" ) +endif() + +# NDK flags +if (ARM64_V8A ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) + set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" ) + endif() +elseif( ARMEABI OR ARMEABI_V7A) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) + if( NOT ANDROID_FORCE_ARM_BUILD AND NOT ARMEABI_V6 ) + set( ANDROID_CXX_FLAGS_RELEASE "-mthumb -fomit-frame-pointer -fno-strict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -finline-limit=64" ) + endif() + else() + # always compile ARMEABI_V6 in arm mode; otherwise there is no difference from ARMEABI + set( ANDROID_CXX_FLAGS_RELEASE "-marm -fomit-frame-pointer -fstrict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-marm -fno-omit-frame-pointer -fno-strict-aliasing" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" ) + endif() + endif() +elseif( X86 OR X86_64 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" ) + endif() + set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" ) + set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer -fno-strict-aliasing" ) +elseif( MIPS OR MIPS64 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-strict-aliasing -finline-functions -funwind-tables -fmessage-length=0" ) + set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer" ) + set( ANDROID_CXX_FLAGS_DEBUG "-fno-omit-frame-pointer" ) + if( NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" ) + set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" ) + endif() +elseif() + set( ANDROID_CXX_FLAGS_RELEASE "" ) + set( ANDROID_CXX_FLAGS_DEBUG "" ) +endif() + +set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" ) # good/necessary when porting desktop libraries + +if( NOT X86 AND NOT ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "-Wno-psabi ${ANDROID_CXX_FLAGS}" ) +endif() + +if( NOT ANDROID_COMPILER_VERSION VERSION_LESS "4.6" ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -no-canonical-prefixes" ) # see https://android-review.googlesource.com/#/c/47564/ +endif() + +# ABI-specific flags +if( ARMEABI_V7A ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv7-a -mfloat-abi=softfp" ) + if( NEON ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=neon" ) + elseif( VFPV3 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3" ) + else() + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3-d16" ) + endif() +elseif( ARMEABI_V6 ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv6 -mfloat-abi=softfp -mfpu=vfp" ) # vfp == vfpv2 +elseif( ARMEABI ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv5te -mtune=xscale -msoft-float" ) +endif() + +if( ANDROID_STL MATCHES "gnustl" AND (EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}") ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " ) + set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " ) + set( CMAKE_CXX_LINK_EXECUTABLE " -o " ) +else() + set( CMAKE_CXX_CREATE_SHARED_LIBRARY " -o " ) + set( CMAKE_CXX_CREATE_SHARED_MODULE " -o " ) + set( CMAKE_CXX_LINK_EXECUTABLE " -o " ) +endif() + +# STL +if( EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}" ) + if( EXISTS "${__libstl}" ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libstl}\"" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libstl}\"" ) + set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libstl}\"" ) + endif() + if( EXISTS "${__libsupcxx}" ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" ) + set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libsupcxx}\"" ) + # C objects: + set( CMAKE_C_CREATE_SHARED_LIBRARY " -o " ) + set( CMAKE_C_CREATE_SHARED_MODULE " -o " ) + set( CMAKE_C_LINK_EXECUTABLE " -o " ) + set( CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" ) + set( CMAKE_C_CREATE_SHARED_MODULE "${CMAKE_C_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" ) + set( CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE} \"${__libsupcxx}\"" ) + endif() + if( ANDROID_STL MATCHES "gnustl" ) + if( NOT EXISTS "${ANDROID_LIBM_PATH}" ) + set( ANDROID_LIBM_PATH -lm ) + endif() + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} ${ANDROID_LIBM_PATH}" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} ${ANDROID_LIBM_PATH}" ) + set( CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} ${ANDROID_LIBM_PATH}" ) + endif() +endif() + +# variables controlling optional build flags +if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7 + # libGLESv2.so in NDK's prior to r7 refers to missing external symbols. + # So this flag option is required for all projects using OpenGL from native. + __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES ON ) +else() + __INIT_VARIABLE( ANDROID_SO_UNDEFINED VALUES OFF ) +endif() +__INIT_VARIABLE( ANDROID_NO_UNDEFINED VALUES ON ) +__INIT_VARIABLE( ANDROID_FUNCTION_LEVEL_LINKING VALUES ON ) +__INIT_VARIABLE( ANDROID_GOLD_LINKER VALUES ON ) +__INIT_VARIABLE( ANDROID_NOEXECSTACK VALUES ON ) +__INIT_VARIABLE( ANDROID_RELRO VALUES ON ) + +set( ANDROID_NO_UNDEFINED ${ANDROID_NO_UNDEFINED} CACHE BOOL "Show all undefined symbols as linker errors" ) +set( ANDROID_SO_UNDEFINED ${ANDROID_SO_UNDEFINED} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" ) +set( ANDROID_FUNCTION_LEVEL_LINKING ${ANDROID_FUNCTION_LEVEL_LINKING} CACHE BOOL "Put each function in separate section and enable garbage collection of unused input sections at link time" ) +set( ANDROID_GOLD_LINKER ${ANDROID_GOLD_LINKER} CACHE BOOL "Enables gold linker" ) +set( ANDROID_NOEXECSTACK ${ANDROID_NOEXECSTACK} CACHE BOOL "Allows or disallows undefined symbols in shared libraries" ) +set( ANDROID_RELRO ${ANDROID_RELRO} CACHE BOOL "Enables RELRO - a memory corruption mitigation technique" ) +mark_as_advanced( ANDROID_NO_UNDEFINED ANDROID_SO_UNDEFINED ANDROID_FUNCTION_LEVEL_LINKING ANDROID_GOLD_LINKER ANDROID_NOEXECSTACK ANDROID_RELRO ) + +# linker flags +set( ANDROID_LINKER_FLAGS "" ) + +if( ARMEABI_V7A ) + # this is *required* to use the following linker flags that routes around + # a CPU bug in some Cortex-A8 implementations: + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--fix-cortex-a8" ) +endif() + +if( ANDROID_NO_UNDEFINED ) + if( MIPS ) + # there is some sysroot-related problem in mips linker... + if( NOT ANDROID_SYSROOT MATCHES "[ ;\"]" ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined -Wl,-rpath-link,${ANDROID_SYSROOT}/usr/lib" ) + endif() + else() + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined" ) + endif() +endif() + +if( ANDROID_SO_UNDEFINED ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-allow-shlib-undefined" ) +endif() + +if( ANDROID_FUNCTION_LEVEL_LINKING ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fdata-sections -ffunction-sections" ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--gc-sections" ) +endif() + +if( ANDROID_COMPILER_VERSION VERSION_EQUAL "4.6" ) + if( ANDROID_GOLD_LINKER AND (CMAKE_HOST_UNIX OR ANDROID_NDK_RELEASE_NUM GREATER 8002) AND (ARMEABI OR ARMEABI_V7A OR X86) ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=gold" ) + elseif( ANDROID_NDK_RELEASE_NUM GREATER 8002 ) # after r8b + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=bfd" ) + elseif( ANDROID_NDK_RELEASE STREQUAL "r8b" AND ARMEABI AND NOT _CMAKE_IN_TRY_COMPILE ) + message( WARNING "The default bfd linker from arm GCC 4.6 toolchain can fail with 'unresolvable R_ARM_THM_CALL relocation' error message. See https://code.google.com/p/android/issues/detail?id=35342 + On Linux and OS X host platform you can workaround this problem using gold linker (default). + Rerun cmake with -DANDROID_GOLD_LINKER=ON option in case of problems. +" ) + endif() +endif() # version 4.6 + +if( ANDROID_NOEXECSTACK ) + if( ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Xclang -mnoexecstack" ) + else() + set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -Wa,--noexecstack" ) + endif() + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,noexecstack" ) +endif() + +if( ANDROID_RELRO ) + set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now" ) +endif() + +if( ANDROID_COMPILER_IS_CLANG ) + set( ANDROID_CXX_FLAGS "-target ${ANDROID_LLVM_TRIPLE} -Qunused-arguments ${ANDROID_CXX_FLAGS}" ) + if( BUILD_WITH_ANDROID_NDK ) + set( ANDROID_CXX_FLAGS "-gcc-toolchain ${ANDROID_TOOLCHAIN_ROOT} ${ANDROID_CXX_FLAGS}" ) + endif() +endif() + +# cache flags +set( CMAKE_CXX_FLAGS "" CACHE STRING "c++ flags" ) +set( CMAKE_C_FLAGS "" CACHE STRING "c flags" ) +set( CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c++ Release flags" ) +set( CMAKE_C_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "c Release flags" ) +set( CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c++ Debug flags" ) +set( CMAKE_C_FLAGS_DEBUG "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c Debug flags" ) +set( CMAKE_SHARED_LINKER_FLAGS "" CACHE STRING "shared linker flags" ) +set( CMAKE_MODULE_LINKER_FLAGS "" CACHE STRING "module linker flags" ) +set( CMAKE_EXE_LINKER_FLAGS "-Wl,-z,nocopyreloc" CACHE STRING "executable linker flags" ) + +# put flags to cache (for debug purpose only) +set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS}" CACHE INTERNAL "Android specific c/c++ flags" ) +set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE}" CACHE INTERNAL "Android specific c/c++ Release flags" ) +set( ANDROID_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG}" CACHE INTERNAL "Android specific c/c++ Debug flags" ) +set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS}" CACHE INTERNAL "Android specific c/c++ linker flags" ) + +# finish flags +set( CMAKE_CXX_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" ) +set( CMAKE_C_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_C_FLAGS}" ) +set( CMAKE_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS_RELEASE}" ) +set( CMAKE_C_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_C_FLAGS_RELEASE}" ) +set( CMAKE_CXX_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_DEBUG}" ) +set( CMAKE_C_FLAGS_DEBUG "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_C_FLAGS_DEBUG}" ) +set( CMAKE_SHARED_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" ) +set( CMAKE_MODULE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" ) +set( CMAKE_EXE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" ) + +if( MIPS AND BUILD_WITH_ANDROID_NDK AND ANDROID_NDK_RELEASE STREQUAL "r8" ) + set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_SHARED_LINKER_FLAGS}" ) + set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_MODULE_LINKER_FLAGS}" ) + set( CMAKE_EXE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.x ${CMAKE_EXE_LINKER_FLAGS}" ) +endif() + +# pie/pic +if( NOT (ANDROID_NATIVE_API_LEVEL LESS 16) AND (NOT DEFINED ANDROID_APP_PIE OR ANDROID_APP_PIE) AND (CMAKE_VERSION VERSION_GREATER 2.8.8) ) + set( CMAKE_POSITION_INDEPENDENT_CODE TRUE ) + set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie") +else() + set( CMAKE_POSITION_INDEPENDENT_CODE FALSE ) + set( CMAKE_CXX_FLAGS "-fpic ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_C_FLAGS "-fpic ${CMAKE_C_FLAGS}" ) +endif() + +# configure rtti +if( DEFINED ANDROID_RTTI AND ANDROID_STL_FORCE_FEATURES ) + if( ANDROID_RTTI ) + set( CMAKE_CXX_FLAGS "-frtti ${CMAKE_CXX_FLAGS}" ) + else() + set( CMAKE_CXX_FLAGS "-fno-rtti ${CMAKE_CXX_FLAGS}" ) + endif() +endif() + +# configure exceptios +if( DEFINED ANDROID_EXCEPTIONS AND ANDROID_STL_FORCE_FEATURES ) + if( ANDROID_EXCEPTIONS ) + set( CMAKE_CXX_FLAGS "-fexceptions ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_C_FLAGS "-fexceptions ${CMAKE_C_FLAGS}" ) + else() + set( CMAKE_CXX_FLAGS "-fno-exceptions ${CMAKE_CXX_FLAGS}" ) + set( CMAKE_C_FLAGS "-fno-exceptions ${CMAKE_C_FLAGS}" ) + endif() +endif() + +# global includes and link directories +include_directories( SYSTEM "${ANDROID_SYSROOT}/usr/include" ${ANDROID_STL_INCLUDE_DIRS} ) +get_filename_component(__android_install_path "${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_ABI_NAME}" ABSOLUTE) # avoid CMP0015 policy warning +link_directories( "${__android_install_path}" ) + +# detect if need link crtbegin_so.o explicitly +if( NOT DEFINED ANDROID_EXPLICIT_CRT_LINK ) + set( __cmd "${CMAKE_CXX_CREATE_SHARED_LIBRARY}" ) + string( REPLACE "" "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_CXX_FLAGS}" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_SHARED_LINKER_FLAGS}" __cmd "${__cmd}" ) + string( REPLACE "" "-shared" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + string( REPLACE "" "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain_crtlink_test.so" __cmd "${__cmd}" ) + string( REPLACE "" "\"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" __cmd "${__cmd}" ) + string( REPLACE "" "" __cmd "${__cmd}" ) + separate_arguments( __cmd ) + foreach( __var ANDROID_NDK ANDROID_NDK_TOOLCHAINS_PATH ANDROID_STANDALONE_TOOLCHAIN ) + if( ${__var} ) + set( __tmp "${${__var}}" ) + separate_arguments( __tmp ) + string( REPLACE "${__tmp}" "${${__var}}" __cmd "${__cmd}") + endif() + endforeach() + string( REPLACE "'" "" __cmd "${__cmd}" ) + string( REPLACE "\"" "" __cmd "${__cmd}" ) + execute_process( COMMAND ${__cmd} RESULT_VARIABLE __cmd_result OUTPUT_QUIET ERROR_QUIET ) + if( __cmd_result EQUAL 0 ) + set( ANDROID_EXPLICIT_CRT_LINK ON ) + else() + set( ANDROID_EXPLICIT_CRT_LINK OFF ) + endif() +endif() + +if( ANDROID_EXPLICIT_CRT_LINK ) + set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" ) + set( CMAKE_CXX_CREATE_SHARED_MODULE "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" ) +endif() + +# setup output directories +set( CMAKE_INSTALL_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" ) + +if( DEFINED LIBRARY_OUTPUT_PATH_ROOT + OR EXISTS "${CMAKE_SOURCE_DIR}/AndroidManifest.xml" + OR (EXISTS "${CMAKE_SOURCE_DIR}/../AndroidManifest.xml" AND EXISTS "${CMAKE_SOURCE_DIR}/../jni/") ) + set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "Root for binaries output, set this to change where Android libs are installed to" ) + if( NOT _CMAKE_IN_TRY_COMPILE ) + if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" ) + set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" ) + else() + set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" ) + endif() + set( LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for Android libs" ) + endif() +endif() + +# copy shaed stl library to build directory +if( NOT _CMAKE_IN_TRY_COMPILE AND __libstl MATCHES "[.]so$" AND DEFINED LIBRARY_OUTPUT_PATH ) + get_filename_component( __libstlname "${__libstl}" NAME ) + execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${__libstl}" "${LIBRARY_OUTPUT_PATH}/${__libstlname}" RESULT_VARIABLE __fileCopyProcess ) + if( NOT __fileCopyProcess EQUAL 0 OR NOT EXISTS "${LIBRARY_OUTPUT_PATH}/${__libstlname}") + message( SEND_ERROR "Failed copying of ${__libstl} to the ${LIBRARY_OUTPUT_PATH}/${__libstlname}" ) + endif() + unset( __fileCopyProcess ) + unset( __libstlname ) +endif() + + +# set these global flags for cmake client scripts to change behavior +set( ANDROID True ) +set( BUILD_ANDROID True ) + +# where is the target environment +set( CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_ROOT}/bin" "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" "${ANDROID_SYSROOT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/share" ) + +# only search for libraries and includes in the ndk toolchain +set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) +set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) +set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) + + +# macro to find packages on the host OS +macro( find_host_package ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) + if( CMAKE_HOST_WIN32 ) + SET( WIN32 1 ) + SET( UNIX ) + elseif( CMAKE_HOST_APPLE ) + SET( APPLE 1 ) + SET( UNIX ) + endif() + find_package( ${ARGN} ) + SET( WIN32 ) + SET( APPLE ) + SET( UNIX 1 ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) +endmacro() + + +# macro to find programs on the host OS +macro( find_host_program ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER ) + if( CMAKE_HOST_WIN32 ) + SET( WIN32 1 ) + SET( UNIX ) + elseif( CMAKE_HOST_APPLE ) + SET( APPLE 1 ) + SET( UNIX ) + endif() + find_program( ${ARGN} ) + SET( WIN32 ) + SET( APPLE ) + SET( UNIX 1 ) + set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY ) + set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY ) +endmacro() + + +# export toolchain settings for the try_compile() command +if( NOT _CMAKE_IN_TRY_COMPILE ) + set( __toolchain_config "") + foreach( __var NDK_CCACHE LIBRARY_OUTPUT_PATH_ROOT ANDROID_FORBID_SYGWIN + ANDROID_NDK_HOST_X64 + ANDROID_NDK + ANDROID_NDK_LAYOUT + ANDROID_STANDALONE_TOOLCHAIN + ANDROID_TOOLCHAIN_NAME + ANDROID_ABI + ANDROID_NATIVE_API_LEVEL + ANDROID_STL + ANDROID_STL_FORCE_FEATURES + ANDROID_FORCE_ARM_BUILD + ANDROID_NO_UNDEFINED + ANDROID_SO_UNDEFINED + ANDROID_FUNCTION_LEVEL_LINKING + ANDROID_GOLD_LINKER + ANDROID_NOEXECSTACK + ANDROID_RELRO + ANDROID_LIBM_PATH + ANDROID_EXPLICIT_CRT_LINK + ANDROID_APP_PIE + ) + if( DEFINED ${__var} ) + if( ${__var} MATCHES " ") + set( __toolchain_config "${__toolchain_config}set( ${__var} \"${${__var}}\" CACHE INTERNAL \"\" )\n" ) + else() + set( __toolchain_config "${__toolchain_config}set( ${__var} ${${__var}} CACHE INTERNAL \"\" )\n" ) + endif() + endif() + endforeach() + file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android.toolchain.config.cmake" "${__toolchain_config}" ) + unset( __toolchain_config ) +endif() + + +# force cmake to produce / instead of \ in build commands for Ninja generator +if( CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_HOST_WIN32 ) + # it is a bad hack after all + # CMake generates Ninja makefiles with UNIX paths only if it thinks that we are going to build with MinGW + set( CMAKE_COMPILER_IS_MINGW TRUE ) # tell CMake that we are MinGW + set( CMAKE_CROSSCOMPILING TRUE ) # stop recursion + enable_language( C ) + enable_language( CXX ) + # unset( CMAKE_COMPILER_IS_MINGW ) # can't unset because CMake does not convert back-slashes in response files without it + unset( MINGW ) +endif() + + +# Variables controlling behavior or set by cmake toolchain: +# ANDROID_ABI : "armeabi-v7a" (default), "armeabi", "armeabi-v7a with NEON", "armeabi-v7a with VFPV3", "armeabi-v6 with VFP", "x86", "mips", "arm64-v8a", "x86_64", "mips64" +# ANDROID_NATIVE_API_LEVEL : 3,4,5,8,9,14,15,16,17,18,19,21 (depends on NDK version) +# ANDROID_STL : gnustl_static/gnustl_shared/stlport_static/stlport_shared/gabi++_static/gabi++_shared/system_re/system/none +# ANDROID_FORBID_SYGWIN : ON/OFF +# ANDROID_NO_UNDEFINED : ON/OFF +# ANDROID_SO_UNDEFINED : OFF/ON (default depends on NDK version) +# ANDROID_FUNCTION_LEVEL_LINKING : ON/OFF +# ANDROID_GOLD_LINKER : ON/OFF +# ANDROID_NOEXECSTACK : ON/OFF +# ANDROID_RELRO : ON/OFF +# ANDROID_FORCE_ARM_BUILD : ON/OFF +# ANDROID_STL_FORCE_FEATURES : ON/OFF +# ANDROID_LIBM_PATH : path to libm.so (set to something like $(TOP)/out/target/product//obj/lib/libm.so) to workaround unresolved `sincos` +# Can be set only at the first run: +# ANDROID_NDK : path to your NDK install +# NDK_CCACHE : path to your ccache executable +# ANDROID_TOOLCHAIN_NAME : the NDK name of compiler toolchain +# ANDROID_NDK_HOST_X64 : try to use x86_64 toolchain (default for x64 host systems) +# ANDROID_NDK_LAYOUT : the inner NDK structure (RELEASE, LINARO, ANDROID) +# LIBRARY_OUTPUT_PATH_ROOT : +# ANDROID_STANDALONE_TOOLCHAIN +# +# Primary read-only variables: +# ANDROID : always TRUE +# ARMEABI : TRUE for arm v6 and older devices +# ARMEABI_V6 : TRUE for arm v6 +# ARMEABI_V7A : TRUE for arm v7a +# ARM64_V8A : TRUE for arm64-v8a +# NEON : TRUE if NEON unit is enabled +# VFPV3 : TRUE if VFP version 3 is enabled +# X86 : TRUE if configured for x86 +# X86_64 : TRUE if configured for x86_64 +# MIPS : TRUE if configured for mips +# MIPS64 : TRUE if configured for mips64 +# BUILD_WITH_ANDROID_NDK : TRUE if NDK is used +# BUILD_WITH_STANDALONE_TOOLCHAIN : TRUE if standalone toolchain is used +# ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86" or "darwin-x86" depending on host platform +# ANDROID_NDK_ABI_NAME : "armeabi", "armeabi-v7a", "x86", "mips", "arm64-v8a", "x86_64", "mips64" depending on ANDROID_ABI +# ANDROID_NDK_RELEASE : from r5 to r10d; set only for NDK +# ANDROID_NDK_RELEASE_NUM : numeric ANDROID_NDK_RELEASE version (1000*major+minor) +# ANDROID_ARCH_NAME : "arm", "x86", "mips", "arm64", "x86_64", "mips64" depending on ANDROID_ABI +# ANDROID_SYSROOT : path to the compiler sysroot +# TOOL_OS_SUFFIX : "" or ".exe" depending on host platform +# ANDROID_COMPILER_IS_CLANG : TRUE if clang compiler is used +# +# Secondary (less stable) read-only variables: +# ANDROID_COMPILER_VERSION : GCC version used (not Clang version) +# ANDROID_CLANG_VERSION : version of clang compiler if clang is used +# ANDROID_CXX_FLAGS : C/C++ compiler flags required by Android platform +# ANDROID_SUPPORTED_ABIS : list of currently allowed values for ANDROID_ABI +# ANDROID_TOOLCHAIN_MACHINE_NAME : "arm-linux-androideabi", "arm-eabi" or "i686-android-linux" +# ANDROID_TOOLCHAIN_ROOT : path to the top level of toolchain (standalone or placed inside NDK) +# ANDROID_CLANG_TOOLCHAIN_ROOT : path to clang tools +# ANDROID_SUPPORTED_NATIVE_API_LEVELS : list of native API levels found inside NDK +# ANDROID_STL_INCLUDE_DIRS : stl include paths +# ANDROID_RTTI : if rtti is enabled by the runtime +# ANDROID_EXCEPTIONS : if exceptions are enabled by the runtime +# ANDROID_GCC_TOOLCHAIN_NAME : read-only, differs from ANDROID_TOOLCHAIN_NAME only if clang is used +# +# Defaults: +# ANDROID_DEFAULT_NDK_API_LEVEL +# ANDROID_DEFAULT_NDK_API_LEVEL_${ARCH} +# ANDROID_NDK_SEARCH_PATHS +# ANDROID_SUPPORTED_ABIS_${ARCH} +# ANDROID_SUPPORTED_NDK_VERSIONS diff --git a/contrib/android-cmake/ndk_links.md b/contrib/android-cmake/ndk_links.md new file mode 100644 index 000000000..6d93d61d2 --- /dev/null +++ b/contrib/android-cmake/ndk_links.md @@ -0,0 +1,211 @@ + +============== r1 ============== (dead links) + +* http://dl.google.com/android/ndk/android-ndk-1.5_r1-windows.zip +* http://dl.google.com/android/ndk/android-ndk-1.5_r1-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-1.5_r1-linux-x86.zip + +============== r2 ============== + +* http://dl.google.com/android/ndk/android-ndk-1.6_r1-windows.zip +* http://dl.google.com/android/ndk/android-ndk-1.6_r1-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-1.6_r1-linux-x86.zip + +============== r3 ============== + +* http://dl.google.com/android/ndk/android-ndk-r3-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r3-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r3-linux-x86.zip + +============== r4 ============== + +* http://dl.google.com/android/ndk/android-ndk-r4-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r4-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r4-linux-x86.zip + +============== r4b ============== + +* http://dl.google.com/android/ndk/android-ndk-r4b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r4b-darwin-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r4b-linux-x86.zip + +============== r5 ============== + +* http://dl.google.com/android/ndk/android-ndk-r5-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r5-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r5-linux-x86.tar.bz2 + +============== r5b ============== + +* http://dl.google.com/android/ndk/android-ndk-r5b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r5b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r5b-linux-x86.tar.bz2 + +============== r5c ============== + +* http://dl.google.com/android/ndk/android-ndk-r5c-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r5c-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r5c-linux-x86.tar.bz2 + +============== r6 ============== + +* http://dl.google.com/android/ndk/android-ndk-r6-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r6-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r6-linux-x86.tar.bz2 + +============== r6b ============== + +* http://dl.google.com/android/ndk/android-ndk-r6b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r6b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r6b-linux-x86.tar.bz2 + +============== r7 ============== + +* http://dl.google.com/android/ndk/android-ndk-r7-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r7-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r7-linux-x86.tar.bz2 + +============== r7b ============== + +* http://dl.google.com/android/ndk/android-ndk-r7b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r7b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r7b-linux-x86.tar.bz2 + +============== r7c ============== + +* http://dl.google.com/android/ndk/android-ndk-r7c-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r7c-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r7c-linux-x86.tar.bz2 + +============== r8 ============== + +* http://dl.google.com/android/ndk/android-ndk-r8-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8-linux-x86.tar.bz2 + +============== r8b ============== + +* http://dl.google.com/android/ndk/android-ndk-r8b-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8b-linux-x86.tar.bz2 + +============== r8c ============== + +* http://dl.google.com/android/ndk/android-ndk-r8c-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8c-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8c-linux-x86.tar.bz2 + +============== r8d ============== + +* http://dl.google.com/android/ndk/android-ndk-r8d-windows.zip +* http://dl.google.com/android/ndk/android-ndk-r8d-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8d-linux-x86.tar.bz2 + +============== r8e ============== + +* http://dl.google.com/android/ndk/android-ndk-r8e-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r8e-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8e-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r8e-linux-x86_64.tar.bz2 + +============== r9 ============== + +* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86-legacy-toolchains.zip +* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86_64-legacy-toolchains.zip +* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86_64-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86_64-legacy-toolchains.tar.bz2 + +============== r9b ============== + +* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86-legacy-toolchains.zip +* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86_64-legacy-toolchains.zip +* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86_64-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86-legacy-toolchains.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86_64-legacy-toolchains.tar.bz2 + +============== r9c ============== + +* http://dl.google.com/android/ndk/android-ndk-r9c-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9c-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9c-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9c-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9c-cxx-stl-libs-with-debugging-info.zip + +============== r9d ============== + +* http://dl.google.com/android/ndk/android-ndk-r9d-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk-r9d-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk-r9d-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9d-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r9d-cxx-stl-libs-with-debug-info.zip + +============== r10 ============== + +* http://dl.google.com/android/ndk/android-ndk32-r10-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk32-r10-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk32-r10-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk64-r10-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk64-r10-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r10-cxx-stl-libs-with-debug-info.zip + +============== r10b ============== + +* http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk32-r10b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10b-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10b-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk32-r10b-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10b-windows-x86.zip +* http://dl.google.com/android/ndk/android-ndk64-r10b-windows-x86_64.zip +* http://dl.google.com/android/ndk/android-ndk64-r10b-darwin-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10b-darwin-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10b-linux-x86.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk64-r10b-linux-x86_64.tar.bz2 +* http://dl.google.com/android/ndk/android-ndk-r10b-cxx-stl-libs-with-debug-info.zip + +============== r10c ============== + +* http://dl.google.com/android/ndk/android-ndk-r10c-windows-x86.exe +* http://dl.google.com/android/ndk/android-ndk-r10c-windows-x86_64.exe +* http://dl.google.com/android/ndk/android-ndk-r10c-darwin-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10c-darwin-x86_64.bin +* http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86_64.bin + +============== r10d ============== + +* http://dl.google.com/android/ndk/android-ndk-r10d-windows-x86.exe +* http://dl.google.com/android/ndk/android-ndk-r10d-windows-x86_64.exe +* http://dl.google.com/android/ndk/android-ndk-r10d-darwin-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10d-darwin-x86_64.bin +* http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86.bin +* http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86_64.bin diff --git a/contrib/clipper/clipper.cpp b/contrib/clipper/clipper.cpp index c8c62bc2a..074f22b21 100644 --- a/contrib/clipper/clipper.cpp +++ b/contrib/clipper/clipper.cpp @@ -26,7 +26,7 @@ * Paper no. DETC2005-85513 pp. 565-575 * * ASME 2005 International Design Engineering Technical Conferences * * and Computers and Information in Engineering Conference (IDETC/CIE2005) * -* September 24–28, 2005 , Long Beach, California, USA * +* September 24-28, 2005 , Long Beach, California, USA * * http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * * * *******************************************************************************/ @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -2365,6 +2366,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge) //ok, so far it looks like we're still in range of the horizontal edge if ( e->xcurr == horzEdge->xtop && !eMaxPair ) { + assert(horzEdge->nextInLML); if (SlopesEqual(*e, *horzEdge->nextInLML, m_UseFullRange)) { //if output polygons share an edge, they'll need joining later ... @@ -2429,6 +2431,7 @@ void Clipper::ProcessHorizontal(TEdge *horzEdge) if ( horzEdge->outIdx >= 0 ) IntersectEdges( horzEdge, eMaxPair, IntPoint(horzEdge->xtop, horzEdge->ycurr), ipBoth); + assert(eMaxPair); if (eMaxPair->outIdx >= 0) throw clipperException("ProcessHorizontal error"); DeleteFromAEL(eMaxPair); DeleteFromAEL(horzEdge); diff --git a/contrib/clipper/clipper.hpp b/contrib/clipper/clipper.hpp index 3d6510dff..7cdac6c3f 100644 --- a/contrib/clipper/clipper.hpp +++ b/contrib/clipper/clipper.hpp @@ -26,7 +26,7 @@ * Paper no. DETC2005-85513 pp. 565-575 * * ASME 2005 International Design Engineering Technical Conferences * * and Computers and Information in Engineering Conference (IDETC/CIE2005) * -* September 24–28, 2005 , Long Beach, California, USA * +* September 24-28, 2005 , Long Beach, California, USA * * http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf * * * *******************************************************************************/ diff --git a/contrib/irrXML/CMakeLists.txt b/contrib/irrXML/CMakeLists.txt new file mode 100644 index 000000000..48941970a --- /dev/null +++ b/contrib/irrXML/CMakeLists.txt @@ -0,0 +1,22 @@ +set( IrrXML_SRCS + CXMLReaderImpl.h + heapsort.h + irrArray.h + irrString.h + irrTypes.h + irrXML.cpp + irrXML.h +) + +if ( MSVC ) + ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS ) + ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS ) +endif ( MSVC ) + +add_library(IrrXML STATIC ${IrrXML_SRCS}) +set(IRRXML_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "IrrXML_Include" ) +set(IRRXML_LIBRARY "IrrXML" CACHE INTERNAL "IrrXML" ) + +install(TARGETS IrrXML + ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} + COMPONENT ${LIBASSIMP_COMPONENT}) diff --git a/contrib/openddlparser/CMakeLists.txt b/contrib/openddlparser/CMakeLists.txt index a39d0219f..9e903ca3f 100644 --- a/contrib/openddlparser/CMakeLists.txt +++ b/contrib/openddlparser/CMakeLists.txt @@ -3,18 +3,40 @@ PROJECT( OpenDDL-Parser ) SET ( OPENDDL_PARSER_VERSION_MAJOR 0 ) SET ( OPENDDL_PARSER_VERSION_MINOR 1 ) SET ( OPENDDL_PARSER_VERSION_PATCH 0 ) -SET ( OPENDDL_PARSER_VERSION ${CPPCORE_VERSION_MAJOR}.${CPPCORE_VERSION_MINOR}.${CPPCORE_VERSION_PATCH} ) +SET ( OPENDDL_PARSER_VERSION ${OPENDDL_PARSER_VERSION_MAJOR}.${OPENDDL_PARSER_VERSION_MINOR}.${OPENDDL_PARSER_VERSION_PATCH} ) SET ( PROJECT_VERSION "${OPENDDL_PARSER_VERSION}" ) +option( DDL_USE_CPP11 "Set to ON to use C++11 features ( always on on windows )." ON ) +option( DDL_DEBUG_OUTPUT "Set to ON to use output debug texts" OFF ) +option( DDL_STATIC_LIBRARY "Set to ON to build static libary of OpenDDL Parser." ON ) +option( COVERALLS "Generate coveralls data" OFF ) + +if ( DDL_USE_CPP11 ) + if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX ) + set( OPENDDL_CXXFLAGS -std=c++0x ) + elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + set( OPENDDL_CXXFLAGS --std=c++11 ) + endif() +else( DDL_USE_CPP11 ) + add_definitions( -DOPENDDL_NO_USE_CPP11 ) +endif( DDL_USE_CPP11) + if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX ) find_package(Threads) else() add_definitions( -D_CRT_SECURE_NO_WARNINGS ) endif() +if ( DDL_STATIC_LIBRARY ) + add_definitions( -DOPENDDL_STATIC_LIBARY ) +endif() + add_definitions( -DOPENDDLPARSER_BUILD ) -add_definitions( -DOPENDDL_NO_USE_CPP11 ) add_definitions( -D_VARIADIC_MAX=10 ) +add_definitions( -DGTEST_HAS_PTHREAD=0 ) +if ( DDL_DEBUG_OUTPUT ) + add_definitions( -DDDL_DEBUG_HEADER_NAME) +endif() INCLUDE_DIRECTORIES( ./ @@ -24,9 +46,10 @@ INCLUDE_DIRECTORIES( ) link_directories( - ./ + ${CMAKE_HOME_DIRECTORY}/lib ) +set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake ) SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib ) SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/lib ) SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_HOME_DIRECTORY}/bin ) @@ -40,18 +63,38 @@ if( WIN32 AND NOT CYGWIN ) endif() elseif( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX ) # Update if necessary - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -std=c++0x") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic ${OPENDDL_CXXFLAGS}") elseif ( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" ) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic -std=c++11") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic ${OPENDDL_CXXFLAGS} -Wwrite-strings") endif() +if (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() + +# Include the doc component. +FIND_PACKAGE( doxygen ) +IF ( DOXYGEN_FOUND ) + CONFIGURE_FILE( doc/openddlparser_doc.in doc/doxygenfile @ONLY ) + ADD_CUSTOM_TARGET( doc ALL ${DOXYGEN_EXECUTABLE} doc/doxygenfile + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen" VERBATIM ) +ENDIF ( DOXYGEN_FOUND ) + SET ( openddl_parser_src + code/OpenDDLCommon.cpp + code/OpenDDLExport.cpp code/OpenDDLParser.cpp + code/OpenDDLStream.cpp code/DDLNode.cpp code/Value.cpp + include/openddlparser/OpenDDLCommon.h + include/openddlparser/OpenDDLExport.h include/openddlparser/OpenDDLParser.h include/openddlparser/OpenDDLParserUtils.h - include/openddlparser/OpenDDLCommon.h + include/openddlparser/OpenDDLStream.h include/openddlparser/DDLNode.h include/openddlparser/Value.h README.md @@ -59,6 +102,69 @@ SET ( openddl_parser_src SOURCE_GROUP( code FILES ${openddl_parser_src} ) -ADD_LIBRARY( openddl_parser SHARED - ${openddl_parser_src} +if ( DDL_STATIC_LIBRARY ) + ADD_LIBRARY( openddl_parser STATIC + ${openddl_parser_src} + ) +else() + ADD_LIBRARY( openddl_parser SHARED + ${openddl_parser_src} + ) +endif() + +SET ( GTEST_PATH contrib/gtest-1.7.0 ) + +SET ( gtest_src + ${GTEST_PATH}/src/gtest-death-test.cc + ${GTEST_PATH}/src/gtest-filepath.cc + ${GTEST_PATH}/src/gtest-internal-inl.h + ${GTEST_PATH}/src/gtest-port.cc + ${GTEST_PATH}/src/gtest-printers.cc + ${GTEST_PATH}/src/gtest-test-part.cc + ${GTEST_PATH}/src/gtest-typed-test.cc + ${GTEST_PATH}/src/gtest.cc + ${GTEST_PATH}/src/gtest_main.cc ) + +SET( openddl_parser_unittest_src + test/UnitTestCommon.h + test/DDLNodeTest.cpp + test/OpenDDLCommonTest.cpp + test/OpenDDLExportTest.cpp + test/OpenDDLParserTest.cpp + test/OpenDDLParserUtilsTest.cpp + test/OpenDDLStreamTest.cpp + test/OpenDDLIntegrationTest.cpp + test/ValueTest.cpp + test/OpenDDLDefectsTest.cpp +) + +SOURCE_GROUP( code FILES ${openddl_parser_unittest_src} ) +SOURCE_GROUP( gtest FILES ${gtest_src} ) + +ADD_EXECUTABLE( openddl_parser_unittest + ${gtest_src} + ${openddl_parser_unittest_src} +) + +target_link_libraries( openddl_parser_unittest openddl_parser ${CMAKE_THREAD_LIBS_INIT} ) + +SET( openddl_parser_demo_src + demo/main.cpp +) + +if (COVERALLS) + set(COVERAGE_SRCS ${gtest_src} ${openddl_parser_unittest_src} ) + + # Create the coveralls target. + coveralls_setup( + "${COVERAGE_SRCS}" # The source files. + ON # If we should upload. + "${PROJECT_SOURCE_DIR}/cmake/") # (Optional) Alternate project cmake module path. +endif() + +ADD_EXECUTABLE( openddl_parser_demo + ${openddl_parser_demo_src} +) + +target_link_libraries( openddl_parser_demo openddl_parser ) diff --git a/contrib/openddlparser/CREDITS b/contrib/openddlparser/CREDITS index a2b01eb13..d3936af83 100644 --- a/contrib/openddlparser/CREDITS +++ b/contrib/openddlparser/CREDITS @@ -12,5 +12,8 @@ Improvements value interface, serveral bugfixes. - Henry Read ( henrya2 ): Static build option, Interface improvements +- (wise86-android) +fix several mem-leaks + - Paul Holland ( pkholland ): Bugfixes. diff --git a/contrib/openddlparser/README.md b/contrib/openddlparser/README.md index 619747d23..a48ea1be0 100644 --- a/contrib/openddlparser/README.md +++ b/contrib/openddlparser/README.md @@ -11,7 +11,7 @@ Current coverity check status: Coverity Scan Build Status - +Current test coverage:[![Coverage Status](https://coveralls.io/repos/github/kimkulling/openddl-parser/badge.svg?branch=master)](https://coveralls.io/github/kimkulling/openddl-parser?branch=cpp_coveralls) Get the source code =================== You can get the code from our git repository, which is located at GitHub. You can clone the repository with the following command: @@ -25,7 +25,7 @@ After installing it you can open a console and enter: > cmake CMakeLists.txt -This command will generate a build environment for your installed build enrironment ( for Visual-Studio-users the project files will be generated, for gcc-users the makefiles will be generated ). +This command will generate a build environment for your preferred build tool ( for Visual-Studio-users the project files will be generated, for gcc-users the makefiles will be generated ). When using an IDE open the IDE and run the build. When using GNU-make type in your console: > make diff --git a/contrib/openddlparser/code/DDLNode.cpp b/contrib/openddlparser/code/DDLNode.cpp index 0cc95bdfc..a7c557fc5 100644 --- a/contrib/openddlparser/code/DDLNode.cpp +++ b/contrib/openddlparser/code/DDLNode.cpp @@ -68,8 +68,8 @@ DDLNode::DDLNode( const std::string &type, const std::string &name, size_t idx, } DDLNode::~DDLNode() { - releaseDataType( m_properties ); - releaseDataType( m_value ); + delete m_properties; + delete m_value; releaseReferencedNames( m_references ); delete m_dtArrayList; @@ -77,6 +77,9 @@ DDLNode::~DDLNode() { if( s_allocatedNodes[ m_idx ] == this ) { s_allocatedNodes[ m_idx ] = ddl_nullptr; } + for ( size_t i = 0; i::iterator it; - it = std::find( m_parent->m_children.begin(), m_parent->m_children.end(), this ); + if( ddl_nullptr != m_parent ) { + DDLNodeIt it = std::find( m_parent->m_children.begin(), m_parent->m_children.end(), this ); if( m_parent->m_children.end() != it ) { m_parent->m_children.erase( it ); } @@ -126,6 +128,8 @@ const std::string &DDLNode::getName() const { } void DDLNode::setProperties( Property *prop ) { + if(m_properties!=ddl_nullptr) + delete m_properties; m_properties = prop; } @@ -187,6 +191,10 @@ Reference *DDLNode::getReferences() const { return m_references; } +void DDLNode::dump(IOStreamBase &/*stream*/) { + // Todo! +} + DDLNode *DDLNode::create( const std::string &type, const std::string &name, DDLNode *parent ) { const size_t idx( s_allocatedNodes.size() ); DDLNode *node = new DDLNode( type, name, idx, parent ); @@ -197,7 +205,7 @@ DDLNode *DDLNode::create( const std::string &type, const std::string &name, DDLN void DDLNode::releaseNodes() { if( s_allocatedNodes.size() > 0 ) { - for( DllNodeList::iterator it = s_allocatedNodes.begin(); it != s_allocatedNodes.end(); it++ ) { + for( DDLNodeIt it = s_allocatedNodes.begin(); it != s_allocatedNodes.end(); it++ ) { if( *it ) { delete *it; } diff --git a/contrib/openddlparser/code/OpenDDLCommon.cpp b/contrib/openddlparser/code/OpenDDLCommon.cpp index 13a96f7a8..5c341a780 100644 --- a/contrib/openddlparser/code/OpenDDLCommon.cpp +++ b/contrib/openddlparser/code/OpenDDLCommon.cpp @@ -22,6 +22,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -----------------------------------------------------------------------------------------------*/ #include #include +#include BEGIN_ODDLPARSER_NS @@ -84,7 +85,14 @@ Name::~Name() { m_id = ddl_nullptr; } -Reference::Reference() +Name::Name( const Name &name ){ + m_type=name.m_type; + m_id=new Text(name.m_id->m_buffer,name.m_id->m_len); +} + + + + Reference::Reference() : m_numRefs( 0 ) , m_referencedName( ddl_nullptr ) { // empty @@ -96,8 +104,16 @@ Reference::Reference( size_t numrefs, Name **names ) if ( numrefs > 0 ) { m_referencedName = new Name *[ numrefs ]; for ( size_t i = 0; i < numrefs; i++ ) { - Name *name = new Name( names[ i ]->m_type, names[ i ]->m_id ); - m_referencedName[ i ] = name; + m_referencedName[ i ] = names[i]; + } + } +} +Reference::Reference(const Reference &ref) { + m_numRefs=ref.m_numRefs; + if(m_numRefs!=0){ + m_referencedName = new Name*[m_numRefs]; + for ( size_t i = 0; i < m_numRefs; i++ ) { + m_referencedName[i] = new Name(*ref.m_referencedName[i]); } } } @@ -107,6 +123,7 @@ Reference::~Reference() { delete m_referencedName[ i ]; } m_numRefs = 0; + delete [] m_referencedName; m_referencedName = ddl_nullptr; } @@ -135,21 +152,30 @@ Property::Property( Text *id ) } Property::~Property() { - m_key = ddl_nullptr; - m_value = ddl_nullptr; - m_ref = ddl_nullptr;; - m_next = ddl_nullptr;; + delete m_key; + if(m_value!=ddl_nullptr) + delete m_value; + if(m_ref!=ddl_nullptr) + delete(m_ref); + if(m_next!=ddl_nullptr) + delete m_next; } DataArrayList::DataArrayList() : m_numItems( 0 ) , m_dataList( ddl_nullptr ) -, m_next( ddl_nullptr ) { +, m_next( ddl_nullptr ) +, m_refs(ddl_nullptr) +, m_numRefs(0){ // empty } DataArrayList::~DataArrayList() { - // empty + delete m_dataList; + if(m_next!=ddl_nullptr) + delete m_next; + if(m_refs!=ddl_nullptr) + delete m_refs; } size_t DataArrayList::size() { diff --git a/contrib/openddlparser/code/OpenDDLExport.cpp b/contrib/openddlparser/code/OpenDDLExport.cpp index 49207c044..e45fb041a 100644 --- a/contrib/openddlparser/code/OpenDDLExport.cpp +++ b/contrib/openddlparser/code/OpenDDLExport.cpp @@ -29,60 +29,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. BEGIN_ODDLPARSER_NS -StreamFormatterBase::StreamFormatterBase() { - -} - -StreamFormatterBase::~StreamFormatterBase() { - -} - -std::string StreamFormatterBase::format( const std::string &statement ) { - std::string tmp( statement ); - return tmp; -} - -IOStreamBase::IOStreamBase( StreamFormatterBase *formatter ) -: m_formatter( formatter ) -, m_file( ddl_nullptr ) { - if (ddl_nullptr == m_formatter) { - m_formatter = new StreamFormatterBase; - } -} - -IOStreamBase::~IOStreamBase() { - delete m_formatter; - m_formatter = ddl_nullptr; -} - -bool IOStreamBase::open( const std::string &name ) { - m_file = ::fopen( name.c_str(), "a" ); - if (m_file == ddl_nullptr) { - return false; - } - - return true; -} - -bool IOStreamBase::close() { - if (ddl_nullptr == m_file) { - return false; - } - - ::fclose( m_file ); - m_file = ddl_nullptr; - - return true; -} - -size_t IOStreamBase::write( const std::string &statement ) { - if (ddl_nullptr == m_file) { - return 0; - } - std::string formatStatement = m_formatter->format( statement ); - return ::fwrite( formatStatement.c_str(), sizeof( char ), formatStatement.size(), m_file ); -} - struct DDLNodeIterator { const DDLNode::DllNodeList &m_childs; size_t m_idx; @@ -189,10 +135,9 @@ bool OpenDDLExport::writeToStream( const std::string &statement ) { } bool OpenDDLExport::writeNode( DDLNode *node, std::string &statement ) { - bool success( true ); writeNodeHeader( node, statement ); if (node->hasProperties()) { - success |= writeProperties( node, statement ); + writeProperties( node, statement ); } writeLineEnd( statement ); @@ -280,7 +225,7 @@ bool OpenDDLExport::writeValueType( Value::ValueType type, size_t numItems, std: statement += "["; char buffer[ 256 ]; ::memset( buffer, '\0', 256 * sizeof( char ) ); - sprintf( buffer, "%d", int(numItems) ); + sprintf( buffer, "%d", static_cast( numItems ) ); statement += buffer; statement += "]"; } @@ -414,11 +359,10 @@ bool OpenDDLExport::writeValueArray( DataArrayList *al, std::string &statement ) } DataArrayList *nextDataArrayList = al ; - Value *nextValue( nextDataArrayList->m_dataList ); while (ddl_nullptr != nextDataArrayList) { if (ddl_nullptr != nextDataArrayList) { statement += "{ "; - nextValue = nextDataArrayList->m_dataList; + Value *nextValue( nextDataArrayList->m_dataList ); size_t idx( 0 ); while (ddl_nullptr != nextValue) { if (idx > 0) { diff --git a/contrib/openddlparser/code/OpenDDLParser.cpp b/contrib/openddlparser/code/OpenDDLParser.cpp index 6f471be36..caa281364 100644 --- a/contrib/openddlparser/code/OpenDDLParser.cpp +++ b/contrib/openddlparser/code/OpenDDLParser.cpp @@ -27,6 +27,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include +#include #include #ifdef _WIN32 @@ -36,7 +37,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. BEGIN_ODDLPARSER_NS -static const char *Version = "0.3.0"; +static const char *Version = "0.4.0"; namespace Grammar { static const char *OpenBracketToken = "{"; @@ -49,7 +50,7 @@ namespace Grammar { static const char *BoolFalse = "false"; static const char *CommaSeparator = ","; - static const char* PrimitiveTypeToken[ Value::ddl_types_max ] = { + static const char *PrimitiveTypeToken[ Value::ddl_types_max ] = { "bool", "int8", "int16", @@ -74,8 +75,8 @@ const char *getTypeToken( Value::ValueType type ) { static void logInvalidTokenError( char *in, const std::string &exp, OpenDDLParser::logCallback callback ) { std::stringstream stream; stream << "Invalid token \"" << *in << "\"" << " expected \"" << exp << "\"" << std::endl; - std::string full(in); - std::string part(full.substr(0,50)); + std::string full( in ); + std::string part( full.substr( 0, 50 ) ); stream << part; callback( ddl_error_msg, stream.str() ); } @@ -85,6 +86,7 @@ static bool isIntegerType( Value::ValueType integerType ) { integerType != Value::ddl_int32 && integerType != Value::ddl_int64 ) { return false; } + return true; } @@ -105,7 +107,7 @@ static DDLNode *createDDLNode( Text *id, OpenDDLParser *parser ) { const std::string type( id->m_buffer ); DDLNode *parent( parser->top() ); DDLNode *node = DDLNode::create( type, "", parent ); - + return node; } @@ -193,10 +195,11 @@ size_t OpenDDLParser::getBufferSize() const { void OpenDDLParser::clear() { m_buffer.resize( 0 ); if( ddl_nullptr != m_context ) { - m_context->m_root = ddl_nullptr; + delete m_context; + m_context=ddl_nullptr; } - DDLNode::releaseNodes(); +// DDLNode::releaseNodes(); } bool OpenDDLParser::parse() { @@ -212,11 +215,11 @@ bool OpenDDLParser::parse() { // do the main parsing char *current( &m_buffer[ 0 ] ); - char *end( &m_buffer[ m_buffer.size() - 1 ] + 1 ); + char *end( &m_buffer[m_buffer.size() - 1 ] + 1 ); size_t pos( current - &m_buffer[ 0 ] ); while( pos < m_buffer.size() ) { current = parseNextNode( current, end ); - if(current==ddl_nullptr) { + if ( current == ddl_nullptr ) { return false; } pos = current - &m_buffer[ 0 ]; @@ -245,7 +248,7 @@ static void dumpId( Identifier *id ) { if( ddl_nullptr != id ) { if ( ddl_nullptr != id->m_text.m_buffer ) { std::cout << id->m_text.m_buffer << std::endl; - } + } } } #endif @@ -271,21 +274,26 @@ char *OpenDDLParser::parseHeader( char *in, char *end ) { } else { std::cerr << "nullptr returned by creating DDLNode." << std::endl; } + delete id; - Name *name(ddl_nullptr); - in = OpenDDLParser::parseName(in, end, &name); + Name *name_(ddl_nullptr); + in = OpenDDLParser::parseName(in, end, &name_); + std::unique_ptr name(name_); if( ddl_nullptr != name && ddl_nullptr != node ) { const std::string nodeName( name->m_id->m_buffer ); node->setName( nodeName ); } - Property *first(ddl_nullptr); + + std::unique_ptr first; in = lookForNextToken(in, end); if (*in == Grammar::OpenPropertyToken[0]) { in++; - Property *prop(ddl_nullptr), *prev(ddl_nullptr); + std::unique_ptr prop, prev; while (*in != Grammar::ClosePropertyToken[0] && in != end) { - in = OpenDDLParser::parseProperty(in, end, &prop); + Property *prop_(ddl_nullptr); + in = OpenDDLParser::parseProperty(in, end, &prop_); + prop.reset(prop_); in = lookForNextToken(in, end); if (*in != Grammar::CommaSeparator[0] && *in != Grammar::ClosePropertyToken[0]) { @@ -295,20 +303,20 @@ char *OpenDDLParser::parseHeader( char *in, char *end ) { if (ddl_nullptr != prop && *in != Grammar::CommaSeparator[0]) { if (ddl_nullptr == first) { - first = prop; + first = std::move(prop); } if (ddl_nullptr != prev) { - prev->m_next = prop; + prev->m_next = prop.release(); } - prev = prop; + prev = std::move(prop); } } - in++; + ++in; } // set the properties - if (ddl_nullptr != first && ddl_nullptr != node) { - node->setProperties(first); + if (first && ddl_nullptr != node) { + node->setProperties(first.release()); } } @@ -322,19 +330,18 @@ char *OpenDDLParser::parseStructure( char *in, char *end ) { bool error( false ); in = lookForNextToken( in, end ); - if( *in == '{' ) { + if( *in == *Grammar::OpenBracketToken) { // loop over all children ( data and nodes ) do { in = parseStructureBody( in, end, error ); if(in == ddl_nullptr){ return ddl_nullptr; } - } while ( *in != '}' ); - in++; + } while ( *in != *Grammar::CloseBracketToken); + ++in; } else { - in++; + ++in; logInvalidTokenError( in, std::string( Grammar::OpenBracketToken ), m_logCallback ); - error = true; return ddl_nullptr; } in = lookForNextToken( in, end ); @@ -373,7 +380,7 @@ static void setNodeDataArrayList( DDLNode *currentNode, DataArrayList *dtArrayLi char *OpenDDLParser::parseStructureBody( char *in, char *end, bool &error ) { if( !isNumeric( *in ) && !isCharacter( *in ) ) { - in++; + ++in; } in = lookForNextToken( in, end ); @@ -431,7 +438,6 @@ DDLNode *OpenDDLParser::popNode() { DDLNode *topNode( top() ); m_stack.pop_back(); - return topNode; } @@ -467,7 +473,14 @@ void OpenDDLParser::normalizeBuffer( std::vector &buffer) { for( size_t readIdx = 0; readIdx( c, end ) && !isNewLine( *c ) ) { + if (isCommentOpenTag(c, end)) { + ++readIdx; + while (!isCommentCloseTag(&buffer[readIdx], end)) { + ++readIdx; + } + ++readIdx; + ++readIdx; + } else if( !isComment( c, end ) && !isNewLine( *c ) ) { newBuffer.push_back( buffer[ readIdx ] ); } else { if( isComment( c, end ) ) { @@ -529,14 +542,17 @@ char *OpenDDLParser::parseIdentifier( char *in, char *end, Text **id ) { // get size of id size_t idLen( 0 ); char *start( in ); - while( !isSeparator( *in ) && !isNewLine( *in ) && ( in != end ) && *in != Grammar::OpenPropertyToken[ 0 ] && *in != Grammar::ClosePropertyToken[ 0 ] && *in != '$' ) { + while( !isSeparator( *in ) && + !isNewLine( *in ) && ( in != end ) && + *in != Grammar::OpenPropertyToken[ 0 ] && + *in != Grammar::ClosePropertyToken[ 0 ] && + *in != '$' ) { ++in; ++idLen; } const size_t len( idLen ); - Text *newId = new Text( start, len ); - *id = newId; + *id = new Text( start, len ); return in; } @@ -552,7 +568,7 @@ char *OpenDDLParser::parsePrimitiveDataType( char *in, char *end, Value::ValueTy for( unsigned int i = 0; i < Value::ddl_types_max; i++ ) { prim_len = strlen( Grammar::PrimitiveTypeToken[ i ] ); if( 0 == strncmp( in, Grammar::PrimitiveTypeToken[ i ], prim_len ) ) { - type = ( Value::ValueType ) i; + type = static_cast( i ); break; } } @@ -567,14 +583,14 @@ char *OpenDDLParser::parsePrimitiveDataType( char *in, char *end, Value::ValueTy bool ok( true ); if( *in == Grammar::OpenArrayToken[ 0 ] ) { ok = false; - in++; + ++in; char *start( in ); while ( in != end ) { - in++; + ++in; if( *in == Grammar::CloseArrayToken[ 0 ] ) { len = ::atoi( start ); ok = true; - in++; + ++in; break; } } @@ -623,10 +639,10 @@ char *OpenDDLParser::parseBooleanLiteral( char *in, char *end, Value **boolean ) char *start( in ); size_t len( 0 ); while( !isSeparator( *in ) && in != end ) { - in++; - len++; + ++in; + ++len; } - len++; + ++len; int res = ::strncmp( Grammar::BoolTrue, start, strlen( Grammar::BoolTrue ) ); if( 0 != res ) { res = ::strncmp( Grammar::BoolFalse, start, strlen( Grammar::BoolFalse ) ); @@ -657,7 +673,7 @@ char *OpenDDLParser::parseIntegerLiteral( char *in, char *end, Value **integer, in = lookForNextToken( in, end ); char *start( in ); while( !isSeparator( *in ) && in != end ) { - in++; + ++in; } if( isNumeric( *start ) ) { @@ -671,29 +687,29 @@ char *OpenDDLParser::parseIntegerLiteral( char *in, char *end, Value **integer, *integer = ValueAllocator::allocPrimData( integerType ); switch( integerType ) { case Value::ddl_int8: - ( *integer )->setInt8( (int8) value ); - break; + ( *integer )->setInt8( (int8) value ); + break; case Value::ddl_int16: - ( *integer )->setInt16( ( int16 ) value ); - break; + ( *integer )->setInt16( ( int16 ) value ); + break; case Value::ddl_int32: - ( *integer )->setInt32( ( int32 ) value ); - break; + ( *integer )->setInt32( ( int32 ) value ); + break; case Value::ddl_int64: - ( *integer )->setInt64( ( int64 ) value ); - break; + ( *integer )->setInt64( ( int64 ) value ); + break; case Value::ddl_unsigned_int8: - ( *integer )->setUnsignedInt8( (uint8) uvalue ); - break; + ( *integer )->setUnsignedInt8( (uint8) uvalue ); + break; case Value::ddl_unsigned_int16: - ( *integer )->setUnsignedInt16( ( uint16 ) uvalue ); - break; + ( *integer )->setUnsignedInt16( ( uint16 ) uvalue ); + break; case Value::ddl_unsigned_int32: - ( *integer )->setUnsignedInt32( ( uint32 ) uvalue ); - break; + ( *integer )->setUnsignedInt32( ( uint32 ) uvalue ); + break; case Value::ddl_unsigned_int64: - ( *integer )->setUnsignedInt64( ( uint64 ) uvalue ); - break; + ( *integer )->setUnsignedInt64( ( uint64 ) uvalue ); + break; default: break; } @@ -711,7 +727,7 @@ char *OpenDDLParser::parseFloatingLiteral( char *in, char *end, Value **floating in = lookForNextToken( in, end ); char *start( in ); while( !isSeparator( *in ) && in != end ) { - in++; + ++in; } // parse the float value @@ -732,8 +748,7 @@ char *OpenDDLParser::parseFloatingLiteral( char *in, char *end, Value **floating } if( ok ) { - if(floatType == Value::ddl_double) - { + if ( floatType == Value::ddl_double ) { const double value( atof( start ) ); *floating = ValueAllocator::allocPrimData( Value::ddl_double ); ( *floating )->setDouble( value ); @@ -757,17 +772,17 @@ char *OpenDDLParser::parseStringLiteral( char *in, char *end, Value **stringData size_t len( 0 ); char *start( in ); if( *start == '\"' ) { - start++; - in++; + ++start; + ++in; while( *in != '\"' && in != end ) { - in++; - len++; + ++in; + ++len; } *stringData = ValueAllocator::allocPrimData( Value::ddl_string, len ); ::strncpy( ( char* ) ( *stringData )->m_data, start, len ); ( *stringData )->m_data[len] = '\0'; - in++; + ++in; } return in; @@ -791,12 +806,12 @@ char *OpenDDLParser::parseHexaLiteral( char *in, char *end, Value **data ) { return in; } - in++; + ++in; if( *in != 'x' && *in != 'X' ) { return in; } - in++; + ++in; bool ok( true ); char *start( in ); int pos( 0 ); @@ -805,8 +820,8 @@ char *OpenDDLParser::parseHexaLiteral( char *in, char *end, Value **data ) { ok = false; break; } - pos++; - in++; + ++pos; + ++in; } if( !ok ) { @@ -816,9 +831,9 @@ char *OpenDDLParser::parseHexaLiteral( char *in, char *end, Value **data ) { int value( 0 ); while( pos > 0 ) { int v = hex2Decimal( *start ); - pos--; + --pos; value = ( value << 4 ) | v; - start++; + ++start; } *data = ValueAllocator::allocPrimData( Value::ddl_unsigned_int64 ); @@ -841,7 +856,7 @@ char *OpenDDLParser::parseProperty( char *in, char *end, Property **prop ) { if( ddl_nullptr != id ) { in = lookForNextToken( in, end ); if( *in == '=' ) { - in++; + ++in; in = getNextToken( in, end ); Value *primData( ddl_nullptr ); if( isInteger( in, end ) ) { @@ -862,6 +877,8 @@ char *OpenDDLParser::parseProperty( char *in, char *end, Property **prop ) { ( *prop )->m_ref = ref; } } + } else { + delete id; } } @@ -878,7 +895,7 @@ char *OpenDDLParser::parseDataList( char *in, char *end, Value::ValueType type, in = lookForNextToken( in, end ); if( *in == '{' ) { - in++; + ++in; Value *current( ddl_nullptr ), *prev( ddl_nullptr ); while( '}' != *in ) { current = ddl_nullptr; @@ -934,7 +951,7 @@ char *OpenDDLParser::parseDataList( char *in, char *end, Value::ValueType type, prev->setNext( current ); prev = current; } - numValues++; + ++numValues; } in = getNextSeparator( in, end ); @@ -942,7 +959,7 @@ char *OpenDDLParser::parseDataList( char *in, char *end, Value::ValueType type, break; } } - in++; + ++in; } return in; @@ -972,7 +989,7 @@ char *OpenDDLParser::parseDataArrayList( char *in, char *end,Value::ValueType ty in = lookForNextToken( in, end ); if( *in == Grammar::OpenBracketToken[ 0 ] ) { - in++; + ++in; Value *currentValue( ddl_nullptr ); Reference *refs( ddl_nullptr ); DataArrayList *prev( ddl_nullptr ), *currentDataList( ddl_nullptr ); @@ -995,7 +1012,7 @@ char *OpenDDLParser::parseDataArrayList( char *in, char *end,Value::ValueType ty } } while( Grammar::CommaSeparator[ 0 ] == *in && in != end ); in = lookForNextToken( in, end ); - in++; + ++in; } return in; diff --git a/contrib/openddlparser/code/OpenDDLStream.cpp b/contrib/openddlparser/code/OpenDDLStream.cpp new file mode 100644 index 000000000..7ea8331bd --- /dev/null +++ b/contrib/openddlparser/code/OpenDDLStream.cpp @@ -0,0 +1,96 @@ +/*----------------------------------------------------------------------------------------------- +The MIT License (MIT) + +Copyright (c) 2014-2015 Kim Kulling + +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. +-----------------------------------------------------------------------------------------------*/ +#include + +BEGIN_ODDLPARSER_NS + +StreamFormatterBase::StreamFormatterBase() { + // empty +} + +StreamFormatterBase::~StreamFormatterBase() { + // empty +} + +std::string StreamFormatterBase::format(const std::string &statement) { + std::string tmp(statement); + return tmp; +} + +IOStreamBase::IOStreamBase(StreamFormatterBase *formatter) + : m_formatter(formatter) + , m_file(ddl_nullptr) { + if (ddl_nullptr == m_formatter) { + m_formatter = new StreamFormatterBase; + } +} + +IOStreamBase::~IOStreamBase() { + delete m_formatter; + m_formatter = ddl_nullptr; +} + +bool IOStreamBase::open(const std::string &name) { + m_file = ::fopen(name.c_str(), "a"); + if (m_file == ddl_nullptr) { + return false; + } + + return true; +} + +bool IOStreamBase::close() { + if (ddl_nullptr == m_file) { + return false; + } + + ::fclose(m_file); + m_file = ddl_nullptr; + + return true; +} + +bool IOStreamBase::isOpen() const { + return ( ddl_nullptr != m_file ); +} + +size_t IOStreamBase::read( size_t sizeToRead, std::string &statement ) { + if (ddl_nullptr == m_file) { + return 0; + } + + statement.resize(sizeToRead); + const size_t readBytes = ::fread( &statement[0], 1, sizeToRead, m_file ); + + return readBytes; +} + +size_t IOStreamBase::write(const std::string &statement) { + if (ddl_nullptr == m_file) { + return 0; + } + std::string formatStatement = m_formatter->format(statement); + return ::fwrite(formatStatement.c_str(), sizeof(char), formatStatement.size(), m_file); +} + +END_ODDLPARSER_NS diff --git a/contrib/openddlparser/code/Value.cpp b/contrib/openddlparser/code/Value.cpp index 3e251c508..b5a35e722 100644 --- a/contrib/openddlparser/code/Value.cpp +++ b/contrib/openddlparser/code/Value.cpp @@ -110,7 +110,17 @@ Value::Value( ValueType type ) } Value::~Value() { - // empty + if(m_data!=ddl_nullptr) { + if (m_type == ddl_ref ) { + Reference *tmp = (Reference *) m_data; + if (tmp != ddl_nullptr) + delete tmp; + }else + delete[] m_data; + + } + if(m_next!=ddl_nullptr) + delete m_next; } void Value::setBool( bool value ) { @@ -273,13 +283,7 @@ void Value::setRef( Reference *ref ) { delete [] m_data; } - m_data = new unsigned char[ sizeof( Reference ) ]; - Reference *myRef = ( Reference * ) m_data; - myRef->m_numRefs = ref->m_numRefs; - myRef->m_referencedName = new Name *[ myRef->m_numRefs ]; - for ( size_t i = 0; i < myRef->m_numRefs; i++ ) { - myRef->m_referencedName[ i ] = new Name( ref->m_referencedName[ i ]->m_type, ref->m_referencedName[ i ]->m_id ); - } + m_data = (unsigned char*) new Reference(*ref); } } } @@ -290,7 +294,7 @@ Reference *Value::getRef() const { return (Reference*) m_data; } -void Value::dump() { +void Value::dump( IOStreamBase &/*stream*/ ) { switch( m_type ) { case ddl_none: std::cout << "None" << std::endl; @@ -350,7 +354,7 @@ Value *Value::getNext() const { return m_next; } -size_t Value::size(){ +size_t Value::size() const{ size_t result=1; Value *n=m_next; while( n!=ddl_nullptr) { @@ -366,7 +370,6 @@ Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) { } Value *data = new Value( type ); - data->m_type = type; switch( type ) { case Value::ddl_bool: data->m_size = sizeof( bool ); @@ -405,10 +408,10 @@ Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) { data->m_size = sizeof( double ); break; case Value::ddl_string: - data->m_size = sizeof( char ); + data->m_size = sizeof( char )*(len+1); break; case Value::ddl_ref: - data->m_size = sizeof( char ); + data->m_size = 0; break; case Value::ddl_none: case Value::ddl_types_max: @@ -417,12 +420,8 @@ Value *ValueAllocator::allocPrimData( Value::ValueType type, size_t len ) { } if( data->m_size ) { - size_t len1( len ); - if( Value::ddl_string == type ) { - len1++; - } - data->m_size *= len1; data->m_data = new unsigned char[ data->m_size ]; + ::memset(data->m_data,0,data->m_size); } return data; diff --git a/contrib/openddlparser/include/openddlparser/DDLNode.h b/contrib/openddlparser/include/openddlparser/DDLNode.h index 137135604..915bd3041 100644 --- a/contrib/openddlparser/include/openddlparser/DDLNode.h +++ b/contrib/openddlparser/include/openddlparser/DDLNode.h @@ -29,6 +29,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. BEGIN_ODDLPARSER_NS +// Forward declarations +class IOStreamBase; class Value; class OpenDDLParser; @@ -53,6 +55,9 @@ public: /// @brief The child-node-list type. typedef std::vector DllNodeList; + /// @brief The child-node-list iterator. + typedef std::vector::iterator DDLNodeIt; + public: /// @brief The class destructor. ~DDLNode(); @@ -81,7 +86,7 @@ public: const std::string &getType() const; /// Set the name of the DDLNode instance. - /// @param type [in] The name. + /// @param name [in] The name. void setName( const std::string &name ); /// @brief Returns the name of the DDLNode instance. @@ -89,7 +94,7 @@ public: const std::string &getName() const; /// @brief Set a new property set. - /// @param prop [in] The first element of the property set. + /// @param prop [in] The first element of the property set. void setProperties( Property *prop ); /// @brief Returns the first element of the assigned property set. @@ -97,7 +102,7 @@ public: Property *getProperties() const; /// @brief Looks for a given property. - /// @param name [in] The name for the property to look for. + /// @param name [in] The name for the property to look for. /// @return true, if a corresponding property is assigned to the node, false if not. bool hasProperty( const std::string &name ); @@ -106,12 +111,12 @@ public: bool hasProperties() const; /// @brief Search for a given property and returns it. Will return ddl_nullptr if no property was found. - /// @param name [in] The name for the property to look for. + /// @param name [in] The name for the property to look for. /// @return The property or ddl_nullptr if no property was found. Property *findPropertyByName( const std::string &name ); /// @brief Set a new value set. - /// @param val [in] The first value instance of the value set. + /// @param val [in] The first value instance of the value set. void setValue( Value *val ); /// @brief Returns the first element of the assigned value set. @@ -119,7 +124,7 @@ public: Value *getValue() const; /// @brief Set a new DataArrayList. - /// @param val [in] The DataArrayList instance. + /// @param dtArrayList [in] The DataArrayList instance. void setDataArrayList( DataArrayList *dtArrayList ); /// @brief Returns the DataArrayList. @@ -127,17 +132,21 @@ public: DataArrayList *getDataArrayList() const; /// @brief Set a new Reference set. - /// @param val [in] The first value instance of the Reference set. + /// @param refs [in] The first value instance of the Reference set. void setReferences( Reference *refs ); /// @brief Returns the first element of the assigned Reference set. /// @return The first property of the assigned Reference set. Reference *getReferences() const; + /// @brief Will dump the node into the stream. + /// @param stream [in] The stream to write to. + void dump(IOStreamBase &stream); + /// @brief The creation method. - /// @param type [in] The DDLNode type. - /// @param name [in] The name for the new DDLNode instance. - /// @param parent [in] The parent node instance or ddl_nullptr if no parent node is there. + /// @param type [in] The DDLNode type. + /// @param name [in] The name for the new DDLNode instance. + /// @param parent [in] The parent node instance or ddl_nullptr if no parent node is there. /// @return The new created node instance. static DDLNode *create( const std::string &type, const std::string &name, DDLNode *parent = ddl_nullptr ); diff --git a/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h b/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h index d3e0fb458..bec62cc9d 100644 --- a/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h +++ b/contrib/openddlparser/include/openddlparser/OpenDDLCommon.h @@ -148,12 +148,12 @@ struct DLL_ODDLPARSER_EXPORT Name { /// @param type [in] The name type. /// @param id [in] The id. Name( NameType type, Text *id ); - + Name( const Name &name ); /// @brief The destructor. ~Name(); private: - Name( const Name & ) ddl_no_copy; + Name &operator = ( const Name& ) ddl_no_copy; }; @@ -164,7 +164,7 @@ struct DLL_ODDLPARSER_EXPORT Reference { /// @brief The default constructor. Reference(); - + Reference( const Reference &ref ); /// @brief The constructor with an array of ref names. /// @param numrefs [in] The number of ref names. /// @param names [in] The ref names. @@ -178,7 +178,6 @@ struct DLL_ODDLPARSER_EXPORT Reference { size_t sizeInBytes(); private: - Reference( const Reference & ) ddl_no_copy; Reference &operator = ( const Reference & ) ddl_no_copy; }; diff --git a/contrib/openddlparser/include/openddlparser/OpenDDLExport.h b/contrib/openddlparser/include/openddlparser/OpenDDLExport.h index 8ede537d9..020d662a0 100644 --- a/contrib/openddlparser/include/openddlparser/OpenDDLExport.h +++ b/contrib/openddlparser/include/openddlparser/OpenDDLExport.h @@ -23,37 +23,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #pragma once #include +#include #include BEGIN_ODDLPARSER_NS -//------------------------------------------------------------------------------------------------- -/// @ingroup IOStreamBase -/// @brief This class represents the stream to write out. -//------------------------------------------------------------------------------------------------- -class DLL_ODDLPARSER_EXPORT StreamFormatterBase { -public: - StreamFormatterBase(); - virtual ~StreamFormatterBase(); - virtual std::string format( const std::string &statement ); -}; - -//------------------------------------------------------------------------------------------------- -/// @ingroup IOStreamBase -/// @brief This class represents the stream to write out. -//------------------------------------------------------------------------------------------------- -class DLL_ODDLPARSER_EXPORT IOStreamBase { -public: - IOStreamBase( StreamFormatterBase *formatter = ddl_nullptr ); - virtual ~IOStreamBase(); - virtual bool open( const std::string &anme ); - virtual bool close(); - virtual size_t write( const std::string &statement ); - -private: - StreamFormatterBase *m_formatter; - FILE *m_file; -}; +// Forward declarations +class IOStreamBase; //------------------------------------------------------------------------------------------------- /// diff --git a/contrib/openddlparser/include/openddlparser/OpenDDLParser.h b/contrib/openddlparser/include/openddlparser/OpenDDLParser.h index efeab6026..ef7f3a72e 100644 --- a/contrib/openddlparser/include/openddlparser/OpenDDLParser.h +++ b/contrib/openddlparser/include/openddlparser/OpenDDLParser.h @@ -39,6 +39,20 @@ struct Identifier; struct Reference; struct Property; +template +inline +bool isEmbeddedCommentOpenTag( T *in, T *end ) { + if ( in == end ) { + return false; + } + + if ( in == '/' && in+1 == '*' ) { + return true; + } + + return false; +} + /// @brief Utility function to search for the next token or the end of the buffer. /// @param in [in] The start position in the buffer. /// @param end [in] The end position in the buffer. @@ -47,7 +61,7 @@ struct Property; template inline T *lookForNextToken( T *in, T *end ) { - while( ( isSpace( *in ) || isNewLine( *in ) || ',' == *in ) && ( in != end ) ) { + while( ( in != end ) && ( isSpace( *in ) || isNewLine( *in ) || ',' == *in ) ) { in++; } return in; diff --git a/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h b/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h index 778a1b46e..64897436e 100644 --- a/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h +++ b/contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h @@ -84,7 +84,7 @@ static const unsigned char chartype_table[ 256 ] = { template inline bool isNumeric( const T in ) { - return ( chartype_table[ static_cast( in ) ] == 1 ); + return ( chartype_table[ static_cast( in ) ] == 1 ); } template @@ -98,7 +98,7 @@ inline bool isInteger( T *in, T *end ) { if( in != end ) { if( *in == '-' ) { - in++; + ++in; } } @@ -108,7 +108,7 @@ bool isInteger( T *in, T *end ) { if( !result ) { break; } - in++; + ++in; } return result; @@ -119,7 +119,7 @@ inline bool isFloat( T *in, T *end ) { if( in != end ) { if( *in == '-' ) { - in++; + ++in; } } @@ -134,12 +134,12 @@ bool isFloat( T *in, T *end ) { if( !result ) { return false; } - in++; + ++in; } // check for 1<.>0f if( *in == '.' ) { - in++; + ++in; } else { return false; } @@ -150,7 +150,7 @@ bool isFloat( T *in, T *end ) { if( !result ) { return false; } - in++; + ++in; } return result; @@ -208,7 +208,7 @@ template inline static T *getNextSeparator( T *in, T *end ) { while( !isSeparator( *in ) || in == end ) { - in++; + ++in; } return in; } @@ -250,5 +250,33 @@ bool isComment( T *in, T *end ) { return false; } +template +inline +bool isCommentOpenTag(T *in, T *end ) { + if (*in == '/') { + if (in + 1 != end) { + if (*(in + 1) == '*') { + return true; + } + } + } + + return false; +} + +template +inline +bool isCommentCloseTag(T *in, T *end) { + if (*in == '*') { + if (in + 1 != end) { + if (*(in + 1) == '/') { + return true; + } + } + } + + return false; +} + END_ODDLPARSER_NS diff --git a/contrib/openddlparser/include/openddlparser/OpenDDLStream.h b/contrib/openddlparser/include/openddlparser/OpenDDLStream.h new file mode 100644 index 000000000..93370da03 --- /dev/null +++ b/contrib/openddlparser/include/openddlparser/OpenDDLStream.h @@ -0,0 +1,89 @@ +/*----------------------------------------------------------------------------------------------- +The MIT License (MIT) + +Copyright (c) 2014-2015 Kim Kulling + +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. +-----------------------------------------------------------------------------------------------*/ +#pragma once + +#include + +BEGIN_ODDLPARSER_NS + +//------------------------------------------------------------------------------------------------- +/// @ingroup IOStreamBase +/// @brief This class represents the stream to write out. +//------------------------------------------------------------------------------------------------- +class DLL_ODDLPARSER_EXPORT StreamFormatterBase { +public: + /// @brief The class constructor. + StreamFormatterBase(); + + /// @brief The class destructor, virtual. + virtual ~StreamFormatterBase(); + + /// @brief Will format the sring and return the new formatted result. + /// @param statement [in] The string to reformat. + /// @return The reformatted result. + virtual std::string format(const std::string &statement); +}; + +//------------------------------------------------------------------------------------------------- +/// @ingroup IOStreamBase +/// @brief This class represents the stream to write out. +//------------------------------------------------------------------------------------------------- +class DLL_ODDLPARSER_EXPORT IOStreamBase { +public: + /// @brief The class constructor with the formatter. + /// @param formatter [in] The formatter to use. + explicit IOStreamBase(StreamFormatterBase *formatter = ddl_nullptr); + + /// @brief The class destructor, virtual. + virtual ~IOStreamBase(); + + /// @brief Will open the stream. + /// @param name [in] The name for the stream. + /// @return true, if the stream was opened successfully, false if not. + virtual bool open(const std::string &name); + + /// @brief Will close the stream. + /// @return true, if the stream was closed successfully, false if not. + virtual bool close(); + + /// @brief Returns true, if the stream is open. + /// @return true, if the stream is open, false if not. + virtual bool isOpen() const; + + /// @brief Will read a string from the stream. + /// @param sizeToRead [in] The size to read in bytes. + /// @param statement [out] The read statements. + /// @return The bytes read from the stream. + virtual size_t read( size_t sizeToRead, std::string &statement ); + + /// @brief Will write a string into the stream. + /// @param statement [in] The string to write. + /// @return The bytes written into the stream. + virtual size_t write(const std::string &statement); + +private: + StreamFormatterBase *m_formatter; + FILE *m_file; +}; + +END_ODDLPARSER_NS diff --git a/contrib/openddlparser/include/openddlparser/Value.h b/contrib/openddlparser/include/openddlparser/Value.h index 242ec8781..77c6da06b 100644 --- a/contrib/openddlparser/include/openddlparser/Value.h +++ b/contrib/openddlparser/include/openddlparser/Value.h @@ -28,8 +28,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. BEGIN_ODDLPARSER_NS +// Forward declarations struct ValueAllocator; +class IOStreamBase; + ///------------------------------------------------------------------------------------------------ /// @brief This class implements a value. /// @@ -213,7 +216,7 @@ public: double getDouble() const; /// @brief Assigns a std::string to the value. - /// @param value [in] The value. + /// @param str [in] The value. void setString( const std::string &str ); /// @brief Returns the std::string value. @@ -229,7 +232,8 @@ public: Reference *getRef() const; /// @brief Dumps the value. - void dump(); + /// @param stream [in] The stream to write in. + void dump( IOStreamBase &stream ); /// @brief Assigns the next value. /// @param next [n] The next value. @@ -241,7 +245,7 @@ public: /// @brief Gets the length of the array. /// @return The number of items in the array. - size_t size(); + size_t size() const; ValueType m_type; size_t m_size; diff --git a/contrib/poly2tri/poly2tri/common/shapes.cc b/contrib/poly2tri/poly2tri/common/shapes.cc index 4080445a7..d0de13e64 100644 --- a/contrib/poly2tri/poly2tri/common/shapes.cc +++ b/contrib/poly2tri/poly2tri/common/shapes.cc @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * http://code.google.com/p/poly2tri/ * @@ -88,7 +88,7 @@ void Triangle::Clear() points_[0]=points_[1]=points_[2] = NULL; } -void Triangle::ClearNeighbor(Triangle *triangle ) +void Triangle::ClearNeighbor(const Triangle *triangle ) { if( neighbors_[0] == triangle ) { @@ -96,14 +96,14 @@ void Triangle::ClearNeighbor(Triangle *triangle ) } else if( neighbors_[1] == triangle ) { - neighbors_[1] = NULL; + neighbors_[1] = NULL; } else { neighbors_[2] = NULL; } } - + void Triangle::ClearNeighbors() { neighbors_[0] = NULL; @@ -116,13 +116,9 @@ void Triangle::ClearDelunayEdges() delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; } -Point* Triangle::OppositePoint(Triangle& t, Point& p) +Point* Triangle::OppositePoint(Triangle& t, const Point& p) { Point *cw = t.PointCW(p); - //double x = cw->x; - //double y = cw->y; - //x = p.x; - //y = p.y; return PointCW(*cw); } @@ -164,8 +160,7 @@ int Triangle::Index(const Point* p) return 2; } assert(0); - - return 0; + return -1; } int Triangle::EdgeIndex(const Point* p1, const Point* p2) @@ -192,7 +187,7 @@ int Triangle::EdgeIndex(const Point* p1, const Point* p2) return -1; } -void Triangle::MarkConstrainedEdge(const int index) +void Triangle::MarkConstrainedEdge(int index) { constrained_edge[index] = true; } @@ -215,7 +210,7 @@ void Triangle::MarkConstrainedEdge(Point* p, Point* q) } // The point counter-clockwise to given point -Point* Triangle::PointCW(Point& point) +Point* Triangle::PointCW(const Point& point) { if (&point == points_[0]) { return points_[2]; @@ -225,12 +220,11 @@ Point* Triangle::PointCW(Point& point) return points_[1]; } assert(0); - - return 0; + return NULL; } // The point counter-clockwise to given point -Point* Triangle::PointCCW(Point& point) +Point* Triangle::PointCCW(const Point& point) { if (&point == points_[0]) { return points_[1]; @@ -240,12 +234,11 @@ Point* Triangle::PointCCW(Point& point) return points_[0]; } assert(0); - - return 0; + return NULL; } // The neighbor clockwise to given point -Triangle* Triangle::NeighborCW(Point& point) +Triangle* Triangle::NeighborCW(const Point& point) { if (&point == points_[0]) { return neighbors_[1]; @@ -256,7 +249,7 @@ Triangle* Triangle::NeighborCW(Point& point) } // The neighbor counter-clockwise to given point -Triangle* Triangle::NeighborCCW(Point& point) +Triangle* Triangle::NeighborCCW(const Point& point) { if (&point == points_[0]) { return neighbors_[2]; @@ -266,7 +259,7 @@ Triangle* Triangle::NeighborCCW(Point& point) return neighbors_[1]; } -bool Triangle::GetConstrainedEdgeCCW(Point& p) +bool Triangle::GetConstrainedEdgeCCW(const Point& p) { if (&p == points_[0]) { return constrained_edge[2]; @@ -276,7 +269,7 @@ bool Triangle::GetConstrainedEdgeCCW(Point& p) return constrained_edge[1]; } -bool Triangle::GetConstrainedEdgeCW(Point& p) +bool Triangle::GetConstrainedEdgeCW(const Point& p) { if (&p == points_[0]) { return constrained_edge[1]; @@ -286,7 +279,7 @@ bool Triangle::GetConstrainedEdgeCW(Point& p) return constrained_edge[0]; } -void Triangle::SetConstrainedEdgeCCW(Point& p, bool ce) +void Triangle::SetConstrainedEdgeCCW(const Point& p, bool ce) { if (&p == points_[0]) { constrained_edge[2] = ce; @@ -297,7 +290,7 @@ void Triangle::SetConstrainedEdgeCCW(Point& p, bool ce) } } -void Triangle::SetConstrainedEdgeCW(Point& p, bool ce) +void Triangle::SetConstrainedEdgeCW(const Point& p, bool ce) { if (&p == points_[0]) { constrained_edge[1] = ce; @@ -308,7 +301,7 @@ void Triangle::SetConstrainedEdgeCW(Point& p, bool ce) } } -bool Triangle::GetDelunayEdgeCCW(Point& p) +bool Triangle::GetDelunayEdgeCCW(const Point& p) { if (&p == points_[0]) { return delaunay_edge[2]; @@ -318,7 +311,7 @@ bool Triangle::GetDelunayEdgeCCW(Point& p) return delaunay_edge[1]; } -bool Triangle::GetDelunayEdgeCW(Point& p) +bool Triangle::GetDelunayEdgeCW(const Point& p) { if (&p == points_[0]) { return delaunay_edge[1]; @@ -328,7 +321,7 @@ bool Triangle::GetDelunayEdgeCW(Point& p) return delaunay_edge[0]; } -void Triangle::SetDelunayEdgeCCW(Point& p, bool e) +void Triangle::SetDelunayEdgeCCW(const Point& p, bool e) { if (&p == points_[0]) { delaunay_edge[2] = e; @@ -339,7 +332,7 @@ void Triangle::SetDelunayEdgeCCW(Point& p, bool e) } } -void Triangle::SetDelunayEdgeCW(Point& p, bool e) +void Triangle::SetDelunayEdgeCW(const Point& p, bool e) { if (&p == points_[0]) { delaunay_edge[1] = e; @@ -351,7 +344,7 @@ void Triangle::SetDelunayEdgeCW(Point& p, bool e) } // The neighbor across to given point -Triangle& Triangle::NeighborAcross(Point& opoint) +Triangle& Triangle::NeighborAcross(const Point& opoint) { if (&opoint == points_[0]) { return *neighbors_[0]; @@ -369,5 +362,4 @@ void Triangle::DebugPrint() cout << points_[2]->x << "," << points_[2]->y << endl; } -} - +} \ No newline at end of file diff --git a/contrib/poly2tri/poly2tri/common/shapes.h b/contrib/poly2tri/poly2tri/common/shapes.h index 4f691838f..ac7389a2d 100644 --- a/contrib/poly2tri/poly2tri/common/shapes.h +++ b/contrib/poly2tri/poly2tri/common/shapes.h @@ -113,7 +113,7 @@ struct Point { /// Convert this point into a unit point. Returns the Length. double Normalize() { - double len = Length(); + const double len = Length(); x /= len; y /= len; return len; @@ -162,50 +162,50 @@ bool constrained_edge[3]; /// Flags to determine if an edge is a Delauney edge bool delaunay_edge[3]; -Point* GetPoint(const int& index); -Point* PointCW(Point& point); -Point* PointCCW(Point& point); -Point* OppositePoint(Triangle& t, Point& p); +Point* GetPoint(int index); +Point* PointCW(const Point& point); +Point* PointCCW(const Point& point); +Point* OppositePoint(Triangle& t, const Point& p); -Triangle* GetNeighbor(const int& index); +Triangle* GetNeighbor(int index); void MarkNeighbor(Point* p1, Point* p2, Triangle* t); void MarkNeighbor(Triangle& t); -void MarkConstrainedEdge(const int index); +void MarkConstrainedEdge(int index); void MarkConstrainedEdge(Edge& edge); void MarkConstrainedEdge(Point* p, Point* q); int Index(const Point* p); int EdgeIndex(const Point* p1, const Point* p2); -Triangle* NeighborCW(Point& point); -Triangle* NeighborCCW(Point& point); -bool GetConstrainedEdgeCCW(Point& p); -bool GetConstrainedEdgeCW(Point& p); -void SetConstrainedEdgeCCW(Point& p, bool ce); -void SetConstrainedEdgeCW(Point& p, bool ce); -bool GetDelunayEdgeCCW(Point& p); -bool GetDelunayEdgeCW(Point& p); -void SetDelunayEdgeCCW(Point& p, bool e); -void SetDelunayEdgeCW(Point& p, bool e); +Triangle* NeighborCW(const Point& point); +Triangle* NeighborCCW(const Point& point); +bool GetConstrainedEdgeCCW(const Point& p); +bool GetConstrainedEdgeCW(const Point& p); +void SetConstrainedEdgeCCW(const Point& p, bool ce); +void SetConstrainedEdgeCW(const Point& p, bool ce); +bool GetDelunayEdgeCCW(const Point& p); +bool GetDelunayEdgeCW(const Point& p); +void SetDelunayEdgeCCW(const Point& p, bool e); +void SetDelunayEdgeCW(const Point& p, bool e); -bool Contains(Point* p); +bool Contains(const Point* p); bool Contains(const Edge& e); -bool Contains(Point* p, Point* q); +bool Contains(const Point* p, const Point* q); void Legalize(Point& point); void Legalize(Point& opoint, Point& npoint); /** * Clears all references to all other triangles and points */ void Clear(); -void ClearNeighbor(Triangle *triangle ); +void ClearNeighbor(const Triangle *triangle); void ClearNeighbors(); void ClearDelunayEdges(); inline bool IsInterior(); inline void IsInterior(bool b); -Triangle& NeighborAcross(Point& opoint); +Triangle& NeighborAcross(const Point& opoint); void DebugPrint(); @@ -258,7 +258,7 @@ inline bool operator ==(const Point& a, const Point& b) inline bool operator !=(const Point& a, const Point& b) { - return a.x != b.x || a.y != b.y; + return !(a.x == b.x) && !(a.y == b.y); } /// Peform the dot product on two vectors. @@ -282,22 +282,22 @@ inline Point Cross(const Point& a, double s) /// Perform the cross product on a scalar and a point. In 2D this produces /// a point. -inline Point Cross(const double s, const Point& a) +inline Point Cross(double s, const Point& a) { return Point(-s * a.y, s * a.x); } -inline Point* Triangle::GetPoint(const int& index) +inline Point* Triangle::GetPoint(int index) { return points_[index]; } -inline Triangle* Triangle::GetNeighbor(const int& index) +inline Triangle* Triangle::GetNeighbor(int index) { return neighbors_[index]; } -inline bool Triangle::Contains(Point* p) +inline bool Triangle::Contains(const Point* p) { return p == points_[0] || p == points_[1] || p == points_[2]; } @@ -307,7 +307,7 @@ inline bool Triangle::Contains(const Edge& e) return Contains(e.p) && Contains(e.q); } -inline bool Triangle::Contains(Point* p, Point* q) +inline bool Triangle::Contains(const Point* p, const Point* q) { return Contains(p) && Contains(q); } @@ -324,6 +324,4 @@ inline void Triangle::IsInterior(bool b) } -#endif - - +#endif \ No newline at end of file diff --git a/contrib/poly2tri/poly2tri/common/utils.h b/contrib/poly2tri/poly2tri/common/utils.h index f123fedaf..2424c712c 100644 --- a/contrib/poly2tri/poly2tri/common/utils.h +++ b/contrib/poly2tri/poly2tri/common/utils.h @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * http://code.google.com/p/poly2tri/ * @@ -28,18 +28,26 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - + #ifndef UTILS_H #define UTILS_H +// Otherwise #defines like M_PI are undeclared under Visual Studio +#define _USE_MATH_DEFINES + #include +#include + +// C99 removes M_PI from math.h +#ifndef M_PI +#define M_PI 3.14159265358979323846264338327 +#endif namespace p2t { -const double PI = 3.1415926535897932384626433832795029; -const double PI_2 = 2 * PI; -const double PI_3div4 = 3 * PI / 4; -const double EPSILON = 1e-15; +const double PI_3div4 = 3 * M_PI / 4; +const double PI_div2 = 1.57079632679489661923; +const double EPSILON = 1e-12; enum Orientation { CW, CCW, COLLINEAR }; @@ -53,7 +61,7 @@ enum Orientation { CW, CCW, COLLINEAR }; * = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3) * */ -Orientation Orient2d(Point& pa, Point& pb, Point& pc) +Orientation Orient2d(const Point& pa, const Point& pb, const Point& pc) { double detleft = (pa.x - pc.x) * (pb.y - pc.y); double detright = (pa.y - pc.y) * (pb.x - pc.x); @@ -66,6 +74,7 @@ Orientation Orient2d(Point& pa, Point& pb, Point& pc) return CW; } +/* bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) { double pdx = pd.x; @@ -97,7 +106,22 @@ bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) return true; } +*/ + +bool InScanArea(const Point& pa, const Point& pb, const Point& pc, const Point& pd) +{ + double oadb = (pa.x - pb.x)*(pd.y - pb.y) - (pd.x - pb.x)*(pa.y - pb.y); + if (oadb >= -EPSILON) { + return false; + } + + double oadc = (pa.x - pc.x)*(pd.y - pc.y) - (pd.x - pc.x)*(pa.y - pc.y); + if (oadc <= EPSILON) { + return false; + } + return true; +} + } #endif - diff --git a/contrib/poly2tri/poly2tri/poly2tri.h b/contrib/poly2tri/poly2tri/poly2tri.h index 487755e2e..29a08d052 100644 --- a/contrib/poly2tri/poly2tri/poly2tri.h +++ b/contrib/poly2tri/poly2tri/poly2tri.h @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * http://code.google.com/p/poly2tri/ * @@ -35,5 +35,4 @@ #include "common/shapes.h" #include "sweep/cdt.h" -#endif - +#endif \ No newline at end of file diff --git a/contrib/poly2tri/poly2tri/sweep/advancing_front.cc b/contrib/poly2tri/poly2tri/sweep/advancing_front.cc index 019df4a6e..38723beef 100644 --- a/contrib/poly2tri/poly2tri/sweep/advancing_front.cc +++ b/contrib/poly2tri/poly2tri/sweep/advancing_front.cc @@ -39,7 +39,7 @@ AdvancingFront::AdvancingFront(Node& head, Node& tail) search_node_ = &head; } -Node* AdvancingFront::LocateNode(const double& x) +Node* AdvancingFront::LocateNode(double x) { Node* node = search_node_; @@ -61,7 +61,7 @@ Node* AdvancingFront::LocateNode(const double& x) return NULL; } -Node* AdvancingFront::FindSearchNode(const double& x) +Node* AdvancingFront::FindSearchNode(double x) { (void)x; // suppress compiler warnings "unused parameter 'x'" // TODO: implement BST index @@ -105,5 +105,4 @@ AdvancingFront::~AdvancingFront() { } -} - +} \ No newline at end of file diff --git a/contrib/poly2tri/poly2tri/sweep/advancing_front.h b/contrib/poly2tri/poly2tri/sweep/advancing_front.h index bab73d449..645dcec97 100644 --- a/contrib/poly2tri/poly2tri/sweep/advancing_front.h +++ b/contrib/poly2tri/poly2tri/sweep/advancing_front.h @@ -74,7 +74,7 @@ Node* search(); void set_search(Node* node); /// Locate insertion point along advancing front -Node* LocateNode(const double& x); +Node* LocateNode(double x); Node* LocatePoint(const Point* point); @@ -82,7 +82,7 @@ private: Node* head_, *tail_, *search_node_; -Node* FindSearchNode(const double& x); +Node* FindSearchNode(double x); }; inline Node* AdvancingFront::head() @@ -115,4 +115,4 @@ inline void AdvancingFront::set_search(Node* node) } -#endif +#endif \ No newline at end of file diff --git a/contrib/poly2tri/poly2tri/sweep/cdt.cc b/contrib/poly2tri/poly2tri/sweep/cdt.cc index f013e47e3..09d088ae3 100644 --- a/contrib/poly2tri/poly2tri/sweep/cdt.cc +++ b/contrib/poly2tri/poly2tri/sweep/cdt.cc @@ -1,72 +1,71 @@ -/* - * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors - * http://code.google.com/p/poly2tri/ - * - * All rights reserved. - * - * Redistribution and use 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 Poly2Tri nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "cdt.h" - -namespace p2t { - -CDT::CDT(std::vector polyline) -{ - sweep_context_ = new SweepContext(polyline); - sweep_ = new Sweep; -} - -void CDT::AddHole(std::vector polyline) -{ - sweep_context_->AddHole(polyline); -} - -void CDT::AddPoint(Point* point) { - sweep_context_->AddPoint(point); -} - -void CDT::Triangulate() -{ - sweep_->Triangulate(*sweep_context_); -} - -std::vector CDT::GetTriangles() -{ - return sweep_context_->GetTriangles(); -} - -std::list CDT::GetMap() -{ - return sweep_context_->GetMap(); -} - -CDT::~CDT() -{ - delete sweep_context_; - delete sweep_; -} - -} - +/* + * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors + * http://code.google.com/p/poly2tri/ + * + * All rights reserved. + * + * Redistribution and use 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 Poly2Tri nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "cdt.h" + +namespace p2t { + +CDT::CDT(const std::vector& polyline) +{ + sweep_context_ = new SweepContext(polyline); + sweep_ = new Sweep; +} + +void CDT::AddHole(const std::vector& polyline) +{ + sweep_context_->AddHole(polyline); +} + +void CDT::AddPoint(Point* point) { + sweep_context_->AddPoint(point); +} + +void CDT::Triangulate() +{ + sweep_->Triangulate(*sweep_context_); +} + +std::vector CDT::GetTriangles() +{ + return sweep_context_->GetTriangles(); +} + +std::list CDT::GetMap() +{ + return sweep_context_->GetMap(); +} + +CDT::~CDT() +{ + delete sweep_context_; + delete sweep_; +} + +} \ No newline at end of file diff --git a/contrib/poly2tri/poly2tri/sweep/cdt.h b/contrib/poly2tri/poly2tri/sweep/cdt.h index 3e6f02408..ea3286d9a 100644 --- a/contrib/poly2tri/poly2tri/sweep/cdt.h +++ b/contrib/poly2tri/poly2tri/sweep/cdt.h @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * http://code.google.com/p/poly2tri/ * @@ -28,7 +28,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - + #ifndef CDT_H #define CDT_H @@ -37,11 +37,11 @@ #include "sweep.h" /** - * + * * @author Mason Green * */ - + namespace p2t { class CDT @@ -50,40 +50,40 @@ public: /** * Constructor - add polyline with non repeating points - * + * * @param polyline */ - CDT(std::vector polyline); - + CDT(const std::vector& polyline); + /** * Destructor - clean up memory */ ~CDT(); - + /** * Add a hole - * + * * @param polyline */ - void AddHole(std::vector polyline); - + void AddHole(const std::vector& polyline); + /** * Add a steiner point - * + * * @param point */ void AddPoint(Point* point); - + /** * Triangulate - do this AFTER you've added the polyline, holes, and Steiner points */ void Triangulate(); - + /** * Get CDT triangles */ std::vector GetTriangles(); - + /** * Get triangle map */ @@ -94,7 +94,7 @@ public: /** * Internals */ - + SweepContext* sweep_context_; Sweep* sweep_; @@ -102,4 +102,4 @@ public: } -#endif +#endif \ No newline at end of file diff --git a/contrib/poly2tri/poly2tri/sweep/sweep.cc b/contrib/poly2tri/poly2tri/sweep/sweep.cc index d3e35aebf..826905ceb 100644 --- a/contrib/poly2tri/poly2tri/sweep/sweep.cc +++ b/contrib/poly2tri/poly2tri/sweep/sweep.cc @@ -1,750 +1,799 @@ -/* - * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors - * http://code.google.com/p/poly2tri/ - * - * All rights reserved. - * - * Redistribution and use 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 Poly2Tri nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include -#include "sweep.h" -#include "sweep_context.h" -#include "advancing_front.h" -#include "../common/utils.h" - -namespace p2t { - -// Triangulate simple polygon with holes -void Sweep::Triangulate(SweepContext& tcx) -{ - tcx.InitTriangulation(); - tcx.CreateAdvancingFront(nodes_); - // Sweep points; build mesh - SweepPoints(tcx); - // Clean up - FinalizationPolygon(tcx); -} - -void Sweep::SweepPoints(SweepContext& tcx) -{ - for (int i = 1; i < tcx.point_count(); i++) { - Point& point = *tcx.GetPoint(i); - Node* node = &PointEvent(tcx, point); - for (unsigned int i = 0; i < point.edge_list.size(); i++) { - EdgeEvent(tcx, point.edge_list[i], node); - } - } -} - -void Sweep::FinalizationPolygon(SweepContext& tcx) -{ - // Get an Internal triangle to start with - Triangle* t = tcx.front()->head()->next->triangle; - Point* p = tcx.front()->head()->next->point; - while (!t->GetConstrainedEdgeCW(*p)) { - t = t->NeighborCCW(*p); - } - - // Collect interior triangles constrained by edges - tcx.MeshClean(*t); -} - -Node& Sweep::PointEvent(SweepContext& tcx, Point& point) -{ - Node& node = tcx.LocateNode(point); - Node& new_node = NewFrontTriangle(tcx, point, node); - - // Only need to check +epsilon since point never have smaller - // x value than node due to how we fetch nodes from the front - if (point.x <= node.point->x + EPSILON) { - Fill(tcx, node); - } - - //tcx.AddNode(new_node); - - FillAdvancingFront(tcx, new_node); - return new_node; -} - -void Sweep::EdgeEvent(SweepContext& tcx, Edge* edge, Node* node) -{ - tcx.edge_event.constrained_edge = edge; - tcx.edge_event.right = (edge->p->x > edge->q->x); - - if (IsEdgeSideOfTriangle(*node->triangle, *edge->p, *edge->q)) { - return; - } - - // For now we will do all needed filling - // TODO: integrate with flip process might give some better performance - // but for now this avoid the issue with cases that needs both flips and fills - FillEdgeEvent(tcx, edge, node); - EdgeEvent(tcx, *edge->p, *edge->q, node->triangle, *edge->q); -} - -void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point) -{ - if (IsEdgeSideOfTriangle(*triangle, ep, eq)) { - return; - } - - Point* p1 = triangle->PointCCW(point); - Orientation o1 = Orient2d(eq, *p1, ep); - if (o1 == COLLINEAR) { - // ASSIMP_CHANGE (aramis_acg) - throw std::runtime_error("EdgeEvent - collinear points not supported"); - if( triangle->Contains(&eq, p1)) { - triangle->MarkConstrainedEdge(&eq, p1 ); - // We are modifying the constraint maybe it would be better to - // not change the given constraint and just keep a variable for the new constraint - tcx.edge_event.constrained_edge->q = p1; - triangle = &triangle->NeighborAcross(point); - EdgeEvent( tcx, ep, *p1, triangle, *p1 ); - } else { - // ASSIMP_CHANGE (aramis_acg) - std::runtime_error("EdgeEvent - collinear points not supported"); - } - return; - } - - Point* p2 = triangle->PointCW(point); - Orientation o2 = Orient2d(eq, *p2, ep); - if (o2 == COLLINEAR) { - // ASSIMP_CHANGE (aramis_acg) - throw std::runtime_error("EdgeEvent - collinear points not supported"); - - if( triangle->Contains(&eq, p2)) { - triangle->MarkConstrainedEdge(&eq, p2 ); - // We are modifying the constraint maybe it would be better to - // not change the given constraint and just keep a variable for the new constraint - tcx.edge_event.constrained_edge->q = p2; - triangle = &triangle->NeighborAcross(point); - EdgeEvent( tcx, ep, *p2, triangle, *p2 ); - } else { - // ASSIMP_CHANGE (aramis_acg) - throw std::runtime_error("EdgeEvent - collinear points not supported"); - } - return; - } - - if (o1 == o2) { - // Need to decide if we are rotating CW or CCW to get to a triangle - // that will cross edge - if (o1 == CW) { - triangle = triangle->NeighborCCW(point); - } else{ - triangle = triangle->NeighborCW(point); - } - EdgeEvent(tcx, ep, eq, triangle, point); - } else { - // This triangle crosses constraint so lets flippin start! - FlipEdgeEvent(tcx, ep, eq, triangle, point); - } -} - -bool Sweep::IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq) -{ - int index = triangle.EdgeIndex(&ep, &eq); - - if (index != -1) { - triangle.MarkConstrainedEdge(index); - Triangle* t = triangle.GetNeighbor(index); - if (t) { - t->MarkConstrainedEdge(&ep, &eq); - } - return true; - } - return false; -} - -Node& Sweep::NewFrontTriangle(SweepContext& tcx, Point& point, Node& node) -{ - Triangle* triangle = new Triangle(point, *node.point, *node.next->point); - - triangle->MarkNeighbor(*node.triangle); - tcx.AddToMap(triangle); - - Node* new_node = new Node(point); - nodes_.push_back(new_node); - - new_node->next = node.next; - new_node->prev = &node; - node.next->prev = new_node; - node.next = new_node; - - if (!Legalize(tcx, *triangle)) { - tcx.MapTriangleToNodes(*triangle); - } - - return *new_node; -} - -void Sweep::Fill(SweepContext& tcx, Node& node) -{ - Triangle* triangle = new Triangle(*node.prev->point, *node.point, *node.next->point); - - // TODO: should copy the constrained_edge value from neighbor triangles - // for now constrained_edge values are copied during the legalize - triangle->MarkNeighbor(*node.prev->triangle); - triangle->MarkNeighbor(*node.triangle); - - tcx.AddToMap(triangle); - - // Update the advancing front - node.prev->next = node.next; - node.next->prev = node.prev; - - // If it was legalized the triangle has already been mapped - if (!Legalize(tcx, *triangle)) { - tcx.MapTriangleToNodes(*triangle); - } - -} - -void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n) -{ - - // Fill right holes - Node* node = n.next; - - while (node->next) { - double angle = HoleAngle(*node); - if (angle > PI_2 || angle < -PI_2) break; - Fill(tcx, *node); - node = node->next; - } - - // Fill left holes - node = n.prev; - - while (node->prev) { - double angle = HoleAngle(*node); - if (angle > PI_2 || angle < -PI_2) break; - Fill(tcx, *node); - node = node->prev; - } - - // Fill right basins - if (n.next && n.next->next) { - double angle = BasinAngle(n); - if (angle < PI_3div4) { - FillBasin(tcx, n); - } - } -} - -double Sweep::BasinAngle(Node& node) -{ - double ax = node.point->x - node.next->next->point->x; - double ay = node.point->y - node.next->next->point->y; - return atan2(ay, ax); -} - -double Sweep::HoleAngle(Node& node) -{ - /* Complex plane - * ab = cosA +i*sinA - * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx) - * atan2(y,x) computes the principal value of the argument function - * applied to the complex number x+iy - * Where x = ax*bx + ay*by - * y = ax*by - ay*bx - */ - double ax = node.next->point->x - node.point->x; - double ay = node.next->point->y - node.point->y; - double bx = node.prev->point->x - node.point->x; - double by = node.prev->point->y - node.point->y; - return atan2(ax * by - ay * bx, ax * bx + ay * by); -} - -bool Sweep::Legalize(SweepContext& tcx, Triangle& t) -{ - // To legalize a triangle we start by finding if any of the three edges - // violate the Delaunay condition - for (int i = 0; i < 3; i++) { - if (t.delaunay_edge[i]) - continue; - - Triangle* ot = t.GetNeighbor(i); - - if (ot) { - Point* p = t.GetPoint(i); - Point* op = ot->OppositePoint(t, *p); - int oi = ot->Index(op); - - // If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization) - // then we should not try to legalize - if (ot->constrained_edge[oi] || ot->delaunay_edge[oi]) { - t.constrained_edge[i] = ot->constrained_edge[oi]; - continue; - } - - bool inside = Incircle(*p, *t.PointCCW(*p), *t.PointCW(*p), *op); - - if (inside) { - // Lets mark this shared edge as Delaunay - t.delaunay_edge[i] = true; - ot->delaunay_edge[oi] = true; - - // Lets rotate shared edge one vertex CW to legalize it - RotateTrianglePair(t, *p, *ot, *op); - - // We now got one valid Delaunay Edge shared by two triangles - // This gives us 4 new edges to check for Delaunay - - // Make sure that triangle to node mapping is done only one time for a specific triangle - bool not_legalized = !Legalize(tcx, t); - if (not_legalized) { - tcx.MapTriangleToNodes(t); - } - - not_legalized = !Legalize(tcx, *ot); - if (not_legalized) - tcx.MapTriangleToNodes(*ot); - - // Reset the Delaunay edges, since they only are valid Delaunay edges - // until we add a new triangle or point. - // XXX: need to think about this. Can these edges be tried after we - // return to previous recursive level? - t.delaunay_edge[i] = false; - ot->delaunay_edge[oi] = false; - - // If triangle have been legalized no need to check the other edges since - // the recursive legalization will handles those so we can end here. - return true; - } - } - } - return false; -} - -bool Sweep::Incircle(Point& pa, Point& pb, Point& pc, Point& pd) -{ - double adx = pa.x - pd.x; - double ady = pa.y - pd.y; - double bdx = pb.x - pd.x; - double bdy = pb.y - pd.y; - - double adxbdy = adx * bdy; - double bdxady = bdx * ady; - double oabd = adxbdy - bdxady; - - if (oabd <= 0) - return false; - - double cdx = pc.x - pd.x; - double cdy = pc.y - pd.y; - - double cdxady = cdx * ady; - double adxcdy = adx * cdy; - double ocad = cdxady - adxcdy; - - if (ocad <= 0) - return false; - - double bdxcdy = bdx * cdy; - double cdxbdy = cdx * bdy; - - double alift = adx * adx + ady * ady; - double blift = bdx * bdx + bdy * bdy; - double clift = cdx * cdx + cdy * cdy; - - double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd; - - return det > 0; -} - -void Sweep::RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) -{ - Triangle* n1, *n2, *n3, *n4; - n1 = t.NeighborCCW(p); - n2 = t.NeighborCW(p); - n3 = ot.NeighborCCW(op); - n4 = ot.NeighborCW(op); - - bool ce1, ce2, ce3, ce4; - ce1 = t.GetConstrainedEdgeCCW(p); - ce2 = t.GetConstrainedEdgeCW(p); - ce3 = ot.GetConstrainedEdgeCCW(op); - ce4 = ot.GetConstrainedEdgeCW(op); - - bool de1, de2, de3, de4; - de1 = t.GetDelunayEdgeCCW(p); - de2 = t.GetDelunayEdgeCW(p); - de3 = ot.GetDelunayEdgeCCW(op); - de4 = ot.GetDelunayEdgeCW(op); - - t.Legalize(p, op); - ot.Legalize(op, p); - - // Remap delaunay_edge - ot.SetDelunayEdgeCCW(p, de1); - t.SetDelunayEdgeCW(p, de2); - t.SetDelunayEdgeCCW(op, de3); - ot.SetDelunayEdgeCW(op, de4); - - // Remap constrained_edge - ot.SetConstrainedEdgeCCW(p, ce1); - t.SetConstrainedEdgeCW(p, ce2); - t.SetConstrainedEdgeCCW(op, ce3); - ot.SetConstrainedEdgeCW(op, ce4); - - // Remap neighbors - // XXX: might optimize the markNeighbor by keeping track of - // what side should be assigned to what neighbor after the - // rotation. Now mark neighbor does lots of testing to find - // the right side. - t.ClearNeighbors(); - ot.ClearNeighbors(); - if (n1) ot.MarkNeighbor(*n1); - if (n2) t.MarkNeighbor(*n2); - if (n3) t.MarkNeighbor(*n3); - if (n4) ot.MarkNeighbor(*n4); - t.MarkNeighbor(ot); -} - -void Sweep::FillBasin(SweepContext& tcx, Node& node) -{ - if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { - tcx.basin.left_node = node.next->next; - } else { - tcx.basin.left_node = node.next; - } - - // Find the bottom and right node - tcx.basin.bottom_node = tcx.basin.left_node; - while (tcx.basin.bottom_node->next - && tcx.basin.bottom_node->point->y >= tcx.basin.bottom_node->next->point->y) { - tcx.basin.bottom_node = tcx.basin.bottom_node->next; - } - if (tcx.basin.bottom_node == tcx.basin.left_node) { - // No valid basin - return; - } - - tcx.basin.right_node = tcx.basin.bottom_node; - while (tcx.basin.right_node->next - && tcx.basin.right_node->point->y < tcx.basin.right_node->next->point->y) { - tcx.basin.right_node = tcx.basin.right_node->next; - } - if (tcx.basin.right_node == tcx.basin.bottom_node) { - // No valid basins - return; - } - - tcx.basin.width = tcx.basin.right_node->point->x - tcx.basin.left_node->point->x; - tcx.basin.left_highest = tcx.basin.left_node->point->y > tcx.basin.right_node->point->y; - - FillBasinReq(tcx, tcx.basin.bottom_node); -} - -void Sweep::FillBasinReq(SweepContext& tcx, Node* node) -{ - // if shallow stop filling - if (IsShallow(tcx, *node)) { - return; - } - - Fill(tcx, *node); - - if (node->prev == tcx.basin.left_node && node->next == tcx.basin.right_node) { - return; - } else if (node->prev == tcx.basin.left_node) { - Orientation o = Orient2d(*node->point, *node->next->point, *node->next->next->point); - if (o == CW) { - return; - } - node = node->next; - } else if (node->next == tcx.basin.right_node) { - Orientation o = Orient2d(*node->point, *node->prev->point, *node->prev->prev->point); - if (o == CCW) { - return; - } - node = node->prev; - } else { - // Continue with the neighbor node with lowest Y value - if (node->prev->point->y < node->next->point->y) { - node = node->prev; - } else { - node = node->next; - } - } - - FillBasinReq(tcx, node); -} - -bool Sweep::IsShallow(SweepContext& tcx, Node& node) -{ - double height; - - if (tcx.basin.left_highest) { - height = tcx.basin.left_node->point->y - node.point->y; - } else { - height = tcx.basin.right_node->point->y - node.point->y; - } - - // if shallow stop filling - if (tcx.basin.width > height) { - return true; - } - return false; -} - -void Sweep::FillEdgeEvent(SweepContext& tcx, Edge* edge, Node* node) -{ - if (tcx.edge_event.right) { - FillRightAboveEdgeEvent(tcx, edge, node); - } else { - FillLeftAboveEdgeEvent(tcx, edge, node); - } -} - -void Sweep::FillRightAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node) -{ - while (node->next->point->x < edge->p->x) { - // Check if next node is below the edge - if (Orient2d(*edge->q, *node->next->point, *edge->p) == CCW) { - FillRightBelowEdgeEvent(tcx, edge, *node); - } else { - node = node->next; - } - } -} - -void Sweep::FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) -{ - if (node.point->x < edge->p->x) { - if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { - // Concave - FillRightConcaveEdgeEvent(tcx, edge, node); - } else{ - // Convex - FillRightConvexEdgeEvent(tcx, edge, node); - // Retry this one - FillRightBelowEdgeEvent(tcx, edge, node); - } - } -} - -void Sweep::FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) -{ - Fill(tcx, *node.next); - if (node.next->point != edge->p) { - // Next above or below edge? - if (Orient2d(*edge->q, *node.next->point, *edge->p) == CCW) { - // Below - if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { - // Next is concave - FillRightConcaveEdgeEvent(tcx, edge, node); - } else { - // Next is convex - } - } - } - -} - -void Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) -{ - // Next concave or convex? - if (Orient2d(*node.next->point, *node.next->next->point, *node.next->next->next->point) == CCW) { - // Concave - FillRightConcaveEdgeEvent(tcx, edge, *node.next); - } else{ - // Convex - // Next above or below edge? - if (Orient2d(*edge->q, *node.next->next->point, *edge->p) == CCW) { - // Below - FillRightConvexEdgeEvent(tcx, edge, *node.next); - } else{ - // Above - } - } -} - -void Sweep::FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node) -{ - while (node->prev->point->x > edge->p->x) { - // Check if next node is below the edge - if (Orient2d(*edge->q, *node->prev->point, *edge->p) == CW) { - FillLeftBelowEdgeEvent(tcx, edge, *node); - } else { - node = node->prev; - } - } -} - -void Sweep::FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) -{ - if (node.point->x > edge->p->x) { - if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) { - // Concave - FillLeftConcaveEdgeEvent(tcx, edge, node); - } else { - // Convex - FillLeftConvexEdgeEvent(tcx, edge, node); - // Retry this one - FillLeftBelowEdgeEvent(tcx, edge, node); - } - } -} - -void Sweep::FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) -{ - // Next concave or convex? - if (Orient2d(*node.prev->point, *node.prev->prev->point, *node.prev->prev->prev->point) == CW) { - // Concave - FillLeftConcaveEdgeEvent(tcx, edge, *node.prev); - } else{ - // Convex - // Next above or below edge? - if (Orient2d(*edge->q, *node.prev->prev->point, *edge->p) == CW) { - // Below - FillLeftConvexEdgeEvent(tcx, edge, *node.prev); - } else{ - // Above - } - } -} - -void Sweep::FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) -{ - Fill(tcx, *node.prev); - if (node.prev->point != edge->p) { - // Next above or below edge? - if (Orient2d(*edge->q, *node.prev->point, *edge->p) == CW) { - // Below - if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) { - // Next is concave - FillLeftConcaveEdgeEvent(tcx, edge, node); - } else{ - // Next is convex - } - } - } - -} - -void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p) -{ - Triangle& ot = t->NeighborAcross(p); - Point& op = *ot.OppositePoint(*t, p); - - if (InScanArea(p, *t->PointCCW(p), *t->PointCW(p), op)) { - // Lets rotate shared edge one vertex CW - RotateTrianglePair(*t, p, ot, op); - tcx.MapTriangleToNodes(*t); - tcx.MapTriangleToNodes(ot); - - if (p == eq && op == ep) { - if (eq == *tcx.edge_event.constrained_edge->q && ep == *tcx.edge_event.constrained_edge->p) { - t->MarkConstrainedEdge(&ep, &eq); - ot.MarkConstrainedEdge(&ep, &eq); - Legalize(tcx, *t); - Legalize(tcx, ot); - } else { - // XXX: I think one of the triangles should be legalized here? - } - } else { - Orientation o = Orient2d(eq, op, ep); - t = &NextFlipTriangle(tcx, (int)o, *t, ot, p, op); - FlipEdgeEvent(tcx, ep, eq, t, p); - } - } else { - Point& newP = NextFlipPoint(ep, eq, ot, op); - FlipScanEdgeEvent(tcx, ep, eq, *t, ot, newP); - EdgeEvent(tcx, ep, eq, t, p); - } -} - -Triangle& Sweep::NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op) -{ - if (o == CCW) { - // ot is not crossing edge after flip - int edge_index = ot.EdgeIndex(&p, &op); - ot.delaunay_edge[edge_index] = true; - Legalize(tcx, ot); - ot.ClearDelunayEdges(); - return t; - } - - // t is not crossing edge after flip - int edge_index = t.EdgeIndex(&p, &op); - - t.delaunay_edge[edge_index] = true; - Legalize(tcx, t); - t.ClearDelunayEdges(); - return ot; -} - -Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op) -{ - Orientation o2d = Orient2d(eq, op, ep); - if (o2d == CW) { - // Right - return *ot.PointCCW(op); - } else if (o2d == CCW) { - // Left - return *ot.PointCW(op); - } else{ - //throw new RuntimeException("[Unsupported] Opposing point on constrained edge"); - // ASSIMP_CHANGE (aramis_acg) - throw std::runtime_error("[Unsupported] Opposing point on constrained edge"); - } -} - -void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, - Triangle& t, Point& p) -{ - Triangle& ot = t.NeighborAcross(p); - Point& op = *ot.OppositePoint(t, p); - - if (InScanArea(eq, *flip_triangle.PointCCW(eq), *flip_triangle.PointCW(eq), op)) { - // flip with new edge op->eq - FlipEdgeEvent(tcx, eq, op, &ot, op); - // TODO: Actually I just figured out that it should be possible to - // improve this by getting the next ot and op before the the above - // flip and continue the flipScanEdgeEvent here - // set new ot and op here and loop back to inScanArea test - // also need to set a new flip_triangle first - // Turns out at first glance that this is somewhat complicated - // so it will have to wait. - } else{ - Point& newP = NextFlipPoint(ep, eq, ot, op); - FlipScanEdgeEvent(tcx, ep, eq, flip_triangle, ot, newP); - } -} - -Sweep::~Sweep() { - - // Clean up memory - for(unsigned int i = 0; i < nodes_.size(); i++) { - delete nodes_[i]; - } - -} - -} - +/* + * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors + * http://code.google.com/p/poly2tri/ + * + * All rights reserved. + * + * Redistribution and use 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 Poly2Tri nor the names of its contributors may be + * used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include "sweep.h" +#include "sweep_context.h" +#include "advancing_front.h" +#include "../common/utils.h" + +namespace p2t { + +// Triangulate simple polygon with holes +void Sweep::Triangulate(SweepContext& tcx) +{ + tcx.InitTriangulation(); + tcx.CreateAdvancingFront(nodes_); + // Sweep points; build mesh + SweepPoints(tcx); + // Clean up + FinalizationPolygon(tcx); +} + +void Sweep::SweepPoints(SweepContext& tcx) +{ + for (size_t i = 1; i < tcx.point_count(); i++) { + Point& point = *tcx.GetPoint(i); + Node* node = &PointEvent(tcx, point); + for (unsigned int i = 0; i < point.edge_list.size(); i++) { + EdgeEvent(tcx, point.edge_list[i], node); + } + } +} + +void Sweep::FinalizationPolygon(SweepContext& tcx) +{ + // Get an Internal triangle to start with + Triangle* t = tcx.front()->head()->next->triangle; + Point* p = tcx.front()->head()->next->point; + while (!t->GetConstrainedEdgeCW(*p)) { + t = t->NeighborCCW(*p); + } + + // Collect interior triangles constrained by edges + tcx.MeshClean(*t); +} + +Node& Sweep::PointEvent(SweepContext& tcx, Point& point) +{ + Node& node = tcx.LocateNode(point); + Node& new_node = NewFrontTriangle(tcx, point, node); + + // Only need to check +epsilon since point never have smaller + // x value than node due to how we fetch nodes from the front + if (point.x <= node.point->x + EPSILON) { + Fill(tcx, node); + } + + //tcx.AddNode(new_node); + + FillAdvancingFront(tcx, new_node); + return new_node; +} + +void Sweep::EdgeEvent(SweepContext& tcx, Edge* edge, Node* node) +{ + tcx.edge_event.constrained_edge = edge; + tcx.edge_event.right = (edge->p->x > edge->q->x); + + if (IsEdgeSideOfTriangle(*node->triangle, *edge->p, *edge->q)) { + return; + } + + // For now we will do all needed filling + // TODO: integrate with flip process might give some better performance + // but for now this avoid the issue with cases that needs both flips and fills + FillEdgeEvent(tcx, edge, node); + EdgeEvent(tcx, *edge->p, *edge->q, node->triangle, *edge->q); +} + +void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point) +{ + if (IsEdgeSideOfTriangle(*triangle, ep, eq)) { + return; + } + + Point* p1 = triangle->PointCCW(point); + Orientation o1 = Orient2d(eq, *p1, ep); + if (o1 == COLLINEAR) { + // ASSIMP_CHANGE (aramis_acg) + throw std::runtime_error("EdgeEvent - collinear points not supported"); + if( triangle->Contains(&eq, p1)) { + triangle->MarkConstrainedEdge(&eq, p1 ); + // We are modifying the constraint maybe it would be better to + // not change the given constraint and just keep a variable for the new constraint + tcx.edge_event.constrained_edge->q = p1; + triangle = &triangle->NeighborAcross(point); + EdgeEvent( tcx, ep, *p1, triangle, *p1 ); + } else { + // ASSIMP_CHANGE (aramis_acg) + std::runtime_error("EdgeEvent - collinear points not supported"); + } + return; + } + + Point* p2 = triangle->PointCW(point); + Orientation o2 = Orient2d(eq, *p2, ep); + if (o2 == COLLINEAR) { + // ASSIMP_CHANGE (aramis_acg) + throw std::runtime_error("EdgeEvent - collinear points not supported"); + + if( triangle->Contains(&eq, p2)) { + triangle->MarkConstrainedEdge(&eq, p2 ); + // We are modifying the constraint maybe it would be better to + // not change the given constraint and just keep a variable for the new constraint + tcx.edge_event.constrained_edge->q = p2; + triangle = &triangle->NeighborAcross(point); + EdgeEvent( tcx, ep, *p2, triangle, *p2 ); + } else { + // ASSIMP_CHANGE (aramis_acg) + throw std::runtime_error("EdgeEvent - collinear points not supported"); + } + return; + } + + if (o1 == o2) { + // Need to decide if we are rotating CW or CCW to get to a triangle + // that will cross edge + if (o1 == CW) { + triangle = triangle->NeighborCCW(point); + } else{ + triangle = triangle->NeighborCW(point); + } + EdgeEvent(tcx, ep, eq, triangle, point); + } else { + // This triangle crosses constraint so lets flippin start! + FlipEdgeEvent(tcx, ep, eq, triangle, point); + } +} + +bool Sweep::IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq) +{ + const int index = triangle.EdgeIndex(&ep, &eq); + + if (index != -1) { + triangle.MarkConstrainedEdge(index); + Triangle* t = triangle.GetNeighbor(index); + if (t) { + t->MarkConstrainedEdge(&ep, &eq); + } + return true; + } + return false; +} + +Node& Sweep::NewFrontTriangle(SweepContext& tcx, Point& point, Node& node) +{ + Triangle* triangle = new Triangle(point, *node.point, *node.next->point); + + triangle->MarkNeighbor(*node.triangle); + tcx.AddToMap(triangle); + + Node* new_node = new Node(point); + nodes_.push_back(new_node); + + new_node->next = node.next; + new_node->prev = &node; + node.next->prev = new_node; + node.next = new_node; + + if (!Legalize(tcx, *triangle)) { + tcx.MapTriangleToNodes(*triangle); + } + + return *new_node; +} + +void Sweep::Fill(SweepContext& tcx, Node& node) +{ + Triangle* triangle = new Triangle(*node.prev->point, *node.point, *node.next->point); + + // TODO: should copy the constrained_edge value from neighbor triangles + // for now constrained_edge values are copied during the legalize + triangle->MarkNeighbor(*node.prev->triangle); + triangle->MarkNeighbor(*node.triangle); + + tcx.AddToMap(triangle); + + // Update the advancing front + node.prev->next = node.next; + node.next->prev = node.prev; + + // If it was legalized the triangle has already been mapped + if (!Legalize(tcx, *triangle)) { + tcx.MapTriangleToNodes(*triangle); + } + +} + +void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n) +{ + + // Fill right holes + Node* node = n.next; + + while (node->next) { + // if HoleAngle exceeds 90 degrees then break. + if (LargeHole_DontFill(node)) break; + Fill(tcx, *node); + node = node->next; + } + + // Fill left holes + node = n.prev; + + while (node->prev) { + // if HoleAngle exceeds 90 degrees then break. + if (LargeHole_DontFill(node)) break; + Fill(tcx, *node); + node = node->prev; + } + + // Fill right basins + if (n.next && n.next->next) { + const double angle = BasinAngle(n); + if (angle < PI_3div4) { + FillBasin(tcx, n); + } + } +} + +// True if HoleAngle exceeds 90 degrees. +bool Sweep::LargeHole_DontFill(const Node* node) const { + + const Node* nextNode = node->next; + const Node* prevNode = node->prev; + if (!AngleExceeds90Degrees(node->point, nextNode->point, prevNode->point)) + return false; + + // Check additional points on front. + const Node* next2Node = nextNode->next; + // "..Plus.." because only want angles on same side as point being added. + if ((next2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, next2Node->point, prevNode->point)) + return false; + + const Node* prev2Node = prevNode->prev; + // "..Plus.." because only want angles on same side as point being added. + if ((prev2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, nextNode->point, prev2Node->point)) + return false; + + return true; +} + +bool Sweep::AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const { + const double angle = Angle(origin, pa, pb); + return ((angle > PI_div2) || (angle < -PI_div2)); +} + +bool Sweep::AngleExceedsPlus90DegreesOrIsNegative(const Point* origin, const Point* pa, const Point* pb) const { + const double angle = Angle(origin, pa, pb); + return (angle > PI_div2) || (angle < 0); +} + +double Sweep::Angle(const Point* origin, const Point* pa, const Point* pb) const { + /* Complex plane + * ab = cosA +i*sinA + * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx) + * atan2(y,x) computes the principal value of the argument function + * applied to the complex number x+iy + * Where x = ax*bx + ay*by + * y = ax*by - ay*bx + */ + const double px = origin->x; + const double py = origin->y; + const double ax = pa->x- px; + const double ay = pa->y - py; + const double bx = pb->x - px; + const double by = pb->y - py; + const double x = ax * by - ay * bx; + const double y = ax * bx + ay * by; + return atan2(x, y); +} + +double Sweep::BasinAngle(const Node& node) const +{ + const double ax = node.point->x - node.next->next->point->x; + const double ay = node.point->y - node.next->next->point->y; + return atan2(ay, ax); +} + +double Sweep::HoleAngle(const Node& node) const +{ + /* Complex plane + * ab = cosA +i*sinA + * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx) + * atan2(y,x) computes the principal value of the argument function + * applied to the complex number x+iy + * Where x = ax*bx + ay*by + * y = ax*by - ay*bx + */ + const double ax = node.next->point->x - node.point->x; + const double ay = node.next->point->y - node.point->y; + const double bx = node.prev->point->x - node.point->x; + const double by = node.prev->point->y - node.point->y; + return atan2(ax * by - ay * bx, ax * bx + ay * by); +} + +bool Sweep::Legalize(SweepContext& tcx, Triangle& t) +{ + // To legalize a triangle we start by finding if any of the three edges + // violate the Delaunay condition + for (int i = 0; i < 3; i++) { + if (t.delaunay_edge[i]) + continue; + + Triangle* ot = t.GetNeighbor(i); + + if (ot) { + Point* p = t.GetPoint(i); + Point* op = ot->OppositePoint(t, *p); + int oi = ot->Index(op); + + // If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization) + // then we should not try to legalize + if (ot->constrained_edge[oi] || ot->delaunay_edge[oi]) { + t.constrained_edge[i] = ot->constrained_edge[oi]; + continue; + } + + bool inside = Incircle(*p, *t.PointCCW(*p), *t.PointCW(*p), *op); + + if (inside) { + // Lets mark this shared edge as Delaunay + t.delaunay_edge[i] = true; + ot->delaunay_edge[oi] = true; + + // Lets rotate shared edge one vertex CW to legalize it + RotateTrianglePair(t, *p, *ot, *op); + + // We now got one valid Delaunay Edge shared by two triangles + // This gives us 4 new edges to check for Delaunay + + // Make sure that triangle to node mapping is done only one time for a specific triangle + bool not_legalized = !Legalize(tcx, t); + if (not_legalized) { + tcx.MapTriangleToNodes(t); + } + + not_legalized = !Legalize(tcx, *ot); + if (not_legalized) + tcx.MapTriangleToNodes(*ot); + + // Reset the Delaunay edges, since they only are valid Delaunay edges + // until we add a new triangle or point. + // XXX: need to think about this. Can these edges be tried after we + // return to previous recursive level? + t.delaunay_edge[i] = false; + ot->delaunay_edge[oi] = false; + + // If triangle have been legalized no need to check the other edges since + // the recursive legalization will handles those so we can end here. + return true; + } + } + } + return false; +} + +bool Sweep::Incircle(const Point& pa, const Point& pb, const Point& pc, const Point& pd) const +{ + const double adx = pa.x - pd.x; + const double ady = pa.y - pd.y; + const double bdx = pb.x - pd.x; + const double bdy = pb.y - pd.y; + + const double adxbdy = adx * bdy; + const double bdxady = bdx * ady; + const double oabd = adxbdy - bdxady; + + if (oabd <= 0) + return false; + + const double cdx = pc.x - pd.x; + const double cdy = pc.y - pd.y; + + const double cdxady = cdx * ady; + const double adxcdy = adx * cdy; + const double ocad = cdxady - adxcdy; + + if (ocad <= 0) + return false; + + const double bdxcdy = bdx * cdy; + const double cdxbdy = cdx * bdy; + + const double alift = adx * adx + ady * ady; + const double blift = bdx * bdx + bdy * bdy; + const double clift = cdx * cdx + cdy * cdy; + + const double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd; + + return det > 0; +} + +void Sweep::RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) const +{ + Triangle* n1, *n2, *n3, *n4; + n1 = t.NeighborCCW(p); + n2 = t.NeighborCW(p); + n3 = ot.NeighborCCW(op); + n4 = ot.NeighborCW(op); + + bool ce1, ce2, ce3, ce4; + ce1 = t.GetConstrainedEdgeCCW(p); + ce2 = t.GetConstrainedEdgeCW(p); + ce3 = ot.GetConstrainedEdgeCCW(op); + ce4 = ot.GetConstrainedEdgeCW(op); + + bool de1, de2, de3, de4; + de1 = t.GetDelunayEdgeCCW(p); + de2 = t.GetDelunayEdgeCW(p); + de3 = ot.GetDelunayEdgeCCW(op); + de4 = ot.GetDelunayEdgeCW(op); + + t.Legalize(p, op); + ot.Legalize(op, p); + + // Remap delaunay_edge + ot.SetDelunayEdgeCCW(p, de1); + t.SetDelunayEdgeCW(p, de2); + t.SetDelunayEdgeCCW(op, de3); + ot.SetDelunayEdgeCW(op, de4); + + // Remap constrained_edge + ot.SetConstrainedEdgeCCW(p, ce1); + t.SetConstrainedEdgeCW(p, ce2); + t.SetConstrainedEdgeCCW(op, ce3); + ot.SetConstrainedEdgeCW(op, ce4); + + // Remap neighbors + // XXX: might optimize the markNeighbor by keeping track of + // what side should be assigned to what neighbor after the + // rotation. Now mark neighbor does lots of testing to find + // the right side. + t.ClearNeighbors(); + ot.ClearNeighbors(); + if (n1) ot.MarkNeighbor(*n1); + if (n2) t.MarkNeighbor(*n2); + if (n3) t.MarkNeighbor(*n3); + if (n4) ot.MarkNeighbor(*n4); + t.MarkNeighbor(ot); +} + +void Sweep::FillBasin(SweepContext& tcx, Node& node) +{ + if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { + tcx.basin.left_node = node.next->next; + } else { + tcx.basin.left_node = node.next; + } + + // Find the bottom and right node + tcx.basin.bottom_node = tcx.basin.left_node; + while (tcx.basin.bottom_node->next + && tcx.basin.bottom_node->point->y >= tcx.basin.bottom_node->next->point->y) { + tcx.basin.bottom_node = tcx.basin.bottom_node->next; + } + if (tcx.basin.bottom_node == tcx.basin.left_node) { + // No valid basin + return; + } + + tcx.basin.right_node = tcx.basin.bottom_node; + while (tcx.basin.right_node->next + && tcx.basin.right_node->point->y < tcx.basin.right_node->next->point->y) { + tcx.basin.right_node = tcx.basin.right_node->next; + } + if (tcx.basin.right_node == tcx.basin.bottom_node) { + // No valid basins + return; + } + + tcx.basin.width = tcx.basin.right_node->point->x - tcx.basin.left_node->point->x; + tcx.basin.left_highest = tcx.basin.left_node->point->y > tcx.basin.right_node->point->y; + + FillBasinReq(tcx, tcx.basin.bottom_node); +} + +void Sweep::FillBasinReq(SweepContext& tcx, Node* node) +{ + // if shallow stop filling + if (IsShallow(tcx, *node)) { + return; + } + + Fill(tcx, *node); + + if (node->prev == tcx.basin.left_node && node->next == tcx.basin.right_node) { + return; + } else if (node->prev == tcx.basin.left_node) { + Orientation o = Orient2d(*node->point, *node->next->point, *node->next->next->point); + if (o == CW) { + return; + } + node = node->next; + } else if (node->next == tcx.basin.right_node) { + Orientation o = Orient2d(*node->point, *node->prev->point, *node->prev->prev->point); + if (o == CCW) { + return; + } + node = node->prev; + } else { + // Continue with the neighbor node with lowest Y value + if (node->prev->point->y < node->next->point->y) { + node = node->prev; + } else { + node = node->next; + } + } + + FillBasinReq(tcx, node); +} + +bool Sweep::IsShallow(SweepContext& tcx, Node& node) +{ + double height; + + if (tcx.basin.left_highest) { + height = tcx.basin.left_node->point->y - node.point->y; + } else { + height = tcx.basin.right_node->point->y - node.point->y; + } + + // if shallow stop filling + if (tcx.basin.width > height) { + return true; + } + return false; +} + +void Sweep::FillEdgeEvent(SweepContext& tcx, Edge* edge, Node* node) +{ + if (tcx.edge_event.right) { + FillRightAboveEdgeEvent(tcx, edge, node); + } else { + FillLeftAboveEdgeEvent(tcx, edge, node); + } +} + +void Sweep::FillRightAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node) +{ + while (node->next->point->x < edge->p->x) { + // Check if next node is below the edge + if (Orient2d(*edge->q, *node->next->point, *edge->p) == CCW) { + FillRightBelowEdgeEvent(tcx, edge, *node); + } else { + node = node->next; + } + } +} + +void Sweep::FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + if (node.point->x < edge->p->x) { + if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { + // Concave + FillRightConcaveEdgeEvent(tcx, edge, node); + } else{ + // Convex + FillRightConvexEdgeEvent(tcx, edge, node); + // Retry this one + FillRightBelowEdgeEvent(tcx, edge, node); + } + } +} + +void Sweep::FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + Fill(tcx, *node.next); + if (node.next->point != edge->p) { + // Next above or below edge? + if (Orient2d(*edge->q, *node.next->point, *edge->p) == CCW) { + // Below + if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { + // Next is concave + FillRightConcaveEdgeEvent(tcx, edge, node); + } else { + // Next is convex + } + } + } + +} + +void Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + // Next concave or convex? + if (Orient2d(*node.next->point, *node.next->next->point, *node.next->next->next->point) == CCW) { + // Concave + FillRightConcaveEdgeEvent(tcx, edge, *node.next); + } else{ + // Convex + // Next above or below edge? + if (Orient2d(*edge->q, *node.next->next->point, *edge->p) == CCW) { + // Below + FillRightConvexEdgeEvent(tcx, edge, *node.next); + } else{ + // Above + } + } +} + +void Sweep::FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node) +{ + while (node->prev->point->x > edge->p->x) { + // Check if next node is below the edge + if (Orient2d(*edge->q, *node->prev->point, *edge->p) == CW) { + FillLeftBelowEdgeEvent(tcx, edge, *node); + } else { + node = node->prev; + } + } +} + +void Sweep::FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + if (node.point->x > edge->p->x) { + if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) { + // Concave + FillLeftConcaveEdgeEvent(tcx, edge, node); + } else { + // Convex + FillLeftConvexEdgeEvent(tcx, edge, node); + // Retry this one + FillLeftBelowEdgeEvent(tcx, edge, node); + } + } +} + +void Sweep::FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + // Next concave or convex? + if (Orient2d(*node.prev->point, *node.prev->prev->point, *node.prev->prev->prev->point) == CW) { + // Concave + FillLeftConcaveEdgeEvent(tcx, edge, *node.prev); + } else{ + // Convex + // Next above or below edge? + if (Orient2d(*edge->q, *node.prev->prev->point, *edge->p) == CW) { + // Below + FillLeftConvexEdgeEvent(tcx, edge, *node.prev); + } else{ + // Above + } + } +} + +void Sweep::FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + Fill(tcx, *node.prev); + if (node.prev->point != edge->p) { + // Next above or below edge? + if (Orient2d(*edge->q, *node.prev->point, *edge->p) == CW) { + // Below + if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) { + // Next is concave + FillLeftConcaveEdgeEvent(tcx, edge, node); + } else{ + // Next is convex + } + } + } + +} + +void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p) +{ + Triangle& ot = t->NeighborAcross(p); + Point& op = *ot.OppositePoint(*t, p); + + if (InScanArea(p, *t->PointCCW(p), *t->PointCW(p), op)) { + // Lets rotate shared edge one vertex CW + RotateTrianglePair(*t, p, ot, op); + tcx.MapTriangleToNodes(*t); + tcx.MapTriangleToNodes(ot); + + if (p == eq && op == ep) { + if (eq == *tcx.edge_event.constrained_edge->q && ep == *tcx.edge_event.constrained_edge->p) { + t->MarkConstrainedEdge(&ep, &eq); + ot.MarkConstrainedEdge(&ep, &eq); + Legalize(tcx, *t); + Legalize(tcx, ot); + } else { + // XXX: I think one of the triangles should be legalized here? + } + } else { + Orientation o = Orient2d(eq, op, ep); + t = &NextFlipTriangle(tcx, (int)o, *t, ot, p, op); + FlipEdgeEvent(tcx, ep, eq, t, p); + } + } else { + Point& newP = NextFlipPoint(ep, eq, ot, op); + FlipScanEdgeEvent(tcx, ep, eq, *t, ot, newP); + EdgeEvent(tcx, ep, eq, t, p); + } +} + +Triangle& Sweep::NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op) +{ + if (o == CCW) { + // ot is not crossing edge after flip + int edge_index = ot.EdgeIndex(&p, &op); + ot.delaunay_edge[edge_index] = true; + Legalize(tcx, ot); + ot.ClearDelunayEdges(); + return t; + } + + // t is not crossing edge after flip + int edge_index = t.EdgeIndex(&p, &op); + + t.delaunay_edge[edge_index] = true; + Legalize(tcx, t); + t.ClearDelunayEdges(); + return ot; +} + +Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op) +{ + Orientation o2d = Orient2d(eq, op, ep); + if (o2d == CW) { + // Right + return *ot.PointCCW(op); + } else if (o2d == CCW) { + // Left + return *ot.PointCW(op); + } + throw std::runtime_error("[Unsupported] Opposing point on constrained edge"); +} + +void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, + Triangle& t, Point& p) +{ + Triangle& ot = t.NeighborAcross(p); + Point& op = *ot.OppositePoint(t, p); + + if (InScanArea(eq, *flip_triangle.PointCCW(eq), *flip_triangle.PointCW(eq), op)) { + // flip with new edge op->eq + FlipEdgeEvent(tcx, eq, op, &ot, op); + // TODO: Actually I just figured out that it should be possible to + // improve this by getting the next ot and op before the the above + // flip and continue the flipScanEdgeEvent here + // set new ot and op here and loop back to inScanArea test + // also need to set a new flip_triangle first + // Turns out at first glance that this is somewhat complicated + // so it will have to wait. + } else{ + Point& newP = NextFlipPoint(ep, eq, ot, op); + FlipScanEdgeEvent(tcx, ep, eq, flip_triangle, ot, newP); + } +} + +Sweep::~Sweep() { + + // Clean up memory + for(size_t i = 0; i < nodes_.size(); i++) { + delete nodes_[i]; + } + +} + +} + diff --git a/contrib/poly2tri/poly2tri/sweep/sweep.h b/contrib/poly2tri/poly2tri/sweep/sweep.h index bd98adfc5..33e34a714 100644 --- a/contrib/poly2tri/poly2tri/sweep/sweep.h +++ b/contrib/poly2tri/poly2tri/sweep/sweep.h @@ -33,7 +33,7 @@ * Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation', * International Journal of Geographical Information Science * - * "FlipScan" Constrained Edge Algorithm invented by Thomas Åhlén, thahlen@gmail.com + * "FlipScan" Constrained Edge Algorithm invented by Thomas ?hl?n, thahlen@gmail.com */ #ifndef SWEEP_H @@ -49,17 +49,17 @@ struct Point; struct Edge; class Triangle; -class Sweep +class Sweep { public: /** * Triangulate - * + * * @param tcx */ void Triangulate(SweepContext& tcx); - + /** * Destructor - clean up memory */ @@ -69,7 +69,7 @@ private: /** * Start sweeping the Y-sorted point set from bottom to top - * + * * @param tcx */ void SweepPoints(SweepContext& tcx); @@ -86,8 +86,8 @@ private: Node& PointEvent(SweepContext& tcx, Point& point); /** - * - * + * + * * @param tcx * @param edge * @param node @@ -98,7 +98,7 @@ private: /** * Creates a new front triangle and legalize it - * + * * @param tcx * @param point * @param node @@ -142,7 +142,7 @@ private: * @param d - point opposite a * @return true if d is inside circle, false if on circle edge */ - bool Incircle(Point& pa, Point& pb, Point& pc, Point& pd); + bool Incircle(const Point& pa, const Point& pb, const Point& pc, const Point& pd) const; /** * Rotates a triangle pair one vertex CW @@ -158,7 +158,7 @@ private: * n4 n4 * */ - void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op); + void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) const; /** * Fills holes in the Advancing Front @@ -169,17 +169,24 @@ private: */ void FillAdvancingFront(SweepContext& tcx, Node& n); + // Decision-making about when to Fill hole. + // Contributed by ToolmakerSteve2 + bool LargeHole_DontFill(const Node* node) const; + bool AngleExceeds90Degrees(const Point* origin, const Point* pa, const Point* pb) const; + bool AngleExceedsPlus90DegreesOrIsNegative(const Point* origin, const Point* pa, const Point* pb) const; + double Angle(const Point* origin, const Point* pa, const Point* pb) const; + /** * * @param node - middle node * @return the angle between 3 front nodes */ - double HoleAngle(Node& node); + double HoleAngle(const Node& node) const; /** * The basin angle is decided against the horizontal line [1,0] */ - double BasinAngle(Node& node); + double BasinAngle(const Node& node) const; /** * Fills a basin that has formed on the Advancing Front to the right @@ -228,22 +235,22 @@ private: /** * After a flip we have two triangles and know that only one will still be * intersecting the edge. So decide which to contiune with and legalize the other - * + * * @param tcx * @param o - should be the result of an orient2d( eq, op, ep ) * @param t - triangle 1 * @param ot - triangle 2 - * @param p - a point shared by both triangles + * @param p - a point shared by both triangles * @param op - another point shared by both triangles * @return returns the triangle still intersecting the edge */ Triangle& NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op); /** - * When we need to traverse from one triangle to the next we need + * When we need to traverse from one triangle to the next we need * the point in current triangle that is the opposite point to the next - * triangle. - * + * triangle. + * * @param ep * @param eq * @param ot @@ -254,10 +261,10 @@ private: /** * Scan part of the FlipScan algorithm
- * When a triangle pair isn't flippable we will scan for the next - * point that is inside the flip triangle scan area. When found + * When a triangle pair isn't flippable we will scan for the next + * point that is inside the flip triangle scan area. When found * we generate a new flipEdgeEvent - * + * * @param tcx * @param ep - last point on the edge we are traversing * @param eq - first point on the edge we are traversing @@ -275,4 +282,4 @@ private: } -#endif +#endif \ No newline at end of file diff --git a/contrib/poly2tri/poly2tri/sweep/sweep_context.cc b/contrib/poly2tri/poly2tri/sweep/sweep_context.cc index 184457cf2..a9f1fdf8e 100644 --- a/contrib/poly2tri/poly2tri/sweep/sweep_context.cc +++ b/contrib/poly2tri/poly2tri/sweep/sweep_context.cc @@ -34,17 +34,18 @@ namespace p2t { -SweepContext::SweepContext(std::vector polyline) +SweepContext::SweepContext(const std::vector& polyline) : points_(polyline), + front_(0), + head_(0), + tail_(0), + af_head_(0), + af_middle_(0), + af_tail_(0) { - basin = Basin(); - edge_event = EdgeEvent(); - - points_ = polyline; - InitEdges(points_); } -void SweepContext::AddHole(std::vector polyline) +void SweepContext::AddHole(const std::vector& polyline) { InitEdges(polyline); for(unsigned int i = 0; i < polyline.size(); i++) { @@ -56,12 +57,12 @@ void SweepContext::AddPoint(Point* point) { points_.push_back(point); } -std::vector SweepContext::GetTriangles() +std::vector &SweepContext::GetTriangles() { return triangles_; } -std::list SweepContext::GetMap() +std::list &SweepContext::GetMap() { return map_; } @@ -94,16 +95,16 @@ void SweepContext::InitTriangulation() } -void SweepContext::InitEdges(std::vector polyline) +void SweepContext::InitEdges(const std::vector& polyline) { - int num_points = static_cast(polyline.size()); - for (int i = 0; i < num_points; i++) { - int j = i < num_points - 1 ? i + 1 : 0; + size_t num_points = polyline.size(); + for (size_t i = 0; i < num_points; i++) { + size_t j = i < num_points - 1 ? i + 1 : 0; edge_list.push_back(new Edge(*polyline[i], *polyline[j])); } } -Point* SweepContext::GetPoint(const int& index) +Point* SweepContext::GetPoint(size_t index) { return points_[index]; } @@ -113,13 +114,13 @@ void SweepContext::AddToMap(Triangle* triangle) map_.push_back(triangle); } -Node& SweepContext::LocateNode(Point& point) +Node& SweepContext::LocateNode(const Point& point) { // TODO implement search tree return *front_->LocateNode(point.x); } -void SweepContext::CreateAdvancingFront(std::vector nodes) +void SweepContext::CreateAdvancingFront(const std::vector& nodes) { (void) nodes; @@ -164,12 +165,20 @@ void SweepContext::RemoveFromMap(Triangle* triangle) void SweepContext::MeshClean(Triangle& triangle) { - if (!triangle.IsInterior()) { - triangle.IsInterior(true); - triangles_.push_back(&triangle); - for (int i = 0; i < 3; i++) { - if (!triangle.constrained_edge[i]) - MeshClean(*triangle.GetNeighbor(i)); + std::vector triangles; + triangles.push_back(&triangle); + + while(!triangles.empty()){ + Triangle *t = triangles.back(); + triangles.pop_back(); + + if (t != NULL && !t->IsInterior()) { + t->IsInterior(true); + triangles_.push_back(t); + for (int i = 0; i < 3; i++) { + if (!t->constrained_edge[i]) + triangles.push_back(t->GetNeighbor(i)); + } } } } diff --git a/contrib/poly2tri/poly2tri/sweep/sweep_context.h b/contrib/poly2tri/poly2tri/sweep/sweep_context.h index 2f7d8e982..ba0d06581 100644 --- a/contrib/poly2tri/poly2tri/sweep/sweep_context.h +++ b/contrib/poly2tri/poly2tri/sweep/sweep_context.h @@ -52,47 +52,47 @@ class SweepContext { public: /// Constructor -SweepContext(std::vector polyline); +SweepContext(const std::vector& polyline); /// Destructor ~SweepContext(); void set_head(Point* p1); -Point* head(); +Point* head() const; void set_tail(Point* p1); -Point* tail(); +Point* tail() const; -int point_count(); +size_t point_count() const; -Node& LocateNode(Point& point); +Node& LocateNode(const Point& point); void RemoveNode(Node* node); -void CreateAdvancingFront(std::vector nodes); +void CreateAdvancingFront(const std::vector& nodes); /// Try to map a node to all sides of this triangle that don't have a neighbor void MapTriangleToNodes(Triangle& t); void AddToMap(Triangle* triangle); -Point* GetPoint(const int& index); +Point* GetPoint(size_t index); Point* GetPoints(); void RemoveFromMap(Triangle* triangle); -void AddHole(std::vector polyline); +void AddHole(const std::vector& polyline); void AddPoint(Point* point); -AdvancingFront* front(); +AdvancingFront* front() const; void MeshClean(Triangle& triangle); -std::vector GetTriangles(); -std::list GetMap(); +std::vector &GetTriangles(); +std::list &GetMap(); std::vector edge_list; @@ -147,18 +147,18 @@ Point* tail_; Node *af_head_, *af_middle_, *af_tail_; void InitTriangulation(); -void InitEdges(std::vector polyline); +void InitEdges(const std::vector& polyline); }; -inline AdvancingFront* SweepContext::front() +inline AdvancingFront* SweepContext::front() const { return front_; } -inline int SweepContext::point_count() +inline size_t SweepContext::point_count() const { - return static_cast(points_.size()); + return points_.size(); } inline void SweepContext::set_head(Point* p1) @@ -166,7 +166,7 @@ inline void SweepContext::set_head(Point* p1) head_ = p1; } -inline Point* SweepContext::head() +inline Point* SweepContext::head() const { return head_; } @@ -176,7 +176,7 @@ inline void SweepContext::set_tail(Point* p1) tail_ = p1; } -inline Point* SweepContext::tail() +inline Point* SweepContext::tail() const { return tail_; } diff --git a/contrib/rapidjson/include/rapidjson/allocators.h b/contrib/rapidjson/include/rapidjson/allocators.h index d74a67155..655f4a385 100644 --- a/contrib/rapidjson/include/rapidjson/allocators.h +++ b/contrib/rapidjson/include/rapidjson/allocators.h @@ -179,9 +179,10 @@ public: size = RAPIDJSON_ALIGN(size); if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity) - AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size); + if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size)) + return NULL; - void *buffer = reinterpret_cast(chunkHead_ + 1) + chunkHead_->size; + void *buffer = reinterpret_cast(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size; chunkHead_->size += size; return buffer; } @@ -194,14 +195,16 @@ public: if (newSize == 0) return NULL; + originalSize = RAPIDJSON_ALIGN(originalSize); + newSize = RAPIDJSON_ALIGN(newSize); + // Do not shrink if new size is smaller than original if (originalSize >= newSize) return originalPtr; // Simply expand it if it is the last allocation and there is sufficient space - if (originalPtr == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) { + if (originalPtr == reinterpret_cast(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) { size_t increment = static_cast(newSize - originalSize); - increment = RAPIDJSON_ALIGN(increment); if (chunkHead_->size + increment <= chunkHead_->capacity) { chunkHead_->size += increment; return originalPtr; @@ -209,11 +212,13 @@ public: } // Realloc process: allocate and copy memory, do not free original buffer. - void* newBuffer = Malloc(newSize); - RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly. - if (originalSize) - std::memcpy(newBuffer, originalPtr, originalSize); - return newBuffer; + if (void* newBuffer = Malloc(newSize)) { + if (originalSize) + std::memcpy(newBuffer, originalPtr, originalSize); + return newBuffer; + } + else + return NULL; } //! Frees a memory block (concept Allocator) @@ -227,15 +232,20 @@ private: //! Creates a new chunk. /*! \param capacity Capacity of the chunk in bytes. + \return true if success. */ - void AddChunk(size_t capacity) { + bool AddChunk(size_t capacity) { if (!baseAllocator_) - ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator()); - ChunkHeader* chunk = reinterpret_cast(baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity)); - chunk->capacity = capacity; - chunk->size = 0; - chunk->next = chunkHead_; - chunkHead_ = chunk; + ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)(); + if (ChunkHeader* chunk = reinterpret_cast(baseAllocator_->Malloc(RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) { + chunk->capacity = capacity; + chunk->size = 0; + chunk->next = chunkHead_; + chunkHead_ = chunk; + return true; + } + else + return false; } static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity. diff --git a/contrib/rapidjson/include/rapidjson/document.h b/contrib/rapidjson/include/rapidjson/document.h index c6acbd907..93b091f64 100644 --- a/contrib/rapidjson/include/rapidjson/document.h +++ b/contrib/rapidjson/include/rapidjson/document.h @@ -20,40 +20,29 @@ #include "reader.h" #include "internal/meta.h" #include "internal/strfunc.h" +#include "memorystream.h" +#include "encodedstream.h" #include // placement new +#include +RAPIDJSON_DIAG_PUSH #ifdef _MSC_VER -RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant -#elif defined(__GNUC__) -RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + +#ifdef __GNUC__ RAPIDJSON_DIAG_OFF(effc++) +#if __GNUC__ >= 6 +RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_NOEXCEPT functions #endif - -/////////////////////////////////////////////////////////////////////////////// -// RAPIDJSON_HAS_STDSTRING - -#ifndef RAPIDJSON_HAS_STDSTRING -#ifdef RAPIDJSON_DOXYGEN_RUNNING -#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation -#else -#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default -#endif -/*! \def RAPIDJSON_HAS_STDSTRING - \ingroup RAPIDJSON_CONFIG - \brief Enable RapidJSON support for \c std::string - - By defining this preprocessor symbol to \c 1, several convenience functions for using - \ref rapidjson::GenericValue with \c std::string are enabled, especially - for construction and comparison. - - \hideinitializer -*/ -#endif // !defined(RAPIDJSON_HAS_STDSTRING) - -#if RAPIDJSON_HAS_STDSTRING -#include -#endif // RAPIDJSON_HAS_STDSTRING +#endif // __GNUC__ #ifndef RAPIDJSON_NOMEMBERITERATORCLASS #include // std::iterator, std::random_access_iterator_tag @@ -69,6 +58,9 @@ RAPIDJSON_NAMESPACE_BEGIN template class GenericValue; +template +class GenericDocument; + //! Name-value pair in a JSON object value. /*! This class was internal to GenericValue. It used to be a inner struct. @@ -155,6 +147,7 @@ public: Otherwise, the copy constructor is implicitly defined. */ GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {} + Iterator& operator=(const NonConstIterator & it) { ptr_ = it.ptr_; return *this; } //! @name stepping //@{ @@ -257,6 +250,7 @@ struct GenericStringRef { typedef CharType Ch; //!< character type of the string //! Create string reference from \c const character array +#ifndef __clang__ // -Wdocumentation /*! This constructor implicitly creates a constant string reference from a \c const character array. It has better performance than @@ -279,11 +273,13 @@ struct GenericStringRef { In such cases, the referenced string should be \b copied to the GenericValue instead. */ +#endif template GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT : s(str), length(N-1) {} //! Explicitly create string reference from \c const character pointer +#ifndef __clang__ // -Wdocumentation /*! This constructor can be used to \b explicitly create a reference to a constant string pointer. @@ -302,18 +298,23 @@ struct GenericStringRef { In such cases, the referenced string should be \b copied to the GenericValue instead. */ +#endif explicit GenericStringRef(const CharType* str) - : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); } + : s(str), length(NotNullStrLen(str)) {} //! Create constant string reference from pointer and length +#ifndef __clang__ // -Wdocumentation /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue \param len length of the string, excluding the trailing NULL terminator \post \ref s == str && \ref length == len \note Constant complexity. */ +#endif GenericStringRef(const CharType* str, SizeType len) - : s(str), length(len) { RAPIDJSON_ASSERT(s != NULL); } + : s(RAPIDJSON_LIKELY(str) ? str : emptyString), length(len) { RAPIDJSON_ASSERT(str != 0 || len == 0u); } + + GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {} //! implicit conversion to plain CharType pointer operator const Ch *() const { return s; } @@ -322,13 +323,24 @@ struct GenericStringRef { const SizeType length; //!< length of the string (excluding the trailing NULL terminator) private: - //! Disallow copy-assignment - GenericStringRef operator=(const GenericStringRef&); + SizeType NotNullStrLen(const CharType* str) { + RAPIDJSON_ASSERT(str != 0); + return internal::StrLen(str); + } + + /// Empty string - used when passing in a NULL pointer + static const Ch emptyString[]; + //! Disallow construction from non-const array template GenericStringRef(CharType (&str)[N]) /* = delete */; + //! Copy assignment operator not permitted - immutable type + GenericStringRef& operator=(const GenericStringRef& rhs) /* = delete */; }; +template +const CharType GenericStringRef::emptyString[] = { CharType() }; + //! Mark a character pointer as constant string /*! Mark a plain character pointer as a "string literal". This function can be used to avoid copying a character string to be referenced as a @@ -343,7 +355,7 @@ private: */ template inline GenericStringRef StringRef(const CharType* str) { - return GenericStringRef(str, internal::StrLen(str)); + return GenericStringRef(str); } //! Mark a character pointer as constant string @@ -401,6 +413,127 @@ template struct IsGenericValue : IsGenericValueImpl::Type {}; } // namespace internal +/////////////////////////////////////////////////////////////////////////////// +// TypeHelper + +namespace internal { + +template +struct TypeHelper {}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsBool(); } + static bool Get(const ValueType& v) { return v.GetBool(); } + static ValueType& Set(ValueType& v, bool data) { return v.SetBool(data); } + static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsInt(); } + static int Get(const ValueType& v) { return v.GetInt(); } + static ValueType& Set(ValueType& v, int data) { return v.SetInt(data); } + static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsUint(); } + static unsigned Get(const ValueType& v) { return v.GetUint(); } + static ValueType& Set(ValueType& v, unsigned data) { return v.SetUint(data); } + static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsInt64(); } + static int64_t Get(const ValueType& v) { return v.GetInt64(); } + static ValueType& Set(ValueType& v, int64_t data) { return v.SetInt64(data); } + static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsUint64(); } + static uint64_t Get(const ValueType& v) { return v.GetUint64(); } + static ValueType& Set(ValueType& v, uint64_t data) { return v.SetUint64(data); } + static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsDouble(); } + static double Get(const ValueType& v) { return v.GetDouble(); } + static ValueType& Set(ValueType& v, double data) { return v.SetDouble(data); } + static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); } +}; + +template +struct TypeHelper { + static bool Is(const ValueType& v) { return v.IsFloat(); } + static float Get(const ValueType& v) { return v.GetFloat(); } + static ValueType& Set(ValueType& v, float data) { return v.SetFloat(data); } + static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); } +}; + +template +struct TypeHelper { + typedef const typename ValueType::Ch* StringType; + static bool Is(const ValueType& v) { return v.IsString(); } + static StringType Get(const ValueType& v) { return v.GetString(); } + static ValueType& Set(ValueType& v, const StringType data) { return v.SetString(typename ValueType::StringRefType(data)); } + static ValueType& Set(ValueType& v, const StringType data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } +}; + +#if RAPIDJSON_HAS_STDSTRING +template +struct TypeHelper > { + typedef std::basic_string StringType; + static bool Is(const ValueType& v) { return v.IsString(); } + static StringType Get(const ValueType& v) { return StringType(v.GetString(), v.GetStringLength()); } + static ValueType& Set(ValueType& v, const StringType& data, typename ValueType::AllocatorType& a) { return v.SetString(data, a); } +}; +#endif + +template +struct TypeHelper { + typedef typename ValueType::Array ArrayType; + static bool Is(const ValueType& v) { return v.IsArray(); } + static ArrayType Get(ValueType& v) { return v.GetArray(); } + static ValueType& Set(ValueType& v, ArrayType data) { return v = data; } + static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v = data; } +}; + +template +struct TypeHelper { + typedef typename ValueType::ConstArray ArrayType; + static bool Is(const ValueType& v) { return v.IsArray(); } + static ArrayType Get(const ValueType& v) { return v.GetArray(); } +}; + +template +struct TypeHelper { + typedef typename ValueType::Object ObjectType; + static bool Is(const ValueType& v) { return v.IsObject(); } + static ObjectType Get(ValueType& v) { return v.GetObject(); } + static ValueType& Set(ValueType& v, ObjectType data) { return v = data; } + static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { return v = data; } +}; + +template +struct TypeHelper { + typedef typename ValueType::ConstObject ObjectType; + static bool Is(const ValueType& v) { return v.IsObject(); } + static ObjectType Get(const ValueType& v) { return v.GetObject(); } +}; + +} // namespace internal + +// Forward declarations +template class GenericArray; +template class GenericObject; + /////////////////////////////////////////////////////////////////////////////// // GenericValue @@ -428,17 +561,21 @@ public: typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array. typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array. typedef GenericValue ValueType; //!< Value type of itself. + typedef GenericArray Array; + typedef GenericArray ConstArray; + typedef GenericObject Object; + typedef GenericObject ConstObject; //!@name Constructors and destructor. //@{ //! Default constructor creates a null value. - GenericValue() RAPIDJSON_NOEXCEPT : data_(), flags_(kNullFlag) {} + GenericValue() RAPIDJSON_NOEXCEPT : data_() { data_.f.flags = kNullFlag; } #if RAPIDJSON_HAS_CXX11_RVALUE_REFS //! Move constructor in C++11 - GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_), flags_(rhs.flags_) { - rhs.flags_ = kNullFlag; // give up contents + GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_) { + rhs.data_.f.flags = kNullFlag; // give up contents } #endif @@ -446,6 +583,16 @@ private: //! Copy constructor is not permitted. GenericValue(const GenericValue& rhs); +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Moving from a GenericDocument is not permitted. + template + GenericValue(GenericDocument&& rhs); + + //! Move assignment from a GenericDocument is not permitted. + template + GenericValue& operator=(GenericDocument&& rhs); +#endif + public: //! Constructor with JSON value type. @@ -453,13 +600,13 @@ public: \param type Type of the value. \note Default content for number is zero. */ - explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() { - static const unsigned defaultFlags[7] = { + explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_() { + static const uint16_t defaultFlags[7] = { kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag, kNumberAnyFlag }; - RAPIDJSON_ASSERT(type <= kNumberType); - flags_ = defaultFlags[type]; + RAPIDJSON_ASSERT(type >= kNullType && type <= kNumberType); + data_.f.flags = defaultFlags[type]; // Use ShortString to store empty string. if (type == kStringType) @@ -471,10 +618,50 @@ public: \tparam SourceAllocator allocator of \c rhs \param rhs Value to copy from (read-only) \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator(). + \param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer) \see CopyFrom() */ - template< typename SourceAllocator > - GenericValue(const GenericValue& rhs, Allocator & allocator); + template + GenericValue(const GenericValue& rhs, Allocator& allocator, bool copyConstStrings = false) { + switch (rhs.GetType()) { + case kObjectType: { + SizeType count = rhs.data_.o.size; + Member* lm = reinterpret_cast(allocator.Malloc(count * sizeof(Member))); + const typename GenericValue::Member* rm = rhs.GetMembersPointer(); + for (SizeType i = 0; i < count; i++) { + new (&lm[i].name) GenericValue(rm[i].name, allocator, copyConstStrings); + new (&lm[i].value) GenericValue(rm[i].value, allocator, copyConstStrings); + } + data_.f.flags = kObjectFlag; + data_.o.size = data_.o.capacity = count; + SetMembersPointer(lm); + } + break; + case kArrayType: { + SizeType count = rhs.data_.a.size; + GenericValue* le = reinterpret_cast(allocator.Malloc(count * sizeof(GenericValue))); + const GenericValue* re = rhs.GetElementsPointer(); + for (SizeType i = 0; i < count; i++) + new (&le[i]) GenericValue(re[i], allocator, copyConstStrings); + data_.f.flags = kArrayFlag; + data_.a.size = data_.a.capacity = count; + SetElementsPointer(le); + } + break; + case kStringType: + if (rhs.data_.f.flags == kConstStringFlag && !copyConstStrings) { + data_.f.flags = rhs.data_.f.flags; + data_ = *reinterpret_cast(&rhs.data_); + } + else + SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator); + break; + default: + data_.f.flags = rhs.data_.f.flags; + data_ = *reinterpret_cast(&rhs.data_); + break; + } + } //! Constructor for boolean value. /*! \param b Boolean value @@ -484,96 +671,125 @@ public: */ #ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen template - explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame))) RAPIDJSON_NOEXCEPT + explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame))) RAPIDJSON_NOEXCEPT // See #472 #else explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT #endif - : data_(), flags_(b ? kTrueFlag : kFalseFlag) { + : data_() { // safe-guard against failing SFINAE RAPIDJSON_STATIC_ASSERT((internal::IsSame::Value)); + data_.f.flags = b ? kTrueFlag : kFalseFlag; } //! Constructor for int value. - explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberIntFlag) { + explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_() { data_.n.i64 = i; - if (i >= 0) - flags_ |= kUintFlag | kUint64Flag; + data_.f.flags = (i >= 0) ? (kNumberIntFlag | kUintFlag | kUint64Flag) : kNumberIntFlag; } //! Constructor for unsigned value. - explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUintFlag) { + explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_() { data_.n.u64 = u; - if (!(u & 0x80000000)) - flags_ |= kIntFlag | kInt64Flag; + data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag); } //! Constructor for int64_t value. - explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberInt64Flag) { + explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_() { data_.n.i64 = i64; + data_.f.flags = kNumberInt64Flag; if (i64 >= 0) { - flags_ |= kNumberUint64Flag; + data_.f.flags |= kNumberUint64Flag; if (!(static_cast(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) - flags_ |= kUintFlag; + data_.f.flags |= kUintFlag; if (!(static_cast(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) - flags_ |= kIntFlag; + data_.f.flags |= kIntFlag; } else if (i64 >= static_cast(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) - flags_ |= kIntFlag; + data_.f.flags |= kIntFlag; } //! Constructor for uint64_t value. - explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUint64Flag) { + explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_() { data_.n.u64 = u64; + data_.f.flags = kNumberUint64Flag; if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000))) - flags_ |= kInt64Flag; + data_.f.flags |= kInt64Flag; if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) - flags_ |= kUintFlag; + data_.f.flags |= kUintFlag; if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) - flags_ |= kIntFlag; + data_.f.flags |= kIntFlag; } //! Constructor for double value. - explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; } + explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; } + + //! Constructor for float value. + explicit GenericValue(float f) RAPIDJSON_NOEXCEPT : data_() { data_.n.d = static_cast(f); data_.f.flags = kNumberDoubleFlag; } //! Constructor for constant string (i.e. do not make a copy of string) - GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(StringRef(s, length)); } + GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); } //! Constructor for constant string (i.e. do not make a copy of string) - explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(s); } + explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(s); } //! Constructor for copy-string (i.e. do make a copy of string) - GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s, length), allocator); } + GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_() { SetStringRaw(StringRef(s, length), allocator); } //! Constructor for copy-string (i.e. do make a copy of string) - GenericValue(const Ch*s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); } + GenericValue(const Ch*s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } #if RAPIDJSON_HAS_STDSTRING //! Constructor for copy-string from a string object (i.e. do make a copy of string) /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. */ - GenericValue(const std::basic_string& s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); } + GenericValue(const std::basic_string& s, Allocator& allocator) : data_() { SetStringRaw(StringRef(s), allocator); } #endif + //! Constructor for Array. + /*! + \param a An array obtained by \c GetArray(). + \note \c Array is always pass-by-value. + \note the source array is moved into this value and the sourec array becomes empty. + */ + GenericValue(Array a) RAPIDJSON_NOEXCEPT : data_(a.value_.data_) { + a.value_.data_ = Data(); + a.value_.data_.f.flags = kArrayFlag; + } + + //! Constructor for Object. + /*! + \param o An object obtained by \c GetObject(). + \note \c Object is always pass-by-value. + \note the source object is moved into this value and the sourec object becomes empty. + */ + GenericValue(Object o) RAPIDJSON_NOEXCEPT : data_(o.value_.data_) { + o.value_.data_ = Data(); + o.value_.data_.f.flags = kObjectFlag; + } + //! Destructor. /*! Need to destruct elements of array, members of object, or copy-string. */ ~GenericValue() { if (Allocator::kNeedFree) { // Shortcut by Allocator's trait - switch(flags_) { + switch(data_.f.flags) { case kArrayFlag: - for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) - v->~GenericValue(); - Allocator::Free(data_.a.elements); + { + GenericValue* e = GetElementsPointer(); + for (GenericValue* v = e; v != e + data_.a.size; ++v) + v->~GenericValue(); + Allocator::Free(e); + } break; case kObjectFlag: for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m) m->~Member(); - Allocator::Free(data_.o.members); + Allocator::Free(GetMembersPointer()); break; case kCopyStringFlag: - Allocator::Free(const_cast(data_.s.str)); + Allocator::Free(const_cast(GetStringPointer())); break; default: @@ -638,12 +854,13 @@ public: \tparam SourceAllocator Allocator type of \c rhs \param rhs Value to copy from (read-only) \param allocator Allocator to use for copying + \param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer) */ template - GenericValue& CopyFrom(const GenericValue& rhs, Allocator& allocator) { - RAPIDJSON_ASSERT((void*)this != (void const*)&rhs); + GenericValue& CopyFrom(const GenericValue& rhs, Allocator& allocator, bool copyConstStrings = false) { + RAPIDJSON_ASSERT(static_cast(this) != static_cast(&rhs)); this->~GenericValue(); - new (this) GenericValue(rhs, allocator); + new (this) GenericValue(rhs, allocator, copyConstStrings); return *this; } @@ -660,6 +877,20 @@ public: return *this; } + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.value, b.value); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + //! Prepare Value for move semantics /*! \return *this */ GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; } @@ -709,7 +940,7 @@ public: else return data_.n.u64 == rhs.data_.n.u64; - default: // kTrueType, kFalseType, kNullType + default: return true; } } @@ -757,20 +988,58 @@ public: //!@name Type //@{ - Type GetType() const { return static_cast(flags_ & kTypeMask); } - bool IsNull() const { return flags_ == kNullFlag; } - bool IsFalse() const { return flags_ == kFalseFlag; } - bool IsTrue() const { return flags_ == kTrueFlag; } - bool IsBool() const { return (flags_ & kBoolFlag) != 0; } - bool IsObject() const { return flags_ == kObjectFlag; } - bool IsArray() const { return flags_ == kArrayFlag; } - bool IsNumber() const { return (flags_ & kNumberFlag) != 0; } - bool IsInt() const { return (flags_ & kIntFlag) != 0; } - bool IsUint() const { return (flags_ & kUintFlag) != 0; } - bool IsInt64() const { return (flags_ & kInt64Flag) != 0; } - bool IsUint64() const { return (flags_ & kUint64Flag) != 0; } - bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; } - bool IsString() const { return (flags_ & kStringFlag) != 0; } + Type GetType() const { return static_cast(data_.f.flags & kTypeMask); } + bool IsNull() const { return data_.f.flags == kNullFlag; } + bool IsFalse() const { return data_.f.flags == kFalseFlag; } + bool IsTrue() const { return data_.f.flags == kTrueFlag; } + bool IsBool() const { return (data_.f.flags & kBoolFlag) != 0; } + bool IsObject() const { return data_.f.flags == kObjectFlag; } + bool IsArray() const { return data_.f.flags == kArrayFlag; } + bool IsNumber() const { return (data_.f.flags & kNumberFlag) != 0; } + bool IsInt() const { return (data_.f.flags & kIntFlag) != 0; } + bool IsUint() const { return (data_.f.flags & kUintFlag) != 0; } + bool IsInt64() const { return (data_.f.flags & kInt64Flag) != 0; } + bool IsUint64() const { return (data_.f.flags & kUint64Flag) != 0; } + bool IsDouble() const { return (data_.f.flags & kDoubleFlag) != 0; } + bool IsString() const { return (data_.f.flags & kStringFlag) != 0; } + + // Checks whether a number can be losslessly converted to a double. + bool IsLosslessDouble() const { + if (!IsNumber()) return false; + if (IsUint64()) { + uint64_t u = GetUint64(); + volatile double d = static_cast(u); + return (d >= 0.0) + && (d < static_cast((std::numeric_limits::max)())) + && (u == static_cast(d)); + } + if (IsInt64()) { + int64_t i = GetInt64(); + volatile double d = static_cast(i); + return (d >= static_cast((std::numeric_limits::min)())) + && (d < static_cast((std::numeric_limits::max)())) + && (i == static_cast(d)); + } + return true; // double, int, uint are always lossless + } + + // Checks whether a number is a float (possible lossy). + bool IsFloat() const { + if ((data_.f.flags & kDoubleFlag) == 0) + return false; + double d = GetDouble(); + return d >= -3.4028234e38 && d <= 3.4028234e38; + } + // Checks whether a number can be losslessly converted to a float. + bool IsLosslessFloat() const { + if (!IsNumber()) return false; + double a = GetDouble(); + if (a < static_cast(-(std::numeric_limits::max)()) + || a > static_cast((std::numeric_limits::max)())) + return false; + double b = static_cast(static_cast(a)); + return a >= b && a <= b; // Prevent -Wfloat-equal + } //@} @@ -784,7 +1053,7 @@ public: //!@name Bool //@{ - bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; } + bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return data_.f.flags == kTrueFlag; } //!< Set boolean value /*! \post IsBool() == true */ GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; } @@ -837,8 +1106,14 @@ public: return member->value; else { RAPIDJSON_ASSERT(false); // see above note - static GenericValue NullValue; - return NullValue; + + // This will generate -Wexit-time-destructors in clang + // static GenericValue NullValue; + // return NullValue; + + // Use static buffer and placement-new to prevent destruction + static char buffer[sizeof(GenericValue)]; + return *new (buffer) GenericValue(); } } template @@ -852,16 +1127,16 @@ public: //! Const member iterator /*! \pre IsObject() == true */ - ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members); } + ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer()); } //! Const \em past-the-end member iterator /*! \pre IsObject() == true */ - ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members + data_.o.size); } + ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(GetMembersPointer() + data_.o.size); } //! Member iterator /*! \pre IsObject() == true */ - MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members); } + MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer()); } //! \em Past-the-end member iterator /*! \pre IsObject() == true */ - MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members + data_.o.size); } + MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); } //! Check whether a member exists in the object. /*! @@ -949,8 +1224,8 @@ public: \return Iterator to member, if it exists. Otherwise returns \ref MemberEnd(). */ - MemberIterator FindMember(const std::basic_string& name) { return FindMember(StringRef(name)); } - ConstMemberIterator FindMember(const std::basic_string& name) const { return FindMember(StringRef(name)); } + MemberIterator FindMember(const std::basic_string& name) { return FindMember(GenericValue(StringRef(name))); } + ConstMemberIterator FindMember(const std::basic_string& name) const { return FindMember(GenericValue(StringRef(name))); } #endif //! Add a member (name-value pair) to the object. @@ -967,20 +1242,21 @@ public: RAPIDJSON_ASSERT(IsObject()); RAPIDJSON_ASSERT(name.IsString()); - Object& o = data_.o; + ObjectData& o = data_.o; if (o.size >= o.capacity) { if (o.capacity == 0) { o.capacity = kDefaultObjectCapacity; - o.members = reinterpret_cast(allocator.Malloc(o.capacity * sizeof(Member))); + SetMembersPointer(reinterpret_cast(allocator.Malloc(o.capacity * sizeof(Member)))); } else { SizeType oldCapacity = o.capacity; o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5 - o.members = reinterpret_cast(allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member))); + SetMembersPointer(reinterpret_cast(allocator.Realloc(GetMembersPointer(), oldCapacity * sizeof(Member), o.capacity * sizeof(Member)))); } } - o.members[o.size].name.RawAssign(name); - o.members[o.size].value.RawAssign(value); + Member* members = GetMembersPointer(); + members[o.size].name.RawAssign(name); + members[o.size].value.RawAssign(value); o.size++; return *this; } @@ -1159,18 +1435,14 @@ public: MemberIterator RemoveMember(MemberIterator m) { RAPIDJSON_ASSERT(IsObject()); RAPIDJSON_ASSERT(data_.o.size > 0); - RAPIDJSON_ASSERT(data_.o.members != 0); + RAPIDJSON_ASSERT(GetMembersPointer() != 0); RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd()); - MemberIterator last(data_.o.members + (data_.o.size - 1)); - if (data_.o.size > 1 && m != last) { - // Move the last one to this place - *m = *last; - } - else { - // Only one left, just destroy - m->~Member(); - } + MemberIterator last(GetMembersPointer() + (data_.o.size - 1)); + if (data_.o.size > 1 && m != last) + *m = *last; // Move the last one to this place + else + m->~Member(); // Only one left, just destroy --data_.o.size; return m; } @@ -1200,7 +1472,7 @@ public: MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) { RAPIDJSON_ASSERT(IsObject()); RAPIDJSON_ASSERT(data_.o.size > 0); - RAPIDJSON_ASSERT(data_.o.members != 0); + RAPIDJSON_ASSERT(GetMembersPointer() != 0); RAPIDJSON_ASSERT(first >= MemberBegin()); RAPIDJSON_ASSERT(first <= last); RAPIDJSON_ASSERT(last <= MemberEnd()); @@ -1208,11 +1480,39 @@ public: MemberIterator pos = MemberBegin() + (first - MemberBegin()); for (MemberIterator itr = pos; itr != last; ++itr) itr->~Member(); - std::memmove(&*pos, &*last, (MemberEnd() - last) * sizeof(Member)); - data_.o.size -= (last - first); + std::memmove(&*pos, &*last, static_cast(MemberEnd() - last) * sizeof(Member)); + data_.o.size -= static_cast(last - first); return pos; } + //! Erase a member in object by its name. + /*! \param name Name of member to be removed. + \return Whether the member existed. + \note Linear time complexity. + */ + bool EraseMember(const Ch* name) { + GenericValue n(StringRef(name)); + return EraseMember(n); + } + +#if RAPIDJSON_HAS_STDSTRING + bool EraseMember(const std::basic_string& name) { return EraseMember(GenericValue(StringRef(name))); } +#endif + + template + bool EraseMember(const GenericValue& name) { + MemberIterator m = FindMember(name); + if (m != MemberEnd()) { + EraseMember(m); + return true; + } + else + return false; + } + + Object GetObject() { RAPIDJSON_ASSERT(IsObject()); return Object(*this); } + ConstObject GetObject() const { RAPIDJSON_ASSERT(IsObject()); return ConstObject(*this); } + //@} //!@name Array @@ -1220,7 +1520,7 @@ public: //! Set this value as an empty array. /*! \post IsArray == true */ - GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } + GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; } //! Get the number of elements in array. SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; } @@ -1237,8 +1537,9 @@ public: */ void Clear() { RAPIDJSON_ASSERT(IsArray()); - for (SizeType i = 0; i < data_.a.size; ++i) - data_.a.elements[i].~GenericValue(); + GenericValue* e = GetElementsPointer(); + for (GenericValue* v = e; v != e + data_.a.size; ++v) + v->~GenericValue(); data_.a.size = 0; } @@ -1250,16 +1551,16 @@ public: GenericValue& operator[](SizeType index) { RAPIDJSON_ASSERT(IsArray()); RAPIDJSON_ASSERT(index < data_.a.size); - return data_.a.elements[index]; + return GetElementsPointer()[index]; } const GenericValue& operator[](SizeType index) const { return const_cast(*this)[index]; } //! Element iterator /*! \pre IsArray() == true */ - ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; } + ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer(); } //! \em Past-the-end element iterator /*! \pre IsArray() == true */ - ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; } + ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return GetElementsPointer() + data_.a.size; } //! Constant element iterator /*! \pre IsArray() == true */ ConstValueIterator Begin() const { return const_cast(*this).Begin(); } @@ -1276,7 +1577,7 @@ public: GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) { RAPIDJSON_ASSERT(IsArray()); if (newCapacity > data_.a.capacity) { - data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)); + SetElementsPointer(reinterpret_cast(allocator.Realloc(GetElementsPointer(), data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue)))); data_.a.capacity = newCapacity; } return *this; @@ -1296,7 +1597,7 @@ public: RAPIDJSON_ASSERT(IsArray()); if (data_.a.size >= data_.a.capacity) Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator); - data_.a.elements[data_.a.size++].RawAssign(value); + GetElementsPointer()[data_.a.size++].RawAssign(value); return *this; } @@ -1350,7 +1651,7 @@ public: GenericValue& PopBack() { RAPIDJSON_ASSERT(IsArray()); RAPIDJSON_ASSERT(!Empty()); - data_.a.elements[--data_.a.size].~GenericValue(); + GetElementsPointer()[--data_.a.size].~GenericValue(); return *this; } @@ -1376,35 +1677,48 @@ public: ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) { RAPIDJSON_ASSERT(IsArray()); RAPIDJSON_ASSERT(data_.a.size > 0); - RAPIDJSON_ASSERT(data_.a.elements != 0); + RAPIDJSON_ASSERT(GetElementsPointer() != 0); RAPIDJSON_ASSERT(first >= Begin()); RAPIDJSON_ASSERT(first <= last); RAPIDJSON_ASSERT(last <= End()); ValueIterator pos = Begin() + (first - Begin()); for (ValueIterator itr = pos; itr != last; ++itr) itr->~GenericValue(); - std::memmove(pos, last, (End() - last) * sizeof(GenericValue)); - data_.a.size -= (last - first); + std::memmove(pos, last, static_cast(End() - last) * sizeof(GenericValue)); + data_.a.size -= static_cast(last - first); return pos; } + Array GetArray() { RAPIDJSON_ASSERT(IsArray()); return Array(*this); } + ConstArray GetArray() const { RAPIDJSON_ASSERT(IsArray()); return ConstArray(*this); } + //@} //!@name Number //@{ - int GetInt() const { RAPIDJSON_ASSERT(flags_ & kIntFlag); return data_.n.i.i; } - unsigned GetUint() const { RAPIDJSON_ASSERT(flags_ & kUintFlag); return data_.n.u.u; } - int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; } - uint64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kUint64Flag); return data_.n.u64; } + int GetInt() const { RAPIDJSON_ASSERT(data_.f.flags & kIntFlag); return data_.n.i.i; } + unsigned GetUint() const { RAPIDJSON_ASSERT(data_.f.flags & kUintFlag); return data_.n.u.u; } + int64_t GetInt64() const { RAPIDJSON_ASSERT(data_.f.flags & kInt64Flag); return data_.n.i64; } + uint64_t GetUint64() const { RAPIDJSON_ASSERT(data_.f.flags & kUint64Flag); return data_.n.u64; } + //! Get the value as double type. + /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessDouble() to check whether the converison is lossless. + */ double GetDouble() const { RAPIDJSON_ASSERT(IsNumber()); - if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. - if ((flags_ & kIntFlag) != 0) return data_.n.i.i; // int -> double - if ((flags_ & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double - if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i64; // int64_t -> double (may lose precision) - RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u64; // uint64_t -> double (may lose precision) + if ((data_.f.flags & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion. + if ((data_.f.flags & kIntFlag) != 0) return data_.n.i.i; // int -> double + if ((data_.f.flags & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double + if ((data_.f.flags & kInt64Flag) != 0) return static_cast(data_.n.i64); // int64_t -> double (may lose precision) + RAPIDJSON_ASSERT((data_.f.flags & kUint64Flag) != 0); return static_cast(data_.n.u64); // uint64_t -> double (may lose precision) + } + + //! Get the value as float type. + /*! \note If the value is 64-bit integer type, it may lose precision. Use \c IsLosslessFloat() to check whether the converison is lossless. + */ + float GetFloat() const { + return static_cast(GetDouble()); } GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; } @@ -1412,18 +1726,19 @@ public: GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; } GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; } GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } + GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(static_cast(f)); return *this; } //@} //!@name String //@{ - const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? data_.ss.str : data_.s.str); } + const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return (data_.f.flags & kInlineStrFlag) ? data_.ss.str : GetStringPointer(); } //! Get the length of string. /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength(). */ - SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); } + SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((data_.f.flags & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); } //! Set this value as a string without copying source string. /*! This version has better performance with supplied length, and also support string containing null character. @@ -1450,7 +1765,7 @@ public: \return The value itself for fluent API. \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length */ - GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; } + GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { return SetString(StringRef(s, length), allocator); } //! Set this value as a string by copying from source string. /*! \param s source string. @@ -1458,7 +1773,15 @@ public: \return The value itself for fluent API. \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length */ - GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); } + GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(StringRef(s), allocator); } + + //! Set this value as a string by copying from source string. + /*! \param s source string reference + \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator(). + \return The value itself for fluent API. + \post IsString() == true && GetString() != s.s && strcmp(GetString(),s) == 0 && GetStringLength() == length + */ + GenericValue& SetString(StringRefType s, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, allocator); return *this; } #if RAPIDJSON_HAS_STDSTRING //! Set this value as a string by copying from source string. @@ -1468,11 +1791,35 @@ public: \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size() \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. */ - GenericValue& SetString(const std::basic_string& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); } + GenericValue& SetString(const std::basic_string& s, Allocator& allocator) { return SetString(StringRef(s), allocator); } #endif //@} + //!@name Array + //@{ + + //! Templated version for checking whether this value is type T. + /*! + \tparam T Either \c bool, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c float, \c const \c char*, \c std::basic_string + */ + template + bool Is() const { return internal::TypeHelper::Is(*this); } + + template + T Get() const { return internal::TypeHelper::Get(*this); } + + template + T Get() { return internal::TypeHelper::Get(*this); } + + template + ValueType& Set(const T& data) { return internal::TypeHelper::Set(*this, data); } + + template + ValueType& Set(const T& data, AllocatorType& allocator) { return internal::TypeHelper::Set(*this, data, allocator); } + + //@} + //! Generate events of this value to a Handler. /*! This function adopts the GoF visitor pattern. Typical usage is to output this JSON value as JSON text via Writer, which is a Handler. @@ -1488,35 +1835,35 @@ public: case kTrueType: return handler.Bool(true); case kObjectType: - if (!handler.StartObject()) + if (RAPIDJSON_UNLIKELY(!handler.StartObject())) return false; for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) { RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator. - if (!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.flags_ & kCopyFlag) != 0)) + if (RAPIDJSON_UNLIKELY(!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.data_.f.flags & kCopyFlag) != 0))) return false; - if (!m->value.Accept(handler)) + if (RAPIDJSON_UNLIKELY(!m->value.Accept(handler))) return false; } return handler.EndObject(data_.o.size); case kArrayType: - if (!handler.StartArray()) + if (RAPIDJSON_UNLIKELY(!handler.StartArray())) return false; - for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v) - if (!v->Accept(handler)) + for (const GenericValue* v = Begin(); v != End(); ++v) + if (RAPIDJSON_UNLIKELY(!v->Accept(handler))) return false; return handler.EndArray(data_.a.size); case kStringType: - return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0); + return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0); default: RAPIDJSON_ASSERT(GetType() == kNumberType); - if (IsInt()) return handler.Int(data_.n.i.i); + if (IsDouble()) return handler.Double(data_.n.d); + else if (IsInt()) return handler.Int(data_.n.i.i); else if (IsUint()) return handler.Uint(data_.n.u.u); else if (IsInt64()) return handler.Int64(data_.n.i64); - else if (IsUint64()) return handler.Uint64(data_.n.u64); - else return handler.Double(data_.n.d); + else return handler.Uint64(data_.n.u64); } } @@ -1525,16 +1872,16 @@ private: template friend class GenericDocument; enum { - kBoolFlag = 0x100, - kNumberFlag = 0x200, - kIntFlag = 0x400, - kUintFlag = 0x800, - kInt64Flag = 0x1000, - kUint64Flag = 0x2000, - kDoubleFlag = 0x4000, - kStringFlag = 0x100000, - kCopyFlag = 0x200000, - kInlineStrFlag = 0x400000, + kBoolFlag = 0x0008, + kNumberFlag = 0x0010, + kIntFlag = 0x0020, + kUintFlag = 0x0040, + kInt64Flag = 0x0080, + kUint64Flag = 0x0100, + kDoubleFlag = 0x0200, + kStringFlag = 0x0400, + kCopyFlag = 0x0800, + kInlineStrFlag = 0x1000, // Initial flags of different types. kNullFlag = kNullType, @@ -1552,16 +1899,27 @@ private: kObjectFlag = kObjectType, kArrayFlag = kArrayType, - kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler + kTypeMask = 0x07 }; static const SizeType kDefaultArrayCapacity = 16; static const SizeType kDefaultObjectCapacity = 16; + struct Flag { +#if RAPIDJSON_48BITPOINTER_OPTIMIZATION + char payload[sizeof(SizeType) * 2 + 6]; // 2 x SizeType + lower 48-bit pointer +#elif RAPIDJSON_64BIT + char payload[sizeof(SizeType) * 2 + sizeof(void*) + 6]; // 6 padding bytes +#else + char payload[sizeof(SizeType) * 2 + sizeof(void*) + 2]; // 2 padding bytes +#endif + uint16_t flags; + }; + struct String { - const Ch* str; SizeType length; - unsigned hashcode; //!< reserved + SizeType hashcode; //!< reserved + const Ch* str; }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars @@ -1570,15 +1928,15 @@ private: // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as // the string terminator as well. For getting the string length back from that value just use // "MaxSize - str[LenPos]". - // This allows to store 11-chars strings in 32-bit mode and 15-chars strings in 64-bit mode - // inline (for `UTF8`-encoded strings). + // This allows to store 13-chars strings in 32-bit mode, 21-chars strings in 64-bit mode, + // 13-chars strings for RAPIDJSON_48BITPOINTER_OPTIMIZATION=1 inline (for `UTF8`-encoded strings). struct ShortString { - enum { MaxChars = sizeof(String) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize }; + enum { MaxChars = sizeof(static_cast(0)->payload) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize }; Ch str[MaxChars]; - inline static bool Usable(SizeType len) { return (MaxSize >= len); } - inline void SetLength(SizeType len) { str[LenPos] = (Ch)(MaxSize - len); } - inline SizeType GetLength() const { return (SizeType)(MaxSize - str[LenPos]); } + inline static bool Usable(SizeType len) { return (MaxSize >= len); } + inline void SetLength(SizeType len) { str[LenPos] = static_cast(MaxSize - len); } + inline SizeType GetLength() const { return static_cast(MaxSize - str[LenPos]); } }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode // By using proper binary layout, retrieval of different integer types do not need conversions. @@ -1607,69 +1965,79 @@ private: double d; }; // 8 bytes - struct Object { - Member* members; + struct ObjectData { SizeType size; SizeType capacity; + Member* members; }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode - struct Array { - GenericValue* elements; + struct ArrayData { SizeType size; SizeType capacity; + GenericValue* elements; }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode union Data { String s; ShortString ss; Number n; - Object o; - Array a; - }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode + ObjectData o; + ArrayData a; + Flag f; + }; // 16 bytes in 32-bit mode, 24 bytes in 64-bit mode, 16 bytes in 64-bit with RAPIDJSON_48BITPOINTER_OPTIMIZATION + + RAPIDJSON_FORCEINLINE const Ch* GetStringPointer() const { return RAPIDJSON_GETPOINTER(Ch, data_.s.str); } + RAPIDJSON_FORCEINLINE const Ch* SetStringPointer(const Ch* str) { return RAPIDJSON_SETPOINTER(Ch, data_.s.str, str); } + RAPIDJSON_FORCEINLINE GenericValue* GetElementsPointer() const { return RAPIDJSON_GETPOINTER(GenericValue, data_.a.elements); } + RAPIDJSON_FORCEINLINE GenericValue* SetElementsPointer(GenericValue* elements) { return RAPIDJSON_SETPOINTER(GenericValue, data_.a.elements, elements); } + RAPIDJSON_FORCEINLINE Member* GetMembersPointer() const { return RAPIDJSON_GETPOINTER(Member, data_.o.members); } + RAPIDJSON_FORCEINLINE Member* SetMembersPointer(Member* members) { return RAPIDJSON_SETPOINTER(Member, data_.o.members, members); } // Initialize this value as array with initial data, without calling destructor. void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) { - flags_ = kArrayFlag; + data_.f.flags = kArrayFlag; if (count) { - data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(GenericValue)); - std::memcpy(data_.a.elements, values, count * sizeof(GenericValue)); + GenericValue* e = static_cast(allocator.Malloc(count * sizeof(GenericValue))); + SetElementsPointer(e); + std::memcpy(e, values, count * sizeof(GenericValue)); } else - data_.a.elements = NULL; + SetElementsPointer(0); data_.a.size = data_.a.capacity = count; } //! Initialize this value as object with initial data, without calling destructor. void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) { - flags_ = kObjectFlag; + data_.f.flags = kObjectFlag; if (count) { - data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member)); - std::memcpy(data_.o.members, members, count * sizeof(Member)); + Member* m = static_cast(allocator.Malloc(count * sizeof(Member))); + SetMembersPointer(m); + std::memcpy(m, members, count * sizeof(Member)); } else - data_.o.members = NULL; + SetMembersPointer(0); data_.o.size = data_.o.capacity = count; } //! Initialize this value as constant string, without calling destructor. void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT { - flags_ = kConstStringFlag; - data_.s.str = s; + data_.f.flags = kConstStringFlag; + SetStringPointer(s); data_.s.length = s.length; } //! Initialize this value as copy string with initial data, without calling destructor. void SetStringRaw(StringRefType s, Allocator& allocator) { - Ch* str = NULL; - if(ShortString::Usable(s.length)) { - flags_ = kShortStringFlag; + Ch* str = 0; + if (ShortString::Usable(s.length)) { + data_.f.flags = kShortStringFlag; data_.ss.SetLength(s.length); str = data_.ss.str; } else { - flags_ = kCopyStringFlag; + data_.f.flags = kCopyStringFlag; data_.s.length = s.length; - str = (Ch *)allocator.Malloc((s.length + 1) * sizeof(Ch)); - data_.s.str = str; + str = static_cast(allocator.Malloc((s.length + 1) * sizeof(Ch))); + SetStringPointer(str); } std::memcpy(str, s, s.length * sizeof(Ch)); str[s.length] = '\0'; @@ -1678,8 +2046,8 @@ private: //! Assignment without calling destructor void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT { data_ = rhs.data_; - flags_ = rhs.flags_; - rhs.flags_ = kNullFlag; + // data_.f.flags = rhs.data_.f.flags; + rhs.data_.f.flags = kNullFlag; } template @@ -1699,7 +2067,6 @@ private: } Data data_; - unsigned flags_; }; //! GenericValue with UTF8 encoding @@ -1724,7 +2091,22 @@ public: typedef Allocator AllocatorType; //!< Allocator type from template parameter. //! Constructor - /*! \param allocator Optional allocator for allocating memory. + /*! Creates an empty document of specified type. + \param type Mandatory type of object to create. + \param allocator Optional allocator for allocating memory. + \param stackCapacity Optional initial capacity of stack in bytes. + \param stackAllocator Optional allocator for allocating memory for stack. + */ + explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : + GenericValue(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + } + + //! Constructor + /*! Creates an empty document which type is Null. + \param allocator Optional allocator for allocating memory. \param stackCapacity Optional initial capacity of stack in bytes. \param stackAllocator Optional allocator for allocating memory for stack. */ @@ -1732,13 +2114,13 @@ public: allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() { if (!allocator_) - ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); } #if RAPIDJSON_HAS_CXX11_RVALUE_REFS //! Move constructor in C++11 GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT - : ValueType(std::move(rhs)), + : ValueType(std::forward(rhs)), // explicit cast to avoid prohibited move from Document allocator_(rhs.allocator_), ownAllocator_(rhs.ownAllocator_), stack_(std::move(rhs.stack_)), @@ -1778,6 +2160,54 @@ public: } #endif + //! Exchange the contents of this document with those of another. + /*! + \param rhs Another document. + \note Constant complexity. + \see GenericValue::Swap + */ + GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT { + ValueType::Swap(rhs); + stack_.Swap(rhs.stack_); + internal::Swap(allocator_, rhs.allocator_); + internal::Swap(ownAllocator_, rhs.ownAllocator_); + internal::Swap(parseResult_, rhs.parseResult_); + return *this; + } + + // Allow Swap with ValueType. + // Refer to Effective C++ 3rd Edition/Item 33: Avoid hiding inherited names. + using ValueType::Swap; + + //! free-standing swap function helper + /*! + Helper function to enable support for common swap implementation pattern based on \c std::swap: + \code + void swap(MyClass& a, MyClass& b) { + using std::swap; + swap(a.doc, b.doc); + // ... + } + \endcode + \see Swap() + */ + friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } + + //! Populate this document by a generator which produces SAX events. + /*! \tparam Generator A functor with bool f(Handler) prototype. + \param g Generator functor which sends SAX events to the parameter. + \return The document itself for fluent API. + */ + template + GenericDocument& Populate(Generator& g) { + ClearStackOnExit scope(*this); + if (g(*this)) { + RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object + ValueType::operator=(*stack_.template Pop(1));// Move value from stack to document + } + return *this; + } + //!@name Parse from stream //!@{ @@ -1790,13 +2220,13 @@ public: */ template GenericDocument& ParseStream(InputStream& is) { - ValueType::SetNull(); // Remove existing root if exist - GenericReader reader(&stack_.GetAllocator()); + GenericReader reader( + stack_.HasAllocator() ? &stack_.GetAllocator() : 0); ClearStackOnExit scope(*this); parseResult_ = reader.template Parse(is, *this); if (parseResult_) { RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object - this->RawAssign(*stack_.template Pop(1)); // Add this-> to prevent issue 13. + ValueType::operator=(*stack_.template Pop(1));// Move value from stack to document } return *this; } @@ -1855,7 +2285,7 @@ public: \param str Read-only zero-terminated string to be parsed. */ template - GenericDocument& Parse(const Ch* str) { + GenericDocument& Parse(const typename SourceEncoding::Ch* str) { RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); GenericStringStream s(str); return ParseStream(s); @@ -1876,6 +2306,42 @@ public: GenericDocument& Parse(const Ch* str) { return Parse(str); } + + template + GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) { + RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); + MemoryStream ms(reinterpret_cast(str), length * sizeof(typename SourceEncoding::Ch)); + EncodedInputStream is(ms); + ParseStream(is); + return *this; + } + + template + GenericDocument& Parse(const Ch* str, size_t length) { + return Parse(str, length); + } + + GenericDocument& Parse(const Ch* str, size_t length) { + return Parse(str, length); + } + +#if RAPIDJSON_HAS_STDSTRING + template + GenericDocument& Parse(const std::basic_string& str) { + // c_str() is constant complexity according to standard. Should be faster than Parse(const char*, size_t) + return Parse(str.c_str()); + } + + template + GenericDocument& Parse(const std::basic_string& str) { + return Parse(str.c_str()); + } + + GenericDocument& Parse(const std::basic_string& str) { + return Parse(str); + } +#endif // RAPIDJSON_HAS_STDSTRING + //!@} //!@name Handling parse errors @@ -1890,10 +2356,26 @@ public: //! Get the position of last parsing error in input, 0 otherwise. size_t GetErrorOffset() const { return parseResult_.Offset(); } + //! Implicit conversion to get the last parse result +#ifndef __clang // -Wdocumentation + /*! \return \ref ParseResult of the last parse operation + + \code + Document doc; + ParseResult ok = doc.Parse(json); + if (!ok) + printf( "JSON parse error: %s (%u)\n", GetParseError_En(ok.Code()), ok.Offset()); + \endcode + */ +#endif + operator ParseResult() const { return parseResult_; } //!@} //! Get the allocator of this document. - Allocator& GetAllocator() { return *allocator_; } + Allocator& GetAllocator() { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } //! Get the capacity of stack in bytes. size_t GetStackCapacity() const { return stack_.GetCapacity(); } @@ -1910,9 +2392,10 @@ private: }; // callers of the following private Handler functions - template friend class GenericReader; // for parsing + // template friend class GenericReader; // for parsing template friend class GenericValue; // for deep copying +public: // Implementation of Handler bool Null() { new (stack_.template Push()) ValueType(); return true; } bool Bool(bool b) { new (stack_.template Push()) ValueType(b); return true; } @@ -1922,6 +2405,14 @@ private: bool Uint64(uint64_t i) { new (stack_.template Push()) ValueType(i); return true; } bool Double(double d) { new (stack_.template Push()) ValueType(d); return true; } + bool RawNumber(const Ch* str, SizeType length, bool copy) { + if (copy) + new (stack_.template Push()) ValueType(str, length, GetAllocator()); + else + new (stack_.template Push()) ValueType(str, length); + return true; + } + bool String(const Ch* str, SizeType length, bool copy) { if (copy) new (stack_.template Push()) ValueType(str, length, GetAllocator()); @@ -1936,7 +2427,7 @@ private: bool EndObject(SizeType memberCount) { typename ValueType::Member* members = stack_.template Pop(memberCount); - stack_.template Top()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator()); + stack_.template Top()->SetObjectRaw(members, memberCount, GetAllocator()); return true; } @@ -1977,38 +2468,146 @@ private: //! GenericDocument with UTF8 encoding typedef GenericDocument > Document; -// defined here due to the dependency on GenericDocument -template -template -inline -GenericValue::GenericValue(const GenericValue& rhs, Allocator& allocator) -{ - switch (rhs.GetType()) { - case kObjectType: - case kArrayType: { // perform deep copy via SAX Handler - GenericDocument d(&allocator); - rhs.Accept(d); - RawAssign(*d.stack_.template Pop(1)); - } - break; - case kStringType: - if (rhs.flags_ == kConstStringFlag) { - flags_ = rhs.flags_; - data_ = *reinterpret_cast(&rhs.data_); - } else { - SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator); - } - break; - default: // kNumberType, kTrueType, kFalseType, kNullType - flags_ = rhs.flags_; - data_ = *reinterpret_cast(&rhs.data_); - } -} +//! Helper class for accessing Value of array type. +/*! + Instance of this helper class is obtained by \c GenericValue::GetArray(). + In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. +*/ +template +class GenericArray { +public: + typedef GenericArray ConstArray; + typedef GenericArray Array; + typedef ValueT PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + typedef ValueType* ValueIterator; // This may be const or non-const iterator + typedef const ValueT* ConstValueIterator; + typedef typename ValueType::AllocatorType AllocatorType; + typedef typename ValueType::StringRefType StringRefType; -RAPIDJSON_NAMESPACE_END + template + friend class GenericValue; -#if defined(_MSC_VER) || defined(__GNUC__) -RAPIDJSON_DIAG_POP + GenericArray(const GenericArray& rhs) : value_(rhs.value_) {} + GenericArray& operator=(const GenericArray& rhs) { value_ = rhs.value_; return *this; } + ~GenericArray() {} + + SizeType Size() const { return value_.Size(); } + SizeType Capacity() const { return value_.Capacity(); } + bool Empty() const { return value_.Empty(); } + void Clear() const { value_.Clear(); } + ValueType& operator[](SizeType index) const { return value_[index]; } + ValueIterator Begin() const { return value_.Begin(); } + ValueIterator End() const { return value_.End(); } + GenericArray Reserve(SizeType newCapacity, AllocatorType &allocator) const { value_.Reserve(newCapacity, allocator); return *this; } + GenericArray PushBack(ValueType& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericArray PushBack(ValueType&& value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericArray PushBack(StringRefType value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (const GenericArray&)) PushBack(T value, AllocatorType& allocator) const { value_.PushBack(value, allocator); return *this; } + GenericArray PopBack() const { value_.PopBack(); return *this; } + ValueIterator Erase(ConstValueIterator pos) const { return value_.Erase(pos); } + ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) const { return value_.Erase(first, last); } + +#if RAPIDJSON_HAS_CXX11_RANGE_FOR + ValueIterator begin() const { return value_.Begin(); } + ValueIterator end() const { return value_.End(); } #endif +private: + GenericArray(); + GenericArray(ValueType& value) : value_(value) {} + ValueType& value_; +}; + +//! Helper class for accessing Value of object type. +/*! + Instance of this helper class is obtained by \c GenericValue::GetObject(). + In addition to all APIs for array type, it provides range-based for loop if \c RAPIDJSON_HAS_CXX11_RANGE_FOR=1. +*/ +template +class GenericObject { +public: + typedef GenericObject ConstObject; + typedef GenericObject Object; + typedef ValueT PlainType; + typedef typename internal::MaybeAddConst::Type ValueType; + typedef GenericMemberIterator MemberIterator; // This may be const or non-const iterator + typedef GenericMemberIterator ConstMemberIterator; + typedef typename ValueType::AllocatorType AllocatorType; + typedef typename ValueType::StringRefType StringRefType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename ValueType::Ch Ch; + + template + friend class GenericValue; + + GenericObject(const GenericObject& rhs) : value_(rhs.value_) {} + GenericObject& operator=(const GenericObject& rhs) { value_ = rhs.value_; return *this; } + ~GenericObject() {} + + SizeType MemberCount() const { return value_.MemberCount(); } + bool ObjectEmpty() const { return value_.ObjectEmpty(); } + template ValueType& operator[](T* name) const { return value_[name]; } + template ValueType& operator[](const GenericValue& name) const { return value_[name]; } +#if RAPIDJSON_HAS_STDSTRING + ValueType& operator[](const std::basic_string& name) const { return value_[name]; } +#endif + MemberIterator MemberBegin() const { return value_.MemberBegin(); } + MemberIterator MemberEnd() const { return value_.MemberEnd(); } + bool HasMember(const Ch* name) const { return value_.HasMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool HasMember(const std::basic_string& name) const { return value_.HasMember(name); } +#endif + template bool HasMember(const GenericValue& name) const { return value_.HasMember(name); } + MemberIterator FindMember(const Ch* name) const { return value_.FindMember(name); } + template MemberIterator FindMember(const GenericValue& name) const { return value_.FindMember(name); } +#if RAPIDJSON_HAS_STDSTRING + MemberIterator FindMember(const std::basic_string& name) const { return value_.FindMember(name); } +#endif + GenericObject AddMember(ValueType& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType& name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#if RAPIDJSON_HAS_STDSTRING + GenericObject AddMember(ValueType& name, std::basic_string& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#endif + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) AddMember(ValueType& name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericObject AddMember(ValueType&& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType&& name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(ValueType& name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(StringRefType name, ValueType&& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } +#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS + GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } + void RemoveAllMembers() { value_.RemoveAllMembers(); } + bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool RemoveMember(const std::basic_string& name) const { return value_.RemoveMember(name); } +#endif + template bool RemoveMember(const GenericValue& name) const { return value_.RemoveMember(name); } + MemberIterator RemoveMember(MemberIterator m) const { return value_.RemoveMember(m); } + MemberIterator EraseMember(ConstMemberIterator pos) const { return value_.EraseMember(pos); } + MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) const { return value_.EraseMember(first, last); } + bool EraseMember(const Ch* name) const { return value_.EraseMember(name); } +#if RAPIDJSON_HAS_STDSTRING + bool EraseMember(const std::basic_string& name) const { return EraseMember(ValueType(StringRef(name))); } +#endif + template bool EraseMember(const GenericValue& name) const { return value_.EraseMember(name); } + +#if RAPIDJSON_HAS_CXX11_RANGE_FOR + MemberIterator begin() const { return value_.MemberBegin(); } + MemberIterator end() const { return value_.MemberEnd(); } +#endif + +private: + GenericObject(); + GenericObject(ValueType& value) : value_(value) {} + ValueType& value_; +}; + +RAPIDJSON_NAMESPACE_END +RAPIDJSON_DIAG_POP + #endif // RAPIDJSON_DOCUMENT_H_ diff --git a/contrib/rapidjson/include/rapidjson/encodedstream.h b/contrib/rapidjson/include/rapidjson/encodedstream.h index 7c8863fee..223601c05 100644 --- a/contrib/rapidjson/include/rapidjson/encodedstream.h +++ b/contrib/rapidjson/include/rapidjson/encodedstream.h @@ -15,13 +15,19 @@ #ifndef RAPIDJSON_ENCODEDSTREAM_H_ #define RAPIDJSON_ENCODEDSTREAM_H_ -#include "rapidjson.h" +#include "stream.h" +#include "memorystream.h" #ifdef __GNUC__ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(effc++) #endif +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + RAPIDJSON_NAMESPACE_BEGIN //! Input byte stream wrapper with a statically bound encoding. @@ -57,10 +63,38 @@ private: Ch current_; }; +//! Specialized for UTF8 MemoryStream. +template <> +class EncodedInputStream, MemoryStream> { +public: + typedef UTF8<>::Ch Ch; + + EncodedInputStream(MemoryStream& is) : is_(is) { + if (static_cast(is_.Peek()) == 0xEFu) is_.Take(); + if (static_cast(is_.Peek()) == 0xBBu) is_.Take(); + if (static_cast(is_.Peek()) == 0xBFu) is_.Take(); + } + Ch Peek() const { return is_.Peek(); } + Ch Take() { return is_.Take(); } + size_t Tell() const { return is_.Tell(); } + + // Not implemented + void Put(Ch) {} + void Flush() {} + Ch* PutBegin() { return 0; } + size_t PutEnd(Ch*) { return 0; } + + MemoryStream& is_; + +private: + EncodedInputStream(const EncodedInputStream&); + EncodedInputStream& operator=(const EncodedInputStream&); +}; + //! Output byte stream wrapper with statically bound encoding. /*! \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE. - \tparam InputByteStream Type of input byte stream. For example, FileWriteStream. + \tparam OutputByteStream Type of input byte stream. For example, FileWriteStream. */ template class EncodedOutputStream { @@ -77,8 +111,8 @@ public: void Flush() { os_.Flush(); } // Not implemented - Ch Peek() const { RAPIDJSON_ASSERT(false); } - Ch Take() { RAPIDJSON_ASSERT(false); } + Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} + Ch Take() { RAPIDJSON_ASSERT(false); return 0;} size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } @@ -142,11 +176,11 @@ private: // FF FE UTF-16LE // EF BB BF UTF-8 - const unsigned char* c = (const unsigned char *)is_->Peek4(); + const unsigned char* c = reinterpret_cast(is_->Peek4()); if (!c) return; - unsigned bom = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24); + unsigned bom = static_cast(c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24)); hasBOM_ = false; if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); } @@ -166,7 +200,7 @@ private: // xx xx xx xx UTF-8 if (!hasBOM_) { - unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0); + int pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0); switch (pattern) { case 0x08: type_ = kUTF32BE; break; case 0x0A: type_ = kUTF16BE; break; @@ -193,7 +227,7 @@ private: //! Output stream wrapper with dynamically bound encoding and automatic encoding detection. /*! \tparam CharType Type of character for writing. - \tparam InputByteStream type of output byte stream to be wrapped. + \tparam OutputByteStream type of output byte stream to be wrapped. */ template class AutoUTFOutputStream { @@ -227,8 +261,8 @@ public: void Flush() { os_->Flush(); } // Not implemented - Ch Peek() const { RAPIDJSON_ASSERT(false); } - Ch Take() { RAPIDJSON_ASSERT(false); } + Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;} + Ch Take() { RAPIDJSON_ASSERT(false); return 0;} size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } @@ -254,6 +288,10 @@ private: RAPIDJSON_NAMESPACE_END +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + #ifdef __GNUC__ RAPIDJSON_DIAG_POP #endif diff --git a/contrib/rapidjson/include/rapidjson/encodings.h b/contrib/rapidjson/include/rapidjson/encodings.h index 90b46ed32..0df1c3435 100644 --- a/contrib/rapidjson/include/rapidjson/encodings.h +++ b/contrib/rapidjson/include/rapidjson/encodings.h @@ -120,19 +120,45 @@ struct UTF8 { } } + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + if (codepoint <= 0x7F) + PutUnsafe(os, static_cast(codepoint & 0xFF)); + else if (codepoint <= 0x7FF) { + PutUnsafe(os, static_cast(0xC0 | ((codepoint >> 6) & 0xFF))); + PutUnsafe(os, static_cast(0x80 | ((codepoint & 0x3F)))); + } + else if (codepoint <= 0xFFFF) { + PutUnsafe(os, static_cast(0xE0 | ((codepoint >> 12) & 0xFF))); + PutUnsafe(os, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + PutUnsafe(os, static_cast(0x80 | (codepoint & 0x3F))); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + PutUnsafe(os, static_cast(0xF0 | ((codepoint >> 18) & 0xFF))); + PutUnsafe(os, static_cast(0x80 | ((codepoint >> 12) & 0x3F))); + PutUnsafe(os, static_cast(0x80 | ((codepoint >> 6) & 0x3F))); + PutUnsafe(os, static_cast(0x80 | (codepoint & 0x3F))); + } + } + template static bool Decode(InputStream& is, unsigned* codepoint) { -#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | ((unsigned char)c & 0x3Fu) -#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0) +#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast(c) & 0x3Fu) +#define TRANS(mask) result &= ((GetRange(static_cast(c)) & mask) != 0) #define TAIL() COPY(); TRANS(0x70) - Ch c = is.Take(); + typename InputStream::Ch c = is.Take(); if (!(c & 0x80)) { - *codepoint = (unsigned char)c; + *codepoint = static_cast(c); return true; } - unsigned char type = GetRange((unsigned char)c); - *codepoint = (0xFF >> type) & (unsigned char)c; + unsigned char type = GetRange(static_cast(c)); + if (type >= 32) { + *codepoint = 0; + } else { + *codepoint = (0xFFu >> type) & static_cast(c); + } bool result = true; switch (type) { case 2: TAIL(); return result; @@ -152,7 +178,7 @@ struct UTF8 { template static bool Validate(InputStream& is, OutputStream& os) { #define COPY() os.Put(c = is.Take()) -#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0) +#define TRANS(mask) result &= ((GetRange(static_cast(c)) & mask) != 0) #define TAIL() COPY(); TRANS(0x70) Ch c; COPY(); @@ -160,7 +186,7 @@ struct UTF8 { return true; bool result = true; - switch (GetRange((unsigned char)c)) { + switch (GetRange(static_cast(c))) { case 2: TAIL(); return result; case 3: TAIL(); TAIL(); return result; case 4: COPY(); TRANS(0x50); TAIL(); return result; @@ -196,12 +222,12 @@ struct UTF8 { template static CharType TakeBOM(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - Ch c = Take(is); - if ((unsigned char)c != 0xEFu) return c; + typename InputByteStream::Ch c = Take(is); + if (static_cast(c) != 0xEFu) return c; c = is.Take(); - if ((unsigned char)c != 0xBBu) return c; + if (static_cast(c) != 0xBBu) return c; c = is.Take(); - if ((unsigned char)c != 0xBFu) return c; + if (static_cast(c) != 0xBFu) return c; c = is.Take(); return c; } @@ -209,13 +235,15 @@ struct UTF8 { template static Ch Take(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - return is.Take(); + return static_cast(is.Take()); } template static void PutBOM(OutputByteStream& os) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(0xEFu); os.Put(0xBBu); os.Put(0xBFu); + os.Put(static_cast(0xEFu)); + os.Put(static_cast(0xBBu)); + os.Put(static_cast(0xBFu)); } template @@ -255,22 +283,38 @@ struct UTF16 { RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); unsigned v = codepoint - 0x10000; os.Put(static_cast((v >> 10) | 0xD800)); - os.Put((v & 0x3FF) | 0xDC00); + os.Put(static_cast((v & 0x3FF) | 0xDC00)); + } + } + + + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); + if (codepoint <= 0xFFFF) { + RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair + PutUnsafe(os, static_cast(codepoint)); + } + else { + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + unsigned v = codepoint - 0x10000; + PutUnsafe(os, static_cast((v >> 10) | 0xD800)); + PutUnsafe(os, static_cast((v & 0x3FF) | 0xDC00)); } } template static bool Decode(InputStream& is, unsigned* codepoint) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); - Ch c = is.Take(); + typename InputStream::Ch c = is.Take(); if (c < 0xD800 || c > 0xDFFF) { - *codepoint = c; + *codepoint = static_cast(c); return true; } else if (c <= 0xDBFF) { - *codepoint = (c & 0x3FF) << 10; + *codepoint = (static_cast(c) & 0x3FF) << 10; c = is.Take(); - *codepoint |= (c & 0x3FF); + *codepoint |= (static_cast(c) & 0x3FF); *codepoint += 0x10000; return c >= 0xDC00 && c <= 0xDFFF; } @@ -281,8 +325,8 @@ struct UTF16 { static bool Validate(InputStream& is, OutputStream& os) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2); RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2); - Ch c; - os.Put(c = is.Take()); + typename InputStream::Ch c; + os.Put(static_cast(c = is.Take())); if (c < 0xD800 || c > 0xDFFF) return true; else if (c <= 0xDBFF) { @@ -300,28 +344,29 @@ struct UTF16LE : UTF16 { static CharType TakeBOM(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); CharType c = Take(is); - return (unsigned short)c == 0xFEFFu ? Take(is) : c; + return static_cast(c) == 0xFEFFu ? Take(is) : c; } template static CharType Take(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = (unsigned char)is.Take(); - c |= (unsigned char)is.Take() << 8; - return c; + unsigned c = static_cast(is.Take()); + c |= static_cast(static_cast(is.Take())) << 8; + return static_cast(c); } template static void PutBOM(OutputByteStream& os) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(0xFFu); os.Put(0xFEu); + os.Put(static_cast(0xFFu)); + os.Put(static_cast(0xFEu)); } template static void Put(OutputByteStream& os, CharType c) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(c & 0xFFu); - os.Put((c >> 8) & 0xFFu); + os.Put(static_cast(static_cast(c) & 0xFFu)); + os.Put(static_cast((static_cast(c) >> 8) & 0xFFu)); } }; @@ -332,28 +377,29 @@ struct UTF16BE : UTF16 { static CharType TakeBOM(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); CharType c = Take(is); - return (unsigned short)c == 0xFEFFu ? Take(is) : c; + return static_cast(c) == 0xFEFFu ? Take(is) : c; } template static CharType Take(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = (unsigned char)is.Take() << 8; - c |= (unsigned char)is.Take(); - return c; + unsigned c = static_cast(static_cast(is.Take())) << 8; + c |= static_cast(is.Take()); + return static_cast(c); } template static void PutBOM(OutputByteStream& os) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(0xFEu); os.Put(0xFFu); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0xFFu)); } template static void Put(OutputByteStream& os, CharType c) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put((c >> 8) & 0xFFu); - os.Put(c & 0xFFu); + os.Put(static_cast((static_cast(c) >> 8) & 0xFFu)); + os.Put(static_cast(static_cast(c) & 0xFFu)); } }; @@ -382,6 +428,13 @@ struct UTF32 { os.Put(codepoint); } + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); + RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); + PutUnsafe(os, codepoint); + } + template static bool Decode(InputStream& is, unsigned* codepoint) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4); @@ -406,32 +459,35 @@ struct UTF32LE : UTF32 { static CharType TakeBOM(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); CharType c = Take(is); - return (unsigned)c == 0x0000FEFFu ? Take(is) : c; + return static_cast(c) == 0x0000FEFFu ? Take(is) : c; } template static CharType Take(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = (unsigned char)is.Take(); - c |= (unsigned char)is.Take() << 8; - c |= (unsigned char)is.Take() << 16; - c |= (unsigned char)is.Take() << 24; - return c; + unsigned c = static_cast(is.Take()); + c |= static_cast(static_cast(is.Take())) << 8; + c |= static_cast(static_cast(is.Take())) << 16; + c |= static_cast(static_cast(is.Take())) << 24; + return static_cast(c); } template static void PutBOM(OutputByteStream& os) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(0xFFu); os.Put(0xFEu); os.Put(0x00u); os.Put(0x00u); + os.Put(static_cast(0xFFu)); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0x00u)); } template static void Put(OutputByteStream& os, CharType c) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(c & 0xFFu); - os.Put((c >> 8) & 0xFFu); - os.Put((c >> 16) & 0xFFu); - os.Put((c >> 24) & 0xFFu); + os.Put(static_cast(c & 0xFFu)); + os.Put(static_cast((c >> 8) & 0xFFu)); + os.Put(static_cast((c >> 16) & 0xFFu)); + os.Put(static_cast((c >> 24) & 0xFFu)); } }; @@ -442,32 +498,35 @@ struct UTF32BE : UTF32 { static CharType TakeBOM(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); CharType c = Take(is); - return (unsigned)c == 0x0000FEFFu ? Take(is) : c; + return static_cast(c) == 0x0000FEFFu ? Take(is) : c; } template static CharType Take(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - CharType c = (unsigned char)is.Take() << 24; - c |= (unsigned char)is.Take() << 16; - c |= (unsigned char)is.Take() << 8; - c |= (unsigned char)is.Take(); - return c; + unsigned c = static_cast(static_cast(is.Take())) << 24; + c |= static_cast(static_cast(is.Take())) << 16; + c |= static_cast(static_cast(is.Take())) << 8; + c |= static_cast(static_cast(is.Take())); + return static_cast(c); } template static void PutBOM(OutputByteStream& os) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(0x00u); os.Put(0x00u); os.Put(0xFEu); os.Put(0xFFu); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0x00u)); + os.Put(static_cast(0xFEu)); + os.Put(static_cast(0xFFu)); } template static void Put(OutputByteStream& os, CharType c) { RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put((c >> 24) & 0xFFu); - os.Put((c >> 16) & 0xFFu); - os.Put((c >> 8) & 0xFFu); - os.Put(c & 0xFFu); + os.Put(static_cast((c >> 24) & 0xFFu)); + os.Put(static_cast((c >> 16) & 0xFFu)); + os.Put(static_cast((c >> 8) & 0xFFu)); + os.Put(static_cast(c & 0xFFu)); } }; @@ -491,31 +550,37 @@ struct ASCII { os.Put(static_cast(codepoint & 0xFF)); } + template + static void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + RAPIDJSON_ASSERT(codepoint <= 0x7F); + PutUnsafe(os, static_cast(codepoint & 0xFF)); + } + template static bool Decode(InputStream& is, unsigned* codepoint) { - unsigned char c = static_cast(is.Take()); + uint8_t c = static_cast(is.Take()); *codepoint = c; return c <= 0X7F; } template static bool Validate(InputStream& is, OutputStream& os) { - unsigned char c = is.Take(); - os.Put(c); + uint8_t c = static_cast(is.Take()); + os.Put(static_cast(c)); return c <= 0x7F; } template static CharType TakeBOM(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - Ch c = Take(is); - return c; + uint8_t c = static_cast(Take(is)); + return static_cast(c); } template static Ch Take(InputByteStream& is) { RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - return is.Take(); + return static_cast(is.Take()); } template @@ -555,21 +620,28 @@ struct AutoUTF { #define RAPIDJSON_ENCODINGS_FUNC(x) UTF8::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::x template - RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) { + static RAPIDJSON_FORCEINLINE void Encode(OutputStream& os, unsigned codepoint) { typedef void (*EncodeFunc)(OutputStream&, unsigned); static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) }; (*f[os.GetType()])(os, codepoint); } + template + static RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) { + typedef void (*EncodeFunc)(OutputStream&, unsigned); + static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) }; + (*f[os.GetType()])(os, codepoint); + } + template - RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) { + static RAPIDJSON_FORCEINLINE bool Decode(InputStream& is, unsigned* codepoint) { typedef bool (*DecodeFunc)(InputStream&, unsigned*); static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) }; return (*f[is.GetType()])(is, codepoint); } template - RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { + static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { typedef bool (*ValidateFunc)(InputStream&, OutputStream&); static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) }; return (*f[is.GetType()])(is, os); @@ -586,7 +658,7 @@ template struct Transcoder { //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream. template - RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { + static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) { unsigned codepoint; if (!SourceEncoding::Decode(is, &codepoint)) return false; @@ -594,31 +666,50 @@ struct Transcoder { return true; } + template + static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) { + unsigned codepoint; + if (!SourceEncoding::Decode(is, &codepoint)) + return false; + TargetEncoding::EncodeUnsafe(os, codepoint); + return true; + } + //! Validate one Unicode codepoint from an encoded stream. template - RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { + static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { return Transcode(is, os); // Since source/target encoding is different, must transcode. } }; +// Forward declaration. +template +inline void PutUnsafe(Stream& stream, typename Stream::Ch c); + //! Specialization of Transcoder with same source and target encoding. template struct Transcoder { template - RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) { + static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) { os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class. return true; } template - RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) { + static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) { + PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class. + return true; + } + + template + static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { return Encoding::Validate(is, os); // source/target encoding are the same } }; RAPIDJSON_NAMESPACE_END -#if defined(__GNUC__) || defined(_MSV_VER) +#if defined(__GNUC__) || defined(_MSC_VER) RAPIDJSON_DIAG_POP #endif diff --git a/contrib/rapidjson/include/rapidjson/error/en.h b/contrib/rapidjson/include/rapidjson/error/en.h index d5f9caab8..2db838bff 100644 --- a/contrib/rapidjson/include/rapidjson/error/en.h +++ b/contrib/rapidjson/include/rapidjson/error/en.h @@ -12,11 +12,17 @@ // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. -#ifndef RAPIDJSON_ERROR_EN_H__ -#define RAPIDJSON_ERROR_EN_H__ +#ifndef RAPIDJSON_ERROR_EN_H_ +#define RAPIDJSON_ERROR_EN_H_ #include "error.h" +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(covered-switch-default) +#endif + RAPIDJSON_NAMESPACE_BEGIN //! Maps error code of parsing into error message. @@ -32,7 +38,7 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); - case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not follow by other values."); + case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values."); case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); @@ -55,11 +61,14 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); - default: - return RAPIDJSON_ERROR_STRING("Unknown error."); + default: return RAPIDJSON_ERROR_STRING("Unknown error."); } } RAPIDJSON_NAMESPACE_END -#endif // RAPIDJSON_ERROR_EN_H__ +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ERROR_EN_H_ diff --git a/contrib/rapidjson/include/rapidjson/error/error.h b/contrib/rapidjson/include/rapidjson/error/error.h index f9094fb95..9311d2f03 100644 --- a/contrib/rapidjson/include/rapidjson/error/error.h +++ b/contrib/rapidjson/include/rapidjson/error/error.h @@ -12,11 +12,16 @@ // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. -#ifndef RAPIDJSON_ERROR_ERROR_H__ -#define RAPIDJSON_ERROR_ERROR_H__ +#ifndef RAPIDJSON_ERROR_ERROR_H_ +#define RAPIDJSON_ERROR_ERROR_H_ #include "../rapidjson.h" +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + /*! \file error.h */ /*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */ @@ -99,7 +104,9 @@ enum ParseErrorCode { \see GenericReader::Parse, GenericDocument::Parse */ struct ParseResult { - + //!! Unspecified boolean type + typedef bool (ParseResult::*BooleanType)() const; +public: //! Default constructor, no error. ParseResult() : code_(kParseErrorNone), offset_(0) {} //! Constructor to set an error. @@ -110,8 +117,8 @@ struct ParseResult { //! Get the error offset, if \ref IsError(), 0 otherwise. size_t Offset() const { return offset_; } - //! Conversion to \c bool, returns \c true, iff !\ref IsError(). - operator bool() const { return !IsError(); } + //! Explicit conversion to \c bool, returns \c true, iff !\ref IsError(). + operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; } //! Whether the result is an error. bool IsError() const { return code_ != kParseErrorNone; } @@ -119,6 +126,10 @@ struct ParseResult { bool operator==(ParseErrorCode code) const { return code_ == code; } friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; } + bool operator!=(const ParseResult& that) const { return !(*this == that); } + bool operator!=(ParseErrorCode code) const { return !(*this == code); } + friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; } + //! Reset error code. void Clear() { Set(kParseErrorNone); } //! Update error code and offset. @@ -143,4 +154,8 @@ typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); RAPIDJSON_NAMESPACE_END -#endif // RAPIDJSON_ERROR_ERROR_H__ +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_ERROR_ERROR_H_ diff --git a/contrib/rapidjson/include/rapidjson/filereadstream.h b/contrib/rapidjson/include/rapidjson/filereadstream.h index 3913eb74b..b56ea13b3 100644 --- a/contrib/rapidjson/include/rapidjson/filereadstream.h +++ b/contrib/rapidjson/include/rapidjson/filereadstream.h @@ -15,9 +15,16 @@ #ifndef RAPIDJSON_FILEREADSTREAM_H_ #define RAPIDJSON_FILEREADSTREAM_H_ -#include "rapidjson.h" +#include "stream.h" #include +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(missing-noreturn) +#endif + RAPIDJSON_NAMESPACE_BEGIN //! File byte stream for input using fread(). @@ -85,4 +92,8 @@ private: RAPIDJSON_NAMESPACE_END +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + #endif // RAPIDJSON_FILESTREAM_H_ diff --git a/contrib/rapidjson/include/rapidjson/filewritestream.h b/contrib/rapidjson/include/rapidjson/filewritestream.h index dfb9cbd02..6378dd60e 100644 --- a/contrib/rapidjson/include/rapidjson/filewritestream.h +++ b/contrib/rapidjson/include/rapidjson/filewritestream.h @@ -15,9 +15,14 @@ #ifndef RAPIDJSON_FILEWRITESTREAM_H_ #define RAPIDJSON_FILEWRITESTREAM_H_ -#include "rapidjson.h" +#include "stream.h" #include +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(unreachable-code) +#endif + RAPIDJSON_NAMESPACE_BEGIN //! Wrapper of C file stream for input using fread(). @@ -57,7 +62,11 @@ public: void Flush() { if (current_ != buffer_) { - fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); + size_t result = fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); + if (result < static_cast(current_ - buffer_)) { + // failure deliberately ignored at this time + // added to avoid warn_unused_result build errors + } current_ = buffer_; } } @@ -88,4 +97,8 @@ inline void PutN(FileWriteStream& stream, char c, size_t n) { RAPIDJSON_NAMESPACE_END +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + #endif // RAPIDJSON_FILESTREAM_H_ diff --git a/contrib/rapidjson/include/rapidjson/fwd.h b/contrib/rapidjson/include/rapidjson/fwd.h new file mode 100644 index 000000000..e8104e841 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/fwd.h @@ -0,0 +1,151 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_FWD_H_ +#define RAPIDJSON_FWD_H_ + +#include "rapidjson.h" + +RAPIDJSON_NAMESPACE_BEGIN + +// encodings.h + +template struct UTF8; +template struct UTF16; +template struct UTF16BE; +template struct UTF16LE; +template struct UTF32; +template struct UTF32BE; +template struct UTF32LE; +template struct ASCII; +template struct AutoUTF; + +template +struct Transcoder; + +// allocators.h + +class CrtAllocator; + +template +class MemoryPoolAllocator; + +// stream.h + +template +struct GenericStringStream; + +typedef GenericStringStream > StringStream; + +template +struct GenericInsituStringStream; + +typedef GenericInsituStringStream > InsituStringStream; + +// stringbuffer.h + +template +class GenericStringBuffer; + +typedef GenericStringBuffer, CrtAllocator> StringBuffer; + +// filereadstream.h + +class FileReadStream; + +// filewritestream.h + +class FileWriteStream; + +// memorybuffer.h + +template +struct GenericMemoryBuffer; + +typedef GenericMemoryBuffer MemoryBuffer; + +// memorystream.h + +struct MemoryStream; + +// reader.h + +template +struct BaseReaderHandler; + +template +class GenericReader; + +typedef GenericReader, UTF8, CrtAllocator> Reader; + +// writer.h + +template +class Writer; + +// prettywriter.h + +template +class PrettyWriter; + +// document.h + +template +struct GenericMember; + +template +class GenericMemberIterator; + +template +struct GenericStringRef; + +template +class GenericValue; + +typedef GenericValue, MemoryPoolAllocator > Value; + +template +class GenericDocument; + +typedef GenericDocument, MemoryPoolAllocator, CrtAllocator> Document; + +// pointer.h + +template +class GenericPointer; + +typedef GenericPointer Pointer; + +// schema.h + +template +class IGenericRemoteSchemaDocumentProvider; + +template +class GenericSchemaDocument; + +typedef GenericSchemaDocument SchemaDocument; +typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProvider; + +template < + typename SchemaDocumentType, + typename OutputHandler, + typename StateAllocator> +class GenericSchemaValidator; + +typedef GenericSchemaValidator, void>, CrtAllocator> SchemaValidator; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_RAPIDJSONFWD_H_ diff --git a/contrib/rapidjson/include/rapidjson/internal/biginteger.h b/contrib/rapidjson/include/rapidjson/internal/biginteger.h index 99a30acf6..9d3e88c99 100644 --- a/contrib/rapidjson/include/rapidjson/internal/biginteger.h +++ b/contrib/rapidjson/include/rapidjson/internal/biginteger.h @@ -19,6 +19,7 @@ #if defined(_MSC_VER) && defined(_M_AMD64) #include // for _umul128 +#pragma intrinsic(_umul128) #endif RAPIDJSON_NAMESPACE_BEGIN @@ -50,7 +51,16 @@ public: if (length > 0) AppendDecimal64(decimals + i, decimals + i + length); } - + + BigInteger& operator=(const BigInteger &rhs) + { + if (this != &rhs) { + count_ = rhs.count_; + std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); + } + return *this; + } + BigInteger& operator=(uint64_t u) { digits_[0] = u; count_ = 1; @@ -230,7 +240,7 @@ private: uint64_t r = 0; for (const char* p = begin; p != end; ++p) { RAPIDJSON_ASSERT(*p >= '0' && *p <= '9'); - r = r * 10 + (*p - '0'); + r = r * 10u + static_cast(*p - '0'); } return r; } diff --git a/contrib/rapidjson/include/rapidjson/internal/diyfp.h b/contrib/rapidjson/include/rapidjson/internal/diyfp.h index 3b6c4238c..29abf8046 100644 --- a/contrib/rapidjson/include/rapidjson/internal/diyfp.h +++ b/contrib/rapidjson/include/rapidjson/internal/diyfp.h @@ -21,9 +21,10 @@ #include "../rapidjson.h" -#if defined(_MSC_VER) && defined(_M_AMD64) +#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER) #include #pragma intrinsic(_BitScanReverse64) +#pragma intrinsic(_umul128) #endif RAPIDJSON_NAMESPACE_BEGIN @@ -34,8 +35,13 @@ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(effc++) #endif +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + struct DiyFp { - DiyFp() {} + DiyFp() : f(), e() {} DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {} @@ -232,8 +238,8 @@ inline DiyFp GetCachedPower(int e, int* K) { } inline DiyFp GetCachedPower10(int exp, int *outExp) { - unsigned index = (exp + 348) / 8; - *outExp = -348 + index * 8; + unsigned index = (static_cast(exp) + 348u) / 8u; + *outExp = -348 + static_cast(index) * 8; return GetCachedPowerByIndex(index); } @@ -241,6 +247,11 @@ inline DiyFp GetCachedPower10(int exp, int *outExp) { RAPIDJSON_DIAG_POP #endif +#ifdef __clang__ +RAPIDJSON_DIAG_POP +RAPIDJSON_DIAG_OFF(padded) +#endif + } // namespace internal RAPIDJSON_NAMESPACE_END diff --git a/contrib/rapidjson/include/rapidjson/internal/dtoa.h b/contrib/rapidjson/include/rapidjson/internal/dtoa.h index 2d8d2e46a..bf2e9b2e5 100644 --- a/contrib/rapidjson/include/rapidjson/internal/dtoa.h +++ b/contrib/rapidjson/include/rapidjson/internal/dtoa.h @@ -29,6 +29,7 @@ namespace internal { #ifdef __GNUC__ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(effc++) +RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124 #endif inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { @@ -40,7 +41,7 @@ inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uin } } -inline unsigned CountDecimalDigit32(uint32_t n) { +inline int CountDecimalDigit32(uint32_t n) { // Simple pure C++ implementation was faster than __builtin_clz version in this situation. if (n < 10) return 1; if (n < 100) return 2; @@ -101,7 +102,8 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff kappa--; if (p2 < delta) { *K += kappa; - GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-kappa]); + int index = -kappa; + GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[index] : 0)); return; } } @@ -145,10 +147,10 @@ inline char* WriteExponent(int K, char* buffer) { return buffer; } -inline char* Prettify(char* buffer, int length, int k) { +inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) { const int kk = length + k; // 10^(kk-1) <= v < 10^kk - if (length <= kk && kk <= 21) { + if (0 <= k && kk <= 21) { // 1234e7 -> 12340000000 for (int i = length; i < kk; i++) buffer[i] = '0'; @@ -158,19 +160,44 @@ inline char* Prettify(char* buffer, int length, int k) { } else if (0 < kk && kk <= 21) { // 1234e-2 -> 12.34 - std::memmove(&buffer[kk + 1], &buffer[kk], length - kk); + std::memmove(&buffer[kk + 1], &buffer[kk], static_cast(length - kk)); buffer[kk] = '.'; - return &buffer[length + 1]; + if (0 > k + maxDecimalPlaces) { + // When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1 + // Remove extra trailing zeros (at least one) after truncation. + for (int i = kk + maxDecimalPlaces; i > kk + 1; i--) + if (buffer[i] != '0') + return &buffer[i + 1]; + return &buffer[kk + 2]; // Reserve one zero + } + else + return &buffer[length + 1]; } else if (-6 < kk && kk <= 0) { // 1234e-6 -> 0.001234 const int offset = 2 - kk; - std::memmove(&buffer[offset], &buffer[0], length); + std::memmove(&buffer[offset], &buffer[0], static_cast(length)); buffer[0] = '0'; buffer[1] = '.'; for (int i = 2; i < offset; i++) buffer[i] = '0'; - return &buffer[length + offset]; + if (length - kk > maxDecimalPlaces) { + // When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1 + // Remove extra trailing zeros (at least one) after truncation. + for (int i = maxDecimalPlaces + 1; i > 2; i--) + if (buffer[i] != '0') + return &buffer[i + 1]; + return &buffer[3]; // Reserve one zero + } + else + return &buffer[length + offset]; + } + else if (kk < -maxDecimalPlaces) { + // Truncate to zero + buffer[0] = '0'; + buffer[1] = '.'; + buffer[2] = '0'; + return &buffer[3]; } else if (length == 1) { // 1e30 @@ -179,14 +206,15 @@ inline char* Prettify(char* buffer, int length, int k) { } else { // 1234e30 -> 1.234e33 - std::memmove(&buffer[2], &buffer[1], length - 1); + std::memmove(&buffer[2], &buffer[1], static_cast(length - 1)); buffer[1] = '.'; buffer[length + 1] = 'e'; return WriteExponent(kk - 1, &buffer[0 + length + 2]); } } -inline char* dtoa(double value, char* buffer) { +inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) { + RAPIDJSON_ASSERT(maxDecimalPlaces >= 1); Double d(value); if (d.IsZero()) { if (d.Sign()) @@ -203,7 +231,7 @@ inline char* dtoa(double value, char* buffer) { } int length, K; Grisu2(value, buffer, &length, &K); - return Prettify(buffer, length, K); + return Prettify(buffer, length, K, maxDecimalPlaces); } } diff --git a/contrib/rapidjson/include/rapidjson/internal/ieee754.h b/contrib/rapidjson/include/rapidjson/internal/ieee754.h index e3f03364c..c2684ba2a 100644 --- a/contrib/rapidjson/include/rapidjson/internal/ieee754.h +++ b/contrib/rapidjson/include/rapidjson/internal/ieee754.h @@ -40,6 +40,7 @@ public: bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } + bool IsNanOrInf() const { return (u_ & kExponentMask) == kExponentMask; } bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } @@ -47,7 +48,7 @@ public: int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } - static unsigned EffectiveSignificandSize(int order) { + static int EffectiveSignificandSize(int order) { if (order >= -1021) return 53; else if (order <= -1074) diff --git a/contrib/rapidjson/include/rapidjson/internal/regex.h b/contrib/rapidjson/include/rapidjson/internal/regex.h new file mode 100644 index 000000000..e1a2faae5 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/internal/regex.h @@ -0,0 +1,734 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_INTERNAL_REGEX_H_ +#define RAPIDJSON_INTERNAL_REGEX_H_ + +#include "../allocators.h" +#include "../stream.h" +#include "stack.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +RAPIDJSON_DIAG_OFF(implicit-fallthrough) +#endif + +#ifdef __GNUC__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(effc++) +#if __GNUC__ >= 7 +RAPIDJSON_DIAG_OFF(implicit-fallthrough) +#endif +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +#ifndef RAPIDJSON_REGEX_VERBOSE +#define RAPIDJSON_REGEX_VERBOSE 0 +#endif + +RAPIDJSON_NAMESPACE_BEGIN +namespace internal { + +/////////////////////////////////////////////////////////////////////////////// +// DecodedStream + +template +class DecodedStream { +public: + DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); } + unsigned Peek() { return codepoint_; } + unsigned Take() { + unsigned c = codepoint_; + if (c) // No further decoding when '\0' + Decode(); + return c; + } + +private: + void Decode() { + if (!Encoding::Decode(ss_, &codepoint_)) + codepoint_ = 0; + } + + SourceStream& ss_; + unsigned codepoint_; +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericRegex + +static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1 +static const SizeType kRegexInvalidRange = ~SizeType(0); + +template +class GenericRegexSearch; + +//! Regular expression engine with subset of ECMAscript grammar. +/*! + Supported regular expression syntax: + - \c ab Concatenation + - \c a|b Alternation + - \c a? Zero or one + - \c a* Zero or more + - \c a+ One or more + - \c a{3} Exactly 3 times + - \c a{3,} At least 3 times + - \c a{3,5} 3 to 5 times + - \c (ab) Grouping + - \c ^a At the beginning + - \c a$ At the end + - \c . Any character + - \c [abc] Character classes + - \c [a-c] Character class range + - \c [a-z0-9_] Character class combination + - \c [^abc] Negated character classes + - \c [^a-c] Negated character class range + - \c [\b] Backspace (U+0008) + - \c \\| \\\\ ... Escape characters + - \c \\f Form feed (U+000C) + - \c \\n Line feed (U+000A) + - \c \\r Carriage return (U+000D) + - \c \\t Tab (U+0009) + - \c \\v Vertical tab (U+000B) + + \note This is a Thompson NFA engine, implemented with reference to + Cox, Russ. "Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby,...).", + https://swtch.com/~rsc/regexp/regexp1.html +*/ +template +class GenericRegex { +public: + typedef Encoding EncodingType; + typedef typename Encoding::Ch Ch; + template friend class GenericRegexSearch; + + GenericRegex(const Ch* source, Allocator* allocator = 0) : + states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(), + anchorBegin_(), anchorEnd_() + { + GenericStringStream ss(source); + DecodedStream, Encoding> ds(ss); + Parse(ds); + } + + ~GenericRegex() {} + + bool IsValid() const { + return root_ != kRegexInvalidState; + } + +private: + enum Operator { + kZeroOrOne, + kZeroOrMore, + kOneOrMore, + kConcatenation, + kAlternation, + kLeftParenthesis + }; + + static const unsigned kAnyCharacterClass = 0xFFFFFFFF; //!< For '.' + static const unsigned kRangeCharacterClass = 0xFFFFFFFE; + static const unsigned kRangeNegationFlag = 0x80000000; + + struct Range { + unsigned start; // + unsigned end; + SizeType next; + }; + + struct State { + SizeType out; //!< Equals to kInvalid for matching state + SizeType out1; //!< Equals to non-kInvalid for split + SizeType rangeStart; + unsigned codepoint; + }; + + struct Frag { + Frag(SizeType s, SizeType o, SizeType m) : start(s), out(o), minIndex(m) {} + SizeType start; + SizeType out; //!< link-list of all output states + SizeType minIndex; + }; + + State& GetState(SizeType index) { + RAPIDJSON_ASSERT(index < stateCount_); + return states_.template Bottom()[index]; + } + + const State& GetState(SizeType index) const { + RAPIDJSON_ASSERT(index < stateCount_); + return states_.template Bottom()[index]; + } + + Range& GetRange(SizeType index) { + RAPIDJSON_ASSERT(index < rangeCount_); + return ranges_.template Bottom()[index]; + } + + const Range& GetRange(SizeType index) const { + RAPIDJSON_ASSERT(index < rangeCount_); + return ranges_.template Bottom()[index]; + } + + template + void Parse(DecodedStream& ds) { + Allocator allocator; + Stack operandStack(&allocator, 256); // Frag + Stack operatorStack(&allocator, 256); // Operator + Stack atomCountStack(&allocator, 256); // unsigned (Atom per parenthesis) + + *atomCountStack.template Push() = 0; + + unsigned codepoint; + while (ds.Peek() != 0) { + switch (codepoint = ds.Take()) { + case '^': + anchorBegin_ = true; + break; + + case '$': + anchorEnd_ = true; + break; + + case '|': + while (!operatorStack.Empty() && *operatorStack.template Top() < kAlternation) + if (!Eval(operandStack, *operatorStack.template Pop(1))) + return; + *operatorStack.template Push() = kAlternation; + *atomCountStack.template Top() = 0; + break; + + case '(': + *operatorStack.template Push() = kLeftParenthesis; + *atomCountStack.template Push() = 0; + break; + + case ')': + while (!operatorStack.Empty() && *operatorStack.template Top() != kLeftParenthesis) + if (!Eval(operandStack, *operatorStack.template Pop(1))) + return; + if (operatorStack.Empty()) + return; + operatorStack.template Pop(1); + atomCountStack.template Pop(1); + ImplicitConcatenation(atomCountStack, operatorStack); + break; + + case '?': + if (!Eval(operandStack, kZeroOrOne)) + return; + break; + + case '*': + if (!Eval(operandStack, kZeroOrMore)) + return; + break; + + case '+': + if (!Eval(operandStack, kOneOrMore)) + return; + break; + + case '{': + { + unsigned n, m; + if (!ParseUnsigned(ds, &n)) + return; + + if (ds.Peek() == ',') { + ds.Take(); + if (ds.Peek() == '}') + m = kInfinityQuantifier; + else if (!ParseUnsigned(ds, &m) || m < n) + return; + } + else + m = n; + + if (!EvalQuantifier(operandStack, n, m) || ds.Peek() != '}') + return; + ds.Take(); + } + break; + + case '.': + PushOperand(operandStack, kAnyCharacterClass); + ImplicitConcatenation(atomCountStack, operatorStack); + break; + + case '[': + { + SizeType range; + if (!ParseRange(ds, &range)) + return; + SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, kRangeCharacterClass); + GetState(s).rangeStart = range; + *operandStack.template Push() = Frag(s, s, s); + } + ImplicitConcatenation(atomCountStack, operatorStack); + break; + + case '\\': // Escape character + if (!CharacterEscape(ds, &codepoint)) + return; // Unsupported escape character + // fall through to default + + default: // Pattern character + PushOperand(operandStack, codepoint); + ImplicitConcatenation(atomCountStack, operatorStack); + } + } + + while (!operatorStack.Empty()) + if (!Eval(operandStack, *operatorStack.template Pop(1))) + return; + + // Link the operand to matching state. + if (operandStack.GetSize() == sizeof(Frag)) { + Frag* e = operandStack.template Pop(1); + Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0)); + root_ = e->start; + +#if RAPIDJSON_REGEX_VERBOSE + printf("root: %d\n", root_); + for (SizeType i = 0; i < stateCount_ ; i++) { + State& s = GetState(i); + printf("[%2d] out: %2d out1: %2d c: '%c'\n", i, s.out, s.out1, (char)s.codepoint); + } + printf("\n"); +#endif + } + } + + SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) { + State* s = states_.template Push(); + s->out = out; + s->out1 = out1; + s->codepoint = codepoint; + s->rangeStart = kRegexInvalidRange; + return stateCount_++; + } + + void PushOperand(Stack& operandStack, unsigned codepoint) { + SizeType s = NewState(kRegexInvalidState, kRegexInvalidState, codepoint); + *operandStack.template Push() = Frag(s, s, s); + } + + void ImplicitConcatenation(Stack& atomCountStack, Stack& operatorStack) { + if (*atomCountStack.template Top()) + *operatorStack.template Push() = kConcatenation; + (*atomCountStack.template Top())++; + } + + SizeType Append(SizeType l1, SizeType l2) { + SizeType old = l1; + while (GetState(l1).out != kRegexInvalidState) + l1 = GetState(l1).out; + GetState(l1).out = l2; + return old; + } + + void Patch(SizeType l, SizeType s) { + for (SizeType next; l != kRegexInvalidState; l = next) { + next = GetState(l).out; + GetState(l).out = s; + } + } + + bool Eval(Stack& operandStack, Operator op) { + switch (op) { + case kConcatenation: + RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2); + { + Frag e2 = *operandStack.template Pop(1); + Frag e1 = *operandStack.template Pop(1); + Patch(e1.out, e2.start); + *operandStack.template Push() = Frag(e1.start, e2.out, Min(e1.minIndex, e2.minIndex)); + } + return true; + + case kAlternation: + if (operandStack.GetSize() >= sizeof(Frag) * 2) { + Frag e2 = *operandStack.template Pop(1); + Frag e1 = *operandStack.template Pop(1); + SizeType s = NewState(e1.start, e2.start, 0); + *operandStack.template Push() = Frag(s, Append(e1.out, e2.out), Min(e1.minIndex, e2.minIndex)); + return true; + } + return false; + + case kZeroOrOne: + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + *operandStack.template Push() = Frag(s, Append(e.out, s), e.minIndex); + return true; + } + return false; + + case kZeroOrMore: + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + Patch(e.out, s); + *operandStack.template Push() = Frag(s, s, e.minIndex); + return true; + } + return false; + + default: + RAPIDJSON_ASSERT(op == kOneOrMore); + if (operandStack.GetSize() >= sizeof(Frag)) { + Frag e = *operandStack.template Pop(1); + SizeType s = NewState(kRegexInvalidState, e.start, 0); + Patch(e.out, s); + *operandStack.template Push() = Frag(e.start, s, e.minIndex); + return true; + } + return false; + } + } + + bool EvalQuantifier(Stack& operandStack, unsigned n, unsigned m) { + RAPIDJSON_ASSERT(n <= m); + RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag)); + + if (n == 0) { + if (m == 0) // a{0} not support + return false; + else if (m == kInfinityQuantifier) + Eval(operandStack, kZeroOrMore); // a{0,} -> a* + else { + Eval(operandStack, kZeroOrOne); // a{0,5} -> a? + for (unsigned i = 0; i < m - 1; i++) + CloneTopOperand(operandStack); // a{0,5} -> a? a? a? a? a? + for (unsigned i = 0; i < m - 1; i++) + Eval(operandStack, kConcatenation); // a{0,5} -> a?a?a?a?a? + } + return true; + } + + for (unsigned i = 0; i < n - 1; i++) // a{3} -> a a a + CloneTopOperand(operandStack); + + if (m == kInfinityQuantifier) + Eval(operandStack, kOneOrMore); // a{3,} -> a a a+ + else if (m > n) { + CloneTopOperand(operandStack); // a{3,5} -> a a a a + Eval(operandStack, kZeroOrOne); // a{3,5} -> a a a a? + for (unsigned i = n; i < m - 1; i++) + CloneTopOperand(operandStack); // a{3,5} -> a a a a? a? + for (unsigned i = n; i < m; i++) + Eval(operandStack, kConcatenation); // a{3,5} -> a a aa?a? + } + + for (unsigned i = 0; i < n - 1; i++) + Eval(operandStack, kConcatenation); // a{3} -> aaa, a{3,} -> aaa+, a{3.5} -> aaaa?a? + + return true; + } + + static SizeType Min(SizeType a, SizeType b) { return a < b ? a : b; } + + void CloneTopOperand(Stack& operandStack) { + const Frag src = *operandStack.template Top(); // Copy constructor to prevent invalidation + SizeType count = stateCount_ - src.minIndex; // Assumes top operand contains states in [src->minIndex, stateCount_) + State* s = states_.template Push(count); + memcpy(s, &GetState(src.minIndex), count * sizeof(State)); + for (SizeType j = 0; j < count; j++) { + if (s[j].out != kRegexInvalidState) + s[j].out += count; + if (s[j].out1 != kRegexInvalidState) + s[j].out1 += count; + } + *operandStack.template Push() = Frag(src.start + count, src.out + count, src.minIndex + count); + stateCount_ += count; + } + + template + bool ParseUnsigned(DecodedStream& ds, unsigned* u) { + unsigned r = 0; + if (ds.Peek() < '0' || ds.Peek() > '9') + return false; + while (ds.Peek() >= '0' && ds.Peek() <= '9') { + if (r >= 429496729 && ds.Peek() > '5') // 2^32 - 1 = 4294967295 + return false; // overflow + r = r * 10 + (ds.Take() - '0'); + } + *u = r; + return true; + } + + template + bool ParseRange(DecodedStream& ds, SizeType* range) { + bool isBegin = true; + bool negate = false; + int step = 0; + SizeType start = kRegexInvalidRange; + SizeType current = kRegexInvalidRange; + unsigned codepoint; + while ((codepoint = ds.Take()) != 0) { + if (isBegin) { + isBegin = false; + if (codepoint == '^') { + negate = true; + continue; + } + } + + switch (codepoint) { + case ']': + if (start == kRegexInvalidRange) + return false; // Error: nothing inside [] + if (step == 2) { // Add trailing '-' + SizeType r = NewRange('-'); + RAPIDJSON_ASSERT(current != kRegexInvalidRange); + GetRange(current).next = r; + } + if (negate) + GetRange(start).start |= kRangeNegationFlag; + *range = start; + return true; + + case '\\': + if (ds.Peek() == 'b') { + ds.Take(); + codepoint = 0x0008; // Escape backspace character + } + else if (!CharacterEscape(ds, &codepoint)) + return false; + // fall through to default + + default: + switch (step) { + case 1: + if (codepoint == '-') { + step++; + break; + } + // fall through to step 0 for other characters + + case 0: + { + SizeType r = NewRange(codepoint); + if (current != kRegexInvalidRange) + GetRange(current).next = r; + if (start == kRegexInvalidRange) + start = r; + current = r; + } + step = 1; + break; + + default: + RAPIDJSON_ASSERT(step == 2); + GetRange(current).end = codepoint; + step = 0; + } + } + } + return false; + } + + SizeType NewRange(unsigned codepoint) { + Range* r = ranges_.template Push(); + r->start = r->end = codepoint; + r->next = kRegexInvalidRange; + return rangeCount_++; + } + + template + bool CharacterEscape(DecodedStream& ds, unsigned* escapedCodepoint) { + unsigned codepoint; + switch (codepoint = ds.Take()) { + case '^': + case '$': + case '|': + case '(': + case ')': + case '?': + case '*': + case '+': + case '.': + case '[': + case ']': + case '{': + case '}': + case '\\': + *escapedCodepoint = codepoint; return true; + case 'f': *escapedCodepoint = 0x000C; return true; + case 'n': *escapedCodepoint = 0x000A; return true; + case 'r': *escapedCodepoint = 0x000D; return true; + case 't': *escapedCodepoint = 0x0009; return true; + case 'v': *escapedCodepoint = 0x000B; return true; + default: + return false; // Unsupported escape character + } + } + + Stack states_; + Stack ranges_; + SizeType root_; + SizeType stateCount_; + SizeType rangeCount_; + + static const unsigned kInfinityQuantifier = ~0u; + + // For SearchWithAnchoring() + bool anchorBegin_; + bool anchorEnd_; +}; + +template +class GenericRegexSearch { +public: + typedef typename RegexType::EncodingType Encoding; + typedef typename Encoding::Ch Ch; + + GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) : + regex_(regex), allocator_(allocator), ownAllocator_(0), + state0_(allocator, 0), state1_(allocator, 0), stateSet_() + { + RAPIDJSON_ASSERT(regex_.IsValid()); + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + stateSet_ = static_cast(allocator_->Malloc(GetStateSetSize())); + state0_.template Reserve(regex_.stateCount_); + state1_.template Reserve(regex_.stateCount_); + } + + ~GenericRegexSearch() { + Allocator::Free(stateSet_); + RAPIDJSON_DELETE(ownAllocator_); + } + + template + bool Match(InputStream& is) { + return SearchWithAnchoring(is, true, true); + } + + bool Match(const Ch* s) { + GenericStringStream is(s); + return Match(is); + } + + template + bool Search(InputStream& is) { + return SearchWithAnchoring(is, regex_.anchorBegin_, regex_.anchorEnd_); + } + + bool Search(const Ch* s) { + GenericStringStream is(s); + return Search(is); + } + +private: + typedef typename RegexType::State State; + typedef typename RegexType::Range Range; + + template + bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) { + DecodedStream ds(is); + + state0_.Clear(); + Stack *current = &state0_, *next = &state1_; + const size_t stateSetSize = GetStateSetSize(); + std::memset(stateSet_, 0, stateSetSize); + + bool matched = AddState(*current, regex_.root_); + unsigned codepoint; + while (!current->Empty() && (codepoint = ds.Take()) != 0) { + std::memset(stateSet_, 0, stateSetSize); + next->Clear(); + matched = false; + for (const SizeType* s = current->template Bottom(); s != current->template End(); ++s) { + const State& sr = regex_.GetState(*s); + if (sr.codepoint == codepoint || + sr.codepoint == RegexType::kAnyCharacterClass || + (sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint))) + { + matched = AddState(*next, sr.out) || matched; + if (!anchorEnd && matched) + return true; + } + if (!anchorBegin) + AddState(*next, regex_.root_); + } + internal::Swap(current, next); + } + + return matched; + } + + size_t GetStateSetSize() const { + return (regex_.stateCount_ + 31) / 32 * 4; + } + + // Return whether the added states is a match state + bool AddState(Stack& l, SizeType index) { + RAPIDJSON_ASSERT(index != kRegexInvalidState); + + const State& s = regex_.GetState(index); + if (s.out1 != kRegexInvalidState) { // Split + bool matched = AddState(l, s.out); + return AddState(l, s.out1) || matched; + } + else if (!(stateSet_[index >> 5] & (1u << (index & 31)))) { + stateSet_[index >> 5] |= (1u << (index & 31)); + *l.template PushUnsafe() = index; + } + return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation. + } + + bool MatchRange(SizeType rangeIndex, unsigned codepoint) const { + bool yes = (regex_.GetRange(rangeIndex).start & RegexType::kRangeNegationFlag) == 0; + while (rangeIndex != kRegexInvalidRange) { + const Range& r = regex_.GetRange(rangeIndex); + if (codepoint >= (r.start & ~RegexType::kRangeNegationFlag) && codepoint <= r.end) + return yes; + rangeIndex = r.next; + } + return !yes; + } + + const RegexType& regex_; + Allocator* allocator_; + Allocator* ownAllocator_; + Stack state0_; + Stack state1_; + uint32_t* stateSet_; +}; + +typedef GenericRegex > Regex; +typedef GenericRegexSearch RegexSearch; + +} // namespace internal +RAPIDJSON_NAMESPACE_END + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_POP +#endif + +#endif // RAPIDJSON_INTERNAL_REGEX_H_ diff --git a/contrib/rapidjson/include/rapidjson/internal/stack.h b/contrib/rapidjson/include/rapidjson/internal/stack.h index 722d56923..5c5398c35 100644 --- a/contrib/rapidjson/include/rapidjson/internal/stack.h +++ b/contrib/rapidjson/include/rapidjson/internal/stack.h @@ -15,7 +15,13 @@ #ifndef RAPIDJSON_INTERNAL_STACK_H_ #define RAPIDJSON_INTERNAL_STACK_H_ -#include "../rapidjson.h" +#include "../allocators.h" +#include "swap.h" + +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif RAPIDJSON_NAMESPACE_BEGIN namespace internal { @@ -32,7 +38,6 @@ public: // Optimization note: Do not allocate memory for stack_ in constructor. // Do it lazily when first Push() -> Expand() -> Resize(). Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) { - RAPIDJSON_ASSERT(stackCapacity > 0); } #if RAPIDJSON_HAS_CXX11_RVALUE_REFS @@ -81,6 +86,15 @@ public: } #endif + void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT { + internal::Swap(allocator_, rhs.allocator_); + internal::Swap(ownAllocator_, rhs.ownAllocator_); + internal::Swap(stack_, rhs.stack_); + internal::Swap(stackTop_, rhs.stackTop_); + internal::Swap(stackEnd_, rhs.stackEnd_); + internal::Swap(initialCapacity_, rhs.initialCapacity_); + } + void Clear() { stackTop_ = stack_; } void ShrinkToFit() { @@ -98,11 +112,22 @@ public: // Optimization note: try to minimize the size of this function for force inline. // Expansion is run very infrequently, so it is moved to another (probably non-inline) function. template - RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { + RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) { // Expand the stack if needed - if (stackTop_ + sizeof(T) * count >= stackEnd_) + if (RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_)) Expand(count); + } + template + RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { + Reserve(count); + return PushUnsafe(count); + } + + template + RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) { + RAPIDJSON_ASSERT(stackTop_); + RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_); T* ret = reinterpret_cast(stackTop_); stackTop_ += sizeof(T) * count; return ret; @@ -122,9 +147,32 @@ public: } template - T* Bottom() { return (T*)stack_; } + const T* Top() const { + RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); + return reinterpret_cast(stackTop_ - sizeof(T)); + } + + template + T* End() { return reinterpret_cast(stackTop_); } + + template + const T* End() const { return reinterpret_cast(stackTop_); } + + template + T* Bottom() { return reinterpret_cast(stack_); } + + template + const T* Bottom() const { return reinterpret_cast(stack_); } + + bool HasAllocator() const { + return allocator_ != 0; + } + + Allocator& GetAllocator() { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } - Allocator& GetAllocator() { return *allocator_; } bool Empty() const { return stackTop_ == stack_; } size_t GetSize() const { return static_cast(stackTop_ - stack_); } size_t GetCapacity() const { return static_cast(stackEnd_ - stack_); } @@ -136,7 +184,7 @@ private: size_t newCapacity; if (stack_ == 0) { if (!allocator_) - ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); newCapacity = initialCapacity_; } else { newCapacity = GetCapacity(); @@ -151,7 +199,7 @@ private: void Resize(size_t newCapacity) { const size_t size = GetSize(); // Backup the current size - stack_ = (char*)allocator_->Realloc(stack_, GetCapacity(), newCapacity); + stack_ = static_cast(allocator_->Realloc(stack_, GetCapacity(), newCapacity)); stackTop_ = stack_ + size; stackEnd_ = stack_ + newCapacity; } @@ -176,4 +224,8 @@ private: } // namespace internal RAPIDJSON_NAMESPACE_END +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + #endif // RAPIDJSON_STACK_H_ diff --git a/contrib/rapidjson/include/rapidjson/internal/strfunc.h b/contrib/rapidjson/include/rapidjson/internal/strfunc.h index 84405065a..226439a76 100644 --- a/contrib/rapidjson/include/rapidjson/internal/strfunc.h +++ b/contrib/rapidjson/include/rapidjson/internal/strfunc.h @@ -15,7 +15,8 @@ #ifndef RAPIDJSON_INTERNAL_STRFUNC_H_ #define RAPIDJSON_INTERNAL_STRFUNC_H_ -#include "../rapidjson.h" +#include "../stream.h" +#include RAPIDJSON_NAMESPACE_BEGIN namespace internal { @@ -28,11 +29,40 @@ namespace internal { */ template inline SizeType StrLen(const Ch* s) { + RAPIDJSON_ASSERT(s != 0); const Ch* p = s; while (*p) ++p; return SizeType(p - s); } +template <> +inline SizeType StrLen(const char* s) { + return SizeType(std::strlen(s)); +} + +template <> +inline SizeType StrLen(const wchar_t* s) { + return SizeType(std::wcslen(s)); +} + +//! Returns number of code points in a encoded string. +template +bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { + RAPIDJSON_ASSERT(s != 0); + RAPIDJSON_ASSERT(outCount != 0); + GenericStringStream is(s); + const typename Encoding::Ch* end = s + length; + SizeType count = 0; + while (is.src_ < end) { + unsigned codepoint; + if (!Encoding::Decode(is, &codepoint)) + return false; + count++; + } + *outCount = count; + return true; +} + } // namespace internal RAPIDJSON_NAMESPACE_END diff --git a/contrib/rapidjson/include/rapidjson/internal/strtod.h b/contrib/rapidjson/include/rapidjson/internal/strtod.h index ace65f677..adf49e349 100644 --- a/contrib/rapidjson/include/rapidjson/internal/strtod.h +++ b/contrib/rapidjson/include/rapidjson/internal/strtod.h @@ -15,7 +15,6 @@ #ifndef RAPIDJSON_STRTOD_ #define RAPIDJSON_STRTOD_ -#include "../rapidjson.h" #include "ieee754.h" #include "biginteger.h" #include "diyfp.h" @@ -95,13 +94,13 @@ inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) { hS_Exp2 -= common_Exp2; BigInteger dS = d; - dS.MultiplyPow5(dS_Exp5) <<= dS_Exp2; + dS.MultiplyPow5(static_cast(dS_Exp5)) <<= static_cast(dS_Exp2); BigInteger bS(bInt); - bS.MultiplyPow5(bS_Exp5) <<= bS_Exp2; + bS.MultiplyPow5(static_cast(bS_Exp5)) <<= static_cast(bS_Exp2); BigInteger hS(1); - hS.MultiplyPow5(hS_Exp5) <<= hS_Exp2; + hS.MultiplyPow5(static_cast(hS_Exp5)) <<= static_cast(hS_Exp2); BigInteger delta(0); dS.Difference(bS, &delta); @@ -134,22 +133,22 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5')) break; - significand = significand * 10 + (decimals[i] - '0'); + significand = significand * 10u + static_cast(decimals[i] - '0'); } if (i < length && decimals[i] >= '5') // Rounding significand++; size_t remaining = length - i; - const unsigned kUlpShift = 3; - const unsigned kUlp = 1 << kUlpShift; - int error = (remaining == 0) ? 0 : kUlp / 2; + const int kUlpShift = 3; + const int kUlp = 1 << kUlpShift; + int64_t error = (remaining == 0) ? 0 : kUlp / 2; DiyFp v(significand, 0); v = v.Normalize(); error <<= -v.e; - const int dExp = (int)decimalPosition - (int)i + exp; + const int dExp = static_cast(decimalPosition) - static_cast(i) + exp; int actualExp; DiyFp cachedPower = GetCachedPower10(dExp, &actualExp); @@ -163,10 +162,10 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6 DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7 }; - int adjustment = dExp - actualExp - 1; + int adjustment = dExp - actualExp - 1; RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7); v = v * kPow10[adjustment]; - if (length + adjustment > 19) // has more digits than decimal digits in 64-bit + if (length + static_cast(adjustment)> 19u) // has more digits than decimal digits in 64-bit error += kUlp / 2; } @@ -178,10 +177,10 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit v = v.Normalize(); error <<= oldExp - v.e; - const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); - unsigned precisionSize = 64 - effectiveSignificandSize; + const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); + int precisionSize = 64 - effectiveSignificandSize; if (precisionSize + kUlpShift >= 64) { - unsigned scaleExp = (precisionSize + kUlpShift) - 63; + int scaleExp = (precisionSize + kUlpShift) - 63; v.f >>= scaleExp; v.e += scaleExp; error = (error >> scaleExp) + 1 + kUlp; @@ -191,7 +190,7 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit DiyFp rounded(v.f >> precisionSize, v.e + precisionSize); const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp; const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp; - if (precisionBits >= halfWay + error) { + if (precisionBits >= halfWay + static_cast(error)) { rounded.f++; if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340) rounded.f >>= 1; @@ -201,12 +200,12 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit *result = rounded.ToDouble(); - return halfWay - error >= precisionBits || precisionBits >= halfWay + error; + return halfWay - static_cast(error) >= precisionBits || precisionBits >= halfWay + static_cast(error); } inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) { const BigInteger dInt(decimals, length); - const int dExp = (int)decimalPosition - (int)length + exp; + const int dExp = static_cast(decimalPosition) - static_cast(length) + exp; Double a(approx); int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp); if (cmp < 0) @@ -246,10 +245,10 @@ inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t // Trim right-most digits const int kMaxDecimalDigit = 780; - if ((int)length > kMaxDecimalDigit) { - int delta = (int(length) - kMaxDecimalDigit); + if (static_cast(length) > kMaxDecimalDigit) { + int delta = (static_cast(length) - kMaxDecimalDigit); exp += delta; - decimalPosition -= delta; + decimalPosition -= static_cast(delta); length = kMaxDecimalDigit; } diff --git a/contrib/rapidjson/include/rapidjson/internal/swap.h b/contrib/rapidjson/include/rapidjson/internal/swap.h index 0590921f1..666e49f97 100644 --- a/contrib/rapidjson/include/rapidjson/internal/swap.h +++ b/contrib/rapidjson/include/rapidjson/internal/swap.h @@ -17,6 +17,11 @@ #include "../rapidjson.h" +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + RAPIDJSON_NAMESPACE_BEGIN namespace internal { @@ -34,4 +39,8 @@ inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT { } // namespace internal RAPIDJSON_NAMESPACE_END +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + #endif // RAPIDJSON_INTERNAL_SWAP_H_ diff --git a/contrib/rapidjson/include/rapidjson/istreamwrapper.h b/contrib/rapidjson/include/rapidjson/istreamwrapper.h new file mode 100644 index 000000000..8639c8c3c --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/istreamwrapper.h @@ -0,0 +1,115 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_ISTREAMWRAPPER_H_ +#define RAPIDJSON_ISTREAMWRAPPER_H_ + +#include "stream.h" +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of \c std::basic_istream into RapidJSON's Stream concept. +/*! + The classes can be wrapped including but not limited to: + + - \c std::istringstream + - \c std::stringstream + - \c std::wistringstream + - \c std::wstringstream + - \c std::ifstream + - \c std::fstream + - \c std::wifstream + - \c std::wfstream + + \tparam StreamType Class derived from \c std::basic_istream. +*/ + +template +class BasicIStreamWrapper { +public: + typedef typename StreamType::char_type Ch; + BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {} + + Ch Peek() const { + typename StreamType::int_type c = stream_.peek(); + return RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast(c) : static_cast('\0'); + } + + Ch Take() { + typename StreamType::int_type c = stream_.get(); + if (RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) { + count_++; + return static_cast(c); + } + else + return '\0'; + } + + // tellg() may return -1 when failed. So we count by ourself. + size_t Tell() const { return count_; } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + // For encoding detection only. + const Ch* Peek4() const { + RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream. + int i; + bool hasError = false; + for (i = 0; i < 4; ++i) { + typename StreamType::int_type c = stream_.get(); + if (c == StreamType::traits_type::eof()) { + hasError = true; + stream_.clear(); + break; + } + peekBuffer_[i] = static_cast(c); + } + for (--i; i >= 0; --i) + stream_.putback(peekBuffer_[i]); + return !hasError ? peekBuffer_ : 0; + } + +private: + BasicIStreamWrapper(const BasicIStreamWrapper&); + BasicIStreamWrapper& operator=(const BasicIStreamWrapper&); + + StreamType& stream_; + size_t count_; //!< Number of characters read. Note: + mutable Ch peekBuffer_[4]; +}; + +typedef BasicIStreamWrapper IStreamWrapper; +typedef BasicIStreamWrapper WIStreamWrapper; + +#if defined(__clang__) || defined(_MSC_VER) +RAPIDJSON_DIAG_POP +#endif + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_ISTREAMWRAPPER_H_ diff --git a/contrib/rapidjson/include/rapidjson/memorybuffer.h b/contrib/rapidjson/include/rapidjson/memorybuffer.h index 2484b2185..39bee1dec 100644 --- a/contrib/rapidjson/include/rapidjson/memorybuffer.h +++ b/contrib/rapidjson/include/rapidjson/memorybuffer.h @@ -15,7 +15,7 @@ #ifndef RAPIDJSON_MEMORYBUFFER_H_ #define RAPIDJSON_MEMORYBUFFER_H_ -#include "rapidjson.h" +#include "stream.h" #include "internal/stack.h" RAPIDJSON_NAMESPACE_BEGIN diff --git a/contrib/rapidjson/include/rapidjson/memorystream.h b/contrib/rapidjson/include/rapidjson/memorystream.h index 99feae5d7..1d71d8a4f 100644 --- a/contrib/rapidjson/include/rapidjson/memorystream.h +++ b/contrib/rapidjson/include/rapidjson/memorystream.h @@ -15,7 +15,13 @@ #ifndef RAPIDJSON_MEMORYSTREAM_H_ #define RAPIDJSON_MEMORYSTREAM_H_ -#include "rapidjson.h" +#include "stream.h" + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(missing-noreturn) +#endif RAPIDJSON_NAMESPACE_BEGIN @@ -36,8 +42,8 @@ struct MemoryStream { MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} - Ch Peek() const { return (src_ == end_) ? '\0' : *src_; } - Ch Take() { return (src_ == end_) ? '\0' : *src_++; } + Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; } + Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; } size_t Tell() const { return static_cast(src_ - begin_); } Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } @@ -58,4 +64,8 @@ struct MemoryStream { RAPIDJSON_NAMESPACE_END +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + #endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/contrib/rapidjson/include/rapidjson/msinttypes/stdint.h b/contrib/rapidjson/include/rapidjson/msinttypes/stdint.h index a26fff4bf..3d4477b9a 100644 --- a/contrib/rapidjson/include/rapidjson/msinttypes/stdint.h +++ b/contrib/rapidjson/include/rapidjson/msinttypes/stdint.h @@ -89,14 +89,14 @@ #include // For Visual Studio 6 in C++ mode and for many Visual Studio versions when -// compiling for ARM we should wrap include with 'extern "C++" {}' -// or compiler give many errors like this: +// compiling for ARM we have to wrap include with 'extern "C++" {}' +// or compiler would give many errors like this: // error C2733: second C linkage of overloaded function 'wmemchr' not allowed -#ifdef __cplusplus +#if defined(__cplusplus) && !defined(_M_ARM) extern "C" { #endif # include -#ifdef __cplusplus +#if defined(__cplusplus) && !defined(_M_ARM) } #endif diff --git a/contrib/rapidjson/include/rapidjson/ostreamwrapper.h b/contrib/rapidjson/include/rapidjson/ostreamwrapper.h new file mode 100644 index 000000000..6f4667c08 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/ostreamwrapper.h @@ -0,0 +1,81 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#ifndef RAPIDJSON_OSTREAMWRAPPER_H_ +#define RAPIDJSON_OSTREAMWRAPPER_H_ + +#include "stream.h" +#include + +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +//! Wrapper of \c std::basic_ostream into RapidJSON's Stream concept. +/*! + The classes can be wrapped including but not limited to: + + - \c std::ostringstream + - \c std::stringstream + - \c std::wpstringstream + - \c std::wstringstream + - \c std::ifstream + - \c std::fstream + - \c std::wofstream + - \c std::wfstream + + \tparam StreamType Class derived from \c std::basic_ostream. +*/ + +template +class BasicOStreamWrapper { +public: + typedef typename StreamType::char_type Ch; + BasicOStreamWrapper(StreamType& stream) : stream_(stream) {} + + void Put(Ch c) { + stream_.put(c); + } + + void Flush() { + stream_.flush(); + } + + // Not implemented + char Peek() const { RAPIDJSON_ASSERT(false); return 0; } + char Take() { RAPIDJSON_ASSERT(false); return 0; } + size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; } + char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; } + +private: + BasicOStreamWrapper(const BasicOStreamWrapper&); + BasicOStreamWrapper& operator=(const BasicOStreamWrapper&); + + StreamType& stream_; +}; + +typedef BasicOStreamWrapper OStreamWrapper; +typedef BasicOStreamWrapper WOStreamWrapper; + +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_OSTREAMWRAPPER_H_ diff --git a/contrib/rapidjson/include/rapidjson/pointer.h b/contrib/rapidjson/include/rapidjson/pointer.h index 5d2aa8d63..0f377efec 100644 --- a/contrib/rapidjson/include/rapidjson/pointer.h +++ b/contrib/rapidjson/include/rapidjson/pointer.h @@ -18,6 +18,16 @@ #include "document.h" #include "internal/itoa.h" +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(switch-enum) +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + RAPIDJSON_NAMESPACE_BEGIN static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token @@ -71,7 +81,7 @@ template class GenericPointer { public: typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value - typedef typename EncodingType::Ch Ch; //!< Character type from Value + typedef typename ValueType::Ch Ch; //!< Character type from Value //! A token is the basic units of internal representation. /*! @@ -96,7 +106,7 @@ public: //@{ //! Default constructor. - GenericPointer() : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} + GenericPointer(Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} //! Constructor that parses a string or URI fragment representation. /*! @@ -155,7 +165,7 @@ public: GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} //! Copy constructor. - GenericPointer(const GenericPointer& rhs) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { + GenericPointer(const GenericPointer& rhs, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { *this = rhs; } @@ -230,7 +240,7 @@ public: template RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >), (GenericPointer)) Append(T* name, Allocator* allocator = 0) const { - return Append(name, StrLen(name), allocator); + return Append(name, internal::StrLen(name), allocator); } #if RAPIDJSON_HAS_STDSTRING @@ -253,17 +263,18 @@ public: */ GenericPointer Append(SizeType index, Allocator* allocator = 0) const { char buffer[21]; - SizeType length = (sizeof(SizeType) == 4 ? internal::u32toa(index, buffer): internal::u64toa(index, buffer)) - buffer; + char* end = sizeof(SizeType) == 4 ? internal::u32toa(index, buffer) : internal::u64toa(index, buffer); + SizeType length = static_cast(end - buffer); buffer[length] = '\0'; if (sizeof(Ch) == 1) { - Token token = { (Ch*)buffer, length, index }; + Token token = { reinterpret_cast(buffer), length, index }; return Append(token, allocator); } else { Ch name[21]; for (size_t i = 0; i <= length; i++) - name[i] = buffer[i]; + name[i] = static_cast(buffer[i]); Token token = { name, length, index }; return Append(token, allocator); } @@ -271,7 +282,7 @@ public: //! Append a token by value, and return a new Pointer /*! - \param value Value (either Uint or String) to be appended. + \param token token to be appended. \param allocator Allocator for the newly return Pointer. \return A new Pointer with appended token. */ @@ -299,6 +310,9 @@ public: //@} + //! Get the allocator of this pointer. + Allocator& GetAllocator() { return *allocator_; } + //!@name Tokens //@{ @@ -390,7 +404,7 @@ public: bool exist = true; for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { if (v->IsArray() && t->name[0] == '-' && t->length == 1) { - v->PushBack(Value().Move(), allocator); + v->PushBack(ValueType().Move(), allocator); v = &((*v)[v->Size() - 1]); exist = false; } @@ -408,7 +422,7 @@ public: if (t->index >= v->Size()) { v->Reserve(t->index + 1, allocator); while (t->index >= v->Size()) - v->PushBack(Value().Move(), allocator); + v->PushBack(ValueType().Move(), allocator); exist = false; } v = &((*v)[t->index]); @@ -416,7 +430,7 @@ public: else { typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); if (m == v->MemberEnd()) { - v->AddMember(Value(t->name, t->length, allocator).Move(), Value().Move(), allocator); + v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator); v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end exist = false; } @@ -435,7 +449,6 @@ public: //! Creates a value in a document. /*! \param document A document to be resolved. - \param allocator Allocator for creating the values if the specified value or its parents are not exist. \param alreadyExist If non-null, it stores whether the resolved value is already exist. \return The resolved newly created, or already exists value. */ @@ -452,9 +465,18 @@ public: //! Query a value in a subtree. /*! \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. + \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token. \return Pointer to the value if it can be resolved. Otherwise null. + + \note + There are only 3 situations when a value cannot be resolved: + 1. A value in the path is not an array nor object. + 2. An object value does not contain the token. + 3. A token is out of range of an array value. + + Use unresolvedTokenIndex to retrieve the token index. */ - ValueType* Get(ValueType& root) const { + ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const { RAPIDJSON_ASSERT(IsValid()); ValueType* v = &root; for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { @@ -463,18 +485,23 @@ public: { typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); if (m == v->MemberEnd()) - return 0; + break; v = &m->value; } - break; + continue; case kArrayType: if (t->index == kPointerInvalidIndex || t->index >= v->Size()) - return 0; + break; v = &((*v)[t->index]); - break; + continue; default: - return 0; + break; } + + // Error: unresolved token + if (unresolvedTokenIndex) + *unresolvedTokenIndex = static_cast(t - tokens_); + return 0; } return v; } @@ -484,7 +511,9 @@ public: \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. \return Pointer to the value if it can be resolved. Otherwise null. */ - const ValueType* Get(const ValueType& root) const { return Get(const_cast(root)); } + const ValueType* Get(const ValueType& root, size_t* unresolvedTokenIndex = 0) const { + return Get(const_cast(root), unresolvedTokenIndex); + } //@} @@ -525,7 +554,7 @@ public: //! Query a value in a subtree with default primitive value. /*! - \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool */ template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) @@ -555,7 +584,7 @@ public: //! Query a value in a document with default primitive value. /*! - \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool */ template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) @@ -601,7 +630,7 @@ public: //! Set a primitive value in a subtree. /*! - \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool */ template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) @@ -637,7 +666,7 @@ public: //! Set a primitive value in a document. /*! - \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool + \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool */ template RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) @@ -729,7 +758,7 @@ private: */ Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) { if (!allocator_) // allocator is independently owned. - ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t) @@ -738,8 +767,12 @@ private: tokenCount_ = rhs.tokenCount_ + extraToken; tokens_ = static_cast(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch))); nameBuffer_ = reinterpret_cast(tokens_ + tokenCount_); - std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token)); - std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch)); + if (rhs.tokenCount_ > 0) { + std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token)); + } + if (nameBufferSize > 0) { + std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch)); + } // Adjust pointers to name buffer std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_; @@ -759,11 +792,13 @@ private: } //! Parse a JSON String or its URI fragment representation into tokens. +#ifndef __clang__ // -Wdocumentation /*! \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated. \param length Length of the source string. \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped. */ +#endif void Parse(const Ch* source, size_t length) { RAPIDJSON_ASSERT(source != NULL); RAPIDJSON_ASSERT(nameBuffer_ == 0); @@ -771,7 +806,7 @@ private: // Create own allocator if user did not supply. if (!allocator_) - ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); // Count number of '/' as tokenCount tokenCount_ = 0; @@ -857,7 +892,7 @@ private: *name++ = c; } - token->length = name - token->name; + token->length = static_cast(name - token->name); if (token->length == 0) isNumber = false; *name++ = '\0'; // Null terminator @@ -944,6 +979,8 @@ private: */ class PercentDecodeStream { public: + typedef typename ValueType::Ch Ch; + //! Constructor /*! \param source Start of the stream @@ -959,11 +996,11 @@ private: src_++; Ch c = 0; for (int j = 0; j < 2; j++) { - c <<= 4; + c = static_cast(c << 4); Ch h = *src_; - if (h >= '0' && h <= '9') c += h - '0'; - else if (h >= 'A' && h <= 'F') c += h - 'A' + 10; - else if (h >= 'a' && h <= 'f') c += h - 'a' + 10; + if (h >= '0' && h <= '9') c = static_cast(c + h - '0'); + else if (h >= 'A' && h <= 'F') c = static_cast(c + h - 'A' + 10); + else if (h >= 'a' && h <= 'f') c = static_cast(c + h - 'a' + 10); else { valid_ = false; return 0; @@ -973,7 +1010,7 @@ private: return c; } - size_t Tell() const { return src_ - head_; } + size_t Tell() const { return static_cast(src_ - head_); } bool IsValid() const { return valid_; } private: @@ -992,8 +1029,8 @@ private: unsigned char u = static_cast(c); static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; os_.Put('%'); - os_.Put(hexDigits[u >> 4]); - os_.Put(hexDigits[u & 15]); + os_.Put(static_cast(hexDigits[u >> 4])); + os_.Put(static_cast(hexDigits[u & 15])); } private: OutputStream& os_; @@ -1041,23 +1078,23 @@ typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, c ////////////////////////////////////////////////////////////////////////////// template -typename T::ValueType* GetValueByPointer(T& root, const GenericPointer& pointer) { - return pointer.Get(root); +typename T::ValueType* GetValueByPointer(T& root, const GenericPointer& pointer, size_t* unresolvedTokenIndex = 0) { + return pointer.Get(root, unresolvedTokenIndex); } template -const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer& pointer) { - return pointer.Get(root); +const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer& pointer, size_t* unresolvedTokenIndex = 0) { + return pointer.Get(root, unresolvedTokenIndex); } template -typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N]) { - return GenericPointer(source, N - 1).Get(root); +typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) { + return GenericPointer(source, N - 1).Get(root, unresolvedTokenIndex); } template -const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N]) { - return GenericPointer(source, N - 1).Get(root); +const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) { + return GenericPointer(source, N - 1).Get(root, unresolvedTokenIndex); } ////////////////////////////////////////////////////////////////////////////// @@ -1310,4 +1347,12 @@ bool EraseValueByPointer(T& root, const CharType(&source)[N]) { RAPIDJSON_NAMESPACE_END +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_POP +#endif + #endif // RAPIDJSON_POINTER_H_ diff --git a/contrib/rapidjson/include/rapidjson/prettywriter.h b/contrib/rapidjson/include/rapidjson/prettywriter.h index 416dd492e..98dfb3060 100644 --- a/contrib/rapidjson/include/rapidjson/prettywriter.h +++ b/contrib/rapidjson/include/rapidjson/prettywriter.h @@ -22,8 +22,21 @@ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(effc++) #endif +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + RAPIDJSON_NAMESPACE_BEGIN +//! Combination of PrettyWriter format flags. +/*! \see PrettyWriter::SetFormatOptions + */ +enum PrettyFormatOptions { + kFormatDefault = 0, //!< Default pretty formatting. + kFormatSingleLineArray = 1 //!< Format arrays on a single line. +}; + //! Writer with indentation and spacing. /*! \tparam OutputStream Type of ouptut os. @@ -31,10 +44,10 @@ RAPIDJSON_NAMESPACE_BEGIN \tparam TargetEncoding Encoding of output stream. \tparam StackAllocator Type of allocator for allocating memory of stack. */ -template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator> -class PrettyWriter : public Writer { +template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> +class PrettyWriter : public Writer { public: - typedef Writer Base; + typedef Writer Base; typedef typename Base::Ch Ch; //! Constructor @@ -42,8 +55,17 @@ public: \param allocator User supplied allocator. If it is null, it will create a private one. \param levelDepth Initial capacity of stack. */ - PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : - Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} + explicit PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {} + + + explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : + Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + PrettyWriter(PrettyWriter&& rhs) : + Base(std::forward(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {} +#endif //! Set custom indentation. /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). @@ -57,6 +79,14 @@ public: return *this; } + //! Set pretty writer formatting options. + /*! \param options Formatting options. + */ + PrettyWriter& SetFormatOptions(PrettyFormatOptions options) { + formatOptions_ = options; + return *this; + } + /*! @name Implementation of Handler \see Handler */ @@ -70,7 +100,15 @@ public: bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); } bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); } + bool RawNumber(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + PrettyPrefix(kNumberType); + return Base::WriteString(str, length); + } + bool String(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); (void)copy; PrettyPrefix(kStringType); return Base::WriteString(str, length); @@ -89,11 +127,19 @@ public: } bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + +#if RAPIDJSON_HAS_STDSTRING + bool Key(const std::basic_string& str) { + return Key(str.data(), SizeType(str.size())); + } +#endif bool EndObject(SizeType memberCount = 0) { (void)memberCount; - RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); - RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); + RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); // not inside an Object + RAPIDJSON_ASSERT(!Base::level_stack_.template Top()->inArray); // currently inside an Array, not Object + RAPIDJSON_ASSERT(0 == Base::level_stack_.template Top()->valueCount % 2); // Object has a Key without a Value + bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; if (!empty) { @@ -104,7 +150,7 @@ public: (void)ret; RAPIDJSON_ASSERT(ret == true); if (Base::level_stack_.Empty()) // end of json text - Base::os_->Flush(); + Base::Flush(); return true; } @@ -120,7 +166,7 @@ public: RAPIDJSON_ASSERT(Base::level_stack_.template Top()->inArray); bool empty = Base::level_stack_.template Pop(1)->valueCount == 0; - if (!empty) { + if (!empty && !(formatOptions_ & kFormatSingleLineArray)) { Base::os_->Put('\n'); WriteIndent(); } @@ -128,7 +174,7 @@ public: (void)ret; RAPIDJSON_ASSERT(ret == true); if (Base::level_stack_.Empty()) // end of json text - Base::os_->Flush(); + Base::Flush(); return true; } @@ -142,6 +188,22 @@ public: bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } //@} + + //! Write a raw JSON value. + /*! + For user to write a stringified JSON as a value. + + \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. + \param length Length of the json. + \param type Type of the root of json. + \note When using PrettyWriter::RawValue(), the result json may not be indented correctly. + */ + bool RawValue(const Ch* json, size_t length, Type type) { + RAPIDJSON_ASSERT(json != 0); + PrettyPrefix(type); + return Base::WriteRawValue(json, length); + } + protected: void PrettyPrefix(Type type) { (void)type; @@ -151,11 +213,14 @@ protected: if (level->inArray) { if (level->valueCount > 0) { Base::os_->Put(','); // add comma if it is not the first element in array - Base::os_->Put('\n'); + if (formatOptions_ & kFormatSingleLineArray) + Base::os_->Put(' '); } - else + + if (!(formatOptions_ & kFormatSingleLineArray)) { Base::os_->Put('\n'); - WriteIndent(); + WriteIndent(); + } } else { // in object if (level->valueCount > 0) { @@ -186,11 +251,12 @@ protected: void WriteIndent() { size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; - PutN(*Base::os_, indentChar_, count); + PutN(*Base::os_, static_cast(indentChar_), count); } Ch indentChar_; unsigned indentCharCount_; + PrettyFormatOptions formatOptions_; private: // Prohibit copy constructor & assignment operator. @@ -200,6 +266,10 @@ private: RAPIDJSON_NAMESPACE_END +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + #ifdef __GNUC__ RAPIDJSON_DIAG_POP #endif diff --git a/contrib/rapidjson/include/rapidjson/rapidjson.h b/contrib/rapidjson/include/rapidjson/rapidjson.h index f22130d3c..5716fdc06 100644 --- a/contrib/rapidjson/include/rapidjson/rapidjson.h +++ b/contrib/rapidjson/include/rapidjson/rapidjson.h @@ -49,6 +49,11 @@ // token stringification #define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x) #define RAPIDJSON_DO_STRINGIFY(x) #x + +// token concatenation +#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y) +#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y) +#define RAPIDJSON_DO_JOIN2(X, Y) X##Y //!@endcond /*! \def RAPIDJSON_MAJOR_VERSION @@ -68,8 +73,8 @@ \brief Version of RapidJSON in ".." string format. */ #define RAPIDJSON_MAJOR_VERSION 1 -#define RAPIDJSON_MINOR_VERSION 0 -#define RAPIDJSON_PATCH_VERSION 2 +#define RAPIDJSON_MINOR_VERSION 1 +#define RAPIDJSON_PATCH_VERSION 0 #define RAPIDJSON_VERSION_STRING \ RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION) @@ -119,6 +124,31 @@ #define RAPIDJSON_NAMESPACE_END } #endif +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_HAS_STDSTRING + +#ifndef RAPIDJSON_HAS_STDSTRING +#ifdef RAPIDJSON_DOXYGEN_RUNNING +#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation +#else +#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default +#endif +/*! \def RAPIDJSON_HAS_STDSTRING + \ingroup RAPIDJSON_CONFIG + \brief Enable RapidJSON support for \c std::string + + By defining this preprocessor symbol to \c 1, several convenience functions for using + \ref rapidjson::GenericValue with \c std::string are enabled, especially + for construction and comparison. + + \hideinitializer +*/ +#endif // !defined(RAPIDJSON_HAS_STDSTRING) + +#if RAPIDJSON_HAS_STDSTRING +#include +#endif // RAPIDJSON_HAS_STDSTRING + /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_NO_INT64DEFINE @@ -134,7 +164,7 @@ */ #ifndef RAPIDJSON_NO_INT64DEFINE //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN -#ifdef _MSC_VER +#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013 #include "msinttypes/stdint.h" #include "msinttypes/inttypes.h" #else @@ -153,9 +183,9 @@ #ifndef RAPIDJSON_FORCEINLINE //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN -#if defined(_MSC_VER) && !defined(NDEBUG) +#if defined(_MSC_VER) && defined(NDEBUG) #define RAPIDJSON_FORCEINLINE __forceinline -#elif defined(__GNUC__) && __GNUC__ >= 4 && !defined(NDEBUG) +#elif defined(__GNUC__) && __GNUC__ >= 4 && defined(NDEBUG) #define RAPIDJSON_FORCEINLINE __attribute__((always_inline)) #else #define RAPIDJSON_FORCEINLINE @@ -211,6 +241,8 @@ # define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN # elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__) # define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64)) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN # elif defined(RAPIDJSON_DOXYGEN_RUNNING) # define RAPIDJSON_ENDIAN # else @@ -223,7 +255,7 @@ //! Whether using 64-bit architecture #ifndef RAPIDJSON_64BIT -#if defined(__LP64__) || defined(_WIN64) +#if defined(__LP64__) || (defined(__x86_64__) && defined(__ILP32__)) || defined(_WIN64) || defined(__EMSCRIPTEN__) #define RAPIDJSON_64BIT 1 #else #define RAPIDJSON_64BIT 0 @@ -238,13 +270,14 @@ \param x pointer to align Some machines require strict data alignment. Currently the default uses 4 bytes - alignment. User can customize by defining the RAPIDJSON_ALIGN function macro., + alignment on 32-bit platforms and 8 bytes alignment for 64-bit platforms. + User can customize by defining the RAPIDJSON_ALIGN function macro. */ #ifndef RAPIDJSON_ALIGN #if RAPIDJSON_64BIT == 1 -#define RAPIDJSON_ALIGN(x) ((x + 7u) & ~7u) +#define RAPIDJSON_ALIGN(x) (((x) + static_cast(7u)) & ~static_cast(7u)) #else -#define RAPIDJSON_ALIGN(x) ((x + 3u) & ~3u) +#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u) #endif #endif @@ -262,17 +295,47 @@ #endif /////////////////////////////////////////////////////////////////////////////// -// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD +// RAPIDJSON_48BITPOINTER_OPTIMIZATION + +//! Use only lower 48-bit address for some pointers. +/*! + \ingroup RAPIDJSON_CONFIG + + This optimization uses the fact that current X86-64 architecture only implement lower 48-bit virtual address. + The higher 16-bit can be used for storing other data. + \c GenericValue uses this optimization to reduce its size form 24 bytes to 16 bytes in 64-bit architecture. +*/ +#ifndef RAPIDJSON_48BITPOINTER_OPTIMIZATION +#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) +#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 1 +#else +#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 0 +#endif +#endif // RAPIDJSON_48BITPOINTER_OPTIMIZATION + +#if RAPIDJSON_48BITPOINTER_OPTIMIZATION == 1 +#if RAPIDJSON_64BIT != 1 +#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1 +#endif +#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast((reinterpret_cast(p) & static_cast(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast(reinterpret_cast(x)))) +#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast(reinterpret_cast(p) & static_cast(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF)))) +#else +#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x)) +#define RAPIDJSON_GETPOINTER(type, p) (p) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_NEON/RAPIDJSON_SIMD /*! \def RAPIDJSON_SIMD \ingroup RAPIDJSON_CONFIG - \brief Enable SSE2/SSE4.2 optimization. + \brief Enable SSE2/SSE4.2/Neon optimization. RapidJSON supports optimized implementations for some parsing operations - based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible - processors. + based on the SSE2, SSE4.2 or NEon SIMD extensions on modern Intel + or ARM compatible processors. - To enable these optimizations, two different symbols can be defined; + To enable these optimizations, three different symbols can be defined; \code // Enable SSE2 optimization. #define RAPIDJSON_SSE2 @@ -281,13 +344,17 @@ #define RAPIDJSON_SSE42 \endcode - \c RAPIDJSON_SSE42 takes precedence, if both are defined. + // Enable ARM Neon optimization. + #define RAPIDJSON_NEON + \endcode + + \c RAPIDJSON_SSE42 takes precedence over SSE2, if both are defined. If any of these symbols is defined, RapidJSON defines the macro \c RAPIDJSON_SIMD to indicate the availability of the optimized code. */ #if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \ - || defined(RAPIDJSON_DOXYGEN_RUNNING) + || defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING) #define RAPIDJSON_SIMD #endif @@ -347,25 +414,33 @@ RAPIDJSON_NAMESPACE_END /////////////////////////////////////////////////////////////////////////////// // RAPIDJSON_STATIC_ASSERT -// Adopt from boost +// Prefer C++11 static_assert, if available #ifndef RAPIDJSON_STATIC_ASSERT +#if __cplusplus >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 ) +#define RAPIDJSON_STATIC_ASSERT(x) \ + static_assert(x, RAPIDJSON_STRINGIFY(x)) +#endif // C++11 +#endif // RAPIDJSON_STATIC_ASSERT + +// Adopt C++03 implementation from boost +#ifndef RAPIDJSON_STATIC_ASSERT +#ifndef __clang__ //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN +#endif RAPIDJSON_NAMESPACE_BEGIN template struct STATIC_ASSERTION_FAILURE; template <> struct STATIC_ASSERTION_FAILURE { enum { value = 1 }; }; -template struct StaticAssertTest {}; +template struct StaticAssertTest {}; RAPIDJSON_NAMESPACE_END -#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y) -#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y) -#define RAPIDJSON_DO_JOIN2(X, Y) X##Y - #if defined(__GNUC__) #define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) #else #define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE #endif +#ifndef __clang__ //!@endcond +#endif /*! \def RAPIDJSON_STATIC_ASSERT \brief (Internal) macro to check for conditions at compile-time @@ -376,6 +451,35 @@ RAPIDJSON_NAMESPACE_END typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \ sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE)> \ RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE +#endif // RAPIDJSON_STATIC_ASSERT + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY + +//! Compiler branching hint for expression with high probability to be true. +/*! + \ingroup RAPIDJSON_CONFIG + \param x Boolean expression likely to be true. +*/ +#ifndef RAPIDJSON_LIKELY +#if defined(__GNUC__) || defined(__clang__) +#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1) +#else +#define RAPIDJSON_LIKELY(x) (x) +#endif +#endif + +//! Compiler branching hint for expression with low probability to be true. +/*! + \ingroup RAPIDJSON_CONFIG + \param x Boolean expression unlikely to be true. +*/ +#ifndef RAPIDJSON_UNLIKELY +#if defined(__GNUC__) || defined(__clang__) +#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else +#define RAPIDJSON_UNLIKELY(x) (x) +#endif #endif /////////////////////////////////////////////////////////////////////////////// @@ -438,8 +542,12 @@ RAPIDJSON_NAMESPACE_END #ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS #if defined(__clang__) -#define RAPIDJSON_HAS_CXX11_RVALUE_REFS __has_feature(cxx_rvalue_references) && \ +#if __has_feature(cxx_rvalue_references) && \ (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306) +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 +#else +#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 +#endif #elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ (defined(_MSC_VER) && _MSC_VER >= 1600) @@ -470,6 +578,17 @@ RAPIDJSON_NAMESPACE_END #define RAPIDJSON_HAS_CXX11_TYPETRAITS 0 #endif +#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR +#if defined(__clang__) +#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for) +#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ + (defined(_MSC_VER) && _MSC_VER >= 1700) +#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1 +#else +#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0 +#endif +#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR + //!@endcond /////////////////////////////////////////////////////////////////////////////// @@ -477,7 +596,7 @@ RAPIDJSON_NAMESPACE_END #ifndef RAPIDJSON_NEW ///! customization point for global \c new -#define RAPIDJSON_NEW(x) new x +#define RAPIDJSON_NEW(TypeName) new TypeName #endif #ifndef RAPIDJSON_DELETE ///! customization point for global \c delete @@ -485,10 +604,7 @@ RAPIDJSON_NAMESPACE_END #endif /////////////////////////////////////////////////////////////////////////////// -// Allocators and Encodings - -#include "allocators.h" -#include "encodings.h" +// Type /*! \namespace rapidjson \brief main RapidJSON namespace @@ -496,148 +612,6 @@ RAPIDJSON_NAMESPACE_END */ RAPIDJSON_NAMESPACE_BEGIN -/////////////////////////////////////////////////////////////////////////////// -// Stream - -/*! \class rapidjson::Stream - \brief Concept for reading and writing characters. - - For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd(). - - For write-only stream, only need to implement Put() and Flush(). - -\code -concept Stream { - typename Ch; //!< Character type of the stream. - - //! Read the current character from stream without moving the read cursor. - Ch Peek() const; - - //! Read the current character from stream and moving the read cursor to next character. - Ch Take(); - - //! Get the current read cursor. - //! \return Number of characters read from start. - size_t Tell(); - - //! Begin writing operation at the current read pointer. - //! \return The begin writer pointer. - Ch* PutBegin(); - - //! Write a character. - void Put(Ch c); - - //! Flush the buffer. - void Flush(); - - //! End the writing operation. - //! \param begin The begin write pointer returned by PutBegin(). - //! \return Number of characters written. - size_t PutEnd(Ch* begin); -} -\endcode -*/ - -//! Provides additional information for stream. -/*! - By using traits pattern, this type provides a default configuration for stream. - For custom stream, this type can be specialized for other configuration. - See TEST(Reader, CustomStringStream) in readertest.cpp for example. -*/ -template -struct StreamTraits { - //! Whether to make local copy of stream for optimization during parsing. - /*! - By default, for safety, streams do not use local copy optimization. - Stream that can be copied fast should specialize this, like StreamTraits. - */ - enum { copyOptimization = 0 }; -}; - -//! Put N copies of a character to a stream. -template -inline void PutN(Stream& stream, Ch c, size_t n) { - for (size_t i = 0; i < n; i++) - stream.Put(c); -} - -/////////////////////////////////////////////////////////////////////////////// -// StringStream - -//! Read-only string stream. -/*! \note implements Stream concept -*/ -template -struct GenericStringStream { - typedef typename Encoding::Ch Ch; - - GenericStringStream(const Ch *src) : src_(src), head_(src) {} - - Ch Peek() const { return *src_; } - Ch Take() { return *src_++; } - size_t Tell() const { return static_cast(src_ - head_); } - - Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } - void Put(Ch) { RAPIDJSON_ASSERT(false); } - void Flush() { RAPIDJSON_ASSERT(false); } - size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } - - const Ch* src_; //!< Current read position. - const Ch* head_; //!< Original head of the string. -}; - -template -struct StreamTraits > { - enum { copyOptimization = 1 }; -}; - -//! String stream with UTF8 encoding. -typedef GenericStringStream > StringStream; - -/////////////////////////////////////////////////////////////////////////////// -// InsituStringStream - -//! A read-write string stream. -/*! This string stream is particularly designed for in-situ parsing. - \note implements Stream concept -*/ -template -struct GenericInsituStringStream { - typedef typename Encoding::Ch Ch; - - GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} - - // Read - Ch Peek() { return *src_; } - Ch Take() { return *src_++; } - size_t Tell() { return static_cast(src_ - head_); } - - // Write - void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } - - Ch* PutBegin() { return dst_ = src_; } - size_t PutEnd(Ch* begin) { return static_cast(dst_ - begin); } - void Flush() {} - - Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; } - void Pop(size_t count) { dst_ -= count; } - - Ch* src_; - Ch* dst_; - Ch* head_; -}; - -template -struct StreamTraits > { - enum { copyOptimization = 1 }; -}; - -//! Insitu string stream with UTF8 encoding. -typedef GenericInsituStringStream > InsituStringStream; - -/////////////////////////////////////////////////////////////////////////////// -// Type - //! Type of JSON value enum Type { kNullType = 0, //!< null diff --git a/contrib/rapidjson/include/rapidjson/reader.h b/contrib/rapidjson/include/rapidjson/reader.h index c5ecf4be5..120c31115 100644 --- a/contrib/rapidjson/include/rapidjson/reader.h +++ b/contrib/rapidjson/include/rapidjson/reader.h @@ -1,5 +1,5 @@ // Tencent is pleased to support the open source community by making RapidJSON available. -// +// // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // // Licensed under the MIT License (the "License"); you may not use this file except @@ -7,9 +7,9 @@ // // http://opensource.org/licenses/MIT // -// Unless required by applicable law or agreed to in writing, software distributed -// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. #ifndef RAPIDJSON_READER_H_ @@ -17,11 +17,13 @@ /*! \file reader.h */ -#include "rapidjson.h" -#include "encodings.h" +#include "allocators.h" +#include "stream.h" +#include "encodedstream.h" #include "internal/meta.h" #include "internal/stack.h" #include "internal/strtod.h" +#include #if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) #include @@ -31,6 +33,8 @@ #include #elif defined(RAPIDJSON_SSE2) #include +#elif defined(RAPIDJSON_NEON) +#include #endif #ifdef _MSC_VER @@ -39,6 +43,13 @@ RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant RAPIDJSON_DIAG_OFF(4702) // unreachable code #endif +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(old-style-cast) +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(switch-enum) +#endif + #ifdef __GNUC__ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(effc++) @@ -49,7 +60,7 @@ RAPIDJSON_DIAG_OFF(effc++) #ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN #define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \ RAPIDJSON_MULTILINEMACRO_BEGIN \ - if (HasParseError()) { return value; } \ + if (RAPIDJSON_UNLIKELY(HasParseError())) { return value; } \ RAPIDJSON_MULTILINEMACRO_END #endif #define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \ @@ -120,7 +131,7 @@ RAPIDJSON_NAMESPACE_BEGIN /////////////////////////////////////////////////////////////////////////////// // ParseFlag -/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS +/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS \ingroup RAPIDJSON_CONFIG \brief User-defined kParseDefaultFlags definition. @@ -140,6 +151,10 @@ enum ParseFlag { kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing. kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error. kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower). + kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments. + kParseNumbersAsStringsFlag = 64, //!< Parse all numbers (ints/doubles) as strings. + kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays. + kParseNanAndInfFlag = 256, //!< Allow parsing NaN, Inf, Infinity, -Inf and -Infinity as doubles. kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS }; @@ -148,7 +163,7 @@ enum ParseFlag { /*! \class rapidjson::Handler \brief Concept for receiving events from GenericReader upon parsing. - The functions return true if no error occurs. If they return false, + The functions return true if no error occurs. If they return false, the event publisher should terminate the process. \code concept Handler { @@ -161,6 +176,8 @@ concept Handler { bool Int64(int64_t i); bool Uint64(uint64_t i); bool Double(double d); + /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length) + bool RawNumber(const Ch* str, SizeType length, bool copy); bool String(const Ch* str, SizeType length, bool copy); bool StartObject(); bool Key(const Ch* str, SizeType length, bool copy); @@ -191,6 +208,8 @@ struct BaseReaderHandler { bool Int64(int64_t) { return static_cast(*this).Default(); } bool Uint64(uint64_t) { return static_cast(*this).Default(); } bool Double(double) { return static_cast(*this).Default(); } + /// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length) + bool RawNumber(const Ch* str, SizeType len, bool copy) { return static_cast(*this).String(str, len, copy); } bool String(const Ch*, SizeType, bool) { return static_cast(*this).Default(); } bool StartObject() { return static_cast(*this).Default(); } bool Key(const Ch* str, SizeType len, bool copy) { return static_cast(*this).String(str, len, copy); } @@ -248,10 +267,17 @@ void SkipWhitespace(InputStream& is) { internal::StreamLocalCopy copy(is); InputStream& s(copy.s); - while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t') + typename InputStream::Ch c; + while ((c = s.Peek()) == ' ' || c == '\n' || c == '\r' || c == '\t') s.Take(); } +inline const char* SkipWhitespace(const char* p, const char* end) { + while (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + return p; +} + #ifdef RAPIDJSON_SSE42 //! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once. inline const char *SkipWhitespace_SIMD(const char* p) { @@ -262,7 +288,7 @@ inline const char *SkipWhitespace_SIMD(const char* p) { return p; // 16-byte align to the next boundary - const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & ~15); + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); while (p != nextAligned) if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') ++p; @@ -271,23 +297,37 @@ inline const char *SkipWhitespace_SIMD(const char* p) { // The rest of string using SIMD static const char whitespace[16] = " \n\r\t"; - const __m128i w = _mm_load_si128((const __m128i *)&whitespace[0]); + const __m128i w = _mm_loadu_si128(reinterpret_cast(&whitespace[0])); for (;; p += 16) { - const __m128i s = _mm_load_si128((const __m128i *)p); - const unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY)); - if (r != 0) { // some of characters is non-whitespace -#ifdef _MSC_VER // Find the index of first non-whitespace - unsigned long offset; - _BitScanForward(&offset, r); - return p + offset; -#else - return p + __builtin_ffs(r) - 1; -#endif - } + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY); + if (r != 16) // some of characters is non-whitespace + return p + r; } } +inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + // Fast return for single non-whitespace + if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + else + return p; + + // The middle of string using SIMD + static const char whitespace[16] = " \n\r\t"; + const __m128i w = _mm_loadu_si128(reinterpret_cast(&whitespace[0])); + + for (; p <= end - 16; p += 16) { + const __m128i s = _mm_loadu_si128(reinterpret_cast(p)); + const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY); + if (r != 16) // some of characters is non-whitespace + return p + r; + } + + return SkipWhitespace(p, end); +} + #elif defined(RAPIDJSON_SSE2) //! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once. @@ -299,7 +339,7 @@ inline const char *SkipWhitespace_SIMD(const char* p) { return p; // 16-byte align to the next boundary - const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & ~15); + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); while (p != nextAligned) if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') ++p; @@ -307,24 +347,22 @@ inline const char *SkipWhitespace_SIMD(const char* p) { return p; // The rest of string - static const char whitespaces[4][17] = { - " ", - "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", - "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r", - "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"}; + #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } + static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; + #undef C16 - const __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]); - const __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]); - const __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]); - const __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]); + const __m128i w0 = _mm_loadu_si128(reinterpret_cast(&whitespaces[0][0])); + const __m128i w1 = _mm_loadu_si128(reinterpret_cast(&whitespaces[1][0])); + const __m128i w2 = _mm_loadu_si128(reinterpret_cast(&whitespaces[2][0])); + const __m128i w3 = _mm_loadu_si128(reinterpret_cast(&whitespaces[3][0])); for (;; p += 16) { - const __m128i s = _mm_load_si128((const __m128i *)p); + const __m128i s = _mm_load_si128(reinterpret_cast(p)); __m128i x = _mm_cmpeq_epi8(s, w0); x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); - unsigned short r = (unsigned short)~_mm_movemask_epi8(x); + unsigned short r = static_cast(~_mm_movemask_epi8(x)); if (r != 0) { // some of characters may be non-whitespace #ifdef _MSC_VER // Find the index of first non-whitespace unsigned long offset; @@ -337,11 +375,134 @@ inline const char *SkipWhitespace_SIMD(const char* p) { } } -#endif // RAPIDJSON_SSE2 +inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + // Fast return for single non-whitespace + if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + else + return p; + + // The rest of string + #define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c } + static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') }; + #undef C16 + + const __m128i w0 = _mm_loadu_si128(reinterpret_cast(&whitespaces[0][0])); + const __m128i w1 = _mm_loadu_si128(reinterpret_cast(&whitespaces[1][0])); + const __m128i w2 = _mm_loadu_si128(reinterpret_cast(&whitespaces[2][0])); + const __m128i w3 = _mm_loadu_si128(reinterpret_cast(&whitespaces[3][0])); + + for (; p <= end - 16; p += 16) { + const __m128i s = _mm_loadu_si128(reinterpret_cast(p)); + __m128i x = _mm_cmpeq_epi8(s, w0); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2)); + x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3)); + unsigned short r = static_cast(~_mm_movemask_epi8(x)); + if (r != 0) { // some of characters may be non-whitespace +#ifdef _MSC_VER // Find the index of first non-whitespace + unsigned long offset; + _BitScanForward(&offset, r); + return p + offset; +#else + return p + __builtin_ffs(r) - 1; +#endif + } + } + + return SkipWhitespace(p, end); +} + +#elif defined(RAPIDJSON_NEON) + +//! Skip whitespace with ARM Neon instructions, testing 16 8-byte characters at once. +inline const char *SkipWhitespace_SIMD(const char* p) { + // Fast return for single non-whitespace + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + // 16-byte align to the next boundary + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') + ++p; + else + return p; + + const uint8x16_t w0 = vmovq_n_u8(' '); + const uint8x16_t w1 = vmovq_n_u8('\n'); + const uint8x16_t w2 = vmovq_n_u8('\r'); + const uint8x16_t w3 = vmovq_n_u8('\t'); + + for (;; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, w0); + x = vorrq_u8(x, vceqq_u8(s, w1)); + x = vorrq_u8(x, vceqq_u8(s, w2)); + x = vorrq_u8(x, vceqq_u8(s, w3)); + + x = vmvnq_u8(x); // Negate + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(reinterpret_cast(x), 0); // extract + uint64_t high = vgetq_lane_u64(reinterpret_cast(x), 1); // extract + + if (low == 0) { + if (high != 0) { + int lz =__builtin_clzll(high);; + return p + 8 + (lz >> 3); + } + } else { + int lz = __builtin_clzll(low);; + return p + (lz >> 3); + } + } +} + +inline const char *SkipWhitespace_SIMD(const char* p, const char* end) { + // Fast return for single non-whitespace + if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')) + ++p; + else + return p; + + const uint8x16_t w0 = vmovq_n_u8(' '); + const uint8x16_t w1 = vmovq_n_u8('\n'); + const uint8x16_t w2 = vmovq_n_u8('\r'); + const uint8x16_t w3 = vmovq_n_u8('\t'); + + for (; p <= end - 16; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, w0); + x = vorrq_u8(x, vceqq_u8(s, w1)); + x = vorrq_u8(x, vceqq_u8(s, w2)); + x = vorrq_u8(x, vceqq_u8(s, w3)); + + x = vmvnq_u8(x); // Negate + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(reinterpret_cast(x), 0); // extract + uint64_t high = vgetq_lane_u64(reinterpret_cast(x), 1); // extract + + if (low == 0) { + if (high != 0) { + int lz = __builtin_clzll(high); + return p + 8 + (lz >> 3); + } + } else { + int lz = __builtin_clzll(low); + return p + (lz >> 3); + } + } + + return SkipWhitespace(p, end); +} + +#endif // RAPIDJSON_NEON #ifdef RAPIDJSON_SIMD //! Template function specialization for InsituStringStream -template<> inline void SkipWhitespace(InsituStringStream& is) { +template<> inline void SkipWhitespace(InsituStringStream& is) { is.src_ = const_cast(SkipWhitespace_SIMD(is.src_)); } @@ -349,23 +510,27 @@ template<> inline void SkipWhitespace(InsituStringStream& is) { template<> inline void SkipWhitespace(StringStream& is) { is.src_ = SkipWhitespace_SIMD(is.src_); } + +template<> inline void SkipWhitespace(EncodedInputStream, MemoryStream>& is) { + is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_); +} #endif // RAPIDJSON_SIMD /////////////////////////////////////////////////////////////////////////////// // GenericReader //! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator. -/*! GenericReader parses JSON text from a stream, and send events synchronously to an +/*! GenericReader parses JSON text from a stream, and send events synchronously to an object implementing Handler concept. - It needs to allocate a stack for storing a single decoded string during + It needs to allocate a stack for storing a single decoded string during non-destructive parsing. - For in-situ parsing, the decoded string is directly written to the source + For in-situ parsing, the decoded string is directly written to the source text string, no temporary buffer is required. A GenericReader object can be reused for parsing multiple JSON text. - + \tparam SourceEncoding Encoding of the input stream. \tparam TargetEncoding Encoding of the parse output. \tparam StackAllocator Allocator type for stack. @@ -398,9 +563,10 @@ public: ClearStackOnExit scope(*this); - SkipWhitespace(is); + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); - if (is.Peek() == '\0') { + if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) { RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell()); RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); } @@ -409,9 +575,10 @@ public: RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); if (!(parseFlags & kParseStopWhenDoneFlag)) { - SkipWhitespace(is); + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); - if (is.Peek() != '\0') { + if (RAPIDJSON_UNLIKELY(is.Peek() != '\0')) { RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell()); RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); } @@ -433,9 +600,86 @@ public: return Parse(is, handler); } + //! Initialize JSON text token-by-token parsing + /*! + */ + void IterativeParseInit() { + parseResult_.Clear(); + state_ = IterativeParsingStartState; + } + + //! Parse one token from JSON text + /*! \tparam InputStream Type of input stream, implementing Stream concept + \tparam Handler Type of handler, implementing Handler concept. + \param is Input stream to be parsed. + \param handler The handler to receive events. + \return Whether the parsing is successful. + */ + template + bool IterativeParseNext(InputStream& is, Handler& handler) { + while (RAPIDJSON_LIKELY(is.Peek() != '\0')) { + SkipWhitespaceAndComments(is); + + Token t = Tokenize(is.Peek()); + IterativeParsingState n = Predict(state_, t); + IterativeParsingState d = Transit(state_, t, n, is, handler); + + // If we've finished or hit an error... + if (RAPIDJSON_UNLIKELY(IsIterativeParsingCompleteState(d))) { + // Report errors. + if (d == IterativeParsingErrorState) { + HandleError(state_, is); + return false; + } + + // Transition to the finish state. + RAPIDJSON_ASSERT(d == IterativeParsingFinishState); + state_ = d; + + // If StopWhenDone is not set... + if (!(parseFlags & kParseStopWhenDoneFlag)) { + // ... and extra non-whitespace data is found... + SkipWhitespaceAndComments(is); + if (is.Peek() != '\0') { + // ... this is considered an error. + HandleError(state_, is); + return false; + } + } + + // Success! We are done! + return true; + } + + // Transition to the new state. + state_ = d; + + // If we parsed anything other than a delimiter, we invoked the handler, so we can return true now. + if (!IsIterativeParsingDelimiterState(n)) + return true; + } + + // We reached the end of file. + stack_.Clear(); + + if (state_ != IterativeParsingFinishState) { + HandleError(state_, is); + return false; + } + + return true; + } + + //! Check if token-by-token parsing JSON text is complete + /*! \return Whether the JSON has been fully decoded. + */ + RAPIDJSON_FORCEINLINE bool IterativeParseComplete() { + return IsIterativeParsingCompleteState(state_); + } + //! Whether a parse error has occured in the last parsing. bool HasParseError() const { return parseResult_.IsError(); } - + //! Get the \ref ParseErrorCode of last parsing. ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); } @@ -462,52 +706,98 @@ private: ClearStackOnExit& operator=(const ClearStackOnExit&); }; + template + void SkipWhitespaceAndComments(InputStream& is) { + SkipWhitespace(is); + + if (parseFlags & kParseCommentsFlag) { + while (RAPIDJSON_UNLIKELY(Consume(is, '/'))) { + if (Consume(is, '*')) { + while (true) { + if (RAPIDJSON_UNLIKELY(is.Peek() == '\0')) + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + else if (Consume(is, '*')) { + if (Consume(is, '/')) + break; + } + else + is.Take(); + } + } + else if (RAPIDJSON_LIKELY(Consume(is, '/'))) + while (is.Peek() != '\0' && is.Take() != '\n') {} + else + RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); + + SkipWhitespace(is); + } + } + } + // Parse object: { string : value, ... } template void ParseObject(InputStream& is, Handler& handler) { RAPIDJSON_ASSERT(is.Peek() == '{'); is.Take(); // Skip '{' - - if (!handler.StartObject()) + + if (RAPIDJSON_UNLIKELY(!handler.StartObject())) RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); - SkipWhitespace(is); + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - if (is.Peek() == '}') { - is.Take(); - if (!handler.EndObject(0)) // empty object + if (Consume(is, '}')) { + if (RAPIDJSON_UNLIKELY(!handler.EndObject(0))) // empty object RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); return; } for (SizeType memberCount = 0;;) { - if (is.Peek() != '"') + if (RAPIDJSON_UNLIKELY(is.Peek() != '"')) RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); ParseString(is, handler, true); RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - SkipWhitespace(is); + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - if (is.Take() != ':') + if (RAPIDJSON_UNLIKELY(!Consume(is, ':'))) RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); - SkipWhitespace(is); + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; ParseValue(is, handler); RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - SkipWhitespace(is); + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; ++memberCount; - switch (is.Take()) { - case ',': SkipWhitespace(is); break; - case '}': - if (!handler.EndObject(memberCount)) + switch (is.Peek()) { + case ',': + is.Take(); + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + break; + case '}': + is.Take(); + if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount))) RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); return; - default: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); + default: + RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); break; // This useless break is only for making warning and coverage happy + } + + if (parseFlags & kParseTrailingCommasFlag) { + if (is.Peek() == '}') { + if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + is.Take(); + return; + } } } } @@ -517,15 +807,15 @@ private: void ParseArray(InputStream& is, Handler& handler) { RAPIDJSON_ASSERT(is.Peek() == '['); is.Take(); // Skip '[' - - if (!handler.StartArray()) - RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); - - SkipWhitespace(is); - if (is.Peek() == ']') { - is.Take(); - if (!handler.EndArray(0)) // empty array + if (RAPIDJSON_UNLIKELY(!handler.StartArray())) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + + if (Consume(is, ']')) { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(0))) // empty array RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); return; } @@ -535,15 +825,28 @@ private: RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; ++elementCount; - SkipWhitespace(is); + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - switch (is.Take()) { - case ',': SkipWhitespace(is); break; - case ']': - if (!handler.EndArray(elementCount)) + if (Consume(is, ',')) { + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; + } + else if (Consume(is, ']')) { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount))) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + return; + } + else + RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); + + if (parseFlags & kParseTrailingCommasFlag) { + if (is.Peek() == ']') { + if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount))) RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); + is.Take(); return; - default: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); + } } } } @@ -553,12 +856,12 @@ private: RAPIDJSON_ASSERT(is.Peek() == 'n'); is.Take(); - if (is.Take() == 'u' && is.Take() == 'l' && is.Take() == 'l') { - if (!handler.Null()) + if (RAPIDJSON_LIKELY(Consume(is, 'u') && Consume(is, 'l') && Consume(is, 'l'))) { + if (RAPIDJSON_UNLIKELY(!handler.Null())) RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); } else - RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1); + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); } template @@ -566,12 +869,12 @@ private: RAPIDJSON_ASSERT(is.Peek() == 't'); is.Take(); - if (is.Take() == 'r' && is.Take() == 'u' && is.Take() == 'e') { - if (!handler.Bool(true)) + if (RAPIDJSON_LIKELY(Consume(is, 'r') && Consume(is, 'u') && Consume(is, 'e'))) { + if (RAPIDJSON_UNLIKELY(!handler.Bool(true))) RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); } else - RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1); + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); } template @@ -579,20 +882,30 @@ private: RAPIDJSON_ASSERT(is.Peek() == 'f'); is.Take(); - if (is.Take() == 'a' && is.Take() == 'l' && is.Take() == 's' && is.Take() == 'e') { - if (!handler.Bool(false)) + if (RAPIDJSON_LIKELY(Consume(is, 'a') && Consume(is, 'l') && Consume(is, 's') && Consume(is, 'e'))) { + if (RAPIDJSON_UNLIKELY(!handler.Bool(false))) RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell()); } else - RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1); + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); + } + + template + RAPIDJSON_FORCEINLINE static bool Consume(InputStream& is, typename InputStream::Ch expect) { + if (RAPIDJSON_LIKELY(is.Peek() == expect)) { + is.Take(); + return true; + } + else + return false; } // Helper function to parse four hexidecimal digits in \uXXXX in ParseString(). template - unsigned ParseHex4(InputStream& is) { + unsigned ParseHex4(InputStream& is, size_t escapeOffset) { unsigned codepoint = 0; for (int i = 0; i < 4; i++) { - Ch c = is.Take(); + Ch c = is.Peek(); codepoint <<= 4; codepoint += static_cast(c); if (c >= '0' && c <= '9') @@ -602,9 +915,10 @@ private: else if (c >= 'a' && c <= 'f') codepoint -= 'a' - 10; else { - RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, is.Tell() - 1); + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, escapeOffset); RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0); } + is.Take(); } return codepoint; } @@ -619,7 +933,14 @@ private: *stack_.template Push() = c; ++length_; } + + RAPIDJSON_FORCEINLINE void* Push(SizeType count) { + length_ += count; + return stack_.template Push(count); + } + size_t Length() const { return length_; } + Ch* Pop() { return stack_.template Pop(length_); } @@ -638,6 +959,9 @@ private: internal::StreamLocalCopy copy(is); InputStream& s(copy.s); + RAPIDJSON_ASSERT(s.Peek() == '\"'); + s.Take(); // Skip '\"' + bool success = false; if (parseFlags & kParseInsituFlag) { typename InputStream::Ch *head = s.PutBegin(); @@ -645,7 +969,7 @@ private: RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; size_t length = s.PutEnd(head) - 1; RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); - const typename TargetEncoding::Ch* const str = (typename TargetEncoding::Ch*)head; + const typename TargetEncoding::Ch* const str = reinterpret_cast(head); success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false)); } else { @@ -656,7 +980,7 @@ private: const typename TargetEncoding::Ch* const str = stackStream.Pop(); success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true)); } - if (!success) + if (RAPIDJSON_UNLIKELY(!success)) RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); } @@ -667,74 +991,421 @@ private: //!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 static const char escape[256] = { - Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/', - Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, - 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, - 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/', + Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, + 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, + 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 }; #undef Z16 //!@endcond - RAPIDJSON_ASSERT(is.Peek() == '\"'); - is.Take(); // Skip '\"' - for (;;) { + // Scan and copy string before "\\\"" or < 0x20. This is an optional optimzation. + if (!(parseFlags & kParseValidateEncodingFlag)) + ScanCopyUnescapedString(is, os); + Ch c = is.Peek(); - if (c == '\\') { // Escape + if (RAPIDJSON_UNLIKELY(c == '\\')) { // Escape + size_t escapeOffset = is.Tell(); // For invalid escaping, report the inital '\\' as error offset is.Take(); - Ch e = is.Take(); - if ((sizeof(Ch) == 1 || unsigned(e) < 256) && escape[(unsigned char)e]) { - os.Put(escape[(unsigned char)e]); + Ch e = is.Peek(); + if ((sizeof(Ch) == 1 || unsigned(e) < 256) && RAPIDJSON_LIKELY(escape[static_cast(e)])) { + is.Take(); + os.Put(static_cast(escape[static_cast(e)])); } - else if (e == 'u') { // Unicode - unsigned codepoint = ParseHex4(is); + else if (RAPIDJSON_LIKELY(e == 'u')) { // Unicode + is.Take(); + unsigned codepoint = ParseHex4(is, escapeOffset); RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - if (codepoint >= 0xD800 && codepoint <= 0xDBFF) { + if (RAPIDJSON_UNLIKELY(codepoint >= 0xD800 && codepoint <= 0xDBFF)) { // Handle UTF-16 surrogate pair - if (is.Take() != '\\' || is.Take() != 'u') - RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2); - unsigned codepoint2 = ParseHex4(is); + if (RAPIDJSON_UNLIKELY(!Consume(is, '\\') || !Consume(is, 'u'))) + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); + unsigned codepoint2 = ParseHex4(is, escapeOffset); RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF) - RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2); + if (RAPIDJSON_UNLIKELY(codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)) + RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, escapeOffset); codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000; } TEncoding::Encode(os, codepoint); } else - RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1); + RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, escapeOffset); } - else if (c == '"') { // Closing double quote + else if (RAPIDJSON_UNLIKELY(c == '"')) { // Closing double quote is.Take(); os.Put('\0'); // null-terminate the string return; } - else if (c == '\0') - RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell() - 1); - else if ((unsigned)c < 0x20) // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF - RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1); - else { - if (parseFlags & kParseValidateEncodingFlag ? - !Transcoder::Validate(is, os) : - !Transcoder::Transcode(is, os)) + else if (RAPIDJSON_UNLIKELY(static_cast(c) < 0x20)) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF + if (c == '\0') + RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell()); + else RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell()); } + else { + size_t offset = is.Tell(); + if (RAPIDJSON_UNLIKELY((parseFlags & kParseValidateEncodingFlag ? + !Transcoder::Validate(is, os) : + !Transcoder::Transcode(is, os)))) + RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, offset); + } } } - template + template + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InputStream&, OutputStream&) { + // Do nothing for generic version + } + +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) + // StringStream -> StackStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream& os) { + const char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = p; + return; + } + else + os.Put(*p++); + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + SizeType length; + #ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; + #else + length = static_cast(__builtin_ffs(r) - 1); + #endif + if (length != 0) { + char* q = reinterpret_cast(os.Push(length)); + for (size_t i = 0; i < length; i++) + q[i] = p[i]; + + p += length; + } + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s); + } + + is.src_ = p; + } + + // InsituStringStream -> InsituStringStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) { + RAPIDJSON_ASSERT(&is == &os); + (void)os; + + if (is.src_ == is.dst_) { + SkipUnescapedString(is); + return; + } + + char* p = is.src_; + char *q = is.dst_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = p; + is.dst_ = q; + return; + } + else + *q++ = *p++; + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (;; p += 16, q += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + size_t length; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; +#else + length = static_cast(__builtin_ffs(r) - 1); +#endif + for (const char* pend = p + length; p != pend; ) + *q++ = *p++; + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(q), s); + } + + is.src_ = p; + is.dst_ = q; + } + + // When read/write pointers are the same for insitu stream, just skip unescaped characters + static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) { + RAPIDJSON_ASSERT(is.src_ == is.dst_); + char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + for (; p != nextAligned; p++) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = is.dst_ = p; + return; + } + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (;; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + size_t length; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + length = offset; +#else + length = static_cast(__builtin_ffs(r) - 1); +#endif + p += length; + break; + } + } + + is.src_ = is.dst_ = p; + } +#elif defined(RAPIDJSON_NEON) + // StringStream -> StackStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream& os) { + const char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = p; + return; + } + else + os.Put(*p++); + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (;; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(reinterpret_cast(x), 0); // extract + uint64_t high = vgetq_lane_u64(reinterpret_cast(x), 1); // extract + + SizeType length = 0; + bool escaped = false; + if (low == 0) { + if (high != 0) { + unsigned lz = (unsigned)__builtin_clzll(high);; + length = 8 + (lz >> 3); + escaped = true; + } + } else { + unsigned lz = (unsigned)__builtin_clzll(low);; + length = lz >> 3; + escaped = true; + } + if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped + if (length != 0) { + char* q = reinterpret_cast(os.Push(length)); + for (size_t i = 0; i < length; i++) + q[i] = p[i]; + + p += length; + } + break; + } + vst1q_u8(reinterpret_cast(os.Push(16)), s); + } + + is.src_ = p; + } + + // InsituStringStream -> InsituStringStream + static RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) { + RAPIDJSON_ASSERT(&is == &os); + (void)os; + + if (is.src_ == is.dst_) { + SkipUnescapedString(is); + return; + } + + char* p = is.src_; + char *q = is.dst_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + while (p != nextAligned) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = p; + is.dst_ = q; + return; + } + else + *q++ = *p++; + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (;; p += 16, q += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(reinterpret_cast(x), 0); // extract + uint64_t high = vgetq_lane_u64(reinterpret_cast(x), 1); // extract + + SizeType length = 0; + bool escaped = false; + if (low == 0) { + if (high != 0) { + unsigned lz = (unsigned)__builtin_clzll(high); + length = 8 + (lz >> 3); + escaped = true; + } + } else { + unsigned lz = (unsigned)__builtin_clzll(low); + length = lz >> 3; + escaped = true; + } + if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped + for (const char* pend = p + length; p != pend; ) { + *q++ = *p++; + } + break; + } + vst1q_u8(reinterpret_cast(q), s); + } + + is.src_ = p; + is.dst_ = q; + } + + // When read/write pointers are the same for insitu stream, just skip unescaped characters + static RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) { + RAPIDJSON_ASSERT(is.src_ == is.dst_); + char* p = is.src_; + + // Scan one by one until alignment (unaligned load may cross page boundary and cause crash) + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + for (; p != nextAligned; p++) + if (RAPIDJSON_UNLIKELY(*p == '\"') || RAPIDJSON_UNLIKELY(*p == '\\') || RAPIDJSON_UNLIKELY(static_cast(*p) < 0x20)) { + is.src_ = is.dst_ = p; + return; + } + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (;; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(reinterpret_cast(x), 0); // extract + uint64_t high = vgetq_lane_u64(reinterpret_cast(x), 1); // extract + + if (low == 0) { + if (high != 0) { + int lz = __builtin_clzll(high); + p += 8 + (lz >> 3); + break; + } + } else { + int lz = __builtin_clzll(low); + p += lz >> 3; + break; + } + } + + is.src_ = is.dst_ = p; + } +#endif // RAPIDJSON_NEON + + template class NumberStream; template - class NumberStream { + class NumberStream { public: + typedef typename InputStream::Ch Ch; + NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; } - ~NumberStream() {} RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); } RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); } RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); } + RAPIDJSON_FORCEINLINE void Push(char) {} + size_t Tell() { return is.Tell(); } size_t Length() { return 0; } const char* Pop() { return 0; } @@ -746,17 +1417,20 @@ private: }; template - class NumberStream : public NumberStream { - typedef NumberStream Base; + class NumberStream : public NumberStream { + typedef NumberStream Base; public: - NumberStream(GenericReader& reader, InputStream& is) : NumberStream(reader, is), stackStream(reader.stack_) {} - ~NumberStream() {} + NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is), stackStream(reader.stack_) {} RAPIDJSON_FORCEINLINE Ch TakePush() { - stackStream.Put((char)Base::is.Peek()); + stackStream.Put(static_cast(Base::is.Peek())); return Base::is.Take(); } + RAPIDJSON_FORCEINLINE void Push(char c) { + stackStream.Put(c); + } + size_t Length() { return stackStream.Length(); } const char* Pop() { @@ -768,34 +1442,48 @@ private: StackStream stackStream; }; + template + class NumberStream : public NumberStream { + typedef NumberStream Base; + public: + NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {} + + RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); } + }; + template void ParseNumber(InputStream& is, Handler& handler) { internal::StreamLocalCopy copy(is); - NumberStream s(*this, copy.s); + NumberStream s(*this, copy.s); + + size_t startOffset = s.Tell(); + double d = 0.0; + bool useNanOrInf = false; // Parse minus - bool minus = false; - if (s.Peek() == '-') { - minus = true; - s.Take(); - } + bool minus = Consume(s, '-'); // Parse int: zero / ( digit1-9 *DIGIT ) unsigned i = 0; uint64_t i64 = 0; bool use64bit = false; int significandDigit = 0; - if (s.Peek() == '0') { + if (RAPIDJSON_UNLIKELY(s.Peek() == '0')) { i = 0; s.TakePush(); } - else if (s.Peek() >= '1' && s.Peek() <= '9') { + else if (RAPIDJSON_LIKELY(s.Peek() >= '1' && s.Peek() <= '9')) { i = static_cast(s.TakePush() - '0'); if (minus) - while (s.Peek() >= '0' && s.Peek() <= '9') { - if (i >= 214748364) { // 2^31 = 2147483648 - if (i != 214748364 || s.Peek() > '8') { + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i >= 214748364)) { // 2^31 = 2147483648 + if (RAPIDJSON_LIKELY(i != 214748364 || s.Peek() > '8')) { i64 = i; use64bit = true; break; @@ -805,9 +1493,9 @@ private: significandDigit++; } else - while (s.Peek() >= '0' && s.Peek() <= '9') { - if (i >= 429496729) { // 2^32 - 1 = 4294967295 - if (i != 429496729 || s.Peek() > '5') { + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i >= 429496729)) { // 2^32 - 1 = 4294967295 + if (RAPIDJSON_LIKELY(i != 429496729 || s.Peek() > '5')) { i64 = i; use64bit = true; break; @@ -817,18 +1505,41 @@ private: significandDigit++; } } + // Parse NaN or Infinity here + else if ((parseFlags & kParseNanAndInfFlag) && RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) { + if (Consume(s, 'N')) { + if (Consume(s, 'a') && Consume(s, 'N')) { + d = std::numeric_limits::quiet_NaN(); + useNanOrInf = true; + } + } + else if (RAPIDJSON_LIKELY(Consume(s, 'I'))) { + if (Consume(s, 'n') && Consume(s, 'f')) { + d = (minus ? -std::numeric_limits::infinity() : std::numeric_limits::infinity()); + useNanOrInf = true; + + if (RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n') + && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) { + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + } + } + } + + if (RAPIDJSON_UNLIKELY(!useNanOrInf)) { + RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); + } + } else RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); // Parse 64bit int bool useDouble = false; - double d = 0.0; if (use64bit) { - if (minus) - while (s.Peek() >= '0' && s.Peek() <= '9') { - if (i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC)) // 2^63 = 9223372036854775808 - if (i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8') { - d = i64; + if (minus) + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC))) // 2^63 = 9223372036854775808 + if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8')) { + d = static_cast(i64); useDouble = true; break; } @@ -836,10 +1547,10 @@ private: significandDigit++; } else - while (s.Peek() >= '0' && s.Peek() <= '9') { - if (i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999)) // 2^64 - 1 = 18446744073709551615 - if (i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5') { - d = i64; + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999))) // 2^64 - 1 = 18446744073709551615 + if (RAPIDJSON_LIKELY(i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5')) { + d = static_cast(i64); useDouble = true; break; } @@ -850,9 +1561,9 @@ private: // Force double for big integer if (useDouble) { - while (s.Peek() >= '0' && s.Peek() <= '9') { - if (d >= 1.7976931348623157e307) // DBL_MAX / 10.0 - RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell()); + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + if (RAPIDJSON_UNLIKELY(d >= 1.7976931348623157e307)) // DBL_MAX / 10.0 + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset); d = d * 10 + (s.TakePush() - '0'); } } @@ -860,11 +1571,10 @@ private: // Parse frac = decimal-point 1*DIGIT int expFrac = 0; size_t decimalPosition; - if (s.Peek() == '.') { - s.Take(); + if (Consume(s, '.')) { decimalPosition = s.Length(); - if (!(s.Peek() >= '0' && s.Peek() <= '9')) + if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9'))) RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell()); if (!useDouble) { @@ -872,8 +1582,8 @@ private: // Use i64 to store significand in 64-bit architecture if (!use64bit) i64 = i; - - while (s.Peek() >= '0' && s.Peek() <= '9') { + + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path break; else { @@ -884,19 +1594,19 @@ private: } } - d = (double)i64; + d = static_cast(i64); #else // Use double to store significand in 32-bit architecture - d = use64bit ? (double)i64 : (double)i; + d = static_cast(use64bit ? i64 : i); #endif useDouble = true; } - while (s.Peek() >= '0' && s.Peek() <= '9') { + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { if (significandDigit < 17) { d = d * 10.0 + (s.TakePush() - '0'); --expFrac; - if (d > 0.0) + if (RAPIDJSON_LIKELY(d > 0.0)) significandDigit++; } else @@ -908,38 +1618,35 @@ private: // Parse exp = e [ minus / plus ] 1*DIGIT int exp = 0; - if (s.Peek() == 'e' || s.Peek() == 'E') { + if (Consume(s, 'e') || Consume(s, 'E')) { if (!useDouble) { - d = use64bit ? i64 : i; + d = static_cast(use64bit ? i64 : i); useDouble = true; } - s.Take(); bool expMinus = false; - if (s.Peek() == '+') - s.Take(); - else if (s.Peek() == '-') { - s.Take(); + if (Consume(s, '+')) + ; + else if (Consume(s, '-')) expMinus = true; - } - if (s.Peek() >= '0' && s.Peek() <= '9') { - exp = s.Take() - '0'; + if (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = static_cast(s.Take() - '0'); if (expMinus) { - while (s.Peek() >= '0' && s.Peek() <= '9') { - exp = exp * 10 + (s.Take() - '0'); + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = exp * 10 + static_cast(s.Take() - '0'); if (exp >= 214748364) { // Issue #313: prevent overflow exponent - while (s.Peek() >= '0' && s.Peek() <= '9') // Consume the rest of exponent + while (RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent s.Take(); } } } else { // positive exp int maxExp = 308 - expFrac; - while (s.Peek() >= '0' && s.Peek() <= '9') { - exp = exp * 10 + (s.Take() - '0'); - if (exp > maxExp) - RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell()); + while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { + exp = exp * 10 + static_cast(s.Take() - '0'); + if (RAPIDJSON_UNLIKELY(exp > maxExp)) + RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset); } } } @@ -952,34 +1659,63 @@ private: // Finish parsing, call event according to the type of number. bool cont = true; - size_t length = s.Length(); - const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not. - if (useDouble) { - int p = exp + expFrac; - if (parseFlags & kParseFullPrecisionFlag) - d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp); - else - d = internal::StrtodNormalPrecision(d, p); - - cont = handler.Double(minus ? -d : d); - } - else { - if (use64bit) { - if (minus) - cont = handler.Int64(-(int64_t)i64); - else - cont = handler.Uint64(i64); + if (parseFlags & kParseNumbersAsStringsFlag) { + if (parseFlags & kParseInsituFlag) { + s.Pop(); // Pop stack no matter if it will be used or not. + typename InputStream::Ch* head = is.PutBegin(); + const size_t length = s.Tell() - startOffset; + RAPIDJSON_ASSERT(length <= 0xFFFFFFFF); + // unable to insert the \0 character here, it will erase the comma after this number + const typename TargetEncoding::Ch* const str = reinterpret_cast(head); + cont = handler.RawNumber(str, SizeType(length), false); } else { - if (minus) - cont = handler.Int(-(int)i); - else - cont = handler.Uint(i); + SizeType numCharsToCopy = static_cast(s.Length()); + StringStream srcStream(s.Pop()); + StackStream dstStream(stack_); + while (numCharsToCopy--) { + Transcoder, TargetEncoding>::Transcode(srcStream, dstStream); + } + dstStream.Put('\0'); + const typename TargetEncoding::Ch* str = dstStream.Pop(); + const SizeType length = static_cast(dstStream.Length()) - 1; + cont = handler.RawNumber(str, SizeType(length), true); } } - if (!cont) - RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); + else { + size_t length = s.Length(); + const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not. + + if (useDouble) { + int p = exp + expFrac; + if (parseFlags & kParseFullPrecisionFlag) + d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp); + else + d = internal::StrtodNormalPrecision(d, p); + + cont = handler.Double(minus ? -d : d); + } + else if (useNanOrInf) { + cont = handler.Double(d); + } + else { + if (use64bit) { + if (minus) + cont = handler.Int64(static_cast(~i64 + 1)); + else + cont = handler.Uint64(i64); + } + else { + if (minus) + cont = handler.Int(static_cast(~i + 1)); + else + cont = handler.Uint(i); + } + } + } + if (RAPIDJSON_UNLIKELY(!cont)) + RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset); } // Parse any JSON value @@ -992,7 +1728,10 @@ private: case '"': ParseString(is, handler); break; case '{': ParseObject(is, handler); break; case '[': ParseArray (is, handler); break; - default : ParseNumber(is, handler); + default : + ParseNumber(is, handler); + break; + } } @@ -1000,27 +1739,29 @@ private: // States enum IterativeParsingState { - IterativeParsingStartState = 0, - IterativeParsingFinishState, - IterativeParsingErrorState, + IterativeParsingFinishState = 0, // sink states at top + IterativeParsingErrorState, // sink states at top + IterativeParsingStartState, // Object states IterativeParsingObjectInitialState, IterativeParsingMemberKeyState, - IterativeParsingKeyValueDelimiterState, IterativeParsingMemberValueState, - IterativeParsingMemberDelimiterState, IterativeParsingObjectFinishState, // Array states IterativeParsingArrayInitialState, IterativeParsingElementState, - IterativeParsingElementDelimiterState, IterativeParsingArrayFinishState, // Single value state IterativeParsingValueState, - + + // Delimiter states (at bottom) + IterativeParsingElementDelimiterState, + IterativeParsingMemberDelimiterState, + IterativeParsingKeyValueDelimiterState, + cIterativeParsingStateCount }; @@ -1064,9 +1805,9 @@ private: #undef N #undef N16 //!@endcond - - if (sizeof(Ch) == 1 || unsigned(c) < 256) - return (Token)tokenMap[(unsigned char)c]; + + if (sizeof(Ch) == 1 || static_cast(c) < 256) + return static_cast(tokenMap[static_cast(c)]); else return NumberToken; } @@ -1074,6 +1815,18 @@ private: RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) { // current state x one lookahead token -> new state static const char G[cIterativeParsingStateCount][kTokenCount] = { + // Finish(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, + // Error(sink state) + { + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, + IterativeParsingErrorState + }, // Start { IterativeParsingArrayInitialState, // Left bracket @@ -1088,18 +1841,6 @@ private: IterativeParsingValueState, // Null IterativeParsingValueState // Number }, - // Finish(sink state) - { - IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, - IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, - IterativeParsingErrorState - }, - // Error(sink state) - { - IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, - IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, - IterativeParsingErrorState - }, // ObjectInitial { IterativeParsingErrorState, // Left bracket @@ -1128,20 +1869,6 @@ private: IterativeParsingErrorState, // Null IterativeParsingErrorState // Number }, - // KeyValueDelimiter - { - IterativeParsingArrayInitialState, // Left bracket(push MemberValue state) - IterativeParsingErrorState, // Right bracket - IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state) - IterativeParsingErrorState, // Right curly bracket - IterativeParsingErrorState, // Comma - IterativeParsingErrorState, // Colon - IterativeParsingMemberValueState, // String - IterativeParsingMemberValueState, // False - IterativeParsingMemberValueState, // True - IterativeParsingMemberValueState, // Null - IterativeParsingMemberValueState // Number - }, // MemberValue { IterativeParsingErrorState, // Left bracket @@ -1156,20 +1883,6 @@ private: IterativeParsingErrorState, // Null IterativeParsingErrorState // Number }, - // MemberDelimiter - { - IterativeParsingErrorState, // Left bracket - IterativeParsingErrorState, // Right bracket - IterativeParsingErrorState, // Left curly bracket - IterativeParsingErrorState, // Right curly bracket - IterativeParsingErrorState, // Comma - IterativeParsingErrorState, // Colon - IterativeParsingMemberKeyState, // String - IterativeParsingErrorState, // False - IterativeParsingErrorState, // True - IterativeParsingErrorState, // Null - IterativeParsingErrorState // Number - }, // ObjectFinish(sink state) { IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, @@ -1204,20 +1917,6 @@ private: IterativeParsingErrorState, // Null IterativeParsingErrorState // Number }, - // ElementDelimiter - { - IterativeParsingArrayInitialState, // Left bracket(push Element state) - IterativeParsingErrorState, // Right bracket - IterativeParsingObjectInitialState, // Left curly bracket(push Element state) - IterativeParsingErrorState, // Right curly bracket - IterativeParsingErrorState, // Comma - IterativeParsingErrorState, // Colon - IterativeParsingElementState, // String - IterativeParsingElementState, // False - IterativeParsingElementState, // True - IterativeParsingElementState, // Null - IterativeParsingElementState // Number - }, // ArrayFinish(sink state) { IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, @@ -1229,10 +1928,52 @@ private: IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState - } + }, + // ElementDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push Element state) + IterativeParsingArrayFinishState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push Element state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingElementState, // String + IterativeParsingElementState, // False + IterativeParsingElementState, // True + IterativeParsingElementState, // Null + IterativeParsingElementState // Number + }, + // MemberDelimiter + { + IterativeParsingErrorState, // Left bracket + IterativeParsingErrorState, // Right bracket + IterativeParsingErrorState, // Left curly bracket + IterativeParsingObjectFinishState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberKeyState, // String + IterativeParsingErrorState, // False + IterativeParsingErrorState, // True + IterativeParsingErrorState, // Null + IterativeParsingErrorState // Number + }, + // KeyValueDelimiter + { + IterativeParsingArrayInitialState, // Left bracket(push MemberValue state) + IterativeParsingErrorState, // Right bracket + IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state) + IterativeParsingErrorState, // Right curly bracket + IterativeParsingErrorState, // Comma + IterativeParsingErrorState, // Colon + IterativeParsingMemberValueState, // String + IterativeParsingMemberValueState, // False + IterativeParsingMemberValueState, // True + IterativeParsingMemberValueState, // Null + IterativeParsingMemberValueState // Number + }, }; // End of G - return (IterativeParsingState)G[state][token]; + return static_cast(G[state][token]); } // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit(). @@ -1309,6 +2050,11 @@ private: case IterativeParsingObjectFinishState: { + // Transit from delimiter is only allowed when trailing commas are enabled + if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingMemberDelimiterState) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorObjectMissName, is.Tell()); + return IterativeParsingErrorState; + } // Get member count. SizeType c = *stack_.template Pop(1); // If the object is not empty, count the last member. @@ -1334,6 +2080,11 @@ private: case IterativeParsingArrayFinishState: { + // Transit from delimiter is only allowed when trailing commas are enabled + if (!(parseFlags & kParseTrailingCommasFlag) && src == IterativeParsingElementDelimiterState) { + RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorValueInvalid, is.Tell()); + return IterativeParsingErrorState; + } // Get element count. SizeType c = *stack_.template Pop(1); // If the array is not empty, count the last element. @@ -1385,55 +2136,68 @@ private: // Error flag has been set. return; } - + switch (src) { - case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); - case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); + case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return; + case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return; case IterativeParsingObjectInitialState: - case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); - case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); - case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); - case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); - default: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); - } + case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return; + case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return; + case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return; + case IterativeParsingKeyValueDelimiterState: + case IterativeParsingArrayInitialState: + case IterativeParsingElementDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell()); return; + default: RAPIDJSON_ASSERT(src == IterativeParsingElementState); RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return; + } } + RAPIDJSON_FORCEINLINE bool IsIterativeParsingDelimiterState(IterativeParsingState s) { + return s >= IterativeParsingElementDelimiterState; + } + + RAPIDJSON_FORCEINLINE bool IsIterativeParsingCompleteState(IterativeParsingState s) { + return s <= IterativeParsingErrorState; + } + template ParseResult IterativeParse(InputStream& is, Handler& handler) { parseResult_.Clear(); ClearStackOnExit scope(*this); IterativeParsingState state = IterativeParsingStartState; - - SkipWhitespace(is); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); while (is.Peek() != '\0') { Token t = Tokenize(is.Peek()); IterativeParsingState n = Predict(state, t); IterativeParsingState d = Transit(state, t, n, is, handler); - + if (d == IterativeParsingErrorState) { HandleError(state, is); break; } - + state = d; - + // Do not further consume streams if a root JSON has been parsed. if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState) break; - - SkipWhitespace(is); + + SkipWhitespaceAndComments(is); + RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_); } - + // Handle the end of file. if (state != IterativeParsingFinishState) HandleError(state, is); - + return parseResult_; } static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. internal::Stack stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. ParseResult parseResult_; + IterativeParsingState state_; }; // class GenericReader //! Reader with UTF8 encoding and default allocator. @@ -1441,6 +2205,11 @@ typedef GenericReader, UTF8<> > Reader; RAPIDJSON_NAMESPACE_END +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + + #ifdef __GNUC__ RAPIDJSON_DIAG_POP #endif diff --git a/contrib/rapidjson/include/rapidjson/schema.h b/contrib/rapidjson/include/rapidjson/schema.h new file mode 100644 index 000000000..abcf1a102 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/schema.h @@ -0,0 +1,2016 @@ +// Tencent is pleased to support the open source community by making RapidJSON available-> +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip-> All rights reserved-> +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License-> You may obtain a copy of the License at +// +// http://opensource->org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied-> See the License for the +// specific language governing permissions and limitations under the License-> + +#ifndef RAPIDJSON_SCHEMA_H_ +#define RAPIDJSON_SCHEMA_H_ + +#include "document.h" +#include "pointer.h" +#include // abs, floor + +#if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX) +#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1 +#else +#define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0 +#endif + +#if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && !defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)) +#define RAPIDJSON_SCHEMA_USE_STDREGEX 1 +#else +#define RAPIDJSON_SCHEMA_USE_STDREGEX 0 +#endif + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX +#include "internal/regex.h" +#elif RAPIDJSON_SCHEMA_USE_STDREGEX +#include +#endif + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX || RAPIDJSON_SCHEMA_USE_STDREGEX +#define RAPIDJSON_SCHEMA_HAS_REGEX 1 +#else +#define RAPIDJSON_SCHEMA_HAS_REGEX 0 +#endif + +#ifndef RAPIDJSON_SCHEMA_VERBOSE +#define RAPIDJSON_SCHEMA_VERBOSE 0 +#endif + +#if RAPIDJSON_SCHEMA_VERBOSE +#include "stringbuffer.h" +#endif + +RAPIDJSON_DIAG_PUSH + +#if defined(__GNUC__) +RAPIDJSON_DIAG_OFF(effc++) +#endif + +#ifdef __clang__ +RAPIDJSON_DIAG_OFF(weak-vtables) +RAPIDJSON_DIAG_OFF(exit-time-destructors) +RAPIDJSON_DIAG_OFF(c++98-compat-pedantic) +RAPIDJSON_DIAG_OFF(variadic-macros) +#endif + +#ifdef _MSC_VER +RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated +#endif + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Verbose Utilities + +#if RAPIDJSON_SCHEMA_VERBOSE + +namespace internal { + +inline void PrintInvalidKeyword(const char* keyword) { + printf("Fail keyword: %s\n", keyword); +} + +inline void PrintInvalidKeyword(const wchar_t* keyword) { + wprintf(L"Fail keyword: %ls\n", keyword); +} + +inline void PrintInvalidDocument(const char* document) { + printf("Fail document: %s\n\n", document); +} + +inline void PrintInvalidDocument(const wchar_t* document) { + wprintf(L"Fail document: %ls\n\n", document); +} + +inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) { + printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d); +} + +inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) { + wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d); +} + +} // namespace internal + +#endif // RAPIDJSON_SCHEMA_VERBOSE + +/////////////////////////////////////////////////////////////////////////////// +// RAPIDJSON_INVALID_KEYWORD_RETURN + +#if RAPIDJSON_SCHEMA_VERBOSE +#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) internal::PrintInvalidKeyword(keyword) +#else +#define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) +#endif + +#define RAPIDJSON_INVALID_KEYWORD_RETURN(keyword)\ +RAPIDJSON_MULTILINEMACRO_BEGIN\ + context.invalidKeyword = keyword.GetString();\ + RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword.GetString());\ + return false;\ +RAPIDJSON_MULTILINEMACRO_END + +/////////////////////////////////////////////////////////////////////////////// +// Forward declarations + +template +class GenericSchemaDocument; + +namespace internal { + +template +class Schema; + +/////////////////////////////////////////////////////////////////////////////// +// ISchemaValidator + +class ISchemaValidator { +public: + virtual ~ISchemaValidator() {} + virtual bool IsValid() const = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// +// ISchemaStateFactory + +template +class ISchemaStateFactory { +public: + virtual ~ISchemaStateFactory() {} + virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&) = 0; + virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0; + virtual void* CreateHasher() = 0; + virtual uint64_t GetHashCode(void* hasher) = 0; + virtual void DestroryHasher(void* hasher) = 0; + virtual void* MallocState(size_t size) = 0; + virtual void FreeState(void* p) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Hasher + +// For comparison of compound value +template +class Hasher { +public: + typedef typename Encoding::Ch Ch; + + Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {} + + bool Null() { return WriteType(kNullType); } + bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); } + bool Int(int i) { Number n; n.u.i = i; n.d = static_cast(i); return WriteNumber(n); } + bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast(u); return WriteNumber(n); } + bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast(i); return WriteNumber(n); } + bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast(u); return WriteNumber(n); } + bool Double(double d) { + Number n; + if (d < 0) n.u.i = static_cast(d); + else n.u.u = static_cast(d); + n.d = d; + return WriteNumber(n); + } + + bool RawNumber(const Ch* str, SizeType len, bool) { + WriteBuffer(kNumberType, str, len * sizeof(Ch)); + return true; + } + + bool String(const Ch* str, SizeType len, bool) { + WriteBuffer(kStringType, str, len * sizeof(Ch)); + return true; + } + + bool StartObject() { return true; } + bool Key(const Ch* str, SizeType len, bool copy) { return String(str, len, copy); } + bool EndObject(SizeType memberCount) { + uint64_t h = Hash(0, kObjectType); + uint64_t* kv = stack_.template Pop(memberCount * 2); + for (SizeType i = 0; i < memberCount; i++) + h ^= Hash(kv[i * 2], kv[i * 2 + 1]); // Use xor to achieve member order insensitive + *stack_.template Push() = h; + return true; + } + + bool StartArray() { return true; } + bool EndArray(SizeType elementCount) { + uint64_t h = Hash(0, kArrayType); + uint64_t* e = stack_.template Pop(elementCount); + for (SizeType i = 0; i < elementCount; i++) + h = Hash(h, e[i]); // Use hash to achieve element order sensitive + *stack_.template Push() = h; + return true; + } + + bool IsValid() const { return stack_.GetSize() == sizeof(uint64_t); } + + uint64_t GetHashCode() const { + RAPIDJSON_ASSERT(IsValid()); + return *stack_.template Top(); + } + +private: + static const size_t kDefaultSize = 256; + struct Number { + union U { + uint64_t u; + int64_t i; + }u; + double d; + }; + + bool WriteType(Type type) { return WriteBuffer(type, 0, 0); } + + bool WriteNumber(const Number& n) { return WriteBuffer(kNumberType, &n, sizeof(n)); } + + bool WriteBuffer(Type type, const void* data, size_t len) { + // FNV-1a from http://isthe.com/chongo/tech/comp/fnv/ + uint64_t h = Hash(RAPIDJSON_UINT64_C2(0x84222325, 0xcbf29ce4), type); + const unsigned char* d = static_cast(data); + for (size_t i = 0; i < len; i++) + h = Hash(h, d[i]); + *stack_.template Push() = h; + return true; + } + + static uint64_t Hash(uint64_t h, uint64_t d) { + static const uint64_t kPrime = RAPIDJSON_UINT64_C2(0x00000100, 0x000001b3); + h ^= d; + h *= kPrime; + return h; + } + + Stack stack_; +}; + +/////////////////////////////////////////////////////////////////////////////// +// SchemaValidationContext + +template +struct SchemaValidationContext { + typedef Schema SchemaType; + typedef ISchemaStateFactory SchemaValidatorFactoryType; + typedef typename SchemaType::ValueType ValueType; + typedef typename ValueType::Ch Ch; + + enum PatternValidatorType { + kPatternValidatorOnly, + kPatternValidatorWithProperty, + kPatternValidatorWithAdditionalProperty + }; + + SchemaValidationContext(SchemaValidatorFactoryType& f, const SchemaType* s) : + factory(f), + schema(s), + valueSchema(), + invalidKeyword(), + hasher(), + arrayElementHashCodes(), + validators(), + validatorCount(), + patternPropertiesValidators(), + patternPropertiesValidatorCount(), + patternPropertiesSchemas(), + patternPropertiesSchemaCount(), + valuePatternValidatorType(kPatternValidatorOnly), + propertyExist(), + inArray(false), + valueUniqueness(false), + arrayUniqueness(false) + { + } + + ~SchemaValidationContext() { + if (hasher) + factory.DestroryHasher(hasher); + if (validators) { + for (SizeType i = 0; i < validatorCount; i++) + factory.DestroySchemaValidator(validators[i]); + factory.FreeState(validators); + } + if (patternPropertiesValidators) { + for (SizeType i = 0; i < patternPropertiesValidatorCount; i++) + factory.DestroySchemaValidator(patternPropertiesValidators[i]); + factory.FreeState(patternPropertiesValidators); + } + if (patternPropertiesSchemas) + factory.FreeState(patternPropertiesSchemas); + if (propertyExist) + factory.FreeState(propertyExist); + } + + SchemaValidatorFactoryType& factory; + const SchemaType* schema; + const SchemaType* valueSchema; + const Ch* invalidKeyword; + void* hasher; // Only validator access + void* arrayElementHashCodes; // Only validator access this + ISchemaValidator** validators; + SizeType validatorCount; + ISchemaValidator** patternPropertiesValidators; + SizeType patternPropertiesValidatorCount; + const SchemaType** patternPropertiesSchemas; + SizeType patternPropertiesSchemaCount; + PatternValidatorType valuePatternValidatorType; + PatternValidatorType objectPatternValidatorType; + SizeType arrayElementIndex; + bool* propertyExist; + bool inArray; + bool valueUniqueness; + bool arrayUniqueness; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Schema + +template +class Schema { +public: + typedef typename SchemaDocumentType::ValueType ValueType; + typedef typename SchemaDocumentType::AllocatorType AllocatorType; + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; + typedef SchemaValidationContext Context; + typedef Schema SchemaType; + typedef GenericValue SValue; + friend class GenericSchemaDocument; + + Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) : + allocator_(allocator), + typeless_(schemaDocument->GetTypeless()), + enum_(), + enumCount_(), + not_(), + type_((1 << kTotalSchemaType) - 1), // typeless + validatorCount_(), + properties_(), + additionalPropertiesSchema_(), + patternProperties_(), + patternPropertyCount_(), + propertyCount_(), + minProperties_(), + maxProperties_(SizeType(~0)), + additionalProperties_(true), + hasDependencies_(), + hasRequired_(), + hasSchemaDependencies_(), + additionalItemsSchema_(), + itemsList_(), + itemsTuple_(), + itemsTupleCount_(), + minItems_(), + maxItems_(SizeType(~0)), + additionalItems_(true), + uniqueItems_(false), + pattern_(), + minLength_(0), + maxLength_(~SizeType(0)), + exclusiveMinimum_(false), + exclusiveMaximum_(false) + { + typedef typename SchemaDocumentType::ValueType ValueType; + typedef typename ValueType::ConstValueIterator ConstValueIterator; + typedef typename ValueType::ConstMemberIterator ConstMemberIterator; + + if (!value.IsObject()) + return; + + if (const ValueType* v = GetMember(value, GetTypeString())) { + type_ = 0; + if (v->IsString()) + AddType(*v); + else if (v->IsArray()) + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) + AddType(*itr); + } + + if (const ValueType* v = GetMember(value, GetEnumString())) + if (v->IsArray() && v->Size() > 0) { + enum_ = static_cast(allocator_->Malloc(sizeof(uint64_t) * v->Size())); + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) { + typedef Hasher > EnumHasherType; + char buffer[256 + 24]; + MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer)); + EnumHasherType h(&hasherAllocator, 256); + itr->Accept(h); + enum_[enumCount_++] = h.GetHashCode(); + } + } + + if (schemaDocument) { + AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document); + AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document); + AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document); + } + + if (const ValueType* v = GetMember(value, GetNotString())) { + schemaDocument->CreateSchema(¬_, p.Append(GetNotString(), allocator_), *v, document); + notValidatorIndex_ = validatorCount_; + validatorCount_++; + } + + // Object + + const ValueType* properties = GetMember(value, GetPropertiesString()); + const ValueType* required = GetMember(value, GetRequiredString()); + const ValueType* dependencies = GetMember(value, GetDependenciesString()); + { + // Gather properties from properties/required/dependencies + SValue allProperties(kArrayType); + + if (properties && properties->IsObject()) + for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) + AddUniqueElement(allProperties, itr->name); + + if (required && required->IsArray()) + for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr) + if (itr->IsString()) + AddUniqueElement(allProperties, *itr); + + if (dependencies && dependencies->IsObject()) + for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) { + AddUniqueElement(allProperties, itr->name); + if (itr->value.IsArray()) + for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i) + if (i->IsString()) + AddUniqueElement(allProperties, *i); + } + + if (allProperties.Size() > 0) { + propertyCount_ = allProperties.Size(); + properties_ = static_cast(allocator_->Malloc(sizeof(Property) * propertyCount_)); + for (SizeType i = 0; i < propertyCount_; i++) { + new (&properties_[i]) Property(); + properties_[i].name = allProperties[i]; + properties_[i].schema = typeless_; + } + } + } + + if (properties && properties->IsObject()) { + PointerType q = p.Append(GetPropertiesString(), allocator_); + for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) { + SizeType index; + if (FindPropertyIndex(itr->name, &index)) + schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document); + } + } + + if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) { + PointerType q = p.Append(GetPatternPropertiesString(), allocator_); + patternProperties_ = static_cast(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount())); + patternPropertyCount_ = 0; + + for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) { + new (&patternProperties_[patternPropertyCount_]) PatternProperty(); + patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name); + schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document); + patternPropertyCount_++; + } + } + + if (required && required->IsArray()) + for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr) + if (itr->IsString()) { + SizeType index; + if (FindPropertyIndex(*itr, &index)) { + properties_[index].required = true; + hasRequired_ = true; + } + } + + if (dependencies && dependencies->IsObject()) { + PointerType q = p.Append(GetDependenciesString(), allocator_); + hasDependencies_ = true; + for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) { + SizeType sourceIndex; + if (FindPropertyIndex(itr->name, &sourceIndex)) { + if (itr->value.IsArray()) { + properties_[sourceIndex].dependencies = static_cast(allocator_->Malloc(sizeof(bool) * propertyCount_)); + std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_); + for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) { + SizeType targetIndex; + if (FindPropertyIndex(*targetItr, &targetIndex)) + properties_[sourceIndex].dependencies[targetIndex] = true; + } + } + else if (itr->value.IsObject()) { + hasSchemaDependencies_ = true; + schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document); + properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_; + validatorCount_++; + } + } + } + } + + if (const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) { + if (v->IsBool()) + additionalProperties_ = v->GetBool(); + else if (v->IsObject()) + schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document); + } + + AssignIfExist(minProperties_, value, GetMinPropertiesString()); + AssignIfExist(maxProperties_, value, GetMaxPropertiesString()); + + // Array + if (const ValueType* v = GetMember(value, GetItemsString())) { + PointerType q = p.Append(GetItemsString(), allocator_); + if (v->IsObject()) // List validation + schemaDocument->CreateSchema(&itemsList_, q, *v, document); + else if (v->IsArray()) { // Tuple validation + itemsTuple_ = static_cast(allocator_->Malloc(sizeof(const Schema*) * v->Size())); + SizeType index = 0; + for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++) + schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document); + } + } + + AssignIfExist(minItems_, value, GetMinItemsString()); + AssignIfExist(maxItems_, value, GetMaxItemsString()); + + if (const ValueType* v = GetMember(value, GetAdditionalItemsString())) { + if (v->IsBool()) + additionalItems_ = v->GetBool(); + else if (v->IsObject()) + schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document); + } + + AssignIfExist(uniqueItems_, value, GetUniqueItemsString()); + + // String + AssignIfExist(minLength_, value, GetMinLengthString()); + AssignIfExist(maxLength_, value, GetMaxLengthString()); + + if (const ValueType* v = GetMember(value, GetPatternString())) + pattern_ = CreatePattern(*v); + + // Number + if (const ValueType* v = GetMember(value, GetMinimumString())) + if (v->IsNumber()) + minimum_.CopyFrom(*v, *allocator_); + + if (const ValueType* v = GetMember(value, GetMaximumString())) + if (v->IsNumber()) + maximum_.CopyFrom(*v, *allocator_); + + AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString()); + AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString()); + + if (const ValueType* v = GetMember(value, GetMultipleOfString())) + if (v->IsNumber() && v->GetDouble() > 0.0) + multipleOf_.CopyFrom(*v, *allocator_); + } + + ~Schema() { + AllocatorType::Free(enum_); + if (properties_) { + for (SizeType i = 0; i < propertyCount_; i++) + properties_[i].~Property(); + AllocatorType::Free(properties_); + } + if (patternProperties_) { + for (SizeType i = 0; i < patternPropertyCount_; i++) + patternProperties_[i].~PatternProperty(); + AllocatorType::Free(patternProperties_); + } + AllocatorType::Free(itemsTuple_); +#if RAPIDJSON_SCHEMA_HAS_REGEX + if (pattern_) { + pattern_->~RegexType(); + AllocatorType::Free(pattern_); + } +#endif + } + + bool BeginValue(Context& context) const { + if (context.inArray) { + if (uniqueItems_) + context.valueUniqueness = true; + + if (itemsList_) + context.valueSchema = itemsList_; + else if (itemsTuple_) { + if (context.arrayElementIndex < itemsTupleCount_) + context.valueSchema = itemsTuple_[context.arrayElementIndex]; + else if (additionalItemsSchema_) + context.valueSchema = additionalItemsSchema_; + else if (additionalItems_) + context.valueSchema = typeless_; + else + RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString()); + } + else + context.valueSchema = typeless_; + + context.arrayElementIndex++; + } + return true; + } + + RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const { + if (context.patternPropertiesValidatorCount > 0) { + bool otherValid = false; + SizeType count = context.patternPropertiesValidatorCount; + if (context.objectPatternValidatorType != Context::kPatternValidatorOnly) + otherValid = context.patternPropertiesValidators[--count]->IsValid(); + + bool patternValid = true; + for (SizeType i = 0; i < count; i++) + if (!context.patternPropertiesValidators[i]->IsValid()) { + patternValid = false; + break; + } + + if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) { + if (!patternValid) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString()); + } + else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) { + if (!patternValid || !otherValid) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString()); + } + else if (!patternValid && !otherValid) // kPatternValidatorWithAdditionalProperty) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString()); + } + + if (enum_) { + const uint64_t h = context.factory.GetHashCode(context.hasher); + for (SizeType i = 0; i < enumCount_; i++) + if (enum_[i] == h) + goto foundEnum; + RAPIDJSON_INVALID_KEYWORD_RETURN(GetEnumString()); + foundEnum:; + } + + if (allOf_.schemas) + for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++) + if (!context.validators[i]->IsValid()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetAllOfString()); + + if (anyOf_.schemas) { + for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++) + if (context.validators[i]->IsValid()) + goto foundAny; + RAPIDJSON_INVALID_KEYWORD_RETURN(GetAnyOfString()); + foundAny:; + } + + if (oneOf_.schemas) { + bool oneValid = false; + for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++) + if (context.validators[i]->IsValid()) { + if (oneValid) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString()); + else + oneValid = true; + } + if (!oneValid) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString()); + } + + if (not_ && context.validators[notValidatorIndex_]->IsValid()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetNotString()); + + return true; + } + + bool Null(Context& context) const { + if (!(type_ & (1 << kNullSchemaType))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + return CreateParallelValidator(context); + } + + bool Bool(Context& context, bool) const { + if (!(type_ & (1 << kBooleanSchemaType))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + return CreateParallelValidator(context); + } + + bool Int(Context& context, int i) const { + if (!CheckInt(context, i)) + return false; + return CreateParallelValidator(context); + } + + bool Uint(Context& context, unsigned u) const { + if (!CheckUint(context, u)) + return false; + return CreateParallelValidator(context); + } + + bool Int64(Context& context, int64_t i) const { + if (!CheckInt(context, i)) + return false; + return CreateParallelValidator(context); + } + + bool Uint64(Context& context, uint64_t u) const { + if (!CheckUint(context, u)) + return false; + return CreateParallelValidator(context); + } + + bool Double(Context& context, double d) const { + if (!(type_ & (1 << kNumberSchemaType))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + + if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d)) + return false; + + if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d)) + return false; + + if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d)) + return false; + + return CreateParallelValidator(context); + } + + bool String(Context& context, const Ch* str, SizeType length, bool) const { + if (!(type_ & (1 << kStringSchemaType))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + + if (minLength_ != 0 || maxLength_ != SizeType(~0)) { + SizeType count; + if (internal::CountStringCodePoint(str, length, &count)) { + if (count < minLength_) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinLengthString()); + if (count > maxLength_) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxLengthString()); + } + } + + if (pattern_ && !IsPatternMatch(pattern_, str, length)) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternString()); + + return CreateParallelValidator(context); + } + + bool StartObject(Context& context) const { + if (!(type_ & (1 << kObjectSchemaType))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + + if (hasDependencies_ || hasRequired_) { + context.propertyExist = static_cast(context.factory.MallocState(sizeof(bool) * propertyCount_)); + std::memset(context.propertyExist, 0, sizeof(bool) * propertyCount_); + } + + if (patternProperties_) { // pre-allocate schema array + SizeType count = patternPropertyCount_ + 1; // extra for valuePatternValidatorType + context.patternPropertiesSchemas = static_cast(context.factory.MallocState(sizeof(const SchemaType*) * count)); + context.patternPropertiesSchemaCount = 0; + std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count); + } + + return CreateParallelValidator(context); + } + + bool Key(Context& context, const Ch* str, SizeType len, bool) const { + if (patternProperties_) { + context.patternPropertiesSchemaCount = 0; + for (SizeType i = 0; i < patternPropertyCount_; i++) + if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema; + context.valueSchema = typeless_; + } + } + + SizeType index; + if (FindPropertyIndex(ValueType(str, len).Move(), &index)) { + if (context.patternPropertiesSchemaCount > 0) { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema; + context.valueSchema = typeless_; + context.valuePatternValidatorType = Context::kPatternValidatorWithProperty; + } + else + context.valueSchema = properties_[index].schema; + + if (context.propertyExist) + context.propertyExist[index] = true; + + return true; + } + + if (additionalPropertiesSchema_) { + if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) { + context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_; + context.valueSchema = typeless_; + context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty; + } + else + context.valueSchema = additionalPropertiesSchema_; + return true; + } + else if (additionalProperties_) { + context.valueSchema = typeless_; + return true; + } + + if (context.patternPropertiesSchemaCount == 0) // patternProperties are not additional properties + RAPIDJSON_INVALID_KEYWORD_RETURN(GetAdditionalPropertiesString()); + + return true; + } + + bool EndObject(Context& context, SizeType memberCount) const { + if (hasRequired_) + for (SizeType index = 0; index < propertyCount_; index++) + if (properties_[index].required) + if (!context.propertyExist[index]) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString()); + + if (memberCount < minProperties_) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinPropertiesString()); + + if (memberCount > maxProperties_) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxPropertiesString()); + + if (hasDependencies_) { + for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) + if (context.propertyExist[sourceIndex]) { + if (properties_[sourceIndex].dependencies) { + for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++) + if (properties_[sourceIndex].dependencies[targetIndex] && !context.propertyExist[targetIndex]) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString()); + } + else if (properties_[sourceIndex].dependenciesSchema) + if (!context.validators[properties_[sourceIndex].dependenciesValidatorIndex]->IsValid()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString()); + } + } + + return true; + } + + bool StartArray(Context& context) const { + if (!(type_ & (1 << kArraySchemaType))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + + context.arrayElementIndex = 0; + context.inArray = true; + + return CreateParallelValidator(context); + } + + bool EndArray(Context& context, SizeType elementCount) const { + context.inArray = false; + + if (elementCount < minItems_) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinItemsString()); + + if (elementCount > maxItems_) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxItemsString()); + + return true; + } + + // Generate functions for string literal according to Ch +#define RAPIDJSON_STRING_(name, ...) \ + static const ValueType& Get##name##String() {\ + static const Ch s[] = { __VA_ARGS__, '\0' };\ + static const ValueType v(s, static_cast(sizeof(s) / sizeof(Ch) - 1));\ + return v;\ + } + + RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l') + RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n') + RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't') + RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y') + RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g') + RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r') + RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r') + RAPIDJSON_STRING_(Type, 't', 'y', 'p', 'e') + RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm') + RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f') + RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f') + RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f') + RAPIDJSON_STRING_(Not, 'n', 'o', 't') + RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd') + RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's') + RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's') + RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's') + RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h') + RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h') + RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n') + RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm') + RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f') + +#undef RAPIDJSON_STRING_ + +private: + enum SchemaValueType { + kNullSchemaType, + kBooleanSchemaType, + kObjectSchemaType, + kArraySchemaType, + kStringSchemaType, + kNumberSchemaType, + kIntegerSchemaType, + kTotalSchemaType + }; + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX + typedef internal::GenericRegex RegexType; +#elif RAPIDJSON_SCHEMA_USE_STDREGEX + typedef std::basic_regex RegexType; +#else + typedef char RegexType; +#endif + + struct SchemaArray { + SchemaArray() : schemas(), count() {} + ~SchemaArray() { AllocatorType::Free(schemas); } + const SchemaType** schemas; + SizeType begin; // begin index of context.validators + SizeType count; + }; + + template + void AddUniqueElement(V1& a, const V2& v) { + for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) + if (*itr == v) + return; + V1 c(v, *allocator_); + a.PushBack(c, *allocator_); + } + + static const ValueType* GetMember(const ValueType& value, const ValueType& name) { + typename ValueType::ConstMemberIterator itr = value.FindMember(name); + return itr != value.MemberEnd() ? &(itr->value) : 0; + } + + static void AssignIfExist(bool& out, const ValueType& value, const ValueType& name) { + if (const ValueType* v = GetMember(value, name)) + if (v->IsBool()) + out = v->GetBool(); + } + + static void AssignIfExist(SizeType& out, const ValueType& value, const ValueType& name) { + if (const ValueType* v = GetMember(value, name)) + if (v->IsUint64() && v->GetUint64() <= SizeType(~0)) + out = static_cast(v->GetUint64()); + } + + void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument, const PointerType& p, const ValueType& value, const ValueType& name, const ValueType& document) { + if (const ValueType* v = GetMember(value, name)) { + if (v->IsArray() && v->Size() > 0) { + PointerType q = p.Append(name, allocator_); + out.count = v->Size(); + out.schemas = static_cast(allocator_->Malloc(out.count * sizeof(const Schema*))); + memset(out.schemas, 0, sizeof(Schema*)* out.count); + for (SizeType i = 0; i < out.count; i++) + schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document); + out.begin = validatorCount_; + validatorCount_ += out.count; + } + } + } + +#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX + template + RegexType* CreatePattern(const ValueType& value) { + if (value.IsString()) { + RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString()); + if (!r->IsValid()) { + r->~RegexType(); + AllocatorType::Free(r); + r = 0; + } + return r; + } + return 0; + } + + static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) { + GenericRegexSearch rs(*pattern); + return rs.Search(str); + } +#elif RAPIDJSON_SCHEMA_USE_STDREGEX + template + RegexType* CreatePattern(const ValueType& value) { + if (value.IsString()) + try { + return new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript); + } + catch (const std::regex_error&) { + } + return 0; + } + + static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType length) { + std::match_results r; + return std::regex_search(str, str + length, r, *pattern); + } +#else + template + RegexType* CreatePattern(const ValueType&) { return 0; } + + static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; } +#endif // RAPIDJSON_SCHEMA_USE_STDREGEX + + void AddType(const ValueType& type) { + if (type == GetNullString() ) type_ |= 1 << kNullSchemaType; + else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType; + else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType; + else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType; + else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType; + else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType; + else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType); + } + + bool CreateParallelValidator(Context& context) const { + if (enum_ || context.arrayUniqueness) + context.hasher = context.factory.CreateHasher(); + + if (validatorCount_) { + RAPIDJSON_ASSERT(context.validators == 0); + context.validators = static_cast(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_)); + context.validatorCount = validatorCount_; + + if (allOf_.schemas) + CreateSchemaValidators(context, allOf_); + + if (anyOf_.schemas) + CreateSchemaValidators(context, anyOf_); + + if (oneOf_.schemas) + CreateSchemaValidators(context, oneOf_); + + if (not_) + context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_); + + if (hasSchemaDependencies_) { + for (SizeType i = 0; i < propertyCount_; i++) + if (properties_[i].dependenciesSchema) + context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema); + } + } + + return true; + } + + void CreateSchemaValidators(Context& context, const SchemaArray& schemas) const { + for (SizeType i = 0; i < schemas.count; i++) + context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i]); + } + + // O(n) + bool FindPropertyIndex(const ValueType& name, SizeType* outIndex) const { + SizeType len = name.GetStringLength(); + const Ch* str = name.GetString(); + for (SizeType index = 0; index < propertyCount_; index++) + if (properties_[index].name.GetStringLength() == len && + (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0)) + { + *outIndex = index; + return true; + } + return false; + } + + bool CheckInt(Context& context, int64_t i) const { + if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + + if (!minimum_.IsNull()) { + if (minimum_.IsInt64()) { + if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); + } + else if (minimum_.IsUint64()) { + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); // i <= max(int64_t) < minimum.GetUint64() + } + else if (!CheckDoubleMinimum(context, static_cast(i))) + return false; + } + + if (!maximum_.IsNull()) { + if (maximum_.IsInt64()) { + if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); + } + else if (maximum_.IsUint64()) { } + /* do nothing */ // i <= max(int64_t) < maximum_.GetUint64() + else if (!CheckDoubleMaximum(context, static_cast(i))) + return false; + } + + if (!multipleOf_.IsNull()) { + if (multipleOf_.IsUint64()) { + if (static_cast(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString()); + } + else if (!CheckDoubleMultipleOf(context, static_cast(i))) + return false; + } + + return true; + } + + bool CheckUint(Context& context, uint64_t i) const { + if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); + + if (!minimum_.IsNull()) { + if (minimum_.IsUint64()) { + if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); + } + else if (minimum_.IsInt64()) + /* do nothing */; // i >= 0 > minimum.Getint64() + else if (!CheckDoubleMinimum(context, static_cast(i))) + return false; + } + + if (!maximum_.IsNull()) { + if (maximum_.IsUint64()) { + if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); + } + else if (maximum_.IsInt64()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); // i >= 0 > maximum_ + else if (!CheckDoubleMaximum(context, static_cast(i))) + return false; + } + + if (!multipleOf_.IsNull()) { + if (multipleOf_.IsUint64()) { + if (i % multipleOf_.GetUint64() != 0) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString()); + } + else if (!CheckDoubleMultipleOf(context, static_cast(i))) + return false; + } + + return true; + } + + bool CheckDoubleMinimum(Context& context, double d) const { + if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); + return true; + } + + bool CheckDoubleMaximum(Context& context, double d) const { + if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble()) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); + return true; + } + + bool CheckDoubleMultipleOf(Context& context, double d) const { + double a = std::abs(d), b = std::abs(multipleOf_.GetDouble()); + double q = std::floor(a / b); + double r = a - q * b; + if (r > 0.0) + RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString()); + return true; + } + + struct Property { + Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(false) {} + ~Property() { AllocatorType::Free(dependencies); } + SValue name; + const SchemaType* schema; + const SchemaType* dependenciesSchema; + SizeType dependenciesValidatorIndex; + bool* dependencies; + bool required; + }; + + struct PatternProperty { + PatternProperty() : schema(), pattern() {} + ~PatternProperty() { + if (pattern) { + pattern->~RegexType(); + AllocatorType::Free(pattern); + } + } + const SchemaType* schema; + RegexType* pattern; + }; + + AllocatorType* allocator_; + const SchemaType* typeless_; + uint64_t* enum_; + SizeType enumCount_; + SchemaArray allOf_; + SchemaArray anyOf_; + SchemaArray oneOf_; + const SchemaType* not_; + unsigned type_; // bitmask of kSchemaType + SizeType validatorCount_; + SizeType notValidatorIndex_; + + Property* properties_; + const SchemaType* additionalPropertiesSchema_; + PatternProperty* patternProperties_; + SizeType patternPropertyCount_; + SizeType propertyCount_; + SizeType minProperties_; + SizeType maxProperties_; + bool additionalProperties_; + bool hasDependencies_; + bool hasRequired_; + bool hasSchemaDependencies_; + + const SchemaType* additionalItemsSchema_; + const SchemaType* itemsList_; + const SchemaType** itemsTuple_; + SizeType itemsTupleCount_; + SizeType minItems_; + SizeType maxItems_; + bool additionalItems_; + bool uniqueItems_; + + RegexType* pattern_; + SizeType minLength_; + SizeType maxLength_; + + SValue minimum_; + SValue maximum_; + SValue multipleOf_; + bool exclusiveMinimum_; + bool exclusiveMaximum_; +}; + +template +struct TokenHelper { + RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) { + *documentStack.template Push() = '/'; + char buffer[21]; + size_t length = static_cast((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer); + for (size_t i = 0; i < length; i++) + *documentStack.template Push() = static_cast(buffer[i]); + } +}; + +// Partial specialized version for char to prevent buffer copying. +template +struct TokenHelper { + RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) { + if (sizeof(SizeType) == 4) { + char *buffer = documentStack.template Push(1 + 10); // '/' + uint + *buffer++ = '/'; + const char* end = internal::u32toa(index, buffer); + documentStack.template Pop(static_cast(10 - (end - buffer))); + } + else { + char *buffer = documentStack.template Push(1 + 20); // '/' + uint64 + *buffer++ = '/'; + const char* end = internal::u64toa(index, buffer); + documentStack.template Pop(static_cast(20 - (end - buffer))); + } + } +}; + +} // namespace internal + +/////////////////////////////////////////////////////////////////////////////// +// IGenericRemoteSchemaDocumentProvider + +template +class IGenericRemoteSchemaDocumentProvider { +public: + typedef typename SchemaDocumentType::Ch Ch; + + virtual ~IGenericRemoteSchemaDocumentProvider() {} + virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0; +}; + +/////////////////////////////////////////////////////////////////////////////// +// GenericSchemaDocument + +//! JSON schema document. +/*! + A JSON schema document is a compiled version of a JSON schema. + It is basically a tree of internal::Schema. + + \note This is an immutable class (i.e. its instance cannot be modified after construction). + \tparam ValueT Type of JSON value (e.g. \c Value ), which also determine the encoding. + \tparam Allocator Allocator type for allocating memory of this document. +*/ +template +class GenericSchemaDocument { +public: + typedef ValueT ValueType; + typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProviderType; + typedef Allocator AllocatorType; + typedef typename ValueType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; + typedef internal::Schema SchemaType; + typedef GenericPointer PointerType; + friend class internal::Schema; + template + friend class GenericSchemaValidator; + + //! Constructor. + /*! + Compile a JSON document into schema document. + + \param document A JSON document as source. + \param remoteProvider An optional remote schema document provider for resolving remote reference. Can be null. + \param allocator An optional allocator instance for allocating memory. Can be null. + */ + explicit GenericSchemaDocument(const ValueType& document, IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) : + remoteProvider_(remoteProvider), + allocator_(allocator), + ownAllocator_(), + root_(), + typeless_(), + schemaMap_(allocator, kInitialSchemaMapSize), + schemaRef_(allocator, kInitialSchemaRefSize) + { + if (!allocator_) + ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)(); + + typeless_ = static_cast(allocator_->Malloc(sizeof(SchemaType))); + new (typeless_) SchemaType(this, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), 0); + + // Generate root schema, it will call CreateSchema() to create sub-schemas, + // And call AddRefSchema() if there are $ref. + CreateSchemaRecursive(&root_, PointerType(), document, document); + + // Resolve $ref + while (!schemaRef_.Empty()) { + SchemaRefEntry* refEntry = schemaRef_.template Pop(1); + if (const SchemaType* s = GetSchema(refEntry->target)) { + if (refEntry->schema) + *refEntry->schema = s; + + // Create entry in map if not exist + if (!GetSchema(refEntry->source)) { + new (schemaMap_.template Push()) SchemaEntry(refEntry->source, const_cast(s), false, allocator_); + } + } + else if (refEntry->schema) + *refEntry->schema = typeless_; + + refEntry->~SchemaRefEntry(); + } + + RAPIDJSON_ASSERT(root_ != 0); + + schemaRef_.ShrinkToFit(); // Deallocate all memory for ref + } + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + //! Move constructor in C++11 + GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT : + remoteProvider_(rhs.remoteProvider_), + allocator_(rhs.allocator_), + ownAllocator_(rhs.ownAllocator_), + root_(rhs.root_), + typeless_(rhs.typeless_), + schemaMap_(std::move(rhs.schemaMap_)), + schemaRef_(std::move(rhs.schemaRef_)) + { + rhs.remoteProvider_ = 0; + rhs.allocator_ = 0; + rhs.ownAllocator_ = 0; + rhs.typeless_ = 0; + } +#endif + + //! Destructor + ~GenericSchemaDocument() { + while (!schemaMap_.Empty()) + schemaMap_.template Pop(1)->~SchemaEntry(); + + if (typeless_) { + typeless_->~SchemaType(); + Allocator::Free(typeless_); + } + + RAPIDJSON_DELETE(ownAllocator_); + } + + //! Get the root schema. + const SchemaType& GetRoot() const { return *root_; } + +private: + //! Prohibit copying + GenericSchemaDocument(const GenericSchemaDocument&); + //! Prohibit assignment + GenericSchemaDocument& operator=(const GenericSchemaDocument&); + + struct SchemaRefEntry { + SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator *allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {} + PointerType source; + PointerType target; + const SchemaType** schema; + }; + + struct SchemaEntry { + SchemaEntry(const PointerType& p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {} + ~SchemaEntry() { + if (owned) { + schema->~SchemaType(); + Allocator::Free(schema); + } + } + PointerType pointer; + SchemaType* schema; + bool owned; + }; + + void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) { + if (schema) + *schema = typeless_; + + if (v.GetType() == kObjectType) { + const SchemaType* s = GetSchema(pointer); + if (!s) + CreateSchema(schema, pointer, v, document); + + for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr) + CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document); + } + else if (v.GetType() == kArrayType) + for (SizeType i = 0; i < v.Size(); i++) + CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document); + } + + void CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) { + RAPIDJSON_ASSERT(pointer.IsValid()); + if (v.IsObject()) { + if (!HandleRefSchema(pointer, schema, v, document)) { + SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_); + new (schemaMap_.template Push()) SchemaEntry(pointer, s, true, allocator_); + if (schema) + *schema = s; + } + } + } + + bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document) { + static const Ch kRefString[] = { '$', 'r', 'e', 'f', '\0' }; + static const ValueType kRefValue(kRefString, 4); + + typename ValueType::ConstMemberIterator itr = v.FindMember(kRefValue); + if (itr == v.MemberEnd()) + return false; + + if (itr->value.IsString()) { + SizeType len = itr->value.GetStringLength(); + if (len > 0) { + const Ch* s = itr->value.GetString(); + SizeType i = 0; + while (i < len && s[i] != '#') // Find the first # + i++; + + if (i > 0) { // Remote reference, resolve immediately + if (remoteProvider_) { + if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i)) { + PointerType pointer(&s[i], len - i, allocator_); + if (pointer.IsValid()) { + if (const SchemaType* sc = remoteDocument->GetSchema(pointer)) { + if (schema) + *schema = sc; + return true; + } + } + } + } + } + else if (s[i] == '#') { // Local reference, defer resolution + PointerType pointer(&s[i], len - i, allocator_); + if (pointer.IsValid()) { + if (const ValueType* nv = pointer.Get(document)) + if (HandleRefSchema(source, schema, *nv, document)) + return true; + + new (schemaRef_.template Push()) SchemaRefEntry(source, pointer, schema, allocator_); + return true; + } + } + } + } + return false; + } + + const SchemaType* GetSchema(const PointerType& pointer) const { + for (const SchemaEntry* target = schemaMap_.template Bottom(); target != schemaMap_.template End(); ++target) + if (pointer == target->pointer) + return target->schema; + return 0; + } + + PointerType GetPointer(const SchemaType* schema) const { + for (const SchemaEntry* target = schemaMap_.template Bottom(); target != schemaMap_.template End(); ++target) + if (schema == target->schema) + return target->pointer; + return PointerType(); + } + + const SchemaType* GetTypeless() const { return typeless_; } + + static const size_t kInitialSchemaMapSize = 64; + static const size_t kInitialSchemaRefSize = 64; + + IRemoteSchemaDocumentProviderType* remoteProvider_; + Allocator *allocator_; + Allocator *ownAllocator_; + const SchemaType* root_; //!< Root schema. + SchemaType* typeless_; + internal::Stack schemaMap_; // Stores created Pointer -> Schemas + internal::Stack schemaRef_; // Stores Pointer from $ref and schema which holds the $ref +}; + +//! GenericSchemaDocument using Value type. +typedef GenericSchemaDocument SchemaDocument; +//! IGenericRemoteSchemaDocumentProvider using SchemaDocument. +typedef IGenericRemoteSchemaDocumentProvider IRemoteSchemaDocumentProvider; + +/////////////////////////////////////////////////////////////////////////////// +// GenericSchemaValidator + +//! JSON Schema Validator. +/*! + A SAX style JSON schema validator. + It uses a \c GenericSchemaDocument to validate SAX events. + It delegates the incoming SAX events to an output handler. + The default output handler does nothing. + It can be reused multiple times by calling \c Reset(). + + \tparam SchemaDocumentType Type of schema document. + \tparam OutputHandler Type of output handler. Default handler does nothing. + \tparam StateAllocator Allocator for storing the internal validation states. +*/ +template < + typename SchemaDocumentType, + typename OutputHandler = BaseReaderHandler, + typename StateAllocator = CrtAllocator> +class GenericSchemaValidator : + public internal::ISchemaStateFactory, + public internal::ISchemaValidator +{ +public: + typedef typename SchemaDocumentType::SchemaType SchemaType; + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename SchemaType::EncodingType EncodingType; + typedef typename EncodingType::Ch Ch; + + //! Constructor without output handler. + /*! + \param schemaDocument The schema document to conform to. + \param allocator Optional allocator for storing internal validation states. + \param schemaStackCapacity Optional initial capacity of schema path stack. + \param documentStackCapacity Optional initial capacity of document path stack. + */ + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(schemaDocument.GetRoot()), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + outputHandler_(0), + valid_(true) +#if RAPIDJSON_SCHEMA_VERBOSE + , depth_(0) +#endif + { + } + + //! Constructor with output handler. + /*! + \param schemaDocument The schema document to conform to. + \param allocator Optional allocator for storing internal validation states. + \param schemaStackCapacity Optional initial capacity of schema path stack. + \param documentStackCapacity Optional initial capacity of document path stack. + */ + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + OutputHandler& outputHandler, + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(schemaDocument.GetRoot()), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + outputHandler_(&outputHandler), + valid_(true) +#if RAPIDJSON_SCHEMA_VERBOSE + , depth_(0) +#endif + { + } + + //! Destructor. + ~GenericSchemaValidator() { + Reset(); + RAPIDJSON_DELETE(ownStateAllocator_); + } + + //! Reset the internal states. + void Reset() { + while (!schemaStack_.Empty()) + PopSchema(); + documentStack_.Clear(); + valid_ = true; + } + + //! Checks whether the current state is valid. + // Implementation of ISchemaValidator + virtual bool IsValid() const { return valid_; } + + //! Gets the JSON pointer pointed to the invalid schema. + PointerType GetInvalidSchemaPointer() const { + return schemaStack_.Empty() ? PointerType() : schemaDocument_->GetPointer(&CurrentSchema()); + } + + //! Gets the keyword of invalid schema. + const Ch* GetInvalidSchemaKeyword() const { + return schemaStack_.Empty() ? 0 : CurrentContext().invalidKeyword; + } + + //! Gets the JSON pointer pointed to the invalid value. + PointerType GetInvalidDocumentPointer() const { + return documentStack_.Empty() ? PointerType() : PointerType(documentStack_.template Bottom(), documentStack_.GetSize() / sizeof(Ch)); + } + +#if RAPIDJSON_SCHEMA_VERBOSE +#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \ +RAPIDJSON_MULTILINEMACRO_BEGIN\ + *documentStack_.template Push() = '\0';\ + documentStack_.template Pop(1);\ + internal::PrintInvalidDocument(documentStack_.template Bottom());\ +RAPIDJSON_MULTILINEMACRO_END +#else +#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() +#endif + +#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\ + if (!valid_) return false; \ + if (!BeginValue() || !CurrentSchema().method arg1) {\ + RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\ + return valid_ = false;\ + } + +#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\ + for (Context* context = schemaStack_.template Bottom(); context != schemaStack_.template End(); context++) {\ + if (context->hasher)\ + static_cast(context->hasher)->method arg2;\ + if (context->validators)\ + for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\ + static_cast(context->validators[i_])->method arg2;\ + if (context->patternPropertiesValidators)\ + for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\ + static_cast(context->patternPropertiesValidators[i_])->method arg2;\ + } + +#define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\ + return valid_ = EndValue() && (!outputHandler_ || outputHandler_->method arg2) + +#define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \ + RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\ + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\ + RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2) + + bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext() ), ( )); } + bool Bool(bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); } + bool Int(int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); } + bool Uint(unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); } + bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); } + bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); } + bool Double(double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); } + bool RawNumber(const Ch* str, SizeType length, bool copy) + { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); } + bool String(const Ch* str, SizeType length, bool copy) + { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); } + + bool StartObject() { + RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext())); + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ()); + return valid_ = !outputHandler_ || outputHandler_->StartObject(); + } + + bool Key(const Ch* str, SizeType len, bool copy) { + if (!valid_) return false; + AppendToken(str, len); + if (!CurrentSchema().Key(CurrentContext(), str, len, copy)) return valid_ = false; + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy)); + return valid_ = !outputHandler_ || outputHandler_->Key(str, len, copy); + } + + bool EndObject(SizeType memberCount) { + if (!valid_) return false; + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount)); + if (!CurrentSchema().EndObject(CurrentContext(), memberCount)) return valid_ = false; + RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount)); + } + + bool StartArray() { + RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext())); + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ()); + return valid_ = !outputHandler_ || outputHandler_->StartArray(); + } + + bool EndArray(SizeType elementCount) { + if (!valid_) return false; + RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount)); + if (!CurrentSchema().EndArray(CurrentContext(), elementCount)) return valid_ = false; + RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount)); + } + +#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_ +#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_ +#undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_ +#undef RAPIDJSON_SCHEMA_HANDLE_VALUE_ + + // Implementation of ISchemaStateFactory + virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root) { + return new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root, +#if RAPIDJSON_SCHEMA_VERBOSE + depth_ + 1, +#endif + &GetStateAllocator()); + } + + virtual void DestroySchemaValidator(ISchemaValidator* validator) { + GenericSchemaValidator* v = static_cast(validator); + v->~GenericSchemaValidator(); + StateAllocator::Free(v); + } + + virtual void* CreateHasher() { + return new (GetStateAllocator().Malloc(sizeof(HasherType))) HasherType(&GetStateAllocator()); + } + + virtual uint64_t GetHashCode(void* hasher) { + return static_cast(hasher)->GetHashCode(); + } + + virtual void DestroryHasher(void* hasher) { + HasherType* h = static_cast(hasher); + h->~HasherType(); + StateAllocator::Free(h); + } + + virtual void* MallocState(size_t size) { + return GetStateAllocator().Malloc(size); + } + + virtual void FreeState(void* p) { + StateAllocator::Free(p); + } + +private: + typedef typename SchemaType::Context Context; + typedef GenericValue, StateAllocator> HashCodeArray; + typedef internal::Hasher HasherType; + + GenericSchemaValidator( + const SchemaDocumentType& schemaDocument, + const SchemaType& root, +#if RAPIDJSON_SCHEMA_VERBOSE + unsigned depth, +#endif + StateAllocator* allocator = 0, + size_t schemaStackCapacity = kDefaultSchemaStackCapacity, + size_t documentStackCapacity = kDefaultDocumentStackCapacity) + : + schemaDocument_(&schemaDocument), + root_(root), + stateAllocator_(allocator), + ownStateAllocator_(0), + schemaStack_(allocator, schemaStackCapacity), + documentStack_(allocator, documentStackCapacity), + outputHandler_(0), + valid_(true) +#if RAPIDJSON_SCHEMA_VERBOSE + , depth_(depth) +#endif + { + } + + StateAllocator& GetStateAllocator() { + if (!stateAllocator_) + stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator)(); + return *stateAllocator_; + } + + bool BeginValue() { + if (schemaStack_.Empty()) + PushSchema(root_); + else { + if (CurrentContext().inArray) + internal::TokenHelper, Ch>::AppendIndexToken(documentStack_, CurrentContext().arrayElementIndex); + + if (!CurrentSchema().BeginValue(CurrentContext())) + return false; + + SizeType count = CurrentContext().patternPropertiesSchemaCount; + const SchemaType** sa = CurrentContext().patternPropertiesSchemas; + typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType; + bool valueUniqueness = CurrentContext().valueUniqueness; + RAPIDJSON_ASSERT(CurrentContext().valueSchema); + PushSchema(*CurrentContext().valueSchema); + + if (count > 0) { + CurrentContext().objectPatternValidatorType = patternValidatorType; + ISchemaValidator**& va = CurrentContext().patternPropertiesValidators; + SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount; + va = static_cast(MallocState(sizeof(ISchemaValidator*) * count)); + for (SizeType i = 0; i < count; i++) + va[validatorCount++] = CreateSchemaValidator(*sa[i]); + } + + CurrentContext().arrayUniqueness = valueUniqueness; + } + return true; + } + + bool EndValue() { + if (!CurrentSchema().EndValue(CurrentContext())) + return false; + +#if RAPIDJSON_SCHEMA_VERBOSE + GenericStringBuffer sb; + schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb); + + *documentStack_.template Push() = '\0'; + documentStack_.template Pop(1); + internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom()); +#endif + + uint64_t h = CurrentContext().arrayUniqueness ? static_cast(CurrentContext().hasher)->GetHashCode() : 0; + + PopSchema(); + + if (!schemaStack_.Empty()) { + Context& context = CurrentContext(); + if (context.valueUniqueness) { + HashCodeArray* a = static_cast(context.arrayElementHashCodes); + if (!a) + CurrentContext().arrayElementHashCodes = a = new (GetStateAllocator().Malloc(sizeof(HashCodeArray))) HashCodeArray(kArrayType); + for (typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr) + if (itr->GetUint64() == h) + RAPIDJSON_INVALID_KEYWORD_RETURN(SchemaType::GetUniqueItemsString()); + a->PushBack(h, GetStateAllocator()); + } + } + + // Remove the last token of document pointer + while (!documentStack_.Empty() && *documentStack_.template Pop(1) != '/') + ; + + return true; + } + + void AppendToken(const Ch* str, SizeType len) { + documentStack_.template Reserve(1 + len * 2); // worst case all characters are escaped as two characters + *documentStack_.template PushUnsafe() = '/'; + for (SizeType i = 0; i < len; i++) { + if (str[i] == '~') { + *documentStack_.template PushUnsafe() = '~'; + *documentStack_.template PushUnsafe() = '0'; + } + else if (str[i] == '/') { + *documentStack_.template PushUnsafe() = '~'; + *documentStack_.template PushUnsafe() = '1'; + } + else + *documentStack_.template PushUnsafe() = str[i]; + } + } + + RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push()) Context(*this, &schema); } + + RAPIDJSON_FORCEINLINE void PopSchema() { + Context* c = schemaStack_.template Pop(1); + if (HashCodeArray* a = static_cast(c->arrayElementHashCodes)) { + a->~HashCodeArray(); + StateAllocator::Free(a); + } + c->~Context(); + } + + const SchemaType& CurrentSchema() const { return *schemaStack_.template Top()->schema; } + Context& CurrentContext() { return *schemaStack_.template Top(); } + const Context& CurrentContext() const { return *schemaStack_.template Top(); } + + static const size_t kDefaultSchemaStackCapacity = 1024; + static const size_t kDefaultDocumentStackCapacity = 256; + const SchemaDocumentType* schemaDocument_; + const SchemaType& root_; + StateAllocator* stateAllocator_; + StateAllocator* ownStateAllocator_; + internal::Stack schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *) + internal::Stack documentStack_; //!< stack to store the current path of validating document (Ch) + OutputHandler* outputHandler_; + bool valid_; +#if RAPIDJSON_SCHEMA_VERBOSE + unsigned depth_; +#endif +}; + +typedef GenericSchemaValidator SchemaValidator; + +/////////////////////////////////////////////////////////////////////////////// +// SchemaValidatingReader + +//! A helper class for parsing with validation. +/*! + This helper class is a functor, designed as a parameter of \ref GenericDocument::Populate(). + + \tparam parseFlags Combination of \ref ParseFlag. + \tparam InputStream Type of input stream, implementing Stream concept. + \tparam SourceEncoding Encoding of the input stream. + \tparam SchemaDocumentType Type of schema document. + \tparam StackAllocator Allocator type for stack. +*/ +template < + unsigned parseFlags, + typename InputStream, + typename SourceEncoding, + typename SchemaDocumentType = SchemaDocument, + typename StackAllocator = CrtAllocator> +class SchemaValidatingReader { +public: + typedef typename SchemaDocumentType::PointerType PointerType; + typedef typename InputStream::Ch Ch; + + //! Constructor + /*! + \param is Input stream. + \param sd Schema document. + */ + SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), isValid_(true) {} + + template + bool operator()(Handler& handler) { + GenericReader reader; + GenericSchemaValidator validator(sd_, handler); + parseResult_ = reader.template Parse(is_, validator); + + isValid_ = validator.IsValid(); + if (isValid_) { + invalidSchemaPointer_ = PointerType(); + invalidSchemaKeyword_ = 0; + invalidDocumentPointer_ = PointerType(); + } + else { + invalidSchemaPointer_ = validator.GetInvalidSchemaPointer(); + invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword(); + invalidDocumentPointer_ = validator.GetInvalidDocumentPointer(); + } + + return parseResult_; + } + + const ParseResult& GetParseResult() const { return parseResult_; } + bool IsValid() const { return isValid_; } + const PointerType& GetInvalidSchemaPointer() const { return invalidSchemaPointer_; } + const Ch* GetInvalidSchemaKeyword() const { return invalidSchemaKeyword_; } + const PointerType& GetInvalidDocumentPointer() const { return invalidDocumentPointer_; } + +private: + InputStream& is_; + const SchemaDocumentType& sd_; + + ParseResult parseResult_; + PointerType invalidSchemaPointer_; + const Ch* invalidSchemaKeyword_; + PointerType invalidDocumentPointer_; + bool isValid_; +}; + +RAPIDJSON_NAMESPACE_END +RAPIDJSON_DIAG_POP + +#endif // RAPIDJSON_SCHEMA_H_ diff --git a/contrib/rapidjson/include/rapidjson/stream.h b/contrib/rapidjson/include/rapidjson/stream.h new file mode 100644 index 000000000..fef82c252 --- /dev/null +++ b/contrib/rapidjson/include/rapidjson/stream.h @@ -0,0 +1,179 @@ +// Tencent is pleased to support the open source community by making RapidJSON available. +// +// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. +// +// Licensed under the MIT License (the "License"); you may not use this file except +// in compliance with the License. You may obtain a copy of the License at +// +// http://opensource.org/licenses/MIT +// +// Unless required by applicable law or agreed to in writing, software distributed +// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +#include "rapidjson.h" + +#ifndef RAPIDJSON_STREAM_H_ +#define RAPIDJSON_STREAM_H_ + +#include "encodings.h" + +RAPIDJSON_NAMESPACE_BEGIN + +/////////////////////////////////////////////////////////////////////////////// +// Stream + +/*! \class rapidjson::Stream + \brief Concept for reading and writing characters. + + For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd(). + + For write-only stream, only need to implement Put() and Flush(). + +\code +concept Stream { + typename Ch; //!< Character type of the stream. + + //! Read the current character from stream without moving the read cursor. + Ch Peek() const; + + //! Read the current character from stream and moving the read cursor to next character. + Ch Take(); + + //! Get the current read cursor. + //! \return Number of characters read from start. + size_t Tell(); + + //! Begin writing operation at the current read pointer. + //! \return The begin writer pointer. + Ch* PutBegin(); + + //! Write a character. + void Put(Ch c); + + //! Flush the buffer. + void Flush(); + + //! End the writing operation. + //! \param begin The begin write pointer returned by PutBegin(). + //! \return Number of characters written. + size_t PutEnd(Ch* begin); +} +\endcode +*/ + +//! Provides additional information for stream. +/*! + By using traits pattern, this type provides a default configuration for stream. + For custom stream, this type can be specialized for other configuration. + See TEST(Reader, CustomStringStream) in readertest.cpp for example. +*/ +template +struct StreamTraits { + //! Whether to make local copy of stream for optimization during parsing. + /*! + By default, for safety, streams do not use local copy optimization. + Stream that can be copied fast should specialize this, like StreamTraits. + */ + enum { copyOptimization = 0 }; +}; + +//! Reserve n characters for writing to a stream. +template +inline void PutReserve(Stream& stream, size_t count) { + (void)stream; + (void)count; +} + +//! Write character to a stream, presuming buffer is reserved. +template +inline void PutUnsafe(Stream& stream, typename Stream::Ch c) { + stream.Put(c); +} + +//! Put N copies of a character to a stream. +template +inline void PutN(Stream& stream, Ch c, size_t n) { + PutReserve(stream, n); + for (size_t i = 0; i < n; i++) + PutUnsafe(stream, c); +} + +/////////////////////////////////////////////////////////////////////////////// +// StringStream + +//! Read-only string stream. +/*! \note implements Stream concept +*/ +template +struct GenericStringStream { + typedef typename Encoding::Ch Ch; + + GenericStringStream(const Ch *src) : src_(src), head_(src) {} + + Ch Peek() const { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() const { return static_cast(src_ - head_); } + + Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } + void Put(Ch) { RAPIDJSON_ASSERT(false); } + void Flush() { RAPIDJSON_ASSERT(false); } + size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } + + const Ch* src_; //!< Current read position. + const Ch* head_; //!< Original head of the string. +}; + +template +struct StreamTraits > { + enum { copyOptimization = 1 }; +}; + +//! String stream with UTF8 encoding. +typedef GenericStringStream > StringStream; + +/////////////////////////////////////////////////////////////////////////////// +// InsituStringStream + +//! A read-write string stream. +/*! This string stream is particularly designed for in-situ parsing. + \note implements Stream concept +*/ +template +struct GenericInsituStringStream { + typedef typename Encoding::Ch Ch; + + GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {} + + // Read + Ch Peek() { return *src_; } + Ch Take() { return *src_++; } + size_t Tell() { return static_cast(src_ - head_); } + + // Write + void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; } + + Ch* PutBegin() { return dst_ = src_; } + size_t PutEnd(Ch* begin) { return static_cast(dst_ - begin); } + void Flush() {} + + Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; } + void Pop(size_t count) { dst_ -= count; } + + Ch* src_; + Ch* dst_; + Ch* head_; +}; + +template +struct StreamTraits > { + enum { copyOptimization = 1 }; +}; + +//! Insitu string stream with UTF8 encoding. +typedef GenericInsituStringStream > InsituStringStream; + +RAPIDJSON_NAMESPACE_END + +#endif // RAPIDJSON_STREAM_H_ diff --git a/contrib/rapidjson/include/rapidjson/stringbuffer.h b/contrib/rapidjson/include/rapidjson/stringbuffer.h index 1c9c80b79..4e38b82c3 100644 --- a/contrib/rapidjson/include/rapidjson/stringbuffer.h +++ b/contrib/rapidjson/include/rapidjson/stringbuffer.h @@ -15,7 +15,8 @@ #ifndef RAPIDJSON_STRINGBUFFER_H_ #define RAPIDJSON_STRINGBUFFER_H_ -#include "rapidjson.h" +#include "stream.h" +#include "internal/stack.h" #if RAPIDJSON_HAS_CXX11_RVALUE_REFS #include // std::move @@ -23,6 +24,11 @@ #include "internal/stack.h" +#if defined(__clang__) +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + RAPIDJSON_NAMESPACE_BEGIN //! Represents an in-memory output stream. @@ -48,6 +54,7 @@ public: #endif void Put(Ch c) { *stack_.template Push() = c; } + void PutUnsafe(Ch c) { *stack_.template PushUnsafe() = c; } void Flush() {} void Clear() { stack_.Clear(); } @@ -57,7 +64,10 @@ public: stack_.ShrinkToFit(); stack_.template Pop(1); } + + void Reserve(size_t count) { stack_.template Reserve(count); } Ch* Push(size_t count) { return stack_.template Push(count); } + Ch* PushUnsafe(size_t count) { return stack_.template PushUnsafe(count); } void Pop(size_t count) { stack_.template Pop(count); } const Ch* GetString() const { @@ -68,8 +78,12 @@ public: return stack_.template Bottom(); } + //! Get the size of string in bytes in the string buffer. size_t GetSize() const { return stack_.GetSize(); } + //! Get the length of string in Ch in the string buffer. + size_t GetLength() const { return stack_.GetSize() / sizeof(Ch); } + static const size_t kDefaultCapacity = 256; mutable internal::Stack stack_; @@ -82,6 +96,16 @@ private: //! String buffer with UTF8 encoding typedef GenericStringBuffer > StringBuffer; +template +inline void PutReserve(GenericStringBuffer& stream, size_t count) { + stream.Reserve(count); +} + +template +inline void PutUnsafe(GenericStringBuffer& stream, typename Encoding::Ch c) { + stream.PutUnsafe(c); +} + //! Implement specialized version of PutN() with memset() for better performance. template<> inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { @@ -90,4 +114,8 @@ inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { RAPIDJSON_NAMESPACE_END +#if defined(__clang__) +RAPIDJSON_DIAG_POP +#endif + #endif // RAPIDJSON_STRINGBUFFER_H_ diff --git a/contrib/rapidjson/include/rapidjson/writer.h b/contrib/rapidjson/include/rapidjson/writer.h index e1eea38b9..e610ebb60 100644 --- a/contrib/rapidjson/include/rapidjson/writer.h +++ b/contrib/rapidjson/include/rapidjson/writer.h @@ -15,7 +15,8 @@ #ifndef RAPIDJSON_WRITER_H_ #define RAPIDJSON_WRITER_H_ -#include "rapidjson.h" +#include "stream.h" +#include "internal/meta.h" #include "internal/stack.h" #include "internal/strfunc.h" #include "internal/dtoa.h" @@ -23,8 +24,16 @@ #include "stringbuffer.h" #include // placement new -#if RAPIDJSON_HAS_STDSTRING -#include +#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER) +#include +#pragma intrinsic(_BitScanForward) +#endif +#ifdef RAPIDJSON_SSE42 +#include +#elif defined(RAPIDJSON_SSE2) +#include +#elif defined(RAPIDJSON_NEON) +#include #endif #ifdef _MSC_VER @@ -32,8 +41,36 @@ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant #endif +#ifdef __clang__ +RAPIDJSON_DIAG_PUSH +RAPIDJSON_DIAG_OFF(padded) +RAPIDJSON_DIAG_OFF(unreachable-code) +RAPIDJSON_DIAG_OFF(c++98-compat) +#endif + RAPIDJSON_NAMESPACE_BEGIN +/////////////////////////////////////////////////////////////////////////////// +// WriteFlag + +/*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS + \ingroup RAPIDJSON_CONFIG + \brief User-defined kWriteDefaultFlags definition. + + User can define this as any \c WriteFlag combinations. +*/ +#ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS +#define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags +#endif + +//! Combination of writeFlags +enum WriteFlag { + kWriteNoFlags = 0, //!< No flags are set. + kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings. + kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN. + kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS +}; + //! JSON writer /*! Writer implements the concept Handler. It generates JSON text by events to an output os. @@ -50,11 +87,13 @@ RAPIDJSON_NAMESPACE_BEGIN \tparam StackAllocator Type of allocator for allocating memory of stack. \note implements Handler concept */ -template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator> +template, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> class Writer { public: typedef typename SourceEncoding::Ch Ch; + static const int kDefaultMaxDecimalPlaces = 324; + //! Constructor /*! \param os Output stream. \param stackAllocator User supplied allocator. If it is null, it will create a private one. @@ -62,11 +101,18 @@ public: */ explicit Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) : - os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), hasRoot_(false) {} + os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} explicit Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : - os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), hasRoot_(false) {} + os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} + +#if RAPIDJSON_HAS_CXX11_RVALUE_REFS + Writer(Writer&& rhs) : + os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) { + rhs.os_ = 0; + } +#endif //! Reset the writer with a new stream. /*! @@ -100,29 +146,66 @@ public: return hasRoot_ && level_stack_.Empty(); } + int GetMaxDecimalPlaces() const { + return maxDecimalPlaces_; + } + + //! Sets the maximum number of decimal places for double output. + /*! + This setting truncates the output with specified number of decimal places. + + For example, + + \code + writer.SetMaxDecimalPlaces(3); + writer.StartArray(); + writer.Double(0.12345); // "0.123" + writer.Double(0.0001); // "0.0" + writer.Double(1.234567890123456e30); // "1.234567890123456e30" (do not truncate significand for positive exponent) + writer.Double(1.23e-4); // "0.0" (do truncate significand for negative exponent) + writer.EndArray(); + \endcode + + The default setting does not truncate any decimal places. You can restore to this setting by calling + \code + writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces); + \endcode + */ + void SetMaxDecimalPlaces(int maxDecimalPlaces) { + maxDecimalPlaces_ = maxDecimalPlaces; + } + /*!@name Implementation of Handler \see Handler */ //@{ - bool Null() { Prefix(kNullType); return WriteNull(); } - bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return WriteBool(b); } - bool Int(int i) { Prefix(kNumberType); return WriteInt(i); } - bool Uint(unsigned u) { Prefix(kNumberType); return WriteUint(u); } - bool Int64(int64_t i64) { Prefix(kNumberType); return WriteInt64(i64); } - bool Uint64(uint64_t u64) { Prefix(kNumberType); return WriteUint64(u64); } + bool Null() { Prefix(kNullType); return EndValue(WriteNull()); } + bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return EndValue(WriteBool(b)); } + bool Int(int i) { Prefix(kNumberType); return EndValue(WriteInt(i)); } + bool Uint(unsigned u) { Prefix(kNumberType); return EndValue(WriteUint(u)); } + bool Int64(int64_t i64) { Prefix(kNumberType); return EndValue(WriteInt64(i64)); } + bool Uint64(uint64_t u64) { Prefix(kNumberType); return EndValue(WriteUint64(u64)); } //! Writes the given \c double value to the stream /*! \param d The value to be written. \return Whether it is succeed. */ - bool Double(double d) { Prefix(kNumberType); return WriteDouble(d); } + bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); } + + bool RawNumber(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); + (void)copy; + Prefix(kNumberType); + return EndValue(WriteString(str, length)); + } bool String(const Ch* str, SizeType length, bool copy = false) { + RAPIDJSON_ASSERT(str != 0); (void)copy; Prefix(kStringType); - return WriteString(str, length); + return EndValue(WriteString(str, length)); } #if RAPIDJSON_HAS_STDSTRING @@ -138,16 +221,21 @@ public: } bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } + +#if RAPIDJSON_HAS_STDSTRING + bool Key(const std::basic_string& str) + { + return Key(str.data(), SizeType(str.size())); + } +#endif bool EndObject(SizeType memberCount = 0) { (void)memberCount; - RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); - RAPIDJSON_ASSERT(!level_stack_.template Top()->inArray); + RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object + RAPIDJSON_ASSERT(!level_stack_.template Top()->inArray); // currently inside an Array, not Object + RAPIDJSON_ASSERT(0 == level_stack_.template Top()->valueCount % 2); // Object has a Key without a Value level_stack_.template Pop(1); - bool ret = WriteEndObject(); - if (level_stack_.Empty()) // end of json text - os_->Flush(); - return ret; + return EndValue(WriteEndObject()); } bool StartArray() { @@ -161,10 +249,7 @@ public: RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); RAPIDJSON_ASSERT(level_stack_.template Top()->inArray); level_stack_.template Pop(1); - bool ret = WriteEndArray(); - if (level_stack_.Empty()) // end of json text - os_->Flush(); - return ret; + return EndValue(WriteEndArray()); } //@} @@ -172,11 +257,33 @@ public: //@{ //! Simpler but slower overload. - bool String(const Ch* str) { return String(str, internal::StrLen(str)); } - bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); } - + bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); } + bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); } + //@} + //! Write a raw JSON value. + /*! + For user to write a stringified JSON as a value. + + \param json A well-formed JSON value. It should not contain null character within [0, length - 1] range. + \param length Length of the json. + \param type Type of the root of json. + */ + bool RawValue(const Ch* json, size_t length, Type type) { + RAPIDJSON_ASSERT(json != 0); + Prefix(type); + return EndValue(WriteRawValue(json, length)); + } + + //! Flush the output stream. + /*! + Allows the user to flush the output stream immediately. + */ + void Flush() { + os_->Flush(); + } + protected: //! Information for each nested level struct Level { @@ -188,15 +295,18 @@ protected: static const size_t kDefaultLevelDepth = 32; bool WriteNull() { - os_->Put('n'); os_->Put('u'); os_->Put('l'); os_->Put('l'); return true; + PutReserve(*os_, 4); + PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true; } bool WriteBool(bool b) { if (b) { - os_->Put('t'); os_->Put('r'); os_->Put('u'); os_->Put('e'); + PutReserve(*os_, 4); + PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'r'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'e'); } else { - os_->Put('f'); os_->Put('a'); os_->Put('l'); os_->Put('s'); os_->Put('e'); + PutReserve(*os_, 5); + PutUnsafe(*os_, 'f'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 's'); PutUnsafe(*os_, 'e'); } return true; } @@ -204,45 +314,69 @@ protected: bool WriteInt(int i) { char buffer[11]; const char* end = internal::i32toa(i, buffer); + PutReserve(*os_, static_cast(end - buffer)); for (const char* p = buffer; p != end; ++p) - os_->Put(*p); + PutUnsafe(*os_, static_cast(*p)); return true; } bool WriteUint(unsigned u) { char buffer[10]; const char* end = internal::u32toa(u, buffer); + PutReserve(*os_, static_cast(end - buffer)); for (const char* p = buffer; p != end; ++p) - os_->Put(*p); + PutUnsafe(*os_, static_cast(*p)); return true; } bool WriteInt64(int64_t i64) { char buffer[21]; const char* end = internal::i64toa(i64, buffer); + PutReserve(*os_, static_cast(end - buffer)); for (const char* p = buffer; p != end; ++p) - os_->Put(*p); + PutUnsafe(*os_, static_cast(*p)); return true; } bool WriteUint64(uint64_t u64) { char buffer[20]; char* end = internal::u64toa(u64, buffer); + PutReserve(*os_, static_cast(end - buffer)); for (char* p = buffer; p != end; ++p) - os_->Put(*p); + PutUnsafe(*os_, static_cast(*p)); return true; } bool WriteDouble(double d) { + if (internal::Double(d).IsNanOrInf()) { + if (!(writeFlags & kWriteNanAndInfFlag)) + return false; + if (internal::Double(d).IsNan()) { + PutReserve(*os_, 3); + PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); + return true; + } + if (internal::Double(d).Sign()) { + PutReserve(*os_, 9); + PutUnsafe(*os_, '-'); + } + else + PutReserve(*os_, 8); + PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); + PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); + return true; + } + char buffer[25]; - char* end = internal::dtoa(d, buffer); + char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); + PutReserve(*os_, static_cast(end - buffer)); for (char* p = buffer; p != end; ++p) - os_->Put(*p); + PutUnsafe(*os_, static_cast(*p)); return true; } bool WriteString(const Ch* str, SizeType length) { - static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; static const char escape[256] = { #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //0 1 2 3 4 5 6 7 8 9 A B C D E F @@ -255,22 +389,27 @@ protected: #undef Z16 }; - os_->Put('\"'); + if (TargetEncoding::supportUnicode) + PutReserve(*os_, 2 + length * 6); // "\uxxxx..." + else + PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..." + + PutUnsafe(*os_, '\"'); GenericStringStream is(str); - while (is.Tell() < length) { + while (ScanWriteUnescapedString(is, length)) { const Ch c = is.Peek(); - if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) { + if (!TargetEncoding::supportUnicode && static_cast(c) >= 0x80) { // Unicode escaping unsigned codepoint; - if (!SourceEncoding::Decode(is, &codepoint)) + if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint))) return false; - os_->Put('\\'); - os_->Put('u'); + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, 'u'); if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) { - os_->Put(hexDigits[(codepoint >> 12) & 15]); - os_->Put(hexDigits[(codepoint >> 8) & 15]); - os_->Put(hexDigits[(codepoint >> 4) & 15]); - os_->Put(hexDigits[(codepoint ) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(codepoint ) & 15]); } else { RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF); @@ -278,45 +417,59 @@ protected: unsigned s = codepoint - 0x010000; unsigned lead = (s >> 10) + 0xD800; unsigned trail = (s & 0x3FF) + 0xDC00; - os_->Put(hexDigits[(lead >> 12) & 15]); - os_->Put(hexDigits[(lead >> 8) & 15]); - os_->Put(hexDigits[(lead >> 4) & 15]); - os_->Put(hexDigits[(lead ) & 15]); - os_->Put('\\'); - os_->Put('u'); - os_->Put(hexDigits[(trail >> 12) & 15]); - os_->Put(hexDigits[(trail >> 8) & 15]); - os_->Put(hexDigits[(trail >> 4) & 15]); - os_->Put(hexDigits[(trail ) & 15]); + PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(lead ) & 15]); + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, 'u'); + PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]); + PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]); + PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]); + PutUnsafe(*os_, hexDigits[(trail ) & 15]); } } - else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) { + else if ((sizeof(Ch) == 1 || static_cast(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast(c)])) { is.Take(); - os_->Put('\\'); - os_->Put(escape[(unsigned char)c]); - if (escape[(unsigned char)c] == 'u') { - os_->Put('0'); - os_->Put('0'); - os_->Put(hexDigits[(unsigned char)c >> 4]); - os_->Put(hexDigits[(unsigned char)c & 0xF]); + PutUnsafe(*os_, '\\'); + PutUnsafe(*os_, static_cast(escape[static_cast(c)])); + if (escape[static_cast(c)] == 'u') { + PutUnsafe(*os_, '0'); + PutUnsafe(*os_, '0'); + PutUnsafe(*os_, hexDigits[static_cast(c) >> 4]); + PutUnsafe(*os_, hexDigits[static_cast(c) & 0xF]); } } - else - if (!Transcoder::Transcode(is, *os_)) - return false; + else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ? + Transcoder::Validate(is, *os_) : + Transcoder::TranscodeUnsafe(is, *os_)))) + return false; } - os_->Put('\"'); + PutUnsafe(*os_, '\"'); return true; } + bool ScanWriteUnescapedString(GenericStringStream& is, size_t length) { + return RAPIDJSON_LIKELY(is.Tell() < length); + } + bool WriteStartObject() { os_->Put('{'); return true; } bool WriteEndObject() { os_->Put('}'); return true; } bool WriteStartArray() { os_->Put('['); return true; } bool WriteEndArray() { os_->Put(']'); return true; } + bool WriteRawValue(const Ch* json, size_t length) { + PutReserve(*os_, length); + for (size_t i = 0; i < length; i++) { + RAPIDJSON_ASSERT(json[i] != '\0'); + PutUnsafe(*os_, json[i]); + } + return true; + } + void Prefix(Type type) { (void)type; - if (level_stack_.GetSize() != 0) { // this value is not at root + if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root Level* level = level_stack_.template Top(); if (level->valueCount > 0) { if (level->inArray) @@ -334,8 +487,16 @@ protected: } } + // Flush the value if it is the top level one. + bool EndValue(bool ret) { + if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text + Flush(); + return ret; + } + OutputStream* os_; internal::Stack level_stack_; + int maxDecimalPlaces_; bool hasRoot_; private: @@ -350,7 +511,7 @@ template<> inline bool Writer::WriteInt(int i) { char *buffer = os_->Push(11); const char* end = internal::i32toa(i, buffer); - os_->Pop(11 - (end - buffer)); + os_->Pop(static_cast(11 - (end - buffer))); return true; } @@ -358,7 +519,7 @@ template<> inline bool Writer::WriteUint(unsigned u) { char *buffer = os_->Push(10); const char* end = internal::u32toa(u, buffer); - os_->Pop(10 - (end - buffer)); + os_->Pop(static_cast(10 - (end - buffer))); return true; } @@ -366,7 +527,7 @@ template<> inline bool Writer::WriteInt64(int64_t i64) { char *buffer = os_->Push(21); const char* end = internal::i64toa(i64, buffer); - os_->Pop(21 - (end - buffer)); + os_->Pop(static_cast(21 - (end - buffer))); return true; } @@ -374,22 +535,177 @@ template<> inline bool Writer::WriteUint64(uint64_t u) { char *buffer = os_->Push(20); const char* end = internal::u64toa(u, buffer); - os_->Pop(20 - (end - buffer)); + os_->Pop(static_cast(20 - (end - buffer))); return true; } template<> inline bool Writer::WriteDouble(double d) { + if (internal::Double(d).IsNanOrInf()) { + // Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag). + if (!(kWriteDefaultFlags & kWriteNanAndInfFlag)) + return false; + if (internal::Double(d).IsNan()) { + PutReserve(*os_, 3); + PutUnsafe(*os_, 'N'); PutUnsafe(*os_, 'a'); PutUnsafe(*os_, 'N'); + return true; + } + if (internal::Double(d).Sign()) { + PutReserve(*os_, 9); + PutUnsafe(*os_, '-'); + } + else + PutReserve(*os_, 8); + PutUnsafe(*os_, 'I'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'f'); + PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'i'); PutUnsafe(*os_, 't'); PutUnsafe(*os_, 'y'); + return true; + } + char *buffer = os_->Push(25); - char* end = internal::dtoa(d, buffer); - os_->Pop(25 - (end - buffer)); + char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); + os_->Pop(static_cast(25 - (end - buffer))); return true; } +#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) +template<> +inline bool Writer::ScanWriteUnescapedString(StringStream& is, size_t length) { + if (length < 16) + return RAPIDJSON_LIKELY(is.Tell() < length); + + if (!RAPIDJSON_LIKELY(is.Tell() < length)) + return false; + + const char* p = is.src_; + const char* end = is.head_ + length; + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + const char* endAligned = reinterpret_cast(reinterpret_cast(end) & static_cast(~15)); + if (nextAligned > end) + return true; + + while (p != nextAligned) + if (*p < 0x20 || *p == '\"' || *p == '\\') { + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); + } + else + os_->PutUnsafe(*p++); + + // The rest of string using SIMD + static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; + static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; + static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; + const __m128i dq = _mm_loadu_si128(reinterpret_cast(&dquote[0])); + const __m128i bs = _mm_loadu_si128(reinterpret_cast(&bslash[0])); + const __m128i sp = _mm_loadu_si128(reinterpret_cast(&space[0])); + + for (; p != endAligned; p += 16) { + const __m128i s = _mm_load_si128(reinterpret_cast(p)); + const __m128i t1 = _mm_cmpeq_epi8(s, dq); + const __m128i t2 = _mm_cmpeq_epi8(s, bs); + const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F + const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); + unsigned short r = static_cast(_mm_movemask_epi8(x)); + if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped + SizeType len; +#ifdef _MSC_VER // Find the index of first escaped + unsigned long offset; + _BitScanForward(&offset, r); + len = offset; +#else + len = static_cast(__builtin_ffs(r) - 1); +#endif + char* q = reinterpret_cast(os_->PushUnsafe(len)); + for (size_t i = 0; i < len; i++) + q[i] = p[i]; + + p += len; + break; + } + _mm_storeu_si128(reinterpret_cast<__m128i *>(os_->PushUnsafe(16)), s); + } + + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); +} +#elif defined(RAPIDJSON_NEON) +template<> +inline bool Writer::ScanWriteUnescapedString(StringStream& is, size_t length) { + if (length < 16) + return RAPIDJSON_LIKELY(is.Tell() < length); + + if (!RAPIDJSON_LIKELY(is.Tell() < length)) + return false; + + const char* p = is.src_; + const char* end = is.head_ + length; + const char* nextAligned = reinterpret_cast((reinterpret_cast(p) + 15) & static_cast(~15)); + const char* endAligned = reinterpret_cast(reinterpret_cast(end) & static_cast(~15)); + if (nextAligned > end) + return true; + + while (p != nextAligned) + if (*p < 0x20 || *p == '\"' || *p == '\\') { + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); + } + else + os_->PutUnsafe(*p++); + + // The rest of string using SIMD + const uint8x16_t s0 = vmovq_n_u8('"'); + const uint8x16_t s1 = vmovq_n_u8('\\'); + const uint8x16_t s2 = vmovq_n_u8('\b'); + const uint8x16_t s3 = vmovq_n_u8(32); + + for (; p != endAligned; p += 16) { + const uint8x16_t s = vld1q_u8(reinterpret_cast(p)); + uint8x16_t x = vceqq_u8(s, s0); + x = vorrq_u8(x, vceqq_u8(s, s1)); + x = vorrq_u8(x, vceqq_u8(s, s2)); + x = vorrq_u8(x, vcltq_u8(s, s3)); + + x = vrev64q_u8(x); // Rev in 64 + uint64_t low = vgetq_lane_u64(reinterpret_cast(x), 0); // extract + uint64_t high = vgetq_lane_u64(reinterpret_cast(x), 1); // extract + + SizeType len = 0; + bool escaped = false; + if (low == 0) { + if (high != 0) { + unsigned lz = (unsigned)__builtin_clzll(high); + len = 8 + (lz >> 3); + escaped = true; + } + } else { + unsigned lz = (unsigned)__builtin_clzll(low); + len = lz >> 3; + escaped = true; + } + if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped + char* q = reinterpret_cast(os_->PushUnsafe(len)); + for (size_t i = 0; i < len; i++) + q[i] = p[i]; + + p += len; + break; + } + vst1q_u8(reinterpret_cast(os_->PushUnsafe(16)), s); + } + + is.src_ = p; + return RAPIDJSON_LIKELY(is.Tell() < length); +} +#endif // RAPIDJSON_NEON + RAPIDJSON_NAMESPACE_END #ifdef _MSC_VER RAPIDJSON_DIAG_POP #endif +#ifdef __clang__ +RAPIDJSON_DIAG_POP +#endif + #endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/contrib/rapidjson/license.txt b/contrib/rapidjson/license.txt index 879293afa..7ccc161c8 100644 --- a/contrib/rapidjson/license.txt +++ b/contrib/rapidjson/license.txt @@ -3,7 +3,7 @@ Tencent is pleased to support the open source community by making RapidJSON avai Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. If you have downloaded a copy of the RapidJSON binary from Tencent, please note that the RapidJSON binary is licensed under the MIT License. -If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON. +If you have downloaded a copy of the RapidJSON source code from Tencent, please note that RapidJSON source code is licensed under the MIT License, except for the third-party components listed below which are subject to different license terms. Your integration of RapidJSON into your own projects may require compliance with the MIT License, as well as the other licenses applicable to the third-party components included within RapidJSON. To avoid the problematic JSON license in your own projects, it's sufficient to exclude the bin/jsonchecker/ directory, as it's the only code under the JSON license. A copy of the MIT License is included in this file. Other dependencies and licenses: diff --git a/contrib/rapidjson/readme.md b/contrib/rapidjson/readme.md index 19da38667..b833a98e8 100644 --- a/contrib/rapidjson/readme.md +++ b/contrib/rapidjson/readme.md @@ -1,17 +1,17 @@ -![](doc/logo/rapidjson.png) +![RapidJSON logo](doc/logo/rapidjson.png) -![](https://img.shields.io/badge/release-v1.0.2-blue.png) +![Release version](https://img.shields.io/badge/release-v1.1.0-blue.svg) -## A fast JSON parser/generator for C++ with both SAX/DOM style API +## A fast JSON parser/generator for C++ with both SAX/DOM style API Tencent is pleased to support the open source community by making RapidJSON available. Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. -* [RapidJSON GitHub](https://github.com/miloyip/rapidjson/) +* [RapidJSON GitHub](https://github.com/Tencent/rapidjson/) * RapidJSON Documentation - * [English](http://miloyip.github.io/rapidjson/) - * [简体中文](http://miloyip.github.io/rapidjson/zh-cn/) + * [English](http://rapidjson.org/) + * [简体中文](http://rapidjson.org/zh-cn/) * [GitBook](https://www.gitbook.com/book/miloyip/rapidjson/) with downloadable PDF/EPUB/MOBI, without API reference. ## Build status @@ -20,33 +20,43 @@ Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights | :---------------: | :-----------------: | :-------------------: | | ![lin-badge] | ![win-badge] | ![cov-badge] | -[lin-badge]: https://travis-ci.org/miloyip/rapidjson.png?branch=master "Travis build status" -[lin-link]: https://travis-ci.org/miloyip/rapidjson "Travis build status" -[win-badge]: https://ci.appveyor.com/api/projects/status/u658dcuwxo14a8m9/branch/master "AppVeyor build status" -[win-link]: https://ci.appveyor.com/project/miloyip/rapidjson/branch/master "AppVeyor build status" -[cov-badge]: https://coveralls.io/repos/miloyip/rapidjson/badge.png?branch=master -[cov-link]: https://coveralls.io/r/miloyip/rapidjson?branch=master +[lin-badge]: https://travis-ci.org/Tencent/rapidjson.svg?branch=master "Travis build status" +[lin-link]: https://travis-ci.org/Tencent/rapidjson "Travis build status" +[win-badge]: https://ci.appveyor.com/api/projects/status/l6qulgqahcayidrf/branch/master?svg=true "AppVeyor build status" +[win-link]: https://ci.appveyor.com/project/miloyip/rapidjson-0fdqj/branch/master "AppVeyor build status" +[cov-badge]: https://coveralls.io/repos/Tencent/rapidjson/badge.svg?branch=master "Coveralls coverage" +[cov-link]: https://coveralls.io/r/Tencent/rapidjson?branch=master "Coveralls coverage" ## Introduction RapidJSON is a JSON parser and generator for C++. It was inspired by [RapidXml](http://rapidxml.sourceforge.net/). -* RapidJSON is small but complete. It supports both SAX and DOM style API. The SAX parser is only a half thousand lines of code. +* RapidJSON is **small** but **complete**. It supports both SAX and DOM style API. The SAX parser is only a half thousand lines of code. -* RapidJSON is fast. Its performance can be comparable to `strlen()`. It also optionally supports SSE2/SSE4.2 for acceleration. +* RapidJSON is **fast**. Its performance can be comparable to `strlen()`. It also optionally supports SSE2/SSE4.2 for acceleration. -* RapidJSON is self-contained. It does not depend on external libraries such as BOOST. It even does not depend on STL. +* RapidJSON is **self-contained** and **header-only**. It does not depend on external libraries such as BOOST. It even does not depend on STL. -* RapidJSON is memory friendly. Each JSON value occupies exactly 16/20 bytes for most 32/64-bit machines (excluding text string). By default it uses a fast memory allocator, and the parser allocates memory compactly during parsing. +* RapidJSON is **memory-friendly**. Each JSON value occupies exactly 16 bytes for most 32/64-bit machines (excluding text string). By default it uses a fast memory allocator, and the parser allocates memory compactly during parsing. -* RapidJSON is Unicode friendly. It supports UTF-8, UTF-16, UTF-32 (LE & BE), and their detection, validation and transcoding internally. For example, you can read a UTF-8 file and let RapidJSON transcode the JSON strings into UTF-16 in the DOM. It also supports surrogates and "\u0000" (null character). +* RapidJSON is **Unicode-friendly**. It supports UTF-8, UTF-16, UTF-32 (LE & BE), and their detection, validation and transcoding internally. For example, you can read a UTF-8 file and let RapidJSON transcode the JSON strings into UTF-16 in the DOM. It also supports surrogates and "\u0000" (null character). More features can be read [here](doc/features.md). -JSON(JavaScript Object Notation) is a light-weight data exchange format. RapidJSON should be in fully compliance with RFC7159/ECMA-404. More information about JSON can be obtained at +JSON(JavaScript Object Notation) is a light-weight data exchange format. RapidJSON should be in fully compliance with RFC7159/ECMA-404, with optional support of relaxed syntax. More information about JSON can be obtained at * [Introducing JSON](http://json.org/) -* [RFC7159: The JavaScript Object Notation (JSON) Data Interchange Format](http://www.ietf.org/rfc/rfc7159.txt) -* [Standard ECMA-404: The JSON Data Interchange Format](http://www.ecma-international.org/publications/standards/Ecma-404.htm) +* [RFC7159: The JavaScript Object Notation (JSON) Data Interchange Format](https://tools.ietf.org/html/rfc7159) +* [Standard ECMA-404: The JSON Data Interchange Format](https://www.ecma-international.org/publications/standards/Ecma-404.htm) + +## Highlights in v1.1 (2016-8-25) + +* Added [JSON Pointer](doc/pointer.md) +* Added [JSON Schema](doc/schema.md) +* Added [relaxed JSON syntax](doc/dom.md) (comment, trailing comma, NaN/Infinity) +* Iterating array/object with [C++11 Range-based for loop](doc/tutorial.md) +* Reduce memory overhead of each `Value` from 24 bytes to 16 bytes in x86-64 architecture. + +For other changes please refer to [change log](CHANGELOG.md). ## Compatibility @@ -63,9 +73,9 @@ Users can build and run the unit tests on their platform/compiler. RapidJSON is a header-only C++ library. Just copy the `include/rapidjson` folder to system or project's include path. RapidJSON uses following software as its dependencies: -* [CMake](http://www.cmake.org) as a general build tool -* (optional)[Doxygen](http://www.doxygen.org) to build documentation -* (optional)[googletest](https://code.google.com/p/googletest/) for unit and performance testing +* [CMake](https://cmake.org/) as a general build tool +* (optional) [Doxygen](http://www.doxygen.org) to build documentation +* (optional) [googletest](https://github.com/google/googletest) for unit and performance testing To generate user documentation and run tests please proceed with the steps below: @@ -74,7 +84,7 @@ To generate user documentation and run tests please proceed with the steps below 3. Change to `build` directory and run `cmake ..` command to configure your build. Windows users can do the same with cmake-gui application. 4. On Windows, build the solution found in the build directory. On Linux, run `make` from the build directory. -On successfull build you will find compiled test and example binaries in `bin` +On successful build you will find compiled test and example binaries in `bin` directory. The generated documentation will be available in `doc/html` directory of the build tree. To run tests after finished build please run `make test` or `ctest` from your build tree. You can get detailed output using `ctest @@ -126,4 +136,25 @@ The following diagram shows the process. ![simpledom](doc/diagram/simpledom.png) -More [examples](https://github.com/miloyip/rapidjson/tree/master/example) are available. +More [examples](https://github.com/Tencent/rapidjson/tree/master/example) are available: + +* DOM API + * [tutorial](https://github.com/Tencent/rapidjson/blob/master/example/tutorial/tutorial.cpp): Basic usage of DOM API. + +* SAX API + * [simplereader](https://github.com/Tencent/rapidjson/blob/master/example/simplereader/simplereader.cpp): Dumps all SAX events while parsing a JSON by `Reader`. + * [condense](https://github.com/Tencent/rapidjson/blob/master/example/condense/condense.cpp): A command line tool to rewrite a JSON, with all whitespaces removed. + * [pretty](https://github.com/Tencent/rapidjson/blob/master/example/pretty/pretty.cpp): A command line tool to rewrite a JSON with indents and newlines by `PrettyWriter`. + * [capitalize](https://github.com/Tencent/rapidjson/blob/master/example/capitalize/capitalize.cpp): A command line tool to capitalize strings in JSON. + * [messagereader](https://github.com/Tencent/rapidjson/blob/master/example/messagereader/messagereader.cpp): Parse a JSON message with SAX API. + * [serialize](https://github.com/Tencent/rapidjson/blob/master/example/serialize/serialize.cpp): Serialize a C++ object into JSON with SAX API. + * [jsonx](https://github.com/Tencent/rapidjson/blob/master/example/jsonx/jsonx.cpp): Implements a `JsonxWriter` which stringify SAX events into [JSONx](https://www-01.ibm.com/support/knowledgecenter/SS9H2Y_7.1.0/com.ibm.dp.doc/json_jsonx.html) (a kind of XML) format. The example is a command line tool which converts input JSON into JSONx format. + +* Schema + * [schemavalidator](https://github.com/Tencent/rapidjson/blob/master/example/schemavalidator/schemavalidator.cpp) : A command line tool to validate a JSON with a JSON schema. + +* Advanced + * [prettyauto](https://github.com/Tencent/rapidjson/blob/master/example/prettyauto/prettyauto.cpp): A modified version of [pretty](https://github.com/Tencent/rapidjson/blob/master/example/pretty/pretty.cpp) to automatically handle JSON with any UTF encodings. + * [parsebyparts](https://github.com/Tencent/rapidjson/blob/master/example/parsebyparts/parsebyparts.cpp): Implements an `AsyncDocumentParser` which can parse JSON in parts, using C++11 thread. + * [filterkey](https://github.com/Tencent/rapidjson/blob/master/example/filterkey/filterkey.cpp): A command line tool to remove all values with user-specified key. + * [filterkeydom](https://github.com/Tencent/rapidjson/blob/master/example/filterkeydom/filterkeydom.cpp): Same tool as above, but it demonstrates how to use a generator to populate a `Document`. diff --git a/contrib/unzip/crypt.h b/contrib/unzip/crypt.h index 622f4bc2e..2aa99c284 100644 --- a/contrib/unzip/crypt.h +++ b/contrib/unzip/crypt.h @@ -32,7 +32,7 @@ /*********************************************************************** * Return the next byte in the pseudo-random sequence */ -static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) +static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) { unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an * unpredictable manner on 16-bit systems; not a problem @@ -45,7 +45,7 @@ static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) /*********************************************************************** * Update the encryption keys with the next byte of plain text */ -static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) +static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c) { (*(pkeys+0)) = CRC32((*(pkeys+0)), c); (*(pkeys+1)) += (*(pkeys+0)) & 0xff; @@ -62,7 +62,7 @@ static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int * Initialize the encryption keys and the random header according to * the given password. */ -static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) +static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab) { *(pkeys+0) = 305419896L; *(pkeys+1) = 591751049L; diff --git a/contrib/unzip/ioapi.c b/contrib/unzip/ioapi.c index b7200df75..f1bee23e6 100644 --- a/contrib/unzip/ioapi.c +++ b/contrib/unzip/ioapi.c @@ -10,11 +10,7 @@ #include #include -# ifdef ASSIMP_BUILD_NO_OWN_ZLIB -# include -# else -# include "../zlib/zlib.h" -# endif +#include "zlib.h" #include "ioapi.h" @@ -33,40 +29,40 @@ #define SEEK_SET 0 #endif -voidpf ZCALLBACK fopen_file_func ( +voidpf ZCALLBACK fopen_file_func OF(( voidpf opaque, const char* filename, - int mode); + int mode)); -uLong ZCALLBACK fread_file_func ( +uLong ZCALLBACK fread_file_func OF(( voidpf opaque, voidpf stream, void* buf, - uLong size); + uLong size)); -uLong ZCALLBACK fwrite_file_func ( +uLong ZCALLBACK fwrite_file_func OF(( voidpf opaque, voidpf stream, const void* buf, - uLong size); + uLong size)); -long ZCALLBACK ftell_file_func ( +long ZCALLBACK ftell_file_func OF(( voidpf opaque, - voidpf stream); + voidpf stream)); -long ZCALLBACK fseek_file_func ( +long ZCALLBACK fseek_file_func OF(( voidpf opaque, voidpf stream, uLong offset, - int origin); + int origin)); -int ZCALLBACK fclose_file_func ( +int ZCALLBACK fclose_file_func OF(( voidpf opaque, - voidpf stream); + voidpf stream)); -int ZCALLBACK ferror_file_func ( +int ZCALLBACK ferror_file_func OF(( voidpf opaque, - voidpf stream); + voidpf stream)); voidpf ZCALLBACK fopen_file_func (opaque, filename, mode) diff --git a/contrib/unzip/ioapi.h b/contrib/unzip/ioapi.h index 06fdd15e9..7d457baab 100644 --- a/contrib/unzip/ioapi.h +++ b/contrib/unzip/ioapi.h @@ -35,13 +35,13 @@ extern "C" { #endif -typedef voidpf (ZCALLBACK *open_file_func) (voidpf opaque, const char* filename, int mode); -typedef uLong (ZCALLBACK *read_file_func) (voidpf opaque, voidpf stream, void* buf, uLong size); -typedef uLong (ZCALLBACK *write_file_func)(voidpf opaque, voidpf stream, const void* buf, uLong size); -typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream); -typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin); -typedef int (ZCALLBACK *close_file_func) (voidpf opaque, voidpf stream); -typedef int (ZCALLBACK *testerror_file_func) (voidpf opaque, voidpf stream); +typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); +typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); +typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); +typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); typedef struct zlib_filefunc_def_s { @@ -57,7 +57,7 @@ typedef struct zlib_filefunc_def_s -void fill_fopen_filefunc (zlib_filefunc_def* pzlib_filefunc_def); +void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); #define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) #define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) diff --git a/contrib/unzip/unzip.c b/contrib/unzip/unzip.c index af00f7d6f..fea6e8913 100644 --- a/contrib/unzip/unzip.c +++ b/contrib/unzip/unzip.c @@ -38,7 +38,12 @@ woven in by Terry Thorsen 1/2003. #include #include #include -#include "./unzip.h" +#include "zlib.h" +#include "unzip.h" + +#if ZLIB_VERNUM < 0x1270 +typedef unsigned long z_crc_t; +#endif #ifdef STDC # include @@ -146,7 +151,7 @@ typedef struct int encrypted; # ifndef NOUNCRYPT unsigned long keys[3]; /* keys defining the pseudo-random sequence */ - const unsigned long* pcrc_32_tab; + const z_crc_t* pcrc_32_tab; # endif } unz_s; @@ -162,10 +167,10 @@ typedef struct */ -local int unzlocal_getByte ( +local int unzlocal_getByte OF(( const zlib_filefunc_def* pzlib_filefunc_def, voidpf filestream, - int *pi); + int *pi)); local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi) const zlib_filefunc_def* pzlib_filefunc_def; @@ -192,10 +197,10 @@ local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi) /* =========================================================================== Reads a long in LSB order from the given gz_stream. Sets */ -local int unzlocal_getShort ( +local int unzlocal_getShort OF(( const zlib_filefunc_def* pzlib_filefunc_def, voidpf filestream, - uLong *pX); + uLong *pX)); local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX) const zlib_filefunc_def* pzlib_filefunc_def; @@ -203,7 +208,7 @@ local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX) uLong *pX; { uLong x ; - int i; + int i = 0; int err; err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); @@ -220,10 +225,10 @@ local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX) return err; } -local int unzlocal_getLong ( +local int unzlocal_getLong OF(( const zlib_filefunc_def* pzlib_filefunc_def, voidpf filestream, - uLong *pX); + uLong *pX)); local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX) const zlib_filefunc_def* pzlib_filefunc_def; @@ -231,7 +236,7 @@ local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX) uLong *pX; { uLong x ; - int i; + int i = 0; int err; err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); @@ -323,9 +328,9 @@ extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivit Locate the Central directory of a zipfile (at the end, just before the global comment) */ -local uLong unzlocal_SearchCentralDir ( +local uLong unzlocal_SearchCentralDir OF(( const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream); + voidpf filestream)); local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream) const zlib_filefunc_def* pzlib_filefunc_def; @@ -562,7 +567,7 @@ local void unzlocal_DosDateToTmuDate (ulDosDate, ptm) /* Get Info about the current file in the zipfile, with internal only info */ -local int unzlocal_GetCurrentFileInfoInternal (unzFile file, +local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file, unz_file_info *pfile_info, unz_file_info_internal *pfile_info_internal, @@ -571,7 +576,7 @@ local int unzlocal_GetCurrentFileInfoInternal (unzFile file, void *extraField, uLong extraFieldBufferSize, char *szComment, - uLong commentBufferSize); + uLong commentBufferSize)); local int unzlocal_GetCurrentFileInfoInternal (file, pfile_info, @@ -609,9 +614,13 @@ local int unzlocal_GetCurrentFileInfoInternal (file, if (err==UNZ_OK) { if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + { err=UNZ_ERRNO; + } else if (uMagic!=0x02014b50) + { err=UNZ_BADZIPFILE; + } } if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) @@ -701,8 +710,9 @@ local int unzlocal_GetCurrentFileInfoInternal (file, lSeek += file_info.size_file_extra - uSizeRead; } else + { lSeek+=file_info.size_file_extra; - + } if ((err==UNZ_OK) && (szComment!=NULL)) { @@ -713,22 +723,22 @@ local int unzlocal_GetCurrentFileInfoInternal (file, uSizeRead = file_info.size_file_comment; } else + { uSizeRead = commentBufferSize; + } if (lSeek!=0) { - if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else + if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)!=0) err=UNZ_ERRNO; } if ((file_info.size_file_comment>0) && (commentBufferSize>0)) if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) err=UNZ_ERRNO; - lSeek+=file_info.size_file_comment - uSizeRead; } else - lSeek+=file_info.size_file_comment; + { + } if ((err==UNZ_OK) && (pfile_info!=NULL)) *pfile_info=file_info; @@ -988,7 +998,7 @@ local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar, else if (uMagic!=0x04034b50) err=UNZ_BADZIPFILE; } - + if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) err=UNZ_ERRNO; /* @@ -1119,7 +1129,7 @@ extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password) if ((s->cur_file_info.compression_method!=0) && (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; + return UNZ_BADZIPFILE; pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; pfile_in_zip_read_info->crc32=0; @@ -1541,6 +1551,7 @@ extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf) char *szComment; uLong uSizeBuf; { + int err=UNZ_OK; unz_s* s; uLong uReadThis ; if (file==NULL) diff --git a/contrib/unzip/unzip.h b/contrib/unzip/unzip.h index e3b7f24ee..b247937c8 100644 --- a/contrib/unzip/unzip.h +++ b/contrib/unzip/unzip.h @@ -50,11 +50,7 @@ extern "C" { #endif #ifndef _ZLIB_H -# ifdef ASSIMP_BUILD_NO_OWN_ZLIB -# include -# else -# include "../zlib/zlib.h" -# endif +#include "zlib.h" #endif #ifndef _ZLIBIOAPI_H @@ -123,9 +119,9 @@ typedef struct unz_file_info_s tm_unz tmu_date; } unz_file_info; -extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, const char* fileName2, - int iCaseSensitivity); + int iCaseSensitivity)); /* Compare two filename (fileName1,fileName2). If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) @@ -136,7 +132,7 @@ extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, */ -extern unzFile ZEXPORT unzOpen (const char *path); +extern unzFile ZEXPORT unzOpen OF((const char *path)); /* Open a Zip file. path contain the full pathname (by example, on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer @@ -147,31 +143,31 @@ extern unzFile ZEXPORT unzOpen (const char *path); of this unzip package. */ -extern unzFile ZEXPORT unzOpen2 (const char *path, - zlib_filefunc_def* pzlib_filefunc_def); +extern unzFile ZEXPORT unzOpen2 OF((const char *path, + zlib_filefunc_def* pzlib_filefunc_def)); /* Open a Zip file, like unzOpen, but provide a set of file low level API for read/write the zip file (see ioapi.h) */ -extern int ZEXPORT unzClose (unzFile file); +extern int ZEXPORT unzClose OF((unzFile file)); /* Close a ZipFile opened with unzipOpen. If there is files inside the .Zip opened with unzOpenCurrentFile (see later), these files MUST be closed with unzipCloseCurrentFile before call unzipClose. return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalInfo (unzFile file, - unz_global_info *pglobal_info); +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); /* Write info about the ZipFile in the *pglobal_info structure. No preparation of the structure is needed return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalComment (unzFile file, +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, char *szComment, - uLong uSizeBuf); + uLong uSizeBuf)); /* Get the global comment string of the ZipFile, in the szComment buffer. uSizeBuf is the size of the szComment buffer. @@ -182,22 +178,22 @@ extern int ZEXPORT unzGetGlobalComment (unzFile file, /***************************************************************************/ /* Unzip package allow you browse the directory of the zipfile */ -extern int ZEXPORT unzGoToFirstFile (unzFile file); +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); /* Set the current file of the zipfile to the first file. return UNZ_OK if there is no problem */ -extern int ZEXPORT unzGoToNextFile (unzFile file); +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); /* Set the current file of the zipfile to the next file. return UNZ_OK if there is no problem return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. */ -extern int ZEXPORT unzLocateFile (unzFile file, +extern int ZEXPORT unzLocateFile OF((unzFile file, const char *szFileName, - int iCaseSensitivity); + int iCaseSensitivity)); /* Try locate the file szFileName in the zipfile. For the iCaseSensitivity signification, see unzStringFileNameCompare @@ -227,14 +223,14 @@ extern int ZEXPORT unzGoToFilePos( /* ****************************************** */ -extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, unz_file_info *pfile_info, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, - uLong commentBufferSize); + uLong commentBufferSize)); /* Get Info about the current file if pfile_info!=NULL, the *pfile_info structure will contain somes info about @@ -253,24 +249,24 @@ extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, from it, and close it (you can close it before reading all the file) */ -extern int ZEXPORT unzOpenCurrentFile (unzFile file); +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); /* Open for reading data the current file in the zipfile. If there is no error, the return value is UNZ_OK. */ -extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, - const char* password); +extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, + const char* password)); /* Open for reading data the current file in the zipfile. password is a crypting password If there is no error, the return value is UNZ_OK. */ -extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, +extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, int* method, int* level, - int raw); + int raw)); /* Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) if raw==1 @@ -280,11 +276,11 @@ extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, but you CANNOT set method parameter as NULL */ -extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, +extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, int* method, int* level, int raw, - const char* password); + const char* password)); /* Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) if raw==1 @@ -295,15 +291,15 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, */ -extern int ZEXPORT unzCloseCurrentFile (unzFile file); +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); /* Close the file in zip opened with unzOpenCurrentFile Return UNZ_CRCERROR if all the file was read but the CRC is not good */ -extern int ZEXPORT unzReadCurrentFile (unzFile file, +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, voidp buf, - unsigned len); + unsigned len)); /* Read bytes from the current file (opened by unzOpenCurrentFile) buf contain buffer where data must be copied @@ -315,19 +311,19 @@ extern int ZEXPORT unzReadCurrentFile (unzFile file, (UNZ_ERRNO for IO error, or zLib error for uncompress error) */ -extern z_off_t ZEXPORT unztell (unzFile file); +extern z_off_t ZEXPORT unztell OF((unzFile file)); /* Give the current position in uncompressed data */ -extern int ZEXPORT unzeof (unzFile file); +extern int ZEXPORT unzeof OF((unzFile file)); /* return 1 if the end of file was reached, 0 elsewhere */ -extern int ZEXPORT unzGetLocalExtrafield (unzFile file, +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, voidp buf, - unsigned len); + unsigned len)); /* Read extra field from the current file (opened by unzOpenCurrentFile) This is the local-header version of the extra field (sometimes, there is diff --git a/contrib/utf8cpp/doc/ReleaseNotes b/contrib/utf8cpp/doc/ReleaseNotes new file mode 100644 index 000000000..364411a23 --- /dev/null +++ b/contrib/utf8cpp/doc/ReleaseNotes @@ -0,0 +1,12 @@ +utf8 cpp library +Release 2.3.4 + +A minor bug fix release. Thanks to all who reported bugs. + +Note: Version 2.3.3 contained a regression, and therefore was removed. + +Changes from version 2.3.2 +- Bug fix [39]: checked.h Line 273 and unchecked.h Line 182 have an extra ';' +- Bug fix [36]: replace_invalid() only works with back_inserter + +Files included in the release: utf8.h, core.h, checked.h, unchecked.h, utf8cpp.html, ReleaseNotes diff --git a/contrib/utf8cpp/doc/utf8cpp.html b/contrib/utf8cpp/doc/utf8cpp.html new file mode 100644 index 000000000..6f2aacbe7 --- /dev/null +++ b/contrib/utf8cpp/doc/utf8cpp.html @@ -0,0 +1,1789 @@ + + + + + + + + + UTF8-CPP: UTF-8 with C++ in a Portable Way + + + + +

+ UTF8-CPP: UTF-8 with C++ in a Portable Way +

+

+ The Sourceforge project page +

+ +

+ Introduction +

+

+ Many C++ developers miss an easy and portable way of handling Unicode encoded + strings. The original C++ Standard (known as C++98 or C++03) is Unicode agnostic. + C++11 provides some support for Unicode on core language and library level: + u8, u, and U character and string literals, char16_t and char32_t character types, + u16string and u32string library classes, and codecvt support for conversions + between Unicode encoding forms. + In the meantime, developers use third party libraries like ICU, OS specific capabilities, or simply + roll out their own solutions. +

+

+ In order to easily handle UTF-8 encoded Unicode strings, I came up with a small + generic library. For anybody used to work with STL algorithms and iterators, it should be + easy and natural to use. The code is freely available for any purpose - check out + the license at the beginning of the utf8.h file. If you run into + bugs or performance issues, please let me know and I'll do my best to address them. +

+

+ The purpose of this article is not to offer an introduction to Unicode in general, + and UTF-8 in particular. If you are not familiar with Unicode, be sure to check out + Unicode Home Page or some other source of + information for Unicode. Also, it is not my aim to advocate the use of UTF-8 + encoded strings in C++ programs; if you want to handle UTF-8 encoded strings from + C++, I am sure you have good reasons for it. +

+

+ Examples of use +

+

+ Introductionary Sample +

+

+ To illustrate the use of the library, let's start with a small but complete program + that opens a file containing UTF-8 encoded text, reads it line by line, checks each line + for invalid UTF-8 byte sequences, and converts it to UTF-16 encoding and back to UTF-8: +

+
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+#include "utf8.h"
+using namespace std;
+int main(int argc, char** argv)
+{
+    if (argc != 2) {
+        cout << "\nUsage: docsample filename\n";
+        return 0;
+    }
+
+    const char* test_file_path = argv[1];
+    // Open the test file (contains UTF-8 encoded text)
+    ifstream fs8(test_file_path);
+    if (!fs8.is_open()) {
+    cout << "Could not open " << test_file_path << endl;
+    return 0;
+    }
+
+    unsigned line_count = 1;
+    string line;
+    // Play with all the lines in the file
+    while (getline(fs8, line)) {
+       // check for invalid utf-8 (for a simple yes/no check, there is also utf8::is_valid function)
+        string::iterator end_it = utf8::find_invalid(line.begin(), line.end());
+        if (end_it != line.end()) {
+            cout << "Invalid UTF-8 encoding detected at line " << line_count << "\n";
+            cout << "This part is fine: " << string(line.begin(), end_it) << "\n";
+        }
+
+        // Get the line length (at least for the valid part)
+        int length = utf8::distance(line.begin(), end_it);
+        cout << "Length of line " << line_count << " is " << length <<  "\n";
+
+        // Convert it to utf-16
+        vector<unsigned short> utf16line;
+        utf8::utf8to16(line.begin(), end_it, back_inserter(utf16line));
+
+        // And back to utf-8
+        string utf8line; 
+        utf8::utf16to8(utf16line.begin(), utf16line.end(), back_inserter(utf8line));
+
+        // Confirm that the conversion went OK:
+        if (utf8line != string(line.begin(), end_it))
+            cout << "Error in UTF-16 conversion at line: " << line_count << "\n";        
+
+        line_count++;
+    }
+    return 0;
+}
+
+

+ In the previous code sample, for each line we performed + a detection of invalid UTF-8 sequences with find_invalid; the number + of characters (more precisely - the number of Unicode code points, including the end + of line and even BOM if there is one) in each line was + determined with a use of utf8::distance; finally, we have converted + each line to UTF-16 encoding with utf8to16 and back to UTF-8 with + utf16to8. +

+

Checking if a file contains valid UTF-8 text

+

+Here is a function that checks whether the content of a file is valid UTF-8 encoded text without +reading the content into the memory: +

+
    
+bool valid_utf8_file(iconst char* file_name)
+{
+    ifstream ifs(file_name);
+    if (!ifs)
+        return false; // even better, throw here
+
+    istreambuf_iterator<char> it(ifs.rdbuf());
+    istreambuf_iterator<char> eos;
+
+    return utf8::is_valid(it, eos);
+}
+
+

+Because the function utf8::is_valid() works with input iterators, we were able +to pass an istreambuf_iterator to it and read the content of the file directly +without loading it to the memory first.

+

+Note that other functions that take input iterator arguments can be used in a similar way. For +instance, to read the content of a UTF-8 encoded text file and convert the text to UTF-16, just +do something like: +

+
+    utf8::utf8to16(it, eos, back_inserter(u16string));
+
+

Ensure that a string contains valid UTF-8 text

+

+If we have some text that "probably" contains UTF-8 encoded text and we want to +replace any invalid UTF-8 sequence with a replacement character, something like +the following function may be used: +

+
+void fix_utf8_string(std::string& str)
+{
+    std::string temp;
+    utf8::replace_invalid(str.begin(), str.end(), back_inserter(temp));
+    str = temp;
+}
+
+

The function will replace any invalid UTF-8 sequence with a Unicode replacement character. +There is an overloaded function that enables the caller to supply their own replacement character. +

+

+ Reference +

+

+ Functions From utf8 Namespace +

+

+ utf8::append +

+

+ Available in version 1.0 and later. +

+

+ Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence + to a UTF-8 string. +

+
+template <typename octet_iterator>
+octet_iterator append(uint32_t cp, octet_iterator result);
+   
+
+

+ octet_iterator: an output iterator.
+ cp: a 32 bit integer representing a code point to append to the + sequence.
+ result: an output iterator to the place in the sequence where to + append the code point.
+ Return value: an iterator pointing to the place + after the newly appended sequence. +

+

+ Example of use: +

+
+unsigned char u[5] = {0,0,0,0,0};
+unsigned char* end = append(0x0448, u);
+assert (u[0] == 0xd1 && u[1] == 0x88 && u[2] == 0 && u[3] == 0 && u[4] == 0);
+
+

+ Note that append does not allocate any memory - it is the burden of + the caller to make sure there is enough memory allocated for the operation. To make + things more interesting, append can add anywhere between 1 and 4 + octets to the sequence. In practice, you would most often want to use + std::back_inserter to ensure that the necessary memory is allocated. +

+

+ In case of an invalid code point, a utf8::invalid_code_point exception + is thrown. +

+

+ utf8::next +

+

+ Available in version 1.0 and later. +

+

+ Given the iterator to the beginning of the UTF-8 sequence, it returns the code + point and moves the iterator to the next position. +

+
+template <typename octet_iterator> 
+uint32_t next(octet_iterator& it, octet_iterator end);
+   
+
+

+ octet_iterator: an input iterator.
+ it: a reference to an iterator pointing to the beginning of an UTF-8 + encoded code point. After the function returns, it is incremented to point to the + beginning of the next code point.
+ end: end of the UTF-8 sequence to be processed. If it + gets equal to end during the extraction of a code point, an + utf8::not_enough_room exception is thrown.
+ Return value: the 32 bit representation of the + processed UTF-8 code point. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+int cp = next(w, twochars + 6);
+assert (cp == 0x65e5);
+assert (w == twochars + 3);
+
+

+ This function is typically used to iterate through a UTF-8 encoded string. +

+

+ In case of an invalid UTF-8 seqence, a utf8::invalid_utf8 exception is + thrown. +

+

+ utf8::peek_next +

+

+ Available in version 2.1 and later. +

+

+ Given the iterator to the beginning of the UTF-8 sequence, it returns the code + point for the following sequence without changing the value of the iterator. +

+
+template <typename octet_iterator> 
+uint32_t peek_next(octet_iterator it, octet_iterator end);
+   
+
+

+ octet_iterator: an input iterator.
+ it: an iterator pointing to the beginning of an UTF-8 + encoded code point.
+ end: end of the UTF-8 sequence to be processed. If it + gets equal to end during the extraction of a code point, an + utf8::not_enough_room exception is thrown.
+ Return value: the 32 bit representation of the + processed UTF-8 code point. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+int cp = peek_next(w, twochars + 6);
+assert (cp == 0x65e5);
+assert (w == twochars);
+
+

+ In case of an invalid UTF-8 seqence, a utf8::invalid_utf8 exception is + thrown. +

+

+ utf8::prior +

+

+ Available in version 1.02 and later. +

+

+ Given a reference to an iterator pointing to an octet in a UTF-8 sequence, it + decreases the iterator until it hits the beginning of the previous UTF-8 encoded + code point and returns the 32 bits representation of the code point. +

+
+template <typename octet_iterator> 
+uint32_t prior(octet_iterator& it, octet_iterator start);
+   
+
+

+ octet_iterator: a bidirectional iterator.
+ it: a reference pointing to an octet within a UTF-8 encoded string. + After the function returns, it is decremented to point to the beginning of the + previous code point.
+ start: an iterator to the beginning of the sequence where the search + for the beginning of a code point is performed. It is a + safety measure to prevent passing the beginning of the string in the search for a + UTF-8 lead octet.
+ Return value: the 32 bit representation of the + previous code point. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+unsigned char* w = twochars + 3;
+int cp = prior (w, twochars);
+assert (cp == 0x65e5);
+assert (w == twochars);
+
+

+ This function has two purposes: one is two iterate backwards through a UTF-8 + encoded string. Note that it is usually a better idea to iterate forward instead, + since utf8::next is faster. The second purpose is to find a beginning + of a UTF-8 sequence if we have a random position within a string. Note that in that + case utf8::prior may not detect an invalid UTF-8 sequence in some scenarios: + for instance if there are superfluous trail octets, it will just skip them. +

+

+ it will typically point to the beginning of + a code point, and start will point to the + beginning of the string to ensure we don't go backwards too far. it is + decreased until it points to a lead UTF-8 octet, and then the UTF-8 sequence + beginning with that octet is decoded to a 32 bit representation and returned. +

+

+ In case start is reached before a UTF-8 lead octet is hit, or if an + invalid UTF-8 sequence is started by the lead octet, an invalid_utf8 + exception is thrown. +

+

In case start equals it, a not_enough_room + exception is thrown. +

+ utf8::previous +

+

+ Deprecated in version 1.02 and later. +

+

+ Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it + decreases the iterator until it hits the beginning of the previous UTF-8 encoded + code point and returns the 32 bits representation of the code point. +

+
+template <typename octet_iterator> 
+uint32_t previous(octet_iterator& it, octet_iterator pass_start);
+   
+
+

+ octet_iterator: a random access iterator.
+ it: a reference pointing to an octet within a UTF-8 encoded string. + After the function returns, it is decremented to point to the beginning of the + previous code point.
+ pass_start: an iterator to the point in the sequence where the search + for the beginning of a code point is aborted if no result was reached. It is a + safety measure to prevent passing the beginning of the string in the search for a + UTF-8 lead octet.
+ Return value: the 32 bit representation of the + previous code point. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+unsigned char* w = twochars + 3;
+int cp = previous (w, twochars - 1);
+assert (cp == 0x65e5);
+assert (w == twochars);
+
+

+ utf8::previous is deprecated, and utf8::prior should + be used instead, although the existing code can continue using this function. + The problem is the parameter pass_start that points to the position + just before the beginning of the sequence. Standard containers don't have the + concept of "pass start" and the function can not be used with their iterators. +

+

+ it will typically point to the beginning of + a code point, and pass_start will point to the octet just before the + beginning of the string to ensure we don't go backwards too far. it is + decreased until it points to a lead UTF-8 octet, and then the UTF-8 sequence + beginning with that octet is decoded to a 32 bit representation and returned. +

+

+ In case pass_start is reached before a UTF-8 lead octet is hit, or if an + invalid UTF-8 sequence is started by the lead octet, an invalid_utf8 + exception is thrown +

+

+ utf8::advance +

+

+ Available in version 1.0 and later. +

+

+ Advances an iterator by the specified number of code points within an UTF-8 + sequence. +

+
+template <typename octet_iterator, typename distance_type> 
+void advance (octet_iterator& it, distance_type n, octet_iterator end);
+   
+
+

+ octet_iterator: an input iterator.
+ distance_type: an integral type convertible to octet_iterator's difference type.
+ it: a reference to an iterator pointing to the beginning of an UTF-8 + encoded code point. After the function returns, it is incremented to point to the + nth following code point.
+ n: a positive integer that shows how many code points we want to + advance.
+ end: end of the UTF-8 sequence to be processed. If it + gets equal to end during the extraction of a code point, an + utf8::not_enough_room exception is thrown.
+

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+unsigned char* w = twochars;
+advance (w, 2, twochars + 6);
+assert (w == twochars + 5);
+
+

+ This function works only "forward". In case of a negative n, there is + no effect. +

+

+ In case of an invalid code point, a utf8::invalid_code_point exception + is thrown. +

+

+ utf8::distance +

+

+ Available in version 1.0 and later. +

+

+ Given the iterators to two UTF-8 encoded code points in a seqence, returns the + number of code points between them. +

+
+template <typename octet_iterator> 
+typename std::iterator_traits<octet_iterator>::difference_type distance (octet_iterator first, octet_iterator last);
+   
+
+

+ octet_iterator: an input iterator.
+ first: an iterator to a beginning of a UTF-8 encoded code point.
+ last: an iterator to a "post-end" of the last UTF-8 encoded code + point in the sequence we are trying to determine the length. It can be the + beginning of a new code point, or not.
+ Return value the distance between the iterators, + in code points. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+size_t dist = utf8::distance(twochars, twochars + 5);
+assert (dist == 2);
+
+

+ This function is used to find the length (in code points) of a UTF-8 encoded + string. The reason it is called distance, rather than, say, + length is mainly because developers are used that length is an + O(1) function. Computing the length of an UTF-8 string is a linear operation, and + it looked better to model it after std::distance algorithm. +

+

+ In case of an invalid UTF-8 seqence, a utf8::invalid_utf8 exception is + thrown. If last does not point to the past-of-end of a UTF-8 seqence, + a utf8::not_enough_room exception is thrown. +

+

+ utf8::utf16to8 +

+

+ Available in version 1.0 and later. +

+

+ Converts a UTF-16 encoded string to UTF-8. +

+
+template <typename u16bit_iterator, typename octet_iterator>
+octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
+   
+
+

+ u16bit_iterator: an input iterator.
+ octet_iterator: an output iterator.
+ start: an iterator pointing to the beginning of the UTF-16 encoded + string to convert.
+ end: an iterator pointing to pass-the-end of the UTF-16 encoded + string to convert.
+ result: an output iterator to the place in the UTF-8 string where to + append the result of conversion.
+ Return value: An iterator pointing to the place + after the appended UTF-8 string. +

+

+ Example of use: +

+
+unsigned short utf16string[] = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+vector<unsigned char> utf8result;
+utf16to8(utf16string, utf16string + 5, back_inserter(utf8result));
+assert (utf8result.size() == 10);    
+
+

+ In case of invalid UTF-16 sequence, a utf8::invalid_utf16 exception is + thrown. +

+

+ utf8::utf8to16 +

+

+ Available in version 1.0 and later. +

+

+ Converts an UTF-8 encoded string to UTF-16 +

+
+template <typename u16bit_iterator, typename octet_iterator>
+u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
+   
+
+

+ octet_iterator: an input iterator.
+ u16bit_iterator: an output iterator.
+ start: an iterator pointing to the beginning of the UTF-8 encoded + string to convert. < br /> end: an iterator pointing to + pass-the-end of the UTF-8 encoded string to convert.
+ result: an output iterator to the place in the UTF-16 string where to + append the result of conversion.
+ Return value: An iterator pointing to the place + after the appended UTF-16 string. +

+

+ Example of use: +

+
+char utf8_with_surrogates[] = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+vector <unsigned short> utf16result;
+utf8to16(utf8_with_surrogates, utf8_with_surrogates + 9, back_inserter(utf16result));
+assert (utf16result.size() == 4);
+assert (utf16result[2] == 0xd834);
+assert (utf16result[3] == 0xdd1e);
+
+

+ In case of an invalid UTF-8 seqence, a utf8::invalid_utf8 exception is + thrown. If end does not point to the past-of-end of a UTF-8 seqence, a + utf8::not_enough_room exception is thrown. +

+

+ utf8::utf32to8 +

+

+ Available in version 1.0 and later. +

+

+ Converts a UTF-32 encoded string to UTF-8. +

+
+template <typename octet_iterator, typename u32bit_iterator>
+octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
+   
+
+

+ octet_iterator: an output iterator.
+ u32bit_iterator: an input iterator.
+ start: an iterator pointing to the beginning of the UTF-32 encoded + string to convert.
+ end: an iterator pointing to pass-the-end of the UTF-32 encoded + string to convert.
+ result: an output iterator to the place in the UTF-8 string where to + append the result of conversion.
+ Return value: An iterator pointing to the place + after the appended UTF-8 string. +

+

+ Example of use: +

+
+int utf32string[] = {0x448, 0x65E5, 0x10346, 0};
+vector<unsigned char> utf8result;
+utf32to8(utf32string, utf32string + 3, back_inserter(utf8result));
+assert (utf8result.size() == 9);
+
+

+ In case of invalid UTF-32 string, a utf8::invalid_code_point exception + is thrown. +

+

+ utf8::utf8to32 +

+

+ Available in version 1.0 and later. +

+

+ Converts a UTF-8 encoded string to UTF-32. +

+
+template <typename octet_iterator, typename u32bit_iterator>
+u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
+   
+
+

+ octet_iterator: an input iterator.
+ u32bit_iterator: an output iterator.
+ start: an iterator pointing to the beginning of the UTF-8 encoded + string to convert.
+ end: an iterator pointing to pass-the-end of the UTF-8 encoded string + to convert.
+ result: an output iterator to the place in the UTF-32 string where to + append the result of conversion.
+ Return value: An iterator pointing to the place + after the appended UTF-32 string. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+vector<int> utf32result;
+utf8to32(twochars, twochars + 5, back_inserter(utf32result));
+assert (utf32result.size() == 2);
+
+

+ In case of an invalid UTF-8 seqence, a utf8::invalid_utf8 exception is + thrown. If end does not point to the past-of-end of a UTF-8 seqence, a + utf8::not_enough_room exception is thrown. +

+

+ utf8::find_invalid +

+

+ Available in version 1.0 and later. +

+

+ Detects an invalid sequence within a UTF-8 string. +

+
+template <typename octet_iterator> 
+octet_iterator find_invalid(octet_iterator start, octet_iterator end);
+
+

+ octet_iterator: an input iterator.
+ start: an iterator pointing to the beginning of the UTF-8 string to + test for validity.
+ end: an iterator pointing to pass-the-end of the UTF-8 string to test + for validity.
+ Return value: an iterator pointing to the first + invalid octet in the UTF-8 string. In case none were found, equals + end. +

+

+ Example of use: +

+
+char utf_invalid[] = "\xe6\x97\xa5\xd1\x88\xfa";
+char* invalid = find_invalid(utf_invalid, utf_invalid + 6);
+assert (invalid == utf_invalid + 5);
+
+

+ This function is typically used to make sure a UTF-8 string is valid before + processing it with other functions. It is especially important to call it if before + doing any of the unchecked operations on it. +

+

+ utf8::is_valid +

+

+ Available in version 1.0 and later. +

+

+ Checks whether a sequence of octets is a valid UTF-8 string. +

+
+template <typename octet_iterator> 
+bool is_valid(octet_iterator start, octet_iterator end);
+   
+
+

+ octet_iterator: an input iterator.
+ start: an iterator pointing to the beginning of the UTF-8 string to + test for validity.
+ end: an iterator pointing to pass-the-end of the UTF-8 string to test + for validity.
+ Return value: true if the sequence + is a valid UTF-8 string; false if not. +

+ Example of use: +
+char utf_invalid[] = "\xe6\x97\xa5\xd1\x88\xfa";
+bool bvalid = is_valid(utf_invalid, utf_invalid + 6);
+assert (bvalid == false);
+
+

+ is_valid is a shorthand for find_invalid(start, end) == + end;. You may want to use it to make sure that a byte seqence is a valid + UTF-8 string without the need to know where it fails if it is not valid. +

+

+ utf8::replace_invalid +

+

+ Available in version 2.0 and later. +

+

+ Replaces all invalid UTF-8 sequences within a string with a replacement marker. +

+
+template <typename octet_iterator, typename output_iterator>
+output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement);
+template <typename octet_iterator, typename output_iterator>
+output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out);
+   
+
+

+ octet_iterator: an input iterator.
+ output_iterator: an output iterator.
+ start: an iterator pointing to the beginning of the UTF-8 string to + look for invalid UTF-8 sequences.
+ end: an iterator pointing to pass-the-end of the UTF-8 string to look + for invalid UTF-8 sequences.
+ out: An output iterator to the range where the result of replacement + is stored.
+ replacement: A Unicode code point for the replacement marker. The + version without this parameter assumes the value 0xfffd
+ Return value: An iterator pointing to the place + after the UTF-8 string with replaced invalid sequences. +

+

+ Example of use: +

+
+char invalid_sequence[] = "a\x80\xe0\xa0\xc0\xaf\xed\xa0\x80z";
+vector<char> replace_invalid_result;
+replace_invalid (invalid_sequence, invalid_sequence + sizeof(invalid_sequence), back_inserter(replace_invalid_result), '?');
+bvalid = is_valid(replace_invalid_result.begin(), replace_invalid_result.end());
+assert (bvalid);
+char* fixed_invalid_sequence = "a????z";
+assert (std::equal(replace_invalid_result.begin(), replace_invalid_result.end(), fixed_invalid_sequence));
+
+

+ replace_invalid does not perform in-place replacement of invalid + sequences. Rather, it produces a copy of the original string with the invalid + sequences replaced with a replacement marker. Therefore, out must not + be in the [start, end] range. +

+

+ If end does not point to the past-of-end of a UTF-8 sequence, a + utf8::not_enough_room exception is thrown. +

+

+ utf8::starts_with_bom +

+

+ Available in version 2.3 and later. Relaces deprecated is_bom() function. +

+

+ Checks whether an octet sequence starts with a UTF-8 byte order mark (BOM) +

+
+template <typename octet_iterator> 
+bool starts_with_bom (octet_iterator it, octet_iterator end);
+
+

+ octet_iterator: an input iterator.
+ it: beginning of the octet sequence to check
+ end: pass-end of the sequence to check
+ Return value: true if the sequence + starts with a UTF-8 byte order mark; false if not. +

+

+ Example of use: +

+
+unsigned char byte_order_mark[] = {0xef, 0xbb, 0xbf};
+bool bbom = starts_with_bom(byte_order_mark, byte_order_mark + sizeof(byte_order_mark));
+assert (bbom == true);
+
+

+ The typical use of this function is to check the first three bytes of a file. If + they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8 + encoded text. +

+

+ utf8::is_bom +

+

+ Available in version 1.0 and later. Deprecated in version 2.3. starts_with_bom() should be used + instead. +

+

+ Checks whether a sequence of three octets is a UTF-8 byte order mark (BOM) +

+
+template <typename octet_iterator> 
+bool is_bom (octet_iterator it);  // Deprecated
+
+

+ octet_iterator: an input iterator.
+ it: beginning of the 3-octet sequence to check
+ Return value: true if the sequence + is UTF-8 byte order mark; false if not. +

+

+ Example of use: +

+
+unsigned char byte_order_mark[] = {0xef, 0xbb, 0xbf};
+bool bbom = is_bom(byte_order_mark);
+assert (bbom == true);
+
+

+ The typical use of this function is to check the first three bytes of a file. If + they form the UTF-8 BOM, we want to skip them before processing the actual UTF-8 + encoded text. +

+

+ If a sequence is + shorter than three bytes, an invalid iterator will be dereferenced. Therefore, this function is deprecated + in favor of starts_with_bom()that takes the end of sequence as an argument. +

+

+ Types From utf8 Namespace +

+

utf8::exception +

+

+ Available in version 2.3 and later. +

+

+ Base class for the exceptions thrown by UTF CPP library functions. +

+
+class exception : public std::exception {};
+
+

+ Example of use: +

+
+try {
+  code_that_uses_utf_cpp_library();
+}
+catch(const utf8::exception& utfcpp_ex) {
+  cerr << utfcpp_ex.what();
+}
+
+ +

utf8::invalid_code_point +

+

+ Available in version 1.0 and later. +

+

+ Thrown by UTF8 CPP functions such as advance and next if an UTF-8 sequence represents and invalid code point. +

+ +
+class invalid_code_point : public exception {
+public: 
+    uint32_t code_point() const;
+};
+
+
+

+ Member function code_point() can be used to determine the invalid code point that + caused the exception to be thrown. +

+

utf8::invalid_utf8 +

+

+ Available in version 1.0 and later. +

+

+ Thrown by UTF8 CPP functions such as next and prior if an invalid UTF-8 sequence + is detected during decoding. +

+ +
+class invalid_utf8 : public exception {
+public: 
+    uint8_t utf8_octet() const;
+};
+
+ +

+ Member function utf8_octet() can be used to determine the beginning of the byte + sequence that caused the exception to be thrown. +

+ +

utf8::invalid_utf16 +

+

+ Available in version 1.0 and later. +

+

+ Thrown by UTF8 CPP function utf16to8 if an invalid UTF-16 sequence + is detected during decoding. +

+ +
+class invalid_utf16 : public exception {
+public: 
+    uint16_t utf16_word() const;
+};
+
+ +

+ Member function utf16_word() can be used to determine the UTF-16 code unit + that caused the exception to be thrown. +

+

utf8::not_enough_room +

+

+ Available in version 1.0 and later. +

+

+ Thrown by UTF8 CPP functions such as next if the end of the decoded UTF-8 sequence + was reached before the code point was decoded. +

+ +
+class not_enough_room : public exception {};
+
+

+ utf8::iterator +

+

+ Available in version 2.0 and later. +

+

+ Adapts the underlying octet iterator to iterate over the sequence of code points, + rather than raw octets. +

+
+template <typename octet_iterator>
+class iterator;
+
+ +
Member functions
+
+
iterator();
the deafult constructor; the underlying octet_iterator is + constructed with its default constructor. +
explicit iterator (const octet_iterator& octet_it, + const octet_iterator& range_start, + const octet_iterator& range_end);
a constructor + that initializes the underlying octet_iterator with octet_it + and sets the range in which the iterator is considered valid. +
octet_iterator base () const;
returns the + underlying octet_iterator. +
uint32_t operator * () const;
decodes the utf-8 sequence + the underlying octet_iterator is pointing to and returns the code point. +
bool operator == (const iterator& rhs) + const;
returns true + if the two underlaying iterators are equal. +
bool operator != (const iterator& rhs) + const;
returns true + if the two underlaying iterators are not equal. +
iterator& operator ++ ();
the prefix increment - moves + the iterator to the next UTF-8 encoded code point. +
iterator operator ++ (int);
+ the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one. +
iterator& operator -- ();
the prefix decrement - moves + the iterator to the previous UTF-8 encoded code point. +
iterator operator -- (int);
+ the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one. +
+

+ Example of use: +

+
+char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+utf8::iterator<char*> it(threechars, threechars, threechars + 9);
+utf8::iterator<char*> it2 = it;
+assert (it2 == it);
+assert (*it == 0x10346);
+assert (*(++it) == 0x65e5);
+assert ((*it++) == 0x65e5);
+assert (*it == 0x0448);
+assert (it != it2);
+utf8::iterator<char*> endit (threechars + 9, threechars, threechars + 9);  
+assert (++it == endit);
+assert (*(--it) == 0x0448);
+assert ((*it--) == 0x0448);
+assert (*it == 0x65e5);
+assert (--it == utf8::iterator<char*>(threechars, threechars, threechars + 9));
+assert (*it == 0x10346);
+
+

+ The purpose of utf8::iterator adapter is to enable easy iteration as well as the use of STL + algorithms with UTF-8 encoded strings. Increment and decrement operators are implemented in terms of + utf8::next() and utf8::prior() functions. +

+

+ Note that utf8::iterator adapter is a checked iterator. It operates on the range specified in + the constructor; any attempt to go out of that range will result in an exception. Even the comparison operators + require both iterator object to be constructed against the same range - otherwise an exception is thrown. Typically, + the range will be determined by sequence container functions begin and end, i.e.: +

+
+std::string s = "example";
+utf8::iterator i (s.begin(), s.begin(), s.end());
+
+

+ Functions From utf8::unchecked Namespace +

+

+ utf8::unchecked::append +

+

+ Available in version 1.0 and later. +

+

+ Encodes a 32 bit code point as a UTF-8 sequence of octets and appends the sequence + to a UTF-8 string. +

+
+template <typename octet_iterator>
+octet_iterator append(uint32_t cp, octet_iterator result);
+   
+
+

+ cp: A 32 bit integer representing a code point to append to the + sequence.
+ result: An output iterator to the place in the sequence where to + append the code point.
+ Return value: An iterator pointing to the place + after the newly appended sequence. +

+

+ Example of use: +

+
+unsigned char u[5] = {0,0,0,0,0};
+unsigned char* end = unchecked::append(0x0448, u);
+assert (u[0] == 0xd1 && u[1] == 0x88 && u[2] == 0 && u[3] == 0 && u[4] == 0);
+
+

+ This is a faster but less safe version of utf8::append. It does not + check for validity of the supplied code point, and may produce an invalid UTF-8 + sequence. +

+

+ utf8::unchecked::next +

+

+ Available in version 1.0 and later. +

+

+ Given the iterator to the beginning of a UTF-8 sequence, it returns the code point + and moves the iterator to the next position. +

+
+template <typename octet_iterator>
+uint32_t next(octet_iterator& it);
+   
+
+

+ it: a reference to an iterator pointing to the beginning of an UTF-8 + encoded code point. After the function returns, it is incremented to point to the + beginning of the next code point.
+ Return value: the 32 bit representation of the + processed UTF-8 code point. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+int cp = unchecked::next(w);
+assert (cp == 0x65e5);
+assert (w == twochars + 3);
+
+

+ This is a faster but less safe version of utf8::next. It does not + check for validity of the supplied UTF-8 sequence. +

+

+ utf8::unchecked::peek_next +

+

+ Available in version 2.1 and later. +

+

+ Given the iterator to the beginning of a UTF-8 sequence, it returns the code point. +

+
+template <typename octet_iterator>
+uint32_t peek_next(octet_iterator it);
+   
+
+

+ it: an iterator pointing to the beginning of an UTF-8 + encoded code point.
+ Return value: the 32 bit representation of the + processed UTF-8 code point. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+int cp = unchecked::peek_next(w);
+assert (cp == 0x65e5);
+assert (w == twochars);
+
+

+ This is a faster but less safe version of utf8::peek_next. It does not + check for validity of the supplied UTF-8 sequence. +

+

+ utf8::unchecked::prior +

+

+ Available in version 1.02 and later. +

+

+ Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it + decreases the iterator until it hits the beginning of the previous UTF-8 encoded + code point and returns the 32 bits representation of the code point. +

+
+template <typename octet_iterator>
+uint32_t prior(octet_iterator& it);
+   
+
+

+ it: a reference pointing to an octet within a UTF-8 encoded string. + After the function returns, it is decremented to point to the beginning of the + previous code point.
+ Return value: the 32 bit representation of the + previous code point. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars + 3;
+int cp = unchecked::prior (w);
+assert (cp == 0x65e5);
+assert (w == twochars);
+
+

+ This is a faster but less safe version of utf8::prior. It does not + check for validity of the supplied UTF-8 sequence and offers no boundary checking. +

+

+ utf8::unchecked::previous (deprecated, see utf8::unchecked::prior) +

+

+ Deprecated in version 1.02 and later. +

+

+ Given a reference to an iterator pointing to an octet in a UTF-8 seqence, it + decreases the iterator until it hits the beginning of the previous UTF-8 encoded + code point and returns the 32 bits representation of the code point. +

+
+template <typename octet_iterator>
+uint32_t previous(octet_iterator& it);
+   
+
+

+ it: a reference pointing to an octet within a UTF-8 encoded string. + After the function returns, it is decremented to point to the beginning of the + previous code point.
+ Return value: the 32 bit representation of the + previous code point. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars + 3;
+int cp = unchecked::previous (w);
+assert (cp == 0x65e5);
+assert (w == twochars);
+
+

+ The reason this function is deprecated is just the consistency with the "checked" + versions, where prior should be used instead of previous. + In fact, unchecked::previous behaves exactly the same as + unchecked::prior +

+

+ This is a faster but less safe version of utf8::previous. It does not + check for validity of the supplied UTF-8 sequence and offers no boundary checking. +

+

+ utf8::unchecked::advance +

+

+ Available in version 1.0 and later. +

+

+ Advances an iterator by the specified number of code points within an UTF-8 + sequence. +

+
+template <typename octet_iterator, typename distance_type>
+void advance (octet_iterator& it, distance_type n);
+   
+
+

+ it: a reference to an iterator pointing to the beginning of an UTF-8 + encoded code point. After the function returns, it is incremented to point to the + nth following code point.
+ n: a positive integer that shows how many code points we want to + advance.
+

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+char* w = twochars;
+unchecked::advance (w, 2);
+assert (w == twochars + 5);
+
+

+ This function works only "forward". In case of a negative n, there is + no effect. +

+

+ This is a faster but less safe version of utf8::advance. It does not + check for validity of the supplied UTF-8 sequence and offers no boundary checking. +

+

+ utf8::unchecked::distance +

+

+ Available in version 1.0 and later. +

+

+ Given the iterators to two UTF-8 encoded code points in a seqence, returns the + number of code points between them. +

+
+template <typename octet_iterator>
+typename std::iterator_traits<octet_iterator>::difference_type distance (octet_iterator first, octet_iterator last);
+
+

+ first: an iterator to a beginning of a UTF-8 encoded code point.
+ last: an iterator to a "post-end" of the last UTF-8 encoded code + point in the sequence we are trying to determine the length. It can be the + beginning of a new code point, or not.
+ Return value the distance between the iterators, + in code points. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+size_t dist = utf8::unchecked::distance(twochars, twochars + 5);
+assert (dist == 2);
+
+

+ This is a faster but less safe version of utf8::distance. It does not + check for validity of the supplied UTF-8 sequence. +

+

+ utf8::unchecked::utf16to8 +

+

+ Available in version 1.0 and later. +

+

+ Converts a UTF-16 encoded string to UTF-8. +

+
+template <typename u16bit_iterator, typename octet_iterator>
+octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result);
+   
+
+

+ start: an iterator pointing to the beginning of the UTF-16 encoded + string to convert.
+ end: an iterator pointing to pass-the-end of the UTF-16 encoded + string to convert.
+ result: an output iterator to the place in the UTF-8 string where to + append the result of conversion.
+ Return value: An iterator pointing to the place + after the appended UTF-8 string. +

+

+ Example of use: +

+
+unsigned short utf16string[] = {0x41, 0x0448, 0x65e5, 0xd834, 0xdd1e};
+vector<unsigned char> utf8result;
+unchecked::utf16to8(utf16string, utf16string + 5, back_inserter(utf8result));
+assert (utf8result.size() == 10);    
+
+

+ This is a faster but less safe version of utf8::utf16to8. It does not + check for validity of the supplied UTF-16 sequence. +

+

+ utf8::unchecked::utf8to16 +

+

+ Available in version 1.0 and later. +

+

+ Converts an UTF-8 encoded string to UTF-16 +

+
+template <typename u16bit_iterator, typename octet_iterator>
+u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result);
+   
+
+

+ start: an iterator pointing to the beginning of the UTF-8 encoded + string to convert. < br /> end: an iterator pointing to + pass-the-end of the UTF-8 encoded string to convert.
+ result: an output iterator to the place in the UTF-16 string where to + append the result of conversion.
+ Return value: An iterator pointing to the place + after the appended UTF-16 string. +

+

+ Example of use: +

+
+char utf8_with_surrogates[] = "\xe6\x97\xa5\xd1\x88\xf0\x9d\x84\x9e";
+vector <unsigned short> utf16result;
+unchecked::utf8to16(utf8_with_surrogates, utf8_with_surrogates + 9, back_inserter(utf16result));
+assert (utf16result.size() == 4);
+assert (utf16result[2] == 0xd834);
+assert (utf16result[3] == 0xdd1e);
+
+

+ This is a faster but less safe version of utf8::utf8to16. It does not + check for validity of the supplied UTF-8 sequence. +

+

+ utf8::unchecked::utf32to8 +

+

+ Available in version 1.0 and later. +

+

+ Converts a UTF-32 encoded string to UTF-8. +

+
+template <typename octet_iterator, typename u32bit_iterator>
+octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result);
+   
+
+

+ start: an iterator pointing to the beginning of the UTF-32 encoded + string to convert.
+ end: an iterator pointing to pass-the-end of the UTF-32 encoded + string to convert.
+ result: an output iterator to the place in the UTF-8 string where to + append the result of conversion.
+ Return value: An iterator pointing to the place + after the appended UTF-8 string. +

+

+ Example of use: +

+
+int utf32string[] = {0x448, 0x65e5, 0x10346, 0};
+vector<unsigned char> utf8result;
+utf32to8(utf32string, utf32string + 3, back_inserter(utf8result));
+assert (utf8result.size() == 9);
+
+

+ This is a faster but less safe version of utf8::utf32to8. It does not + check for validity of the supplied UTF-32 sequence. +

+

+ utf8::unchecked::utf8to32 +

+

+ Available in version 1.0 and later. +

+

+ Converts a UTF-8 encoded string to UTF-32. +

+
+template <typename octet_iterator, typename u32bit_iterator>
+u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result);
+   
+
+

+ start: an iterator pointing to the beginning of the UTF-8 encoded + string to convert.
+ end: an iterator pointing to pass-the-end of the UTF-8 encoded string + to convert.
+ result: an output iterator to the place in the UTF-32 string where to + append the result of conversion.
+ Return value: An iterator pointing to the place + after the appended UTF-32 string. +

+

+ Example of use: +

+
+char* twochars = "\xe6\x97\xa5\xd1\x88";
+vector<int> utf32result;
+unchecked::utf8to32(twochars, twochars + 5, back_inserter(utf32result));
+assert (utf32result.size() == 2);
+
+

+ This is a faster but less safe version of utf8::utf8to32. It does not + check for validity of the supplied UTF-8 sequence. +

+

+ Types From utf8::unchecked Namespace +

+

+ utf8::iterator +

+

+ Available in version 2.0 and later. +

+

+ Adapts the underlying octet iterator to iterate over the sequence of code points, + rather than raw octets. +

+
+template <typename octet_iterator>
+class iterator;
+
+ +
Member functions
+
+
iterator();
the deafult constructor; the underlying octet_iterator is + constructed with its default constructor. +
explicit iterator (const octet_iterator& octet_it); +
a constructor + that initializes the underlying octet_iterator with octet_it +
octet_iterator base () const;
returns the + underlying octet_iterator. +
uint32_t operator * () const;
decodes the utf-8 sequence + the underlying octet_iterator is pointing to and returns the code point. +
bool operator == (const iterator& rhs) + const;
returns true + if the two underlaying iterators are equal. +
bool operator != (const iterator& rhs) + const;
returns true + if the two underlaying iterators are not equal. +
iterator& operator ++ ();
the prefix increment - moves + the iterator to the next UTF-8 encoded code point. +
iterator operator ++ (int);
+ the postfix increment - moves the iterator to the next UTF-8 encoded code point and returns the current one. +
iterator& operator -- ();
the prefix decrement - moves + the iterator to the previous UTF-8 encoded code point. +
iterator operator -- (int);
+ the postfix decrement - moves the iterator to the previous UTF-8 encoded code point and returns the current one. +
+

+ Example of use: +

+
+char* threechars = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88";
+utf8::unchecked::iterator<char*> un_it(threechars);
+utf8::unchecked::iterator<char*> un_it2 = un_it;
+assert (un_it2 == un_it);
+assert (*un_it == 0x10346);
+assert (*(++un_it) == 0x65e5);
+assert ((*un_it++) == 0x65e5);
+assert (*un_it == 0x0448);
+assert (un_it != un_it2);
+utf8::::unchecked::iterator<char*> un_endit (threechars + 9);  
+assert (++un_it == un_endit);
+assert (*(--un_it) == 0x0448);
+assert ((*un_it--) == 0x0448);
+assert (*un_it == 0x65e5);
+assert (--un_it == utf8::unchecked::iterator<char*>(threechars));
+assert (*un_it == 0x10346);
+
+

+ This is an unchecked version of utf8::iterator. It is faster in many cases, but offers + no validity or range checks. +

+

+ Points of interest +

+

+ Design goals and decisions +

+

+ The library was designed to be: +

+
    +
  1. + Generic: for better or worse, there are many C++ string classes out there, and + the library should work with as many of them as possible. +
  2. +
  3. + Portable: the library should be portable both accross different platforms and + compilers. The only non-portable code is a small section that declares unsigned + integers of different sizes: three typedefs. They can be changed by the users of + the library if they don't match their platform. The default setting should work + for Windows (both 32 and 64 bit), and most 32 bit and 64 bit Unix derivatives. +
  4. +
  5. + Lightweight: follow the "pay only for what you use" guideline. +
  6. +
  7. + Unintrusive: avoid forcing any particular design or even programming style on the + user. This is a library, not a framework. +
  8. +
+

+ Alternatives +

+

+ In case you want to look into other means of working with UTF-8 strings from C++, + here is the list of solutions I am aware of: +

+
    +
  1. + ICU Library. It is very powerful, + complete, feature-rich, mature, and widely used. Also big, intrusive, + non-generic, and doesn't play well with the Standard Library. I definitelly + recommend looking at ICU even if you don't plan to use it. +
  2. +
  3. + C++11 language and library features. Still far from complete, and not widely + supported by compiler vendors. +
  4. +
  5. + Glib::ustring. + A class specifically made to work with UTF-8 strings, and also feel like + std::string. If you prefer to have yet another string class in your + code, it may be worth a look. Be aware of the licensing issues, though. +
  6. +
  7. + Platform dependent solutions: Windows and POSIX have functions to convert strings + from one encoding to another. That is only a subset of what my library offers, + but if that is all you need it may be good enough. +
  8. +
+ +
    +
  1. + The Unicode Consortium. +
  2. +
  3. + ICU Library. +
  4. +
  5. + UTF-8 at Wikipedia +
  6. +
  7. + UTF-8 and Unicode FAQ for + Unix/Linux +
  8. +
+ + diff --git a/contrib/utf8cpp/source/utf8.h b/contrib/utf8cpp/source/utf8.h new file mode 100644 index 000000000..82b13f59f --- /dev/null +++ b/contrib/utf8cpp/source/utf8.h @@ -0,0 +1,34 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +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. +*/ + + +#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include "utf8/checked.h" +#include "utf8/unchecked.h" + +#endif // header guard diff --git a/contrib/utf8cpp/source/utf8/checked.h b/contrib/utf8cpp/source/utf8/checked.h new file mode 100644 index 000000000..133115513 --- /dev/null +++ b/contrib/utf8cpp/source/utf8/checked.h @@ -0,0 +1,327 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +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. +*/ + + +#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include "core.h" +#include + +namespace utf8 +{ + // Base for the exceptions that may be thrown from the library + class exception : public ::std::exception { + }; + + // Exceptions that may be thrown from the library functions. + class invalid_code_point : public exception { + uint32_t cp; + public: + invalid_code_point(uint32_t cp) : cp(cp) {} + virtual const char* what() const throw() { return "Invalid code point"; } + uint32_t code_point() const {return cp;} + }; + + class invalid_utf8 : public exception { + uint8_t u8; + public: + invalid_utf8 (uint8_t u) : u8(u) {} + virtual const char* what() const throw() { return "Invalid UTF-8"; } + uint8_t utf8_octet() const {return u8;} + }; + + class invalid_utf16 : public exception { + uint16_t u16; + public: + invalid_utf16 (uint16_t u) : u16(u) {} + virtual const char* what() const throw() { return "Invalid UTF-16"; } + uint16_t utf16_word() const {return u16;} + }; + + class not_enough_room : public exception { + public: + virtual const char* what() const throw() { return "Not enough space"; } + }; + + /// The library API - functions intended to be called by the users + + template + octet_iterator append(uint32_t cp, octet_iterator result) + { + if (!utf8::internal::is_code_point_valid(cp)) + throw invalid_code_point(cp); + + if (cp < 0x80) // one octet + *(result++) = static_cast(cp); + else if (cp < 0x800) { // two octets + *(result++) = static_cast((cp >> 6) | 0xc0); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else if (cp < 0x10000) { // three octets + *(result++) = static_cast((cp >> 12) | 0xe0); + *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else { // four octets + *(result++) = static_cast((cp >> 18) | 0xf0); + *(result++) = static_cast(((cp >> 12) & 0x3f) | 0x80); + *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + return result; + } + + template + output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement) + { + while (start != end) { + octet_iterator sequence_start = start; + internal::utf_error err_code = utf8::internal::validate_next(start, end); + switch (err_code) { + case internal::UTF8_OK : + for (octet_iterator it = sequence_start; it != start; ++it) + *out++ = *it; + break; + case internal::NOT_ENOUGH_ROOM: + throw not_enough_room(); + case internal::INVALID_LEAD: + out = utf8::append (replacement, out); + ++start; + break; + case internal::INCOMPLETE_SEQUENCE: + case internal::OVERLONG_SEQUENCE: + case internal::INVALID_CODE_POINT: + out = utf8::append (replacement, out); + ++start; + // just one replacement mark for the sequence + while (start != end && utf8::internal::is_trail(*start)) + ++start; + break; + } + } + return out; + } + + template + inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out) + { + static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd); + return utf8::replace_invalid(start, end, out, replacement_marker); + } + + template + uint32_t next(octet_iterator& it, octet_iterator end) + { + uint32_t cp = 0; + internal::utf_error err_code = utf8::internal::validate_next(it, end, cp); + switch (err_code) { + case internal::UTF8_OK : + break; + case internal::NOT_ENOUGH_ROOM : + throw not_enough_room(); + case internal::INVALID_LEAD : + case internal::INCOMPLETE_SEQUENCE : + case internal::OVERLONG_SEQUENCE : + throw invalid_utf8(*it); + case internal::INVALID_CODE_POINT : + throw invalid_code_point(cp); + } + return cp; + } + + template + uint32_t peek_next(octet_iterator it, octet_iterator end) + { + return utf8::next(it, end); + } + + template + uint32_t prior(octet_iterator& it, octet_iterator start) + { + // can't do much if it == start + if (it == start) + throw not_enough_room(); + + octet_iterator end = it; + // Go back until we hit either a lead octet or start + while (utf8::internal::is_trail(*(--it))) + if (it == start) + throw invalid_utf8(*it); // error - no lead byte in the sequence + return utf8::peek_next(it, end); + } + + /// Deprecated in versions that include "prior" + template + uint32_t previous(octet_iterator& it, octet_iterator pass_start) + { + octet_iterator end = it; + while (utf8::internal::is_trail(*(--it))) + if (it == pass_start) + throw invalid_utf8(*it); // error - no lead byte in the sequence + octet_iterator temp = it; + return utf8::next(temp, end); + } + + template + void advance (octet_iterator& it, distance_type n, octet_iterator end) + { + for (distance_type i = 0; i < n; ++i) + utf8::next(it, end); + } + + template + typename std::iterator_traits::difference_type + distance (octet_iterator first, octet_iterator last) + { + typename std::iterator_traits::difference_type dist; + for (dist = 0; first < last; ++dist) + utf8::next(first, last); + return dist; + } + + template + octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) + { + while (start != end) { + uint32_t cp = utf8::internal::mask16(*start++); + // Take care of surrogate pairs first + if (utf8::internal::is_lead_surrogate(cp)) { + if (start != end) { + uint32_t trail_surrogate = utf8::internal::mask16(*start++); + if (utf8::internal::is_trail_surrogate(trail_surrogate)) + cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; + else + throw invalid_utf16(static_cast(trail_surrogate)); + } + else + throw invalid_utf16(static_cast(cp)); + + } + // Lone trail surrogate + else if (utf8::internal::is_trail_surrogate(cp)) + throw invalid_utf16(static_cast(cp)); + + result = utf8::append(cp, result); + } + return result; + } + + template + u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) + { + while (start != end) { + uint32_t cp = utf8::next(start, end); + if (cp > 0xffff) { //make a surrogate pair + *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); + *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); + } + else + *result++ = static_cast(cp); + } + return result; + } + + template + octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) + { + while (start != end) + result = utf8::append(*(start++), result); + + return result; + } + + template + u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) + { + while (start != end) + (*result++) = utf8::next(start, end); + + return result; + } + + // The iterator class + template + class iterator : public std::iterator { + octet_iterator it; + octet_iterator range_start; + octet_iterator range_end; + public: + iterator () {} + explicit iterator (const octet_iterator& octet_it, + const octet_iterator& range_start, + const octet_iterator& range_end) : + it(octet_it), range_start(range_start), range_end(range_end) + { + if (it < range_start || it > range_end) + throw std::out_of_range("Invalid utf-8 iterator position"); + } + // the default "big three" are OK + octet_iterator base () const { return it; } + uint32_t operator * () const + { + octet_iterator temp = it; + return utf8::next(temp, range_end); + } + bool operator == (const iterator& rhs) const + { + if (range_start != rhs.range_start || range_end != rhs.range_end) + throw std::logic_error("Comparing utf-8 iterators defined with different ranges"); + return (it == rhs.it); + } + bool operator != (const iterator& rhs) const + { + return !(operator == (rhs)); + } + iterator& operator ++ () + { + utf8::next(it, range_end); + return *this; + } + iterator operator ++ (int) + { + iterator temp = *this; + utf8::next(it, range_end); + return temp; + } + iterator& operator -- () + { + utf8::prior(it, range_start); + return *this; + } + iterator operator -- (int) + { + iterator temp = *this; + utf8::prior(it, range_start); + return temp; + } + }; // class iterator + +} // namespace utf8 + +#endif //header guard + + diff --git a/contrib/utf8cpp/source/utf8/core.h b/contrib/utf8cpp/source/utf8/core.h new file mode 100644 index 000000000..693d388c0 --- /dev/null +++ b/contrib/utf8cpp/source/utf8/core.h @@ -0,0 +1,329 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +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. +*/ + + +#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include + +namespace utf8 +{ + // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers + // You may need to change them to match your system. + // These typedefs have the same names as ones from cstdint, or boost/cstdint + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; + +// Helper code - not intended to be directly called by the library users. May be changed at any time +namespace internal +{ + // Unicode constants + // Leading (high) surrogates: 0xd800 - 0xdbff + // Trailing (low) surrogates: 0xdc00 - 0xdfff + const uint16_t LEAD_SURROGATE_MIN = 0xd800u; + const uint16_t LEAD_SURROGATE_MAX = 0xdbffu; + const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u; + const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu; + const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10); + const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN; + + // Maximum valid value for a Unicode code point + const uint32_t CODE_POINT_MAX = 0x0010ffffu; + + template + inline uint8_t mask8(octet_type oc) + { + return static_cast(0xff & oc); + } + template + inline uint16_t mask16(u16_type oc) + { + return static_cast(0xffff & oc); + } + template + inline bool is_trail(octet_type oc) + { + return ((utf8::internal::mask8(oc) >> 6) == 0x2); + } + + template + inline bool is_lead_surrogate(u16 cp) + { + return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX); + } + + template + inline bool is_trail_surrogate(u16 cp) + { + return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); + } + + template + inline bool is_surrogate(u16 cp) + { + return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); + } + + template + inline bool is_code_point_valid(u32 cp) + { + return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp)); + } + + template + inline typename std::iterator_traits::difference_type + sequence_length(octet_iterator lead_it) + { + uint8_t lead = utf8::internal::mask8(*lead_it); + if (lead < 0x80) + return 1; + else if ((lead >> 5) == 0x6) + return 2; + else if ((lead >> 4) == 0xe) + return 3; + else if ((lead >> 3) == 0x1e) + return 4; + else + return 0; + } + + template + inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length) + { + if (cp < 0x80) { + if (length != 1) + return true; + } + else if (cp < 0x800) { + if (length != 2) + return true; + } + else if (cp < 0x10000) { + if (length != 3) + return true; + } + + return false; + } + + enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT}; + + /// Helper for get_sequence_x + template + utf_error increase_safely(octet_iterator& it, octet_iterator end) + { + if (++it == end) + return NOT_ENOUGH_ROOM; + + if (!utf8::internal::is_trail(*it)) + return INCOMPLETE_SEQUENCE; + + return UTF8_OK; + } + + #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;} + + /// get_sequence_x functions decode utf-8 sequences of the length x + template + utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + return UTF8_OK; + } + + template + utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f); + + return UTF8_OK; + } + + template + utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point += (*it) & 0x3f; + + return UTF8_OK; + } + + template + utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point += (utf8::internal::mask8(*it) << 6) & 0xfff; + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point += (*it) & 0x3f; + + return UTF8_OK; + } + + #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR + + template + utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + // Save the original value of it so we can go back in case of failure + // Of course, it does not make much sense with i.e. stream iterators + octet_iterator original_it = it; + + uint32_t cp = 0; + // Determine the sequence length based on the lead octet + typedef typename std::iterator_traits::difference_type octet_difference_type; + const octet_difference_type length = utf8::internal::sequence_length(it); + + // Get trail octets and calculate the code point + utf_error err = UTF8_OK; + switch (length) { + case 0: + return INVALID_LEAD; + case 1: + err = utf8::internal::get_sequence_1(it, end, cp); + break; + case 2: + err = utf8::internal::get_sequence_2(it, end, cp); + break; + case 3: + err = utf8::internal::get_sequence_3(it, end, cp); + break; + case 4: + err = utf8::internal::get_sequence_4(it, end, cp); + break; + } + + if (err == UTF8_OK) { + // Decoding succeeded. Now, security checks... + if (utf8::internal::is_code_point_valid(cp)) { + if (!utf8::internal::is_overlong_sequence(cp, length)){ + // Passed! Return here. + code_point = cp; + ++it; + return UTF8_OK; + } + else + err = OVERLONG_SEQUENCE; + } + else + err = INVALID_CODE_POINT; + } + + // Failure branch - restore the original value of the iterator + it = original_it; + return err; + } + + template + inline utf_error validate_next(octet_iterator& it, octet_iterator end) { + uint32_t ignored; + return utf8::internal::validate_next(it, end, ignored); + } + +} // namespace internal + + /// The library API - functions intended to be called by the users + + // Byte order mark + const uint8_t bom[] = {0xef, 0xbb, 0xbf}; + + template + octet_iterator find_invalid(octet_iterator start, octet_iterator end) + { + octet_iterator result = start; + while (result != end) { + utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end); + if (err_code != internal::UTF8_OK) + return result; + } + return result; + } + + template + inline bool is_valid(octet_iterator start, octet_iterator end) + { + return (utf8::find_invalid(start, end) == end); + } + + template + inline bool starts_with_bom (octet_iterator it, octet_iterator end) + { + return ( + ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) && + ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) && + ((it != end) && (utf8::internal::mask8(*it)) == bom[2]) + ); + } + + //Deprecated in release 2.3 + template + inline bool is_bom (octet_iterator it) + { + return ( + (utf8::internal::mask8(*it++)) == bom[0] && + (utf8::internal::mask8(*it++)) == bom[1] && + (utf8::internal::mask8(*it)) == bom[2] + ); + } +} // namespace utf8 + +#endif // header guard + + diff --git a/contrib/utf8cpp/source/utf8/unchecked.h b/contrib/utf8cpp/source/utf8/unchecked.h new file mode 100644 index 000000000..cb2427166 --- /dev/null +++ b/contrib/utf8cpp/source/utf8/unchecked.h @@ -0,0 +1,228 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +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. +*/ + + +#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include "core.h" + +namespace utf8 +{ + namespace unchecked + { + template + octet_iterator append(uint32_t cp, octet_iterator result) + { + if (cp < 0x80) // one octet + *(result++) = static_cast(cp); + else if (cp < 0x800) { // two octets + *(result++) = static_cast((cp >> 6) | 0xc0); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else if (cp < 0x10000) { // three octets + *(result++) = static_cast((cp >> 12) | 0xe0); + *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else { // four octets + *(result++) = static_cast((cp >> 18) | 0xf0); + *(result++) = static_cast(((cp >> 12) & 0x3f)| 0x80); + *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + return result; + } + + template + uint32_t next(octet_iterator& it) + { + uint32_t cp = utf8::internal::mask8(*it); + typename std::iterator_traits::difference_type length = utf8::internal::sequence_length(it); + switch (length) { + case 1: + break; + case 2: + it++; + cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f); + break; + case 3: + ++it; + cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); + ++it; + cp += (*it) & 0x3f; + break; + case 4: + ++it; + cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); + ++it; + cp += (utf8::internal::mask8(*it) << 6) & 0xfff; + ++it; + cp += (*it) & 0x3f; + break; + } + ++it; + return cp; + } + + template + uint32_t peek_next(octet_iterator it) + { + return utf8::unchecked::next(it); + } + + template + uint32_t prior(octet_iterator& it) + { + while (utf8::internal::is_trail(*(--it))) ; + octet_iterator temp = it; + return utf8::unchecked::next(temp); + } + + // Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous) + template + inline uint32_t previous(octet_iterator& it) + { + return utf8::unchecked::prior(it); + } + + template + void advance (octet_iterator& it, distance_type n) + { + for (distance_type i = 0; i < n; ++i) + utf8::unchecked::next(it); + } + + template + typename std::iterator_traits::difference_type + distance (octet_iterator first, octet_iterator last) + { + typename std::iterator_traits::difference_type dist; + for (dist = 0; first < last; ++dist) + utf8::unchecked::next(first); + return dist; + } + + template + octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) + { + while (start != end) { + uint32_t cp = utf8::internal::mask16(*start++); + // Take care of surrogate pairs first + if (utf8::internal::is_lead_surrogate(cp)) { + uint32_t trail_surrogate = utf8::internal::mask16(*start++); + cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; + } + result = utf8::unchecked::append(cp, result); + } + return result; + } + + template + u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) + { + while (start < end) { + uint32_t cp = utf8::unchecked::next(start); + if (cp > 0xffff) { //make a surrogate pair + *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); + *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); + } + else + *result++ = static_cast(cp); + } + return result; + } + + template + octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) + { + while (start != end) + result = utf8::unchecked::append(*(start++), result); + + return result; + } + + template + u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) + { + while (start < end) + (*result++) = utf8::unchecked::next(start); + + return result; + } + + // The iterator class + template + class iterator : public std::iterator { + octet_iterator it; + public: + iterator () {} + explicit iterator (const octet_iterator& octet_it): it(octet_it) {} + // the default "big three" are OK + octet_iterator base () const { return it; } + uint32_t operator * () const + { + octet_iterator temp = it; + return utf8::unchecked::next(temp); + } + bool operator == (const iterator& rhs) const + { + return (it == rhs.it); + } + bool operator != (const iterator& rhs) const + { + return !(operator == (rhs)); + } + iterator& operator ++ () + { + ::std::advance(it, utf8::internal::sequence_length(it)); + return *this; + } + iterator operator ++ (int) + { + iterator temp = *this; + ::std::advance(it, utf8::internal::sequence_length(it)); + return temp; + } + iterator& operator -- () + { + utf8::unchecked::prior(it); + return *this; + } + iterator operator -- (int) + { + iterator temp = *this; + utf8::unchecked::prior(it); + return temp; + } + }; // class iterator + + } // namespace utf8::unchecked +} // namespace utf8 + + +#endif // header guard + diff --git a/contrib/zip/.gitignore b/contrib/zip/.gitignore new file mode 100644 index 000000000..4f9972c56 --- /dev/null +++ b/contrib/zip/.gitignore @@ -0,0 +1,38 @@ +/build/ +/test/build/ +/xcodeproj/ + +# Object files +*.o +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib +*.suo + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Temporary +*.swp +.DS_Store diff --git a/contrib/zip/.travis.yml b/contrib/zip/.travis.yml new file mode 100644 index 000000000..d8ccb728d --- /dev/null +++ b/contrib/zip/.travis.yml @@ -0,0 +1,10 @@ +language: c +# Compiler selection +compiler: + - clang + - gcc +# Build steps +script: + - mkdir build + - cd build + - cmake -DCMAKE_BUILD_TYPE=Debug .. && make && make test diff --git a/contrib/zip/CMakeLists.txt b/contrib/zip/CMakeLists.txt new file mode 100644 index 000000000..450ef3a98 --- /dev/null +++ b/contrib/zip/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 2.8) +project(zip) + +if (MSVC) + # Use secure functions by defaualt and suppress warnings about "deprecated" functions + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1") +endif (MSVC) + +# zip +set(SRC src/miniz.h src/zip.h src/zip.c) +add_library(${CMAKE_PROJECT_NAME} ${SRC}) + +# test +enable_testing() +add_subdirectory(test) + diff --git a/contrib/zip/README.md b/contrib/zip/README.md new file mode 100644 index 000000000..24de5e61a --- /dev/null +++ b/contrib/zip/README.md @@ -0,0 +1,139 @@ +### A portable (OSX/Linux/Windows), simple zip library written in C +This is done by hacking awesome [miniz](https://code.google.com/p/miniz) library and layering functions on top of the miniz v1.15 API. + +[![Windows][win-badge]][win-link] [![OS X][osx-linux-badge]][osx-linux-link] + +[win-badge]: https://img.shields.io/appveyor/ci/kuba--/zip/master.svg?label=windows "AppVeyor build status" +[win-link]: https://ci.appveyor.com/project/kuba--/zip "AppVeyor build status" +[osx-linux-badge]: https://img.shields.io/travis/kuba--/zip/master.svg?label=linux/osx "Travis CI build status" +[osx-linux-link]: https://travis-ci.org/kuba--/zip "Travis CI build status" + +# The Idea + +... Some day, I was looking for zip library written in C for my project, but I could not find anything simple enough and lightweight. +Everything what I tried required 'crazy mental gymnastics' to integrate or had some limitations or was too heavy. +I hate frameworks, factories and adding new dependencies. If I must to install all those dependencies and link new library, I'm getting almost sick. +I wanted something powerfull and small enough, so I could add just a few files and compile them into my project. +And finally I found miniz. +Miniz is a lossless, high performance data compression library in a single source file. I only needed simple interface to append buffers or files to the current zip-entry. Thanks to this feature I'm able to merge many files/buffers and compress them on-the-fly. + +It was the reason, why I decided to write zip module on top of the miniz. It required a little bit hacking and wrapping some functions, but I kept simplicity. So, you can grab these 3 files and compile them into your project. I hope that interface is also extremely simple, so you will not have any problems to understand it. + +# Examples + +* Create a new zip archive with default compression level. +```c + struct zip_t *zip = zip_open("foo.zip", ZIP_DEFAULT_COMPRESSION_LEVEL, 'w'); + { + zip_entry_open(zip, "foo-1.txt"); + { + char *buf = "Some data here..."; + zip_entry_write(zip, buf, strlen(buf)); + } + zip_entry_close(zip); + + zip_entry_open(zip, "foo-2.txt"); + { + // merge 3 files into one entry and compress them on-the-fly. + zip_entry_fwrite(zip, "foo-2.1.txt"); + zip_entry_fwrite(zip, "foo-2.2.txt"); + zip_entry_fwrite(zip, "foo-2.3.txt"); + } + zip_entry_close(zip); + } + zip_close(zip); +``` + +* Append to the existing zip archive. +```c + struct zip_t *zip = zip_open("foo.zip", ZIP_DEFAULT_COMPRESSION_LEVEL, 'a'); + { + zip_entry_open(zip, "foo-3.txt"); + { + char *buf = "Append some data here..."; + zip_entry_write(zip, buf, strlen(buf)); + } + zip_entry_close(zip); + } + zip_close(zip); +``` + +* Extract a zip archive into a folder. +```c + int on_extract_entry(const char *filename, void *arg) { + static int i = 0; + int n = *(int *)arg; + printf("Extracted: %s (%d of %d)\n", filename, ++i, n); + + return 0; + } + + int arg = 2; + zip_extract("foo.zip", "/tmp", on_extract_entry, &arg); +``` + +* Extract a zip entry into memory. +```c + void *buf = NULL; + size_t bufsize; + + struct zip_t *zip = zip_open("foo.zip", 0, 'r'); + { + zip_entry_open(zip, "foo-1.txt"); + { + zip_entry_read(zip, &buf, &bufsize); + } + zip_entry_close(zip); + } + zip_close(zip); + + free(buf); +``` + +* Extract a zip entry into memory using callback. +```c + struct buffer_t { + char *data; + size_t size; + }; + + static size_t on_extract(void *arg, unsigned long long offset, const void *data, size_t size) { + struct buffer_t *buf = (struct buffer_t *)arg; + buf->data = realloc(buf->data, buf->size + size + 1); + assert(NULL != buf->data); + + memcpy(&(buf->data[buf->size]), data, size); + buf->size += size; + buf->data[buf->size] = 0; + + return size; + } + + struct buffer_t buf = {0}; + struct zip_t *zip = zip_open("foo.zip", 0, 'r'); + { + zip_entry_open(zip, "foo-1.txt"); + { + zip_entry_extract(zip, on_extract, &buf); + } + zip_entry_close(zip); + } + zip_close(zip); + + free(buf.data); +``` + + +* Extract a zip entry into a file. +```c + struct zip_t *zip = zip_open("foo.zip", 0, 'r'); + { + zip_entry_open(zip, "foo-2.txt"); + { + zip_entry_fread(zip, "foo-2.txt"); + } + zip_entry_close(zip); + } + zip_close(zip); +``` + diff --git a/contrib/zip/UNLICENSE b/contrib/zip/UNLICENSE new file mode 100644 index 000000000..ed7cccdf2 --- /dev/null +++ b/contrib/zip/UNLICENSE @@ -0,0 +1,26 @@ +/* + This is free and unencumbered software released into the public domain. + + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this software, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. + + In jurisdictions that recognize copyright laws, the author or authors + of this software dedicate any and all copyright interest in the + software to the public domain. We make this dedication for the benefit + of the public at large and to the detriment of our heirs and + successors. We intend this dedication to be an overt act of + relinquishment in perpetuity of all present and future rights to this + software under copyright law. + + 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 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. + + For more information, please refer to +*/ diff --git a/contrib/zip/appveyor.yml b/contrib/zip/appveyor.yml new file mode 100644 index 000000000..297cad8b0 --- /dev/null +++ b/contrib/zip/appveyor.yml @@ -0,0 +1,14 @@ +version: 1.0.{build} +build_script: +- cmd: >- + cd c:\projects\zip + + mkdir build + + cd build + + cmake -G"Visual Studio 14" -DCMAKE_BUILD_TYPE=Debug .. + + cmake --build . --config %CMAKE_BUILD_TYPE% + + ctest --verbose -C "Debug" diff --git a/contrib/zip/src/miniz.h b/contrib/zip/src/miniz.h new file mode 100644 index 000000000..916fb1ff8 --- /dev/null +++ b/contrib/zip/src/miniz.h @@ -0,0 +1,4927 @@ +/* + miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing + See "unlicense" statement at the end of this file. + Rich Geldreich , last updated Oct. 13, 2013 + Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt + + Most API's defined in miniz.c are optional. For example, to disable the archive related functions just define + MINIZ_NO_ARCHIVE_APIS, or to get rid of all stdio usage define MINIZ_NO_STDIO (see the list below for more macros). + + * Change History + 10/13/13 v1.15 r4 - Interim bugfix release while I work on the next major release with Zip64 support (almost there!): + - Critical fix for the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY bug (thanks kahmyong.moon@hp.com) which could cause locate files to not find files. This bug + would only have occured in earlier versions if you explicitly used this flag, OR if you used mz_zip_extract_archive_file_to_heap() or mz_zip_add_mem_to_archive_file_in_place() + (which used this flag). If you can't switch to v1.15 but want to fix this bug, just remove the uses of this flag from both helper funcs (and of course don't use the flag). + - Bugfix in mz_zip_reader_extract_to_mem_no_alloc() from kymoon when pUser_read_buf is not NULL and compressed size is > uncompressed size + - Fixing mz_zip_reader_extract_*() funcs so they don't try to extract compressed data from directory entries, to account for weird zipfiles which contain zero-size compressed data on dir entries. + Hopefully this fix won't cause any issues on weird zip archives, because it assumes the low 16-bits of zip external attributes are DOS attributes (which I believe they always are in practice). + - Fixing mz_zip_reader_is_file_a_directory() so it doesn't check the internal attributes, just the filename and external attributes + - mz_zip_reader_init_file() - missing MZ_FCLOSE() call if the seek failed + - Added cmake support for Linux builds which builds all the examples, tested with clang v3.3 and gcc v4.6. + - Clang fix for tdefl_write_image_to_png_file_in_memory() from toffaletti + - Merged MZ_FORCEINLINE fix from hdeanclark + - Fix include before config #ifdef, thanks emil.brink + - Added tdefl_write_image_to_png_file_in_memory_ex(): supports Y flipping (super useful for OpenGL apps), and explicit control over the compression level (so you can + set it to 1 for real-time compression). + - Merged in some compiler fixes from paulharris's github repro. + - Retested this build under Windows (VS 2010, including static analysis), tcc 0.9.26, gcc v4.6 and clang v3.3. + - Added example6.c, which dumps an image of the mandelbrot set to a PNG file. + - Modified example2 to help test the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY flag more. + - In r3: Bugfix to mz_zip_writer_add_file() found during merge: Fix possible src file fclose() leak if alignment bytes+local header file write faiiled +  - In r4: Minor bugfix to mz_zip_writer_add_from_zip_reader(): Was pushing the wrong central dir header offset, appears harmless in this release, but it became a problem in the zip64 branch + 5/20/12 v1.14 - MinGW32/64 GCC 4.6.1 compiler fixes: added MZ_FORCEINLINE, #include (thanks fermtect). + 5/19/12 v1.13 - From jason@cornsyrup.org and kelwert@mtu.edu - Fix mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit. + - Temporarily/locally slammed in "typedef unsigned long mz_ulong" and re-ran a randomized regression test on ~500k files. + - Eliminated a bunch of warnings when compiling with GCC 32-bit/64. + - Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze (static analysis) option and fixed all warnings (except for the silly + "Use of the comma-operator in a tested expression.." analysis warning, which I purposely use to work around a MSVC compiler warning). + - Created 32-bit and 64-bit Codeblocks projects/workspace. Built and tested Linux executables. The codeblocks workspace is compatible with Linux+Win32/x64. + - Added miniz_tester solution/project, which is a useful little app derived from LZHAM's tester app that I use as part of the regression test. + - Ran miniz.c and tinfl.c through another series of regression testing on ~500,000 files and archives. + - Modified example5.c so it purposely disables a bunch of high-level functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the MINIZ_NO_STDIO bug report.) + - Fix ftell() usage in examples so they exit with an error on files which are too large (a limitation of the examples, not miniz itself). + 4/12/12 v1.12 - More comments, added low-level example5.c, fixed a couple minor level_and_flags issues in the archive API's. + level_and_flags can now be set to MZ_DEFAULT_COMPRESSION. Thanks to Bruce Dawson for the feedback/bug report. + 5/28/11 v1.11 - Added statement from unlicense.org + 5/27/11 v1.10 - Substantial compressor optimizations: + - Level 1 is now ~4x faster than before. The L1 compressor's throughput now varies between 70-110MB/sec. on a + - Core i7 (actual throughput varies depending on the type of data, and x64 vs. x86). + - Improved baseline L2-L9 compression perf. Also, greatly improved compression perf. issues on some file types. + - Refactored the compression code for better readability and maintainability. + - Added level 10 compression level (L10 has slightly better ratio than level 9, but could have a potentially large + drop in throughput on some files). + 5/15/11 v1.09 - Initial stable release. + + * Low-level Deflate/Inflate implementation notes: + + Compression: Use the "tdefl" API's. The compressor supports raw, static, and dynamic blocks, lazy or + greedy parsing, match length filtering, RLE-only, and Huffman-only streams. It performs and compresses + approximately as well as zlib. + + Decompression: Use the "tinfl" API's. The entire decompressor is implemented as a single function + coroutine: see tinfl_decompress(). It supports decompression into a 32KB (or larger power of 2) wrapping buffer, or into a memory + block large enough to hold the entire file. + + The low-level tdefl/tinfl API's do not make any use of dynamic memory allocation. + + * zlib-style API notes: + + miniz.c implements a fairly large subset of zlib. There's enough functionality present for it to be a drop-in + zlib replacement in many apps: + The z_stream struct, optional memory allocation callbacks + deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound + inflateInit/inflateInit2/inflate/inflateEnd + compress, compress2, compressBound, uncompress + CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly routines. + Supports raw deflate streams or standard zlib streams with adler-32 checking. + + Limitations: + The callback API's are not implemented yet. No support for gzip headers or zlib static dictionaries. + I've tried to closely emulate zlib's various flavors of stream flushing and return status codes, but + there are no guarantees that miniz.c pulls this off perfectly. + + * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function, originally written by + Alex Evans. Supports 1-4 bytes/pixel images. + + * ZIP archive API notes: + + The ZIP archive API's where designed with simplicity and efficiency in mind, with just enough abstraction to + get the job done with minimal fuss. There are simple API's to retrieve file information, read files from + existing archives, create new archives, append new files to existing archives, or clone archive data from + one archive to another. It supports archives located in memory or the heap, on disk (using stdio.h), + or you can specify custom file read/write callbacks. + + - Archive reading: Just call this function to read a single file from a disk archive: + + void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, + size_t *pSize, mz_uint zip_flags); + + For more complex cases, use the "mz_zip_reader" functions. Upon opening an archive, the entire central + directory is located and read as-is into memory, and subsequent file access only occurs when reading individual files. + + - Archives file scanning: The simple way is to use this function to scan a loaded archive for a specific file: + + int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags); + + The locate operation can optionally check file comments too, which (as one example) can be used to identify + multiple versions of the same file in an archive. This function uses a simple linear search through the central + directory, so it's not very fast. + + Alternately, you can iterate through all the files in an archive (using mz_zip_reader_get_num_files()) and + retrieve detailed info on each file by calling mz_zip_reader_file_stat(). + + - Archive creation: Use the "mz_zip_writer" functions. The ZIP writer immediately writes compressed file data + to disk and builds an exact image of the central directory in memory. The central directory image is written + all at once at the end of the archive file when the archive is finalized. + + The archive writer can optionally align each file's local header and file data to any power of 2 alignment, + which can be useful when the archive will be read from optical media. Also, the writer supports placing + arbitrary data blobs at the very beginning of ZIP archives. Archives written using either feature are still + readable by any ZIP tool. + + - Archive appending: The simple way to add a single file to an archive is to call this function: + + mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, + const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); + + The archive will be created if it doesn't already exist, otherwise it'll be appended to. + Note the appending is done in-place and is not an atomic operation, so if something goes wrong + during the operation it's possible the archive could be left without a central directory (although the local + file headers and file data will be fine, so the archive will be recoverable). + + For more complex archive modification scenarios: + 1. The safest way is to use a mz_zip_reader to read the existing archive, cloning only those bits you want to + preserve into a new archive using using the mz_zip_writer_add_from_zip_reader() function (which compiles the + compressed file data as-is). When you're done, delete the old archive and rename the newly written archive, and + you're done. This is safe but requires a bunch of temporary disk space or heap memory. + + 2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using mz_zip_writer_init_from_reader(), + append new files as needed, then finalize the archive which will write an updated central directory to the + original archive. (This is basically what mz_zip_add_mem_to_archive_file_in_place() does.) There's a + possibility that the archive's central directory could be lost with this method if anything goes wrong, though. + + - ZIP archive support limitations: + No zip64 or spanning support. Extraction functions can only handle unencrypted, stored or deflated files. + Requires streams capable of seeking. + + * This is a header file library, like stb_image.c. To get only a header file, either cut and paste the + below header, or create miniz.h, #define MINIZ_HEADER_FILE_ONLY, and then include miniz.c from it. + + * Important: For best perf. be sure to customize the below macros for your target platform: + #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 + #define MINIZ_LITTLE_ENDIAN 1 + #define MINIZ_HAS_64BIT_REGISTERS 1 + + * On platforms using glibc, Be sure to "#define _LARGEFILE64_SOURCE 1" before including miniz.c to ensure miniz + uses the 64-bit variants: fopen64(), stat64(), etc. Otherwise you won't be able to process large files + (i.e. 32-bit stat() fails for me on files > 0x7FFFFFFF bytes). +*/ + +#ifndef MINIZ_HEADER_INCLUDED +#define MINIZ_HEADER_INCLUDED + +#include + +// Defines to completely disable specific portions of miniz.c: +// If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl. + +// Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O. +//#define MINIZ_NO_STDIO + +// If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able to get the current time, or +// get/set file times, and the C run-time funcs that get/set times won't be called. +// The current downside is the times written to your archives will be from 1979. +//#define MINIZ_NO_TIME + +// Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's. +//#define MINIZ_NO_ARCHIVE_APIS + +// Define MINIZ_NO_ARCHIVE_APIS to disable all writing related ZIP archive API's. +//#define MINIZ_NO_ARCHIVE_WRITING_APIS + +// Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression API's. +//#define MINIZ_NO_ZLIB_APIS + +// Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib. +//#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES + +// Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc. +// Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc +// callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user +// functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work. +//#define MINIZ_NO_MALLOC + +#if defined(__TINYC__) && (defined(__linux) || defined(__linux__)) + // TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc on Linux + #define MINIZ_NO_TIME +#endif + +#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS) + #include +#endif + +#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__) +// MINIZ_X86_OR_X64_CPU is only used to help set the below macros. +#define MINIZ_X86_OR_X64_CPU 1 +#endif + +#if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU +// Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian. +#define MINIZ_LITTLE_ENDIAN 1 +#endif + +#if MINIZ_X86_OR_X64_CPU +// Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. +#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0 +#endif + +#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__) +// Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions). +#define MINIZ_HAS_64BIT_REGISTERS 1 +#endif + +#ifdef __APPLE__ +#define ftello64 ftello +#define fseeko64 fseeko +#define fopen64 fopen +#define freopen64 freopen +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// ------------------- zlib-style API Definitions. + +// For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits! +typedef unsigned long mz_ulong; + +// mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap. +void mz_free(void *p); + +#define MZ_ADLER32_INIT (1) +// mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL. +mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len); + +#define MZ_CRC32_INIT (0) +// mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL. +mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len); + +// Compression strategies. +enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 }; + +// Method +#define MZ_DEFLATED 8 + +#ifndef MINIZ_NO_ZLIB_APIS + +// Heap allocation callbacks. +// Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long. +typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size); +typedef void (*mz_free_func)(void *opaque, void *address); +typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size); + +#define MZ_VERSION "9.1.15" +#define MZ_VERNUM 0x91F0 +#define MZ_VER_MAJOR 9 +#define MZ_VER_MINOR 1 +#define MZ_VER_REVISION 15 +#define MZ_VER_SUBREVISION 0 + +// Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs). +enum { MZ_NO_FLUSH = 0, MZ_PARTIAL_FLUSH = 1, MZ_SYNC_FLUSH = 2, MZ_FULL_FLUSH = 3, MZ_FINISH = 4, MZ_BLOCK = 5 }; + +// Return status codes. MZ_PARAM_ERROR is non-standard. +enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 }; + +// Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL. +enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_UBER_COMPRESSION = 10, MZ_DEFAULT_LEVEL = 6, MZ_DEFAULT_COMPRESSION = -1 }; + +// Window bits +#define MZ_DEFAULT_WINDOW_BITS 15 + +struct mz_internal_state; + +// Compression/decompression stream struct. +typedef struct mz_stream_s +{ + const unsigned char *next_in; // pointer to next byte to read + unsigned int avail_in; // number of bytes available at next_in + mz_ulong total_in; // total number of bytes consumed so far + + unsigned char *next_out; // pointer to next byte to write + unsigned int avail_out; // number of bytes that can be written to next_out + mz_ulong total_out; // total number of bytes produced so far + + char *msg; // error msg (unused) + struct mz_internal_state *state; // internal state, allocated by zalloc/zfree + + mz_alloc_func zalloc; // optional heap allocation function (defaults to malloc) + mz_free_func zfree; // optional heap free function (defaults to free) + void *opaque; // heap alloc function user pointer + + int data_type; // data_type (unused) + mz_ulong adler; // adler32 of the source or uncompressed data + mz_ulong reserved; // not used +} mz_stream; + +typedef mz_stream *mz_streamp; + +// Returns the version string of miniz.c. +const char *mz_version(void); + +// mz_deflateInit() initializes a compressor with default options: +// Parameters: +// pStream must point to an initialized mz_stream struct. +// level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION]. +// level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio. +// (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.) +// Return values: +// MZ_OK on success. +// MZ_STREAM_ERROR if the stream is bogus. +// MZ_PARAM_ERROR if the input parameters are bogus. +// MZ_MEM_ERROR on out of memory. +int mz_deflateInit(mz_streamp pStream, int level); + +// mz_deflateInit2() is like mz_deflate(), except with more control: +// Additional parameters: +// method must be MZ_DEFLATED +// window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer) +// mem_level must be between [1, 9] (it's checked but ignored by miniz.c) +int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy); + +// Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2(). +int mz_deflateReset(mz_streamp pStream); + +// mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible. +// Parameters: +// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. +// flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH. +// Return values: +// MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full). +// MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore. +// MZ_STREAM_ERROR if the stream is bogus. +// MZ_PARAM_ERROR if one of the parameters is invalid. +// MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.) +int mz_deflate(mz_streamp pStream, int flush); + +// mz_deflateEnd() deinitializes a compressor: +// Return values: +// MZ_OK on success. +// MZ_STREAM_ERROR if the stream is bogus. +int mz_deflateEnd(mz_streamp pStream); + +// mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH. +mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len); + +// Single-call compression functions mz_compress() and mz_compress2(): +// Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure. +int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); +int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level); + +// mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress(). +mz_ulong mz_compressBound(mz_ulong source_len); + +// Initializes a decompressor. +int mz_inflateInit(mz_streamp pStream); + +// mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer: +// window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate). +int mz_inflateInit2(mz_streamp pStream, int window_bits); + +// Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible. +// Parameters: +// pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. +// flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH. +// On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster). +// MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data. +// Return values: +// MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full. +// MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified. +// MZ_STREAM_ERROR if the stream is bogus. +// MZ_DATA_ERROR if the deflate stream is invalid. +// MZ_PARAM_ERROR if one of the parameters is invalid. +// MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again +// with more input data, or with more room in the output buffer (except when using single call decompression, described above). +int mz_inflate(mz_streamp pStream, int flush); + +// Deinitializes a decompressor. +int mz_inflateEnd(mz_streamp pStream); + +// Single-call decompression. +// Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure. +int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); + +// Returns a string description of the specified error code, or NULL if the error code is invalid. +const char *mz_error(int err); + +// Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports. +// Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project. +#ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES + typedef unsigned char Byte; + typedef unsigned int uInt; + typedef mz_ulong uLong; + typedef Byte Bytef; + typedef uInt uIntf; + typedef char charf; + typedef int intf; + typedef void *voidpf; + typedef uLong uLongf; + typedef void *voidp; + typedef void *const voidpc; + #define Z_NULL 0 + #define Z_NO_FLUSH MZ_NO_FLUSH + #define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH + #define Z_SYNC_FLUSH MZ_SYNC_FLUSH + #define Z_FULL_FLUSH MZ_FULL_FLUSH + #define Z_FINISH MZ_FINISH + #define Z_BLOCK MZ_BLOCK + #define Z_OK MZ_OK + #define Z_STREAM_END MZ_STREAM_END + #define Z_NEED_DICT MZ_NEED_DICT + #define Z_ERRNO MZ_ERRNO + #define Z_STREAM_ERROR MZ_STREAM_ERROR + #define Z_DATA_ERROR MZ_DATA_ERROR + #define Z_MEM_ERROR MZ_MEM_ERROR + #define Z_BUF_ERROR MZ_BUF_ERROR + #define Z_VERSION_ERROR MZ_VERSION_ERROR + #define Z_PARAM_ERROR MZ_PARAM_ERROR + #define Z_NO_COMPRESSION MZ_NO_COMPRESSION + #define Z_BEST_SPEED MZ_BEST_SPEED + #define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION + #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION + #define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY + #define Z_FILTERED MZ_FILTERED + #define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY + #define Z_RLE MZ_RLE + #define Z_FIXED MZ_FIXED + #define Z_DEFLATED MZ_DEFLATED + #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS + #define alloc_func mz_alloc_func + #define free_func mz_free_func + #define internal_state mz_internal_state + #define z_stream mz_stream + #define deflateInit mz_deflateInit + #define deflateInit2 mz_deflateInit2 + #define deflateReset mz_deflateReset + #define deflate mz_deflate + #define deflateEnd mz_deflateEnd + #define deflateBound mz_deflateBound + #define compress mz_compress + #define compress2 mz_compress2 + #define compressBound mz_compressBound + #define inflateInit mz_inflateInit + #define inflateInit2 mz_inflateInit2 + #define inflate mz_inflate + #define inflateEnd mz_inflateEnd + #define uncompress mz_uncompress + #define crc32 mz_crc32 + #define adler32 mz_adler32 + #define MAX_WBITS 15 + #define MAX_MEM_LEVEL 9 + #define zError mz_error + #define ZLIB_VERSION MZ_VERSION + #define ZLIB_VERNUM MZ_VERNUM + #define ZLIB_VER_MAJOR MZ_VER_MAJOR + #define ZLIB_VER_MINOR MZ_VER_MINOR + #define ZLIB_VER_REVISION MZ_VER_REVISION + #define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION + #define zlibVersion mz_version + #define zlib_version mz_version() +#endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES + +#endif // MINIZ_NO_ZLIB_APIS + +// ------------------- Types and macros + +typedef unsigned char mz_uint8; +typedef signed short mz_int16; +typedef unsigned short mz_uint16; +typedef unsigned int mz_uint32; +typedef unsigned int mz_uint; +typedef long long mz_int64; +typedef unsigned long long mz_uint64; +typedef int mz_bool; + +#define MZ_FALSE (0) +#define MZ_TRUE (1) + +// An attempt to work around MSVC's spammy "warning C4127: conditional expression is constant" message. +#ifdef _MSC_VER + #define MZ_MACRO_END while (0, 0) +#else + #define MZ_MACRO_END while (0) +#endif + +// ------------------- ZIP archive reading/writing + +#ifndef MINIZ_NO_ARCHIVE_APIS + +enum +{ + MZ_ZIP_MAX_IO_BUF_SIZE = 64*1024, + MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260, + MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256 +}; + +typedef struct +{ + mz_uint32 m_file_index; + mz_uint32 m_central_dir_ofs; + mz_uint16 m_version_made_by; + mz_uint16 m_version_needed; + mz_uint16 m_bit_flag; + mz_uint16 m_method; +#ifndef MINIZ_NO_TIME + time_t m_time; +#endif + mz_uint32 m_crc32; + mz_uint64 m_comp_size; + mz_uint64 m_uncomp_size; + mz_uint16 m_internal_attr; + mz_uint32 m_external_attr; + mz_uint64 m_local_header_ofs; + mz_uint32 m_comment_size; + char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE]; + char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE]; +} mz_zip_archive_file_stat; + +typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n); +typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n); + +struct mz_zip_internal_state_tag; +typedef struct mz_zip_internal_state_tag mz_zip_internal_state; + +typedef enum +{ + MZ_ZIP_MODE_INVALID = 0, + MZ_ZIP_MODE_READING = 1, + MZ_ZIP_MODE_WRITING = 2, + MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3 +} mz_zip_mode; + +typedef struct mz_zip_archive_tag +{ + mz_uint64 m_archive_size; + mz_uint64 m_central_directory_file_ofs; + mz_uint m_total_files; + mz_zip_mode m_zip_mode; + + mz_uint m_file_offset_alignment; + + mz_alloc_func m_pAlloc; + mz_free_func m_pFree; + mz_realloc_func m_pRealloc; + void *m_pAlloc_opaque; + + mz_file_read_func m_pRead; + mz_file_write_func m_pWrite; + void *m_pIO_opaque; + + mz_zip_internal_state *m_pState; + +} mz_zip_archive; + +typedef enum +{ + MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100, + MZ_ZIP_FLAG_IGNORE_PATH = 0x0200, + MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400, + MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800 +} mz_zip_flags; + +// ZIP archive reading + +// Inits a ZIP archive reader. +// These functions read and validate the archive's central directory. +mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags); +mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags); + +#ifndef MINIZ_NO_STDIO +mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags); +#endif + +// Returns the total number of files in the archive. +mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip); + +// Returns detailed information about an archive file entry. +mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat); + +// Determines if an archive file entry is a directory entry. +mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index); +mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index); + +// Retrieves the filename of an archive file entry. +// Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename. +mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size); + +// Attempts to locates a file in the archive's central directory. +// Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH +// Returns -1 if the file cannot be found. +int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags); + +// Extracts a archive file to a memory buffer using no memory allocation. +mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); +mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); + +// Extracts a archive file to a memory buffer. +mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags); +mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags); + +// Extracts a archive file to a dynamically allocated heap buffer. +void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags); +void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags); + +// Extracts a archive file using a callback function to output the file's data. +mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); +mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); + +#ifndef MINIZ_NO_STDIO +// Extracts a archive file to a disk file and sets its last accessed and modified times. +// This function only extracts files, not archive directory records. +mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags); +mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags); +#endif + +// Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used. +mz_bool mz_zip_reader_end(mz_zip_archive *pZip); + +// ZIP archive writing + +#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS + +// Inits a ZIP archive writer. +mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size); +mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size); + +#ifndef MINIZ_NO_STDIO +mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning); +#endif + +// Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive. +// For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called. +// For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it). +// Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL. +// Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before +// the archive is finalized the file's central directory will be hosed. +mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename); + +// Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive. +// To add a directory entry, call this method with an archive name ending in a forwardslash with empty buffer. +// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. +mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags); +mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32); + +#ifndef MINIZ_NO_STDIO +// Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive. +// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. +mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); +#endif + +// Adds a file to an archive by fully cloning the data from another archive. +// This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data, and comment fields. +mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index); + +// Finalizes the archive by writing the central directory records followed by the end of central directory record. +// After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end(). +// An archive must be manually finalized by calling this function for it to be valid. +mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip); +mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize); + +// Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used. +// Note for the archive to be valid, it must have been finalized before ending. +mz_bool mz_zip_writer_end(mz_zip_archive *pZip); + +// Misc. high-level helper functions: + +// mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive. +// level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. +mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); + +// Reads a single file from an archive into a heap block. +// Returns NULL on failure. +void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint zip_flags); + +#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS + +#endif // #ifndef MINIZ_NO_ARCHIVE_APIS + +// ------------------- Low-level Decompression API Definitions + +// Decompression flags used by tinfl_decompress(). +// TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream. +// TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input. +// TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB). +// TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes. +enum +{ + TINFL_FLAG_PARSE_ZLIB_HEADER = 1, + TINFL_FLAG_HAS_MORE_INPUT = 2, + TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4, + TINFL_FLAG_COMPUTE_ADLER32 = 8 +}; + +// High level decompression functions: +// tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc(). +// On entry: +// pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress. +// On return: +// Function returns a pointer to the decompressed data, or NULL on failure. +// *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data. +// The caller must call mz_free() on the returned block when it's no longer needed. +void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); + +// tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory. +// Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success. +#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1)) +size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); + +// tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer. +// Returns 1 on success or 0 on failure. +typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser); +int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + +struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor; + +// Max size of LZ dictionary. +#define TINFL_LZ_DICT_SIZE 32768 + +// Return status. +typedef enum +{ + TINFL_STATUS_BAD_PARAM = -3, + TINFL_STATUS_ADLER32_MISMATCH = -2, + TINFL_STATUS_FAILED = -1, + TINFL_STATUS_DONE = 0, + TINFL_STATUS_NEEDS_MORE_INPUT = 1, + TINFL_STATUS_HAS_MORE_OUTPUT = 2 +} tinfl_status; + +// Initializes the decompressor to its initial state. +#define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END +#define tinfl_get_adler32(r) (r)->m_check_adler32 + +// Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability. +// This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output. +tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags); + +// Internal/private bits follow. +enum +{ + TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19, + TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS +}; + +typedef struct +{ + mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0]; + mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2]; +} tinfl_huff_table; + +#if MINIZ_HAS_64BIT_REGISTERS + #define TINFL_USE_64BIT_BITBUF 1 +#endif + +#if TINFL_USE_64BIT_BITBUF + typedef mz_uint64 tinfl_bit_buf_t; + #define TINFL_BITBUF_SIZE (64) +#else + typedef mz_uint32 tinfl_bit_buf_t; + #define TINFL_BITBUF_SIZE (32) +#endif + +struct tinfl_decompressor_tag +{ + mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES]; + tinfl_bit_buf_t m_bit_buf; + size_t m_dist_from_out_buf_start; + tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES]; + mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137]; +}; + +// ------------------- Low-level Compression API Definitions + +// Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently). +#define TDEFL_LESS_MEMORY 0 + +// tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search): +// TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression). +enum +{ + TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF +}; + +// TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data. +// TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers). +// TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing. +// TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory). +// TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1) +// TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled. +// TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables. +// TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks. +// The low 12 bits are reserved to control the max # of hash probes per dictionary lookup (see TDEFL_MAX_PROBES_MASK). +enum +{ + TDEFL_WRITE_ZLIB_HEADER = 0x01000, + TDEFL_COMPUTE_ADLER32 = 0x02000, + TDEFL_GREEDY_PARSING_FLAG = 0x04000, + TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000, + TDEFL_RLE_MATCHES = 0x10000, + TDEFL_FILTER_MATCHES = 0x20000, + TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000, + TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000 +}; + +// High level compression functions: +// tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc(). +// On entry: +// pSrc_buf, src_buf_len: Pointer and size of source block to compress. +// flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression. +// On return: +// Function returns a pointer to the compressed data, or NULL on failure. +// *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data. +// The caller must free() the returned block when it's no longer needed. +void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); + +// tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory. +// Returns 0 on failure. +size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); + +// Compresses an image to a compressed PNG file in memory. +// On entry: +// pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4. +// The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory. +// level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL +// If flip is true, the image will be flipped on the Y axis (useful for OpenGL apps). +// On return: +// Function returns a pointer to the compressed data, or NULL on failure. +// *pLen_out will be set to the size of the PNG image file. +// The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed. +void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip); +void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out); + +// Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time. +typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser); + +// tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally. +mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + +enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 }; + +// TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes). +#if TDEFL_LESS_MEMORY +enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; +#else +enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13 ) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; +#endif + +// The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions. +typedef enum +{ + TDEFL_STATUS_BAD_PARAM = -2, + TDEFL_STATUS_PUT_BUF_FAILED = -1, + TDEFL_STATUS_OKAY = 0, + TDEFL_STATUS_DONE = 1, +} tdefl_status; + +// Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums +typedef enum +{ + TDEFL_NO_FLUSH = 0, + TDEFL_SYNC_FLUSH = 2, + TDEFL_FULL_FLUSH = 3, + TDEFL_FINISH = 4 +} tdefl_flush; + +// tdefl's compression state structure. +typedef struct +{ + tdefl_put_buf_func_ptr m_pPut_buf_func; + void *m_pPut_buf_user; + mz_uint m_flags, m_max_probes[2]; + int m_greedy_parsing; + mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size; + mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end; + mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer; + mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish; + tdefl_status m_prev_return_status; + const void *m_pIn_buf; + void *m_pOut_buf; + size_t *m_pIn_buf_size, *m_pOut_buf_size; + tdefl_flush m_flush; + const mz_uint8 *m_pSrc; + size_t m_src_buf_left, m_out_buf_ofs; + mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1]; + mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; + mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE]; + mz_uint16 m_next[TDEFL_LZ_DICT_SIZE]; + mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE]; + mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE]; +} tdefl_compressor; + +// Initializes the compressor. +// There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory. +// pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression. +// If pBut_buf_func is NULL the user should always call the tdefl_compress() API. +// flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.) +tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); + +// Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible. +tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush); + +// tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr. +// tdefl_compress_buffer() always consumes the entire input buffer. +tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush); + +tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d); +mz_uint32 tdefl_get_adler32(tdefl_compressor *d); + +// Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't defined, because it uses some of its macros. +#ifndef MINIZ_NO_ZLIB_APIS +// Create tdefl_compress() flags given zlib-style compression parameters. +// level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files) +// window_bits may be -15 (raw deflate) or 15 (zlib) +// strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED +mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy); +#endif // #ifndef MINIZ_NO_ZLIB_APIS + +#ifdef __cplusplus +} +#endif + +#endif // MINIZ_HEADER_INCLUDED + +// ------------------- End of Header: Implementation follows. (If you only want the header, define MINIZ_HEADER_FILE_ONLY.) + +#ifndef MINIZ_HEADER_FILE_ONLY + +typedef unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 : -1]; +typedef unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 : -1]; +typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1]; + +#include +#include + +#define MZ_ASSERT(x) assert(x) + +#ifdef MINIZ_NO_MALLOC + #define MZ_MALLOC(x) NULL + #define MZ_FREE(x) (void)x, ((void)0) + #define MZ_REALLOC(p, x) NULL +#else + #define MZ_MALLOC(x) malloc(x) + #define MZ_FREE(x) free(x) + #define MZ_REALLOC(p, x) realloc(p, x) +#endif + +#define MZ_MAX(a,b) (((a)>(b))?(a):(b)) +#define MZ_MIN(a,b) (((a)<(b))?(a):(b)) +#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj)) + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN + #define MZ_READ_LE16(p) *((const mz_uint16 *)(p)) + #define MZ_READ_LE32(p) *((const mz_uint32 *)(p)) +#else + #define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U)) + #define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U)) +#endif + +#ifdef _MSC_VER + #define MZ_FORCEINLINE __forceinline +#elif defined(__GNUC__) + #define MZ_FORCEINLINE inline __attribute__((__always_inline__)) +#else + #define MZ_FORCEINLINE inline +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +// ------------------- zlib-style API's + +mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) +{ + mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552; + if (!ptr) return MZ_ADLER32_INIT; + while (buf_len) { + for (i = 0; i + 7 < block_len; i += 8, ptr += 8) { + s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1; + s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; + } + for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1; + s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552; + } + return (s2 << 16) + s1; +} + +// Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ +mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) +{ + static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; + mz_uint32 crcu32 = (mz_uint32)crc; + if (!ptr) return MZ_CRC32_INIT; + crcu32 = ~crcu32; while (buf_len--) { mz_uint8 b = *ptr++; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)]; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)]; } + return ~crcu32; +} + +void mz_free(void *p) +{ + MZ_FREE(p); +} + +#ifndef MINIZ_NO_ZLIB_APIS + +static void *def_alloc_func(void *opaque, size_t items, size_t size) { (void)opaque, (void)items, (void)size; return MZ_MALLOC(items * size); } +static void def_free_func(void *opaque, void *address) { (void)opaque, (void)address; MZ_FREE(address); } +static void *def_realloc_func(void *opaque, void *address, size_t items, size_t size) { (void)opaque, (void)address, (void)items, (void)size; return MZ_REALLOC(address, items * size); } + +const char *mz_version(void) +{ + return MZ_VERSION; +} + +int mz_deflateInit(mz_streamp pStream, int level) +{ + return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY); +} + +int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy) +{ + tdefl_compressor *pComp; + mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy); + + if (!pStream) return MZ_STREAM_ERROR; + if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) return MZ_PARAM_ERROR; + + pStream->data_type = 0; + pStream->adler = MZ_ADLER32_INIT; + pStream->msg = NULL; + pStream->reserved = 0; + pStream->total_in = 0; + pStream->total_out = 0; + if (!pStream->zalloc) pStream->zalloc = def_alloc_func; + if (!pStream->zfree) pStream->zfree = def_free_func; + + pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor)); + if (!pComp) + return MZ_MEM_ERROR; + + pStream->state = (struct mz_internal_state *)pComp; + + if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) + { + mz_deflateEnd(pStream); + return MZ_PARAM_ERROR; + } + + return MZ_OK; +} + +int mz_deflateReset(mz_streamp pStream) +{ + if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR; + pStream->total_in = pStream->total_out = 0; + tdefl_init((tdefl_compressor*)pStream->state, NULL, NULL, ((tdefl_compressor*)pStream->state)->m_flags); + return MZ_OK; +} + +int mz_deflate(mz_streamp pStream, int flush) +{ + size_t in_bytes, out_bytes; + mz_ulong orig_total_in, orig_total_out; + int mz_status = MZ_OK; + + if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return MZ_STREAM_ERROR; + if (!pStream->avail_out) return MZ_BUF_ERROR; + + if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; + + if (((tdefl_compressor*)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE) + return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR; + + orig_total_in = pStream->total_in; orig_total_out = pStream->total_out; + for ( ; ; ) + { + tdefl_status defl_status; + in_bytes = pStream->avail_in; out_bytes = pStream->avail_out; + + defl_status = tdefl_compress((tdefl_compressor*)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush); + pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; pStream->adler = tdefl_get_adler32((tdefl_compressor*)pStream->state); + + pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; + pStream->total_out += (mz_uint)out_bytes; + + if (defl_status < 0) + { + mz_status = MZ_STREAM_ERROR; + break; + } + else if (defl_status == TDEFL_STATUS_DONE) + { + mz_status = MZ_STREAM_END; + break; + } + else if (!pStream->avail_out) + break; + else if ((!pStream->avail_in) && (flush != MZ_FINISH)) + { + if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out)) + break; + return MZ_BUF_ERROR; // Can't make forward progress without some input. + } + } + return mz_status; +} + +int mz_deflateEnd(mz_streamp pStream) +{ + if (!pStream) return MZ_STREAM_ERROR; + if (pStream->state) + { + pStream->zfree(pStream->opaque, pStream->state); + pStream->state = NULL; + } + return MZ_OK; +} + +mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len) +{ + (void)pStream; + // This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) + return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5); +} + +int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level) +{ + int status; + mz_stream stream; + memset(&stream, 0, sizeof(stream)); + + // In case mz_ulong is 64-bits (argh I hate longs). + if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; + + stream.next_in = pSource; + stream.avail_in = (mz_uint32)source_len; + stream.next_out = pDest; + stream.avail_out = (mz_uint32)*pDest_len; + + status = mz_deflateInit(&stream, level); + if (status != MZ_OK) return status; + + status = mz_deflate(&stream, MZ_FINISH); + if (status != MZ_STREAM_END) + { + mz_deflateEnd(&stream); + return (status == MZ_OK) ? MZ_BUF_ERROR : status; + } + + *pDest_len = stream.total_out; + return mz_deflateEnd(&stream); +} + +int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) +{ + return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION); +} + +mz_ulong mz_compressBound(mz_ulong source_len) +{ + return mz_deflateBound(NULL, source_len); +} + +typedef struct +{ + tinfl_decompressor m_decomp; + mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; int m_window_bits; + mz_uint8 m_dict[TINFL_LZ_DICT_SIZE]; + tinfl_status m_last_status; +} inflate_state; + +int mz_inflateInit2(mz_streamp pStream, int window_bits) +{ + inflate_state *pDecomp; + if (!pStream) return MZ_STREAM_ERROR; + if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR; + + pStream->data_type = 0; + pStream->adler = 0; + pStream->msg = NULL; + pStream->total_in = 0; + pStream->total_out = 0; + pStream->reserved = 0; + if (!pStream->zalloc) pStream->zalloc = def_alloc_func; + if (!pStream->zfree) pStream->zfree = def_free_func; + + pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state)); + if (!pDecomp) return MZ_MEM_ERROR; + + pStream->state = (struct mz_internal_state *)pDecomp; + + tinfl_init(&pDecomp->m_decomp); + pDecomp->m_dict_ofs = 0; + pDecomp->m_dict_avail = 0; + pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT; + pDecomp->m_first_call = 1; + pDecomp->m_has_flushed = 0; + pDecomp->m_window_bits = window_bits; + + return MZ_OK; +} + +int mz_inflateInit(mz_streamp pStream) +{ + return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS); +} + +int mz_inflate(mz_streamp pStream, int flush) +{ + inflate_state* pState; + mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32; + size_t in_bytes, out_bytes, orig_avail_in; + tinfl_status status; + + if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR; + if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; + if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; + + pState = (inflate_state*)pStream->state; + if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER; + orig_avail_in = pStream->avail_in; + + first_call = pState->m_first_call; pState->m_first_call = 0; + if (pState->m_last_status < 0) return MZ_DATA_ERROR; + + if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; + pState->m_has_flushed |= (flush == MZ_FINISH); + + if ((flush == MZ_FINISH) && (first_call)) + { + // MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. + decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; + in_bytes = pStream->avail_in; out_bytes = pStream->avail_out; + status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags); + pState->m_last_status = status; + pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes; + pStream->adler = tinfl_get_adler32(&pState->m_decomp); + pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes; + + if (status < 0) + return MZ_DATA_ERROR; + else if (status != TINFL_STATUS_DONE) + { + pState->m_last_status = TINFL_STATUS_FAILED; + return MZ_BUF_ERROR; + } + return MZ_STREAM_END; + } + // flush != MZ_FINISH then we must assume there's more input. + if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT; + + if (pState->m_dict_avail) + { + n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); + memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); + pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n; + pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); + return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; + } + + for ( ; ; ) + { + in_bytes = pStream->avail_in; + out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs; + + status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags); + pState->m_last_status = status; + + pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; pStream->adler = tinfl_get_adler32(&pState->m_decomp); + + pState->m_dict_avail = (mz_uint)out_bytes; + + n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); + memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); + pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n; + pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); + + if (status < 0) + return MZ_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). + else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in)) + return MZ_BUF_ERROR; // Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. + else if (flush == MZ_FINISH) + { + // The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. + if (status == TINFL_STATUS_DONE) + return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END; + // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. + else if (!pStream->avail_out) + return MZ_BUF_ERROR; + } + else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail)) + break; + } + + return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; +} + +int mz_inflateEnd(mz_streamp pStream) +{ + if (!pStream) + return MZ_STREAM_ERROR; + if (pStream->state) + { + pStream->zfree(pStream->opaque, pStream->state); + pStream->state = NULL; + } + return MZ_OK; +} + +int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) +{ + mz_stream stream; + int status; + memset(&stream, 0, sizeof(stream)); + + // In case mz_ulong is 64-bits (argh I hate longs). + if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; + + stream.next_in = pSource; + stream.avail_in = (mz_uint32)source_len; + stream.next_out = pDest; + stream.avail_out = (mz_uint32)*pDest_len; + + status = mz_inflateInit(&stream); + if (status != MZ_OK) + return status; + + status = mz_inflate(&stream, MZ_FINISH); + if (status != MZ_STREAM_END) + { + mz_inflateEnd(&stream); + return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status; + } + *pDest_len = stream.total_out; + + return mz_inflateEnd(&stream); +} + +const char *mz_error(int err) +{ + static struct { int m_err; const char *m_pDesc; } s_error_descs[] = + { + { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" }, + { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" } + }; + mz_uint i; for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) if (s_error_descs[i].m_err == err) return s_error_descs[i].m_pDesc; + return NULL; +} + +#endif //MINIZ_NO_ZLIB_APIS + +// ------------------- Low-level Decompression (completely independent from all compression API's) + +#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l) +#define TINFL_MEMSET(p, c, l) memset(p, c, l) + +#define TINFL_CR_BEGIN switch(r->m_state) { case 0: +#define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END +#define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END +#define TINFL_CR_FINISH } + +// TODO: If the caller has indicated that there's no more input, and we attempt to read beyond the input buf, then something is wrong with the input because the inflator never +// reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario. +#define TINFL_GET_BYTE(state_index, c) do { \ + if (pIn_buf_cur >= pIn_buf_end) { \ + for ( ; ; ) { \ + if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \ + TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \ + if (pIn_buf_cur < pIn_buf_end) { \ + c = *pIn_buf_cur++; \ + break; \ + } \ + } else { \ + c = 0; \ + break; \ + } \ + } \ + } else c = *pIn_buf_cur++; } MZ_MACRO_END + +#define TINFL_NEED_BITS(state_index, n) do { mz_uint c; TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; } while (num_bits < (mz_uint)(n)) +#define TINFL_SKIP_BITS(state_index, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END +#define TINFL_GET_BITS(state_index, b, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } b = bit_buf & ((1 << (n)) - 1); bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END + +// TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. +// It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a +// Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the +// bit buffer contains >=15 bits (deflate's max. Huffman code size). +#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \ + do { \ + temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \ + if (temp >= 0) { \ + code_len = temp >> 9; \ + if ((code_len) && (num_bits >= code_len)) \ + break; \ + } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \ + code_len = TINFL_FAST_LOOKUP_BITS; \ + do { \ + temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \ + } while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \ + } TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \ + } while (num_bits < 15); + +// TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read +// beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully +// decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32. +// The slow path is only executed at the very end of the input buffer. +#define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \ + int temp; mz_uint code_len, c; \ + if (num_bits < 15) { \ + if ((pIn_buf_end - pIn_buf_cur) < 2) { \ + TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \ + } else { \ + bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); pIn_buf_cur += 2; num_bits += 16; \ + } \ + } \ + if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \ + code_len = temp >> 9, temp &= 511; \ + else { \ + code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \ + } sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END + +tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags) +{ + static const int s_length_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 }; + static const int s_length_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + static const int s_dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + static const int s_dist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + static const mz_uint8 s_length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + static const int s_min_table_sizes[3] = { 257, 1, 4 }; + + tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf; + const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size; + mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size; + size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start; + + // Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). + if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; } + + num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start; + TINFL_CR_BEGIN + + bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1; + if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) + { + TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1); + counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8)); + if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4))))); + if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); } + } + + do + { + TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1; + if (r->m_type == 0) + { + TINFL_SKIP_BITS(5, num_bits & 7); + for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); } + if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); } + while ((counter) && (num_bits)) + { + TINFL_GET_BITS(51, dist, 8); + while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); } + *pOut_buf_cur++ = (mz_uint8)dist; + counter--; + } + while (counter) + { + size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); } + while (pIn_buf_cur >= pIn_buf_end) + { + if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) + { + TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT); + } + else + { + TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED); + } + } + n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter); + TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n; + } + } + else if (r->m_type == 3) + { + TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED); + } + else + { + if (r->m_type == 1) + { + mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i; + r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32); + for ( i = 0; i <= 143; ++i) *p++ = 8; for ( ; i <= 255; ++i) *p++ = 9; for ( ; i <= 279; ++i) *p++ = 7; for ( ; i <= 287; ++i) *p++ = 8; + } + else + { + for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; } + MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; } + r->m_table_sizes[2] = 19; + } + for ( ; (int)r->m_type >= 0; r->m_type--) + { + int tree_next, tree_cur; tinfl_huff_table *pTable; + mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree); + for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++; + used_syms = 0, total = 0; next_code[0] = next_code[1] = 0; + for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); } + if ((65536 != total) && (used_syms > 1)) + { + TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED); + } + for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index) + { + mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue; + cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1); + if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; } + if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } + rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1); + for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) + { + tree_cur -= ((rev_code >>= 1) & 1); + if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1]; + } + tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index; + } + if (r->m_type == 2) + { + for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]); ) + { + mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; } + if ((dist == 16) && (!counter)) + { + TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED); + } + num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16]; + TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s; + } + if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) + { + TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED); + } + TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]); + } + } + for ( ; ; ) + { + mz_uint8 *pSrc; + for ( ; ; ) + { + if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2)) + { + TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]); + if (counter >= 256) + break; + while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); } + *pOut_buf_cur++ = (mz_uint8)counter; + } + else + { + int sym2; mz_uint code_len; +#if TINFL_USE_64BIT_BITBUF + if (num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; } +#else + if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } +#endif + if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) + code_len = sym2 >> 9; + else + { + code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0); + } + counter = sym2; bit_buf >>= code_len; num_bits -= code_len; + if (counter & 256) + break; + +#if !TINFL_USE_64BIT_BITBUF + if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } +#endif + if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) + code_len = sym2 >> 9; + else + { + code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0); + } + bit_buf >>= code_len; num_bits -= code_len; + + pOut_buf_cur[0] = (mz_uint8)counter; + if (sym2 & 256) + { + pOut_buf_cur++; + counter = sym2; + break; + } + pOut_buf_cur[1] = (mz_uint8)sym2; + pOut_buf_cur += 2; + } + } + if ((counter &= 511) == 256) break; + + num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257]; + if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; } + + TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]); + num_extra = s_dist_extra[dist]; dist = s_dist_base[dist]; + if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; } + + dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start; + if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) + { + TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED); + } + + pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask); + + if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) + { + while (counter--) + { + while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); } + *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask]; + } + continue; + } +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES + else if ((counter >= 9) && (counter <= dist)) + { + const mz_uint8 *pSrc_end = pSrc + (counter & ~7); + do + { + ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0]; + ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1]; + pOut_buf_cur += 8; + } while ((pSrc += 8) < pSrc_end); + if ((counter &= 7) < 3) + { + if (counter) + { + pOut_buf_cur[0] = pSrc[0]; + if (counter > 1) + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur += counter; + } + continue; + } + } +#endif + do + { + pOut_buf_cur[0] = pSrc[0]; + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur[2] = pSrc[2]; + pOut_buf_cur += 3; pSrc += 3; + } while ((int)(counter -= 3) > 2); + if ((int)counter > 0) + { + pOut_buf_cur[0] = pSrc[0]; + if ((int)counter > 1) + pOut_buf_cur[1] = pSrc[1]; + pOut_buf_cur += counter; + } + } + } + } while (!(r->m_final & 1)); + if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) + { + TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; } + } + TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE); + TINFL_CR_FINISH + +common_exit: + r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start; + *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next; + if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0)) + { + const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size; + mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552; + while (buf_len) + { + for (i = 0; i + 7 < block_len; i += 8, ptr += 8) + { + s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1; + s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; + } + for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1; + s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552; + } + r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH; + } + return status; +} + +// Higher level helper functions. +void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) +{ + tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0; + *pOut_len = 0; + tinfl_init(&decomp); + for ( ; ; ) + { + size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity; + tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8*)pBuf, pBuf ? (mz_uint8*)pBuf + *pOut_len : NULL, &dst_buf_size, + (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); + if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) + { + MZ_FREE(pBuf); *pOut_len = 0; return NULL; + } + src_buf_ofs += src_buf_size; + *pOut_len += dst_buf_size; + if (status == TINFL_STATUS_DONE) break; + new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128; + pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity); + if (!pNew_buf) + { + MZ_FREE(pBuf); *pOut_len = 0; return NULL; + } + pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity; + } + return pBuf; +} + +size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) +{ + tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp); + status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); + return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len; +} + +int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) +{ + int result = 0; + tinfl_decompressor decomp; + mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0; + if (!pDict) + return TINFL_STATUS_FAILED; + tinfl_init(&decomp); + for ( ; ; ) + { + size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs; + tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size, + (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); + in_buf_ofs += in_buf_size; + if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user))) + break; + if (status != TINFL_STATUS_HAS_MORE_OUTPUT) + { + result = (status == TINFL_STATUS_DONE); + break; + } + dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1); + } + MZ_FREE(pDict); + *pIn_buf_size = in_buf_ofs; + return result; +} + +// ------------------- Low-level Compression (independent from all decompression API's) + +// Purposely making these tables static for faster init and thread safety. +static const mz_uint16 s_tdefl_len_sym[256] = { + 257,258,259,260,261,262,263,264,265,265,266,266,267,267,268,268,269,269,269,269,270,270,270,270,271,271,271,271,272,272,272,272, + 273,273,273,273,273,273,273,273,274,274,274,274,274,274,274,274,275,275,275,275,275,275,275,275,276,276,276,276,276,276,276,276, + 277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278, + 279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280, + 281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281, + 282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282, + 283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283, + 284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,285 }; + +static const mz_uint8 s_tdefl_len_extra[256] = { + 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0 }; + +static const mz_uint8 s_tdefl_small_dist_sym[512] = { + 0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, + 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17, + 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, + 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, + 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17 }; + +static const mz_uint8 s_tdefl_small_dist_extra[512] = { + 0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7 }; + +static const mz_uint8 s_tdefl_large_dist_sym[128] = { + 0,0,18,19,20,20,21,21,22,22,22,22,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26, + 26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28, + 28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 }; + +static const mz_uint8 s_tdefl_large_dist_extra[128] = { + 0,0,8,8,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13 }; + +// Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. +typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq; +static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1) +{ + mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; tdefl_sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1; MZ_CLEAR_OBJ(hist); + for (i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; } + while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--; + for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) + { + const mz_uint32* pHist = &hist[pass << 8]; + mz_uint offsets[256], cur_ofs = 0; + for (i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; } + for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i]; + { tdefl_sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; } + } + return pCur_syms; +} + +// tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. +static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) +{ + int root, leaf, next, avbl, used, dpth; + if (n==0) return; else if (n==1) { A[0].m_key = 1; return; } + A[0].m_key += A[1].m_key; root = 0; leaf = 2; + for (next=1; next < n-1; next++) + { + if (leaf>=n || A[root].m_key=n || (root=0; next--) A[next].m_key = A[A[next].m_key].m_key+1; + avbl = 1; used = dpth = 0; root = n-2; next = n-1; + while (avbl>0) + { + while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; } + while (avbl>used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; } + avbl = 2*used; dpth++; used = 0; + } +} + +// Limits canonical Huffman code table's max code size. +enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 }; +static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size) +{ + int i; mz_uint32 total = 0; if (code_list_len <= 1) return; + for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i]; + for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i)); + while (total != (1UL << max_code_size)) + { + pNum_codes[max_code_size]--; + for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; } + total--; + } +} + +static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table) +{ + int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; MZ_CLEAR_OBJ(num_codes); + if (static_table) + { + for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++; + } + else + { + tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms; + int num_used_syms = 0; + const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0]; + for (i = 0; i < table_len; i++) if (pSym_count[i]) { syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; syms0[num_used_syms++].m_sym_index = (mz_uint16)i; } + + pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms); + + for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++; + + tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit); + + MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]); + for (i = 1, j = num_used_syms; i <= code_size_limit; i++) + for (l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i); + } + + next_code[1] = 0; for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1); + + for (i = 0; i < table_len; i++) + { + mz_uint rev_code = 0, code, code_size; if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue; + code = next_code[code_size]++; for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1); + d->m_huff_codes[table_num][i] = (mz_uint16)rev_code; + } +} + +#define TDEFL_PUT_BITS(b, l) do { \ + mz_uint bits = b; mz_uint len = l; MZ_ASSERT(bits <= ((1U << len) - 1U)); \ + d->m_bit_buffer |= (bits << d->m_bits_in); d->m_bits_in += len; \ + while (d->m_bits_in >= 8) { \ + if (d->m_pOutput_buf < d->m_pOutput_buf_end) \ + *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \ + d->m_bit_buffer >>= 8; \ + d->m_bits_in -= 8; \ + } \ +} MZ_MACRO_END + +#define TDEFL_RLE_PREV_CODE_SIZE() { if (rle_repeat_count) { \ + if (rle_repeat_count < 3) { \ + d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \ + while (rle_repeat_count--) packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \ + } else { \ + d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); packed_code_sizes[num_packed_code_sizes++] = 16; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \ +} rle_repeat_count = 0; } } + +#define TDEFL_RLE_ZERO_CODE_SIZE() { if (rle_z_count) { \ + if (rle_z_count < 3) { \ + d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); while (rle_z_count--) packed_code_sizes[num_packed_code_sizes++] = 0; \ + } else if (rle_z_count <= 10) { \ + d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); packed_code_sizes[num_packed_code_sizes++] = 17; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \ + } else { \ + d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); packed_code_sizes[num_packed_code_sizes++] = 18; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \ +} rle_z_count = 0; } } + +static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; + +static void tdefl_start_dynamic_block(tdefl_compressor *d) +{ + int num_lit_codes, num_dist_codes, num_bit_lengths; mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index; + mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF; + + d->m_huff_count[0][256] = 1; + + tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE); + tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE); + + for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break; + for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break; + + memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes); + memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes); + total_code_sizes_to_pack = num_lit_codes + num_dist_codes; num_packed_code_sizes = 0; rle_z_count = 0; rle_repeat_count = 0; + + memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2); + for (i = 0; i < total_code_sizes_to_pack; i++) + { + mz_uint8 code_size = code_sizes_to_pack[i]; + if (!code_size) + { + TDEFL_RLE_PREV_CODE_SIZE(); + if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); } + } + else + { + TDEFL_RLE_ZERO_CODE_SIZE(); + if (code_size != prev_code_size) + { + TDEFL_RLE_PREV_CODE_SIZE(); + d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); packed_code_sizes[num_packed_code_sizes++] = code_size; + } + else if (++rle_repeat_count == 6) + { + TDEFL_RLE_PREV_CODE_SIZE(); + } + } + prev_code_size = code_size; + } + if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } else { TDEFL_RLE_ZERO_CODE_SIZE(); } + + tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE); + + TDEFL_PUT_BITS(2, 2); + + TDEFL_PUT_BITS(num_lit_codes - 257, 5); + TDEFL_PUT_BITS(num_dist_codes - 1, 5); + + for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break; + num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4); + for (i = 0; (int)i < num_bit_lengths; i++) TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3); + + for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes; ) + { + mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2); + TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]); + if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]); + } +} + +static void tdefl_start_static_block(tdefl_compressor *d) +{ + mz_uint i; + mz_uint8 *p = &d->m_huff_code_sizes[0][0]; + + for (i = 0; i <= 143; ++i) *p++ = 8; + for ( ; i <= 255; ++i) *p++ = 9; + for ( ; i <= 279; ++i) *p++ = 7; + for ( ; i <= 287; ++i) *p++ = 8; + + memset(d->m_huff_code_sizes[1], 5, 32); + + tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE); + tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE); + + TDEFL_PUT_BITS(1, 2); +} + +static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS +static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) +{ + mz_uint flags; + mz_uint8 *pLZ_codes; + mz_uint8 *pOutput_buf = d->m_pOutput_buf; + mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf; + mz_uint64 bit_buffer = d->m_bit_buffer; + mz_uint bits_in = d->m_bits_in; + +#define TDEFL_PUT_BITS_FAST(b, l) { bit_buffer |= (((mz_uint64)(b)) << bits_in); bits_in += (l); } + + flags = 1; + for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1) + { + if (flags == 1) + flags = *pLZ_codes++ | 0x100; + + if (flags & 1) + { + mz_uint s0, s1, n0, n1, sym, num_extra_bits; + mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); pLZ_codes += 3; + + MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); + + // This sequence coaxes MSVC into using cmov's vs. jmp's. + s0 = s_tdefl_small_dist_sym[match_dist & 511]; + n0 = s_tdefl_small_dist_extra[match_dist & 511]; + s1 = s_tdefl_large_dist_sym[match_dist >> 8]; + n1 = s_tdefl_large_dist_extra[match_dist >> 8]; + sym = (match_dist < 512) ? s0 : s1; + num_extra_bits = (match_dist < 512) ? n0 : n1; + + MZ_ASSERT(d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); + } + else + { + mz_uint lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + + if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) + { + flags >>= 1; + lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + + if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) + { + flags >>= 1; + lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + } + } + } + + if (pOutput_buf >= d->m_pOutput_buf_end) + return MZ_FALSE; + + *(mz_uint64*)pOutput_buf = bit_buffer; + pOutput_buf += (bits_in >> 3); + bit_buffer >>= (bits_in & ~7); + bits_in &= 7; + } + +#undef TDEFL_PUT_BITS_FAST + + d->m_pOutput_buf = pOutput_buf; + d->m_bits_in = 0; + d->m_bit_buffer = 0; + + while (bits_in) + { + mz_uint32 n = MZ_MIN(bits_in, 16); + TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n); + bit_buffer >>= n; + bits_in -= n; + } + + TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); + + return (d->m_pOutput_buf < d->m_pOutput_buf_end); +} +#else +static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) +{ + mz_uint flags; + mz_uint8 *pLZ_codes; + + flags = 1; + for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1) + { + if (flags == 1) + flags = *pLZ_codes++ | 0x100; + if (flags & 1) + { + mz_uint sym, num_extra_bits; + mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); pLZ_codes += 3; + + MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); + TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); + + if (match_dist < 512) + { + sym = s_tdefl_small_dist_sym[match_dist]; num_extra_bits = s_tdefl_small_dist_extra[match_dist]; + } + else + { + sym = s_tdefl_large_dist_sym[match_dist >> 8]; num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8]; + } + MZ_ASSERT(d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); + TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); + } + else + { + mz_uint lit = *pLZ_codes++; + MZ_ASSERT(d->m_huff_code_sizes[0][lit]); + TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); + } + } + + TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); + + return (d->m_pOutput_buf < d->m_pOutput_buf_end); +} +#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS + +static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block) +{ + if (static_block) + tdefl_start_static_block(d); + else + tdefl_start_dynamic_block(d); + return tdefl_compress_lz_codes(d); +} + +static int tdefl_flush_block(tdefl_compressor *d, int flush) +{ + mz_uint saved_bit_buf, saved_bits_in; + mz_uint8 *pSaved_output_buf; + mz_bool comp_block_succeeded = MZ_FALSE; + int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size; + mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf; + + d->m_pOutput_buf = pOutput_buf_start; + d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16; + + MZ_ASSERT(!d->m_output_flush_remaining); + d->m_output_flush_ofs = 0; + d->m_output_flush_remaining = 0; + + *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left); + d->m_pLZ_code_buf -= (d->m_num_flags_left == 8); + + if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) + { + TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8); + } + + TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1); + + pSaved_output_buf = d->m_pOutput_buf; saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in; + + if (!use_raw_block) + comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48)); + + // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. + if ( ((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) && + ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size) ) + { + mz_uint i; d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; + TDEFL_PUT_BITS(0, 2); + if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } + for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) + { + TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16); + } + for (i = 0; i < d->m_total_lz_bytes; ++i) + { + TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8); + } + } + // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. + else if (!comp_block_succeeded) + { + d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; + tdefl_compress_block(d, MZ_TRUE); + } + + if (flush) + { + if (flush == TDEFL_FINISH) + { + if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } + if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { mz_uint i, a = d->m_adler32; for (i = 0; i < 4; i++) { TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); a <<= 8; } } + } + else + { + mz_uint i, z = 0; TDEFL_PUT_BITS(0, 3); if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } for (i = 2; i; --i, z ^= 0xFFFF) { TDEFL_PUT_BITS(z & 0xFFFF, 16); } + } + } + + MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end); + + memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); + memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); + + d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; d->m_total_lz_bytes = 0; d->m_block_index++; + + if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) + { + if (d->m_pPut_buf_func) + { + *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; + if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user)) + return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED); + } + else if (pOutput_buf_start == d->m_output_buf) + { + int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs)); + memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy); + d->m_out_buf_ofs += bytes_to_copy; + if ((n -= bytes_to_copy) != 0) + { + d->m_output_flush_ofs = bytes_to_copy; + d->m_output_flush_remaining = n; + } + } + else + { + d->m_out_buf_ofs += n; + } + } + + return d->m_output_flush_remaining; +} + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES +#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16*)(p) +static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) +{ + mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; + mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; + const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q; + mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s); + MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return; + for ( ; ; ) + { + for ( ; ; ) + { + if (--num_probes_left == 0) return; + #define TDEFL_PROBE \ + next_probe_pos = d->m_next[probe_pos]; \ + if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \ + probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ + if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break; + TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; + } + if (!dist) break; q = (const mz_uint16*)(d->m_dict + probe_pos); if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; p = s; probe_len = 32; + do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && + (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) ); + if (!probe_len) + { + *pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); break; + } + else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len) + { + *pMatch_dist = dist; if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break; + c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]); + } + } +} +#else +static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) +{ + mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; + mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; + const mz_uint8 *s = d->m_dict + pos, *p, *q; + mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1]; + MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return; + for ( ; ; ) + { + for ( ; ; ) + { + if (--num_probes_left == 0) return; + #define TDEFL_PROBE \ + next_probe_pos = d->m_next[probe_pos]; \ + if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \ + probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ + if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break; + TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; + } + if (!dist) break; p = s; q = d->m_dict + probe_pos; for (probe_len = 0; probe_len < max_match_len; probe_len++) if (*p++ != *q++) break; + if (probe_len > match_len) + { + *pMatch_dist = dist; if ((*pMatch_len = match_len = probe_len) == max_match_len) return; + c0 = d->m_dict[pos + match_len]; c1 = d->m_dict[pos + match_len - 1]; + } + } +} +#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN +static mz_bool tdefl_compress_fast(tdefl_compressor *d) +{ + // Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. + mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left; + mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags; + mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; + + while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) + { + const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096; + mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; + mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size); + d->m_src_buf_left -= num_bytes_to_process; + lookahead_size += num_bytes_to_process; + + while (num_bytes_to_process) + { + mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process); + memcpy(d->m_dict + dst_pos, d->m_pSrc, n); + if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) + memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos)); + d->m_pSrc += n; + dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK; + num_bytes_to_process -= n; + } + + dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size); + if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break; + + while (lookahead_size >= 4) + { + mz_uint cur_match_dist, cur_match_len = 1; + mz_uint8 *pCur_dict = d->m_dict + cur_pos; + mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF; + mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK; + mz_uint probe_pos = d->m_hash[hash]; + d->m_hash[hash] = (mz_uint16)lookahead_pos; + + if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram)) + { + const mz_uint16 *p = (const mz_uint16 *)pCur_dict; + const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos); + mz_uint32 probe_len = 32; + do { } while ( (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && + (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) ); + cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q); + if (!probe_len) + cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0; + + if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U))) + { + cur_match_len = 1; + *pLZ_code_buf++ = (mz_uint8)first_trigram; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + d->m_huff_count[0][(mz_uint8)first_trigram]++; + } + else + { + mz_uint32 s0, s1; + cur_match_len = MZ_MIN(cur_match_len, lookahead_size); + + MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE)); + + cur_match_dist--; + + pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN); + *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist; + pLZ_code_buf += 3; + *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80); + + s0 = s_tdefl_small_dist_sym[cur_match_dist & 511]; + s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8]; + d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++; + + d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++; + } + } + else + { + *pLZ_code_buf++ = (mz_uint8)first_trigram; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + d->m_huff_count[0][(mz_uint8)first_trigram]++; + } + + if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; } + + total_lz_bytes += cur_match_len; + lookahead_pos += cur_match_len; + dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE); + cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK; + MZ_ASSERT(lookahead_size >= cur_match_len); + lookahead_size -= cur_match_len; + + if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) + { + int n; + d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; + if ((n = tdefl_flush_block(d, 0)) != 0) + return (n < 0) ? MZ_FALSE : MZ_TRUE; + total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left; + } + } + + while (lookahead_size) + { + mz_uint8 lit = d->m_dict[cur_pos]; + + total_lz_bytes++; + *pLZ_code_buf++ = lit; + *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); + if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; } + + d->m_huff_count[0][lit]++; + + lookahead_pos++; + dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE); + cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; + lookahead_size--; + + if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) + { + int n; + d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; + if ((n = tdefl_flush_block(d, 0)) != 0) + return (n < 0) ? MZ_FALSE : MZ_TRUE; + total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left; + } + } + } + + d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; + d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; + return MZ_TRUE; +} +#endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN + +static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit) +{ + d->m_total_lz_bytes++; + *d->m_pLZ_code_buf++ = lit; + *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; } + d->m_huff_count[0][lit]++; +} + +static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist) +{ + mz_uint32 s0, s1; + + MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE)); + + d->m_total_lz_bytes += match_len; + + d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN); + + match_dist -= 1; + d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF); + d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); d->m_pLZ_code_buf += 3; + + *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; } + + s0 = s_tdefl_small_dist_sym[match_dist & 511]; s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127]; + d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++; + + if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++; +} + +static mz_bool tdefl_compress_normal(tdefl_compressor *d) +{ + const mz_uint8 *pSrc = d->m_pSrc; size_t src_buf_left = d->m_src_buf_left; + tdefl_flush flush = d->m_flush; + + while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) + { + mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos; + // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. + if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) + { + mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2; + mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]; + mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size); + const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process; + src_buf_left -= num_bytes_to_process; + d->m_lookahead_size += num_bytes_to_process; + while (pSrc != pSrc_end) + { + mz_uint8 c = *pSrc++; d->m_dict[dst_pos] = c; if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; + hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); + d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos); + dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; ins_pos++; + } + } + else + { + while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) + { + mz_uint8 c = *pSrc++; + mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; + src_buf_left--; + d->m_dict[dst_pos] = c; + if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) + d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; + if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) + { + mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2; + mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); + d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos); + } + } + } + d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size); + if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) + break; + + // Simple lazy/greedy parsing state machine. + len_to_move = 1; cur_match_dist = 0; cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; + if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) + { + if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) + { + mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK]; + cur_match_len = 0; while (cur_match_len < d->m_lookahead_size) { if (d->m_dict[cur_pos + cur_match_len] != c) break; cur_match_len++; } + if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1; + } + } + else + { + tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len); + } + if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) + { + cur_match_dist = cur_match_len = 0; + } + if (d->m_saved_match_len) + { + if (cur_match_len > d->m_saved_match_len) + { + tdefl_record_literal(d, (mz_uint8)d->m_saved_lit); + if (cur_match_len >= 128) + { + tdefl_record_match(d, cur_match_len, cur_match_dist); + d->m_saved_match_len = 0; len_to_move = cur_match_len; + } + else + { + d->m_saved_lit = d->m_dict[cur_pos]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len; + } + } + else + { + tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist); + len_to_move = d->m_saved_match_len - 1; d->m_saved_match_len = 0; + } + } + else if (!cur_match_dist) + tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]); + else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128)) + { + tdefl_record_match(d, cur_match_len, cur_match_dist); + len_to_move = cur_match_len; + } + else + { + d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len; + } + // Move the lookahead forward by len_to_move bytes. + d->m_lookahead_pos += len_to_move; + MZ_ASSERT(d->m_lookahead_size >= len_to_move); + d->m_lookahead_size -= len_to_move; + d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE); + // Check if it's time to flush the current LZ codes to the internal output buffer. + if ( (d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) || + ( (d->m_total_lz_bytes > 31*1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) ) + { + int n; + d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left; + if ((n = tdefl_flush_block(d, 0)) != 0) + return (n < 0) ? MZ_FALSE : MZ_TRUE; + } + } + + d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left; + return MZ_TRUE; +} + +static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) +{ + if (d->m_pIn_buf_size) + { + *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; + } + + if (d->m_pOut_buf_size) + { + size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining); + memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n); + d->m_output_flush_ofs += (mz_uint)n; + d->m_output_flush_remaining -= (mz_uint)n; + d->m_out_buf_ofs += n; + + *d->m_pOut_buf_size = d->m_out_buf_ofs; + } + + return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY; +} + +tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush) +{ + if (!d) + { + if (pIn_buf_size) *pIn_buf_size = 0; + if (pOut_buf_size) *pOut_buf_size = 0; + return TDEFL_STATUS_BAD_PARAM; + } + + d->m_pIn_buf = pIn_buf; d->m_pIn_buf_size = pIn_buf_size; + d->m_pOut_buf = pOut_buf; d->m_pOut_buf_size = pOut_buf_size; + d->m_pSrc = (const mz_uint8 *)(pIn_buf); d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0; + d->m_out_buf_ofs = 0; + d->m_flush = flush; + + if ( ((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) || + (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf) ) + { + if (pIn_buf_size) *pIn_buf_size = 0; + if (pOut_buf_size) *pOut_buf_size = 0; + return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM); + } + d->m_wants_to_finish |= (flush == TDEFL_FINISH); + + if ((d->m_output_flush_remaining) || (d->m_finished)) + return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); + +#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN + if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) && + ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) && + ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0)) + { + if (!tdefl_compress_fast(d)) + return d->m_prev_return_status; + } + else +#endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN + { + if (!tdefl_compress_normal(d)) + return d->m_prev_return_status; + } + + if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf)) + d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf); + + if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining)) + { + if (tdefl_flush_block(d, flush) < 0) + return d->m_prev_return_status; + d->m_finished = (flush == TDEFL_FINISH); + if (flush == TDEFL_FULL_FLUSH) { MZ_CLEAR_OBJ(d->m_hash); MZ_CLEAR_OBJ(d->m_next); d->m_dict_size = 0; } + } + + return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); +} + +tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush) +{ + MZ_ASSERT(d->m_pPut_buf_func); return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush); +} + +tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) +{ + d->m_pPut_buf_func = pPut_buf_func; d->m_pPut_buf_user = pPut_buf_user; + d->m_flags = (mz_uint)(flags); d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0; + d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3; + if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash); + d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0; + d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0; + d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; + d->m_pOutput_buf = d->m_output_buf; d->m_pOutput_buf_end = d->m_output_buf; d->m_prev_return_status = TDEFL_STATUS_OKAY; + d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; d->m_adler32 = 1; + d->m_pIn_buf = NULL; d->m_pOut_buf = NULL; + d->m_pIn_buf_size = NULL; d->m_pOut_buf_size = NULL; + d->m_flush = TDEFL_NO_FLUSH; d->m_pSrc = NULL; d->m_src_buf_left = 0; d->m_out_buf_ofs = 0; + memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); + memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); + return TDEFL_STATUS_OKAY; +} + +tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) +{ + return d->m_prev_return_status; +} + +mz_uint32 tdefl_get_adler32(tdefl_compressor *d) +{ + return d->m_adler32; +} + +mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) +{ + tdefl_compressor *pComp; mz_bool succeeded; if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE; + pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); if (!pComp) return MZ_FALSE; + succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY); + succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE); + MZ_FREE(pComp); return succeeded; +} + +typedef struct +{ + size_t m_size, m_capacity; + mz_uint8 *m_pBuf; + mz_bool m_expandable; +} tdefl_output_buffer; + +static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser) +{ + tdefl_output_buffer *p = (tdefl_output_buffer *)pUser; + size_t new_size = p->m_size + len; + if (new_size > p->m_capacity) + { + size_t new_capacity = p->m_capacity; mz_uint8 *pNew_buf; if (!p->m_expandable) return MZ_FALSE; + do { new_capacity = MZ_MAX(128U, new_capacity << 1U); } while (new_size > new_capacity); + pNew_buf = (mz_uint8*)MZ_REALLOC(p->m_pBuf, new_capacity); if (!pNew_buf) return MZ_FALSE; + p->m_pBuf = pNew_buf; p->m_capacity = new_capacity; + } + memcpy((mz_uint8*)p->m_pBuf + p->m_size, pBuf, len); p->m_size = new_size; + return MZ_TRUE; +} + +void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) +{ + tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); + if (!pOut_len) return MZ_FALSE; else *pOut_len = 0; + out_buf.m_expandable = MZ_TRUE; + if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return NULL; + *pOut_len = out_buf.m_size; return out_buf.m_pBuf; +} + +size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) +{ + tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); + if (!pOut_buf) return 0; + out_buf.m_pBuf = (mz_uint8*)pOut_buf; out_buf.m_capacity = out_buf_len; + if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0; + return out_buf.m_size; +} + +#ifndef MINIZ_NO_ZLIB_APIS +static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 }; + +// level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). +mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy) +{ + mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); + if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER; + + if (!level) comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; + else if (strategy == MZ_FILTERED) comp_flags |= TDEFL_FILTER_MATCHES; + else if (strategy == MZ_HUFFMAN_ONLY) comp_flags &= ~TDEFL_MAX_PROBES_MASK; + else if (strategy == MZ_FIXED) comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS; + else if (strategy == MZ_RLE) comp_flags |= TDEFL_RLE_MATCHES; + + return comp_flags; +} +#endif //MINIZ_NO_ZLIB_APIS + +#ifdef _MSC_VER +#pragma warning (push) +#pragma warning (disable:4204) // nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal) +#endif + +// Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at +// http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/. +// This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck. +void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip) +{ + // Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined. + static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 }; + tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); tdefl_output_buffer out_buf; int i, bpl = w * num_chans, y, z; mz_uint32 c; *pLen_out = 0; + if (!pComp) return NULL; + MZ_CLEAR_OBJ(out_buf); out_buf.m_expandable = MZ_TRUE; out_buf.m_capacity = 57+MZ_MAX(64, (1+bpl)*h); if (NULL == (out_buf.m_pBuf = (mz_uint8*)MZ_MALLOC(out_buf.m_capacity))) { MZ_FREE(pComp); return NULL; } + // write dummy header + for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf); + // compress image data + tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER); + for (y = 0; y < h; ++y) { tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8*)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); } + if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; } + // write real header + *pLen_out = out_buf.m_size-41; + { + static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06}; + mz_uint8 pnghdr[41]={0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52, + 0,0,(mz_uint8)(w>>8),(mz_uint8)w,0,0,(mz_uint8)(h>>8),(mz_uint8)h,8,chans[num_chans],0,0,0,0,0,0,0, + (mz_uint8)(*pLen_out>>24),(mz_uint8)(*pLen_out>>16),(mz_uint8)(*pLen_out>>8),(mz_uint8)*pLen_out,0x49,0x44,0x41,0x54}; + c=(mz_uint32)mz_crc32(MZ_CRC32_INIT,pnghdr+12,17); for (i=0; i<4; ++i, c<<=8) ((mz_uint8*)(pnghdr+29))[i]=(mz_uint8)(c>>24); + memcpy(out_buf.m_pBuf, pnghdr, 41); + } + // write footer (IDAT CRC-32, followed by IEND chunk) + if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; } + c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,out_buf.m_pBuf+41-4, *pLen_out+4); for (i=0; i<4; ++i, c<<=8) (out_buf.m_pBuf+out_buf.m_size-16)[i] = (mz_uint8)(c >> 24); + // compute final size of file, grab compressed data buffer and return + *pLen_out += 57; MZ_FREE(pComp); return out_buf.m_pBuf; +} +void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out) +{ + // Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out) + return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE); +} + +#ifdef _MSC_VER +#pragma warning (pop) +#endif + +// ------------------- .ZIP archive reading + +#ifndef MINIZ_NO_ARCHIVE_APIS + +#ifdef MINIZ_NO_STDIO + #define MZ_FILE void * +#else + #include + #include + + #if defined(_MSC_VER) || defined(__MINGW64__) + static FILE *mz_fopen(const char *pFilename, const char *pMode) + { + FILE* pFile = NULL; + fopen_s(&pFile, pFilename, pMode); + return pFile; + } + static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) + { + FILE* pFile = NULL; + if (freopen_s(&pFile, pPath, pMode, pStream)) + return NULL; + return pFile; + } + #ifndef MINIZ_NO_TIME + #include + #endif + #define MZ_FILE FILE + #define MZ_FOPEN mz_fopen + #define MZ_FCLOSE fclose + #define MZ_FREAD fread + #define MZ_FWRITE fwrite + #define MZ_FTELL64 _ftelli64 + #define MZ_FSEEK64 _fseeki64 + #define MZ_FILE_STAT_STRUCT _stat + #define MZ_FILE_STAT _stat + #define MZ_FFLUSH fflush + #define MZ_FREOPEN mz_freopen + #define MZ_DELETE_FILE remove + #elif defined(__MINGW32__) + #ifndef MINIZ_NO_TIME + #include + #endif + #define MZ_FILE FILE + #define MZ_FOPEN(f, m) fopen(f, m) + #define MZ_FCLOSE fclose + #define MZ_FREAD fread + #define MZ_FWRITE fwrite + #define MZ_FTELL64 ftello64 + #define MZ_FSEEK64 fseeko64 + #define MZ_FILE_STAT_STRUCT _stat + #define MZ_FILE_STAT _stat + #define MZ_FFLUSH fflush + #define MZ_FREOPEN(f, m, s) freopen(f, m, s) + #define MZ_DELETE_FILE remove + #elif defined(__TINYC__) + #ifndef MINIZ_NO_TIME + #include + #endif + #define MZ_FILE FILE + #define MZ_FOPEN(f, m) fopen(f, m) + #define MZ_FCLOSE fclose + #define MZ_FREAD fread + #define MZ_FWRITE fwrite + #define MZ_FTELL64 ftell + #define MZ_FSEEK64 fseek + #define MZ_FILE_STAT_STRUCT stat + #define MZ_FILE_STAT stat + #define MZ_FFLUSH fflush + #define MZ_FREOPEN(f, m, s) freopen(f, m, s) + #define MZ_DELETE_FILE remove + #elif defined(__GNUC__) && _LARGEFILE64_SOURCE + #ifndef MINIZ_NO_TIME + #include + #endif + #define MZ_FILE FILE + #define MZ_FOPEN(f, m) fopen64(f, m) + #define MZ_FCLOSE fclose + #define MZ_FREAD fread + #define MZ_FWRITE fwrite + #define MZ_FTELL64 ftello64 + #define MZ_FSEEK64 fseeko64 + #define MZ_FILE_STAT_STRUCT stat64 + #define MZ_FILE_STAT stat64 + #define MZ_FFLUSH fflush + #define MZ_FREOPEN(p, m, s) freopen64(p, m, s) + #define MZ_DELETE_FILE remove + #else + #ifndef MINIZ_NO_TIME + #include + #endif + #define MZ_FILE FILE + #define MZ_FOPEN(f, m) fopen(f, m) + #define MZ_FCLOSE fclose + #define MZ_FREAD fread + #define MZ_FWRITE fwrite + #define MZ_FTELL64 ftello + #define MZ_FSEEK64 fseeko + #define MZ_FILE_STAT_STRUCT stat + #define MZ_FILE_STAT stat + #define MZ_FFLUSH fflush + #define MZ_FREOPEN(f, m, s) freopen(f, m, s) + #define MZ_DELETE_FILE remove + #endif // #ifdef _MSC_VER +#endif // #ifdef MINIZ_NO_STDIO + +#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c)) + +// Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff. +enum +{ + // ZIP archive identifiers and record sizes + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50, MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50, MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50, + MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22, + // Central directory header record offsets + MZ_ZIP_CDH_SIG_OFS = 0, MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6, MZ_ZIP_CDH_BIT_FLAG_OFS = 8, + MZ_ZIP_CDH_METHOD_OFS = 10, MZ_ZIP_CDH_FILE_TIME_OFS = 12, MZ_ZIP_CDH_FILE_DATE_OFS = 14, MZ_ZIP_CDH_CRC32_OFS = 16, + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20, MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24, MZ_ZIP_CDH_FILENAME_LEN_OFS = 28, MZ_ZIP_CDH_EXTRA_LEN_OFS = 30, + MZ_ZIP_CDH_COMMENT_LEN_OFS = 32, MZ_ZIP_CDH_DISK_START_OFS = 34, MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36, MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38, MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42, + // Local directory header offsets + MZ_ZIP_LDH_SIG_OFS = 0, MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4, MZ_ZIP_LDH_BIT_FLAG_OFS = 6, MZ_ZIP_LDH_METHOD_OFS = 8, MZ_ZIP_LDH_FILE_TIME_OFS = 10, + MZ_ZIP_LDH_FILE_DATE_OFS = 12, MZ_ZIP_LDH_CRC32_OFS = 14, MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18, MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22, + MZ_ZIP_LDH_FILENAME_LEN_OFS = 26, MZ_ZIP_LDH_EXTRA_LEN_OFS = 28, + // End of central directory offsets + MZ_ZIP_ECDH_SIG_OFS = 0, MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4, MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6, MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8, + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10, MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20, +}; + +typedef struct +{ + void *m_p; + size_t m_size, m_capacity; + mz_uint m_element_size; +} mz_zip_array; + +struct mz_zip_internal_state_tag +{ + mz_zip_array m_central_dir; + mz_zip_array m_central_dir_offsets; + mz_zip_array m_sorted_central_dir_offsets; + MZ_FILE *m_pFile; + void *m_pMem; + size_t m_mem_size; + size_t m_mem_capacity; +}; + +#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size +#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index] + +static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray) +{ + pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p); + memset(pArray, 0, sizeof(mz_zip_array)); +} + +static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing) +{ + void *pNew_p; size_t new_capacity = min_new_capacity; MZ_ASSERT(pArray->m_element_size); if (pArray->m_capacity >= min_new_capacity) return MZ_TRUE; + if (growing) { new_capacity = MZ_MAX(1, pArray->m_capacity); while (new_capacity < min_new_capacity) new_capacity *= 2; } + if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) return MZ_FALSE; + pArray->m_p = pNew_p; pArray->m_capacity = new_capacity; + return MZ_TRUE; +} + +static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing) +{ + if (new_capacity > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) return MZ_FALSE; } + return MZ_TRUE; +} + +static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing) +{ + if (new_size > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) return MZ_FALSE; } + pArray->m_size = new_size; + return MZ_TRUE; +} + +static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n) +{ + return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE); +} + +static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n) +{ + if (n==0) return MZ_TRUE; + assert(NULL!=pElements); + size_t orig_size = pArray->m_size; if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) return MZ_FALSE; + memcpy((mz_uint8*)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size); + return MZ_TRUE; +} + +#ifndef MINIZ_NO_TIME +static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date) +{ + struct tm tm; + memset(&tm, 0, sizeof(tm)); tm.tm_isdst = -1; + tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900; tm.tm_mon = ((dos_date >> 5) & 15) - 1; tm.tm_mday = dos_date & 31; + tm.tm_hour = (dos_time >> 11) & 31; tm.tm_min = (dos_time >> 5) & 63; tm.tm_sec = (dos_time << 1) & 62; + return mktime(&tm); +} + +static void mz_zip_time_to_dos_time(time_t time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date) +{ +#ifdef _MSC_VER + struct tm tm_struct; + struct tm *tm = &tm_struct; + errno_t err = localtime_s(tm, &time); + if (err) + { + *pDOS_date = 0; *pDOS_time = 0; + return; + } +#else + struct tm *tm = localtime(&time); +#endif + *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1)); + *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday); +} +#endif + +#ifndef MINIZ_NO_STDIO +static mz_bool mz_zip_get_file_modified_time(const char *pFilename, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date) +{ +#ifdef MINIZ_NO_TIME + (void)pFilename; *pDOS_date = *pDOS_time = 0; +#else + struct MZ_FILE_STAT_STRUCT file_stat; + // On Linux with x86 glibc, this call will fail on large files (>= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. + if (MZ_FILE_STAT(pFilename, &file_stat) != 0) + return MZ_FALSE; + mz_zip_time_to_dos_time(file_stat.st_mtime, pDOS_time, pDOS_date); +#endif // #ifdef MINIZ_NO_TIME + return MZ_TRUE; +} + +#ifndef MINIZ_NO_TIME +static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time, time_t modified_time) +{ + struct utimbuf t; t.actime = access_time; t.modtime = modified_time; + return !utime(pFilename, &t); +} +#endif // #ifndef MINIZ_NO_TIME +#endif // #ifndef MINIZ_NO_STDIO + +static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint32 flags) +{ + (void)flags; + if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) + return MZ_FALSE; + + if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func; + if (!pZip->m_pFree) pZip->m_pFree = def_free_func; + if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func; + + pZip->m_zip_mode = MZ_ZIP_MODE_READING; + pZip->m_archive_size = 0; + pZip->m_central_directory_file_ofs = 0; + pZip->m_total_files = 0; + + if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) + return MZ_FALSE; + memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); + return MZ_TRUE; +} + +static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index) +{ + const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; + const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index)); + mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS); + mz_uint8 l = 0, r = 0; + pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + pE = pL + MZ_MIN(l_len, r_len); + while (pL < pE) + { + if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) + break; + pL++; pR++; + } + return (pL == pE) ? (l_len < r_len) : (l < r); +} + +#define MZ_SWAP_UINT32(a, b) do { mz_uint32 t = a; a = b; b = t; } MZ_MACRO_END + +// Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.) +static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip) +{ + mz_zip_internal_state *pState = pZip->m_pState; + const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets; + const mz_zip_array *pCentral_dir = &pState->m_central_dir; + mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); + const int size = pZip->m_total_files; + int start = (size - 2) >> 1, end; + while (start >= 0) + { + int child, root = start; + for ( ; ; ) + { + if ((child = (root << 1) + 1) >= size) + break; + child += (((child + 1) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1]))); + if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) + break; + MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child; + } + start--; + } + + end = size - 1; + while (end > 0) + { + int child, root = 0; + MZ_SWAP_UINT32(pIndices[end], pIndices[0]); + for ( ; ; ) + { + if ((child = (root << 1) + 1) >= end) + break; + child += (((child + 1) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1])); + if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) + break; + MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child; + } + end--; + } +} + +static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint32 flags) +{ + mz_uint cdir_size, num_this_disk, cdir_disk_index; + mz_uint64 cdir_ofs; + mz_int64 cur_file_ofs; + const mz_uint8 *p; + mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; mz_uint8 *pBuf = (mz_uint8 *)buf_u32; + mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0); + // Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there. + if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + return MZ_FALSE; + // Find the end of central directory record by scanning the file from the end towards the beginning. + cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0); + for ( ; ; ) + { + int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n) + return MZ_FALSE; + for (i = n - 4; i >= 0; --i) + if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) + break; + if (i >= 0) + { + cur_file_ofs += i; + break; + } + if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE))) + return MZ_FALSE; + cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0); + } + // Read and verify the end of central directory record. + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) + return MZ_FALSE; + if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) || + ((pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) != MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS))) + return MZ_FALSE; + + num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS); + cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS); + if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1))) + return MZ_FALSE; + + if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) + return MZ_FALSE; + + cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS); + if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size) + return MZ_FALSE; + + pZip->m_central_directory_file_ofs = cdir_ofs; + + if (pZip->m_total_files) + { + mz_uint i, n; + + // Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and another to hold the sorted indices. + if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) || + (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE))) + return MZ_FALSE; + + if (sort_central_dir) + { + if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE)) + return MZ_FALSE; + } + + if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size) + return MZ_FALSE; + + // Now create an index into the central directory file records, do some basic sanity checking on each record, and check for zip64 entries (which are not yet supported). + p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p; + for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) + { + mz_uint total_header_size, comp_size, decomp_size, disk_index; + if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)) + return MZ_FALSE; + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p); + if (sort_central_dir) + MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i; + comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); + if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) || (comp_size == 0xFFFFFFFF)) + return MZ_FALSE; + disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS); + if ((disk_index != num_this_disk) && (disk_index != 1)) + return MZ_FALSE; + if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size) + return MZ_FALSE; + if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n) + return MZ_FALSE; + n -= total_header_size; p += total_header_size; + } + } + + if (sort_central_dir) + mz_zip_reader_sort_central_dir_offsets_by_filename(pZip); + + return MZ_TRUE; +} + +mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags) +{ + if ((!pZip) || (!pZip->m_pRead)) + return MZ_FALSE; + if (!mz_zip_reader_init_internal(pZip, flags)) + return MZ_FALSE; + pZip->m_archive_size = size; + if (!mz_zip_reader_read_central_dir(pZip, flags)) + { + mz_zip_reader_end(pZip); + return MZ_FALSE; + } + return MZ_TRUE; +} + +static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) +{ + mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; + size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n); + memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s); + return s; +} + +mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags) +{ + if (!mz_zip_reader_init_internal(pZip, flags)) + return MZ_FALSE; + pZip->m_archive_size = size; + pZip->m_pRead = mz_zip_mem_read_func; + pZip->m_pIO_opaque = pZip; +#ifdef __cplusplus + pZip->m_pState->m_pMem = const_cast(pMem); +#else + pZip->m_pState->m_pMem = (void *)pMem; +#endif + pZip->m_pState->m_mem_size = size; + if (!mz_zip_reader_read_central_dir(pZip, flags)) + { + mz_zip_reader_end(pZip); + return MZ_FALSE; + } + return MZ_TRUE; +} + +#ifndef MINIZ_NO_STDIO +static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) +{ + mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; + mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); + if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) + return 0; + return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile); +} + +mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags) +{ + mz_uint64 file_size; + MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb"); + if (!pFile) + return MZ_FALSE; + if (MZ_FSEEK64(pFile, 0, SEEK_END)) + { + MZ_FCLOSE(pFile); + return MZ_FALSE; + } + file_size = MZ_FTELL64(pFile); + if (!mz_zip_reader_init_internal(pZip, flags)) + { + MZ_FCLOSE(pFile); + return MZ_FALSE; + } + pZip->m_pRead = mz_zip_file_read_func; + pZip->m_pIO_opaque = pZip; + pZip->m_pState->m_pFile = pFile; + pZip->m_archive_size = file_size; + if (!mz_zip_reader_read_central_dir(pZip, flags)) + { + mz_zip_reader_end(pZip); + return MZ_FALSE; + } + return MZ_TRUE; +} +#endif // #ifndef MINIZ_NO_STDIO + +mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip) +{ + return pZip ? pZip->m_total_files : 0; +} + +static MZ_FORCEINLINE const mz_uint8 *mz_zip_reader_get_cdh(mz_zip_archive *pZip, mz_uint file_index) +{ + if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) + return NULL; + return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); +} + +mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index) +{ + mz_uint m_bit_flag; + const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); + if (!p) + return MZ_FALSE; + m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); + return (m_bit_flag & 1); +} + +mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index) +{ + mz_uint filename_len, external_attr; + const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); + if (!p) + return MZ_FALSE; + + // First see if the filename ends with a '/' character. + filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + if (filename_len) + { + if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/') + return MZ_TRUE; + } + + // Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. + // Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field. + // FIXME: Remove this check? Is it necessary - we already check the filename. + external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); + if ((external_attr & 0x10) != 0) + return MZ_TRUE; + + return MZ_FALSE; +} + +mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat) +{ + mz_uint n; + const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); + if ((!p) || (!pStat)) + return MZ_FALSE; + + // Unpack the central directory record. + pStat->m_file_index = file_index; + pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index); + pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS); + pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS); + pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); + pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS); +#ifndef MINIZ_NO_TIME + pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS)); +#endif + pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS); + pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); + pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS); + pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); + pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS); + + // Copy as much of the filename and comment as possible. + n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1); + memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); pStat->m_filename[n] = '\0'; + + n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1); + pStat->m_comment_size = n; + memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n); pStat->m_comment[n] = '\0'; + + return MZ_TRUE; +} + +mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size) +{ + mz_uint n; + const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); + if (!p) { if (filename_buf_size) pFilename[0] = '\0'; return 0; } + n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); + if (filename_buf_size) + { + n = MZ_MIN(n, filename_buf_size - 1); + memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); + pFilename[n] = '\0'; + } + return n + 1; +} + +static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags) +{ + mz_uint i; + if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE) + return 0 == memcmp(pA, pB, len); + for (i = 0; i < len; ++i) + if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i])) + return MZ_FALSE; + return MZ_TRUE; +} + +static MZ_FORCEINLINE int mz_zip_reader_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len) +{ + const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; + mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS); + mz_uint8 l = 0, r = 0; + pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + pE = pL + MZ_MIN(l_len, r_len); + while (pL < pE) + { + if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) + break; + pL++; pR++; + } + return (pL == pE) ? (int)(l_len - r_len) : (l - r); +} + +static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename) +{ + mz_zip_internal_state *pState = pZip->m_pState; + const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets; + const mz_zip_array *pCentral_dir = &pState->m_central_dir; + mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); + const int size = pZip->m_total_files; + const mz_uint filename_len = (mz_uint)strlen(pFilename); + int l = 0, h = size - 1; + while (l <= h) + { + int m = (l + h) >> 1, file_index = pIndices[m], comp = mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len); + if (!comp) + return file_index; + else if (comp < 0) + l = m + 1; + else + h = m - 1; + } + return -1; +} + +int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags) +{ + mz_uint file_index; size_t name_len, comment_len; + if ((!pZip) || (!pZip->m_pState) || (!pName) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) + return -1; + if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size)) + return mz_zip_reader_locate_file_binary_search(pZip, pName); + name_len = strlen(pName); if (name_len > 0xFFFF) return -1; + comment_len = pComment ? strlen(pComment) : 0; if (comment_len > 0xFFFF) return -1; + for (file_index = 0; file_index < pZip->m_total_files; file_index++) + { + const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); + mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS); + const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; + if (filename_len < name_len) + continue; + if (comment_len) + { + mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS); + const char *pFile_comment = pFilename + filename_len + file_extra_len; + if ((file_comment_len != comment_len) || (!mz_zip_reader_string_equal(pComment, pFile_comment, file_comment_len, flags))) + continue; + } + if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) + { + int ofs = filename_len - 1; + do + { + if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':')) + break; + } while (--ofs >= 0); + ofs++; + pFilename += ofs; filename_len -= ofs; + } + if ((filename_len == name_len) && (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags))) + return file_index; + } + return -1; +} + +mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) +{ + int status = TINFL_STATUS_DONE; + mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail; + mz_zip_archive_file_stat file_stat; + void *pRead_buf; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; + tinfl_decompressor inflator; + + if ((buf_size) && (!pBuf)) + return MZ_FALSE; + + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + return MZ_FALSE; + + // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes) + if (!file_stat.m_comp_size) + return MZ_TRUE; + + // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers). + // I'm torn how to handle this case - should it fail instead? + if (mz_zip_reader_is_file_a_directory(pZip, file_index)) + return MZ_TRUE; + + // Encryption and patch files are not supported. + if (file_stat.m_bit_flag & (1 | 32)) + return MZ_FALSE; + + // This function only supports stored and deflate. + if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) + return MZ_FALSE; + + // Ensure supplied output buffer is large enough. + needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size; + if (buf_size < needed_size) + return MZ_FALSE; + + // Read and parse the local directory entry. + cur_file_ofs = file_stat.m_local_header_ofs; + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return MZ_FALSE; + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + return MZ_FALSE; + + cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) + return MZ_FALSE; + + if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) + { + // The file is stored or the caller has requested the compressed data. + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size) + return MZ_FALSE; + return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32); + } + + // Decompress the file either directly from memory or from a file input buffer. + tinfl_init(&inflator); + + if (pZip->m_pState->m_pMem) + { + // Read directly from the archive in memory. + pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; + read_buf_size = read_buf_avail = file_stat.m_comp_size; + comp_remaining = 0; + } + else if (pUser_read_buf) + { + // Use a user provided read buffer. + if (!user_read_buf_size) + return MZ_FALSE; + pRead_buf = (mz_uint8 *)pUser_read_buf; + read_buf_size = user_read_buf_size; + read_buf_avail = 0; + comp_remaining = file_stat.m_comp_size; + } + else + { + // Temporarily allocate a read buffer. + read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE); +#ifdef _MSC_VER + if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) +#else + if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) +#endif + return MZ_FALSE; + if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) + return MZ_FALSE; + read_buf_avail = 0; + comp_remaining = file_stat.m_comp_size; + } + + do + { + size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs); + if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) + { + read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + status = TINFL_STATUS_FAILED; + break; + } + cur_file_ofs += read_buf_avail; + comp_remaining -= read_buf_avail; + read_buf_ofs = 0; + } + in_buf_size = (size_t)read_buf_avail; + status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0)); + read_buf_avail -= in_buf_size; + read_buf_ofs += in_buf_size; + out_buf_ofs += out_buf_size; + } while (status == TINFL_STATUS_NEEDS_MORE_INPUT); + + if (status == TINFL_STATUS_DONE) + { + // Make sure the entire file was decompressed, and check its CRC. + if ((out_buf_ofs != file_stat.m_uncomp_size) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)) + status = TINFL_STATUS_FAILED; + } + + if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf)) + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + + return status == TINFL_STATUS_DONE; +} + +mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) +{ + int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); + if (file_index < 0) + return MZ_FALSE; + return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size); +} + +mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags) +{ + return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0); +} + +mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags) +{ + return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0); +} + +void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags) +{ + mz_uint64 comp_size, uncomp_size, alloc_size; + const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); + void *pBuf; + + if (pSize) + *pSize = 0; + if (!p) + return NULL; + + comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); + + alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size; +#ifdef _MSC_VER + if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) +#else + if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) +#endif + return NULL; + if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size))) + return NULL; + + if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return NULL; + } + + if (pSize) *pSize = (size_t)alloc_size; + return pBuf; +} + +void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags) +{ + int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); + if (file_index < 0) + { + if (pSize) *pSize = 0; + return MZ_FALSE; + } + return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags); +} + +mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) +{ + int status = TINFL_STATUS_DONE; mz_uint file_crc32 = MZ_CRC32_INIT; + mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs; + mz_zip_archive_file_stat file_stat; + void *pRead_buf = NULL; void *pWrite_buf = NULL; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; + + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + return MZ_FALSE; + + // Empty file, or a directory (but not always a directory - I've seen odd zips with directories that have compressed data which inflates to 0 bytes) + if (!file_stat.m_comp_size) + return MZ_TRUE; + + // Entry is a subdirectory (I've seen old zips with dir entries which have compressed deflate data which inflates to 0 bytes, but these entries claim to uncompress to 512 bytes in the headers). + // I'm torn how to handle this case - should it fail instead? + if (mz_zip_reader_is_file_a_directory(pZip, file_index)) + return MZ_TRUE; + + // Encryption and patch files are not supported. + if (file_stat.m_bit_flag & (1 | 32)) + return MZ_FALSE; + + // This function only supports stored and deflate. + if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) + return MZ_FALSE; + + // Read and parse the local directory entry. + cur_file_ofs = file_stat.m_local_header_ofs; + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return MZ_FALSE; + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + return MZ_FALSE; + + cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) + return MZ_FALSE; + + // Decompress the file either directly from memory or from a file input buffer. + if (pZip->m_pState->m_pMem) + { + pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; + read_buf_size = read_buf_avail = file_stat.m_comp_size; + comp_remaining = 0; + } + else + { + read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE); + if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) + return MZ_FALSE; + read_buf_avail = 0; + comp_remaining = file_stat.m_comp_size; + } + + if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) + { + // The file is stored or the caller has requested the compressed data. + if (pZip->m_pState->m_pMem) + { +#ifdef _MSC_VER + if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF)) +#else + if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF)) +#endif + return MZ_FALSE; + if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size) + status = TINFL_STATUS_FAILED; + else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size); + out_buf_ofs += file_stat.m_comp_size; + } + else + { + while (comp_remaining) + { + read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + status = TINFL_STATUS_FAILED; + break; + } + + if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail); + + if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + status = TINFL_STATUS_FAILED; + break; + } + cur_file_ofs += read_buf_avail; + out_buf_ofs += read_buf_avail; + comp_remaining -= read_buf_avail; + } + } + } + else + { + tinfl_decompressor inflator; + tinfl_init(&inflator); + + if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE))) + status = TINFL_STATUS_FAILED; + else + { + do + { + mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); + size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); + if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) + { + read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); + if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) + { + status = TINFL_STATUS_FAILED; + break; + } + cur_file_ofs += read_buf_avail; + comp_remaining -= read_buf_avail; + read_buf_ofs = 0; + } + + in_buf_size = (size_t)read_buf_avail; + status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0); + read_buf_avail -= in_buf_size; + read_buf_ofs += in_buf_size; + + if (out_buf_size) + { + if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size) + { + status = TINFL_STATUS_FAILED; + break; + } + file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size); + if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) + { + status = TINFL_STATUS_FAILED; + break; + } + } + } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT)); + } + } + + if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) + { + // Make sure the entire file was decompressed, and check its CRC. + if ((out_buf_ofs != file_stat.m_uncomp_size) || (file_crc32 != file_stat.m_crc32)) + status = TINFL_STATUS_FAILED; + } + + if (!pZip->m_pState->m_pMem) + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + if (pWrite_buf) + pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf); + + return status == TINFL_STATUS_DONE; +} + +mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) +{ + int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); + if (file_index < 0) + return MZ_FALSE; + return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags); +} + +#ifndef MINIZ_NO_STDIO +static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n) +{ + (void)ofs; return MZ_FWRITE(pBuf, 1, n, (MZ_FILE*)pOpaque); +} + +mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags) +{ + mz_bool status; + mz_zip_archive_file_stat file_stat; + MZ_FILE *pFile; + if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) + return MZ_FALSE; + pFile = MZ_FOPEN(pDst_filename, "wb"); + if (!pFile) + return MZ_FALSE; + status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags); + if (MZ_FCLOSE(pFile) == EOF) + return MZ_FALSE; +#ifndef MINIZ_NO_TIME + if (status) + mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time); +#endif + return status; +} +#endif // #ifndef MINIZ_NO_STDIO + +mz_bool mz_zip_reader_end(mz_zip_archive *pZip) +{ + if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) + return MZ_FALSE; + + if (pZip->m_pState) + { + mz_zip_internal_state *pState = pZip->m_pState; pZip->m_pState = NULL; + mz_zip_array_clear(pZip, &pState->m_central_dir); + mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); + mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); + +#ifndef MINIZ_NO_STDIO + if (pState->m_pFile) + { + MZ_FCLOSE(pState->m_pFile); + pState->m_pFile = NULL; + } +#endif // #ifndef MINIZ_NO_STDIO + + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + } + pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; + + return MZ_TRUE; +} + +#ifndef MINIZ_NO_STDIO +mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags) +{ + int file_index = mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags); + if (file_index < 0) + return MZ_FALSE; + return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags); +} +#endif + +// ------------------- .ZIP archive writing + +#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS + +static void mz_write_le16(mz_uint8 *p, mz_uint16 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); } +static void mz_write_le32(mz_uint8 *p, mz_uint32 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); p[2] = (mz_uint8)(v >> 16); p[3] = (mz_uint8)(v >> 24); } +#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v)) +#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v)) + +mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size) +{ + if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) + return MZ_FALSE; + + if (pZip->m_file_offset_alignment) + { + // Ensure user specified file offset alignment is a power of 2. + if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1)) + return MZ_FALSE; + } + + if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func; + if (!pZip->m_pFree) pZip->m_pFree = def_free_func; + if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func; + + pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; + pZip->m_archive_size = existing_size; + pZip->m_central_directory_file_ofs = 0; + pZip->m_total_files = 0; + + if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) + return MZ_FALSE; + memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); + MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); + return MZ_TRUE; +} + +static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) +{ + mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; + mz_zip_internal_state *pState = pZip->m_pState; + mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size); +#ifdef _MSC_VER + if ((!n) || ((0, sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))) +#else + if ((!n) || ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))) +#endif + return 0; + if (new_size > pState->m_mem_capacity) + { + void *pNew_block; + size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); while (new_capacity < new_size) new_capacity *= 2; + if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity))) + return 0; + pState->m_pMem = pNew_block; pState->m_mem_capacity = new_capacity; + } + memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n); + pState->m_mem_size = (size_t)new_size; + return n; +} + +mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size) +{ + pZip->m_pWrite = mz_zip_heap_write_func; + pZip->m_pIO_opaque = pZip; + if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) + return MZ_FALSE; + if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning))) + { + if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size))) + { + mz_zip_writer_end(pZip); + return MZ_FALSE; + } + pZip->m_pState->m_mem_capacity = initial_allocation_size; + } + return MZ_TRUE; +} + +#ifndef MINIZ_NO_STDIO +static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) +{ + mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; + mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); + if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) + return 0; + return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile); +} + +mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning) +{ + MZ_FILE *pFile; + pZip->m_pWrite = mz_zip_file_write_func; + pZip->m_pIO_opaque = pZip; + if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) + return MZ_FALSE; + if (NULL == (pFile = MZ_FOPEN(pFilename, "wb"))) + { + mz_zip_writer_end(pZip); + return MZ_FALSE; + } + pZip->m_pState->m_pFile = pFile; + if (size_to_reserve_at_beginning) + { + mz_uint64 cur_ofs = 0; char buf[4096]; MZ_CLEAR_OBJ(buf); + do + { + size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) + { + mz_zip_writer_end(pZip); + return MZ_FALSE; + } + cur_ofs += n; size_to_reserve_at_beginning -= n; + } while (size_to_reserve_at_beginning); + } + return MZ_TRUE; +} +#endif // #ifndef MINIZ_NO_STDIO + +mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename) +{ + mz_zip_internal_state *pState; + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) + return MZ_FALSE; + // No sense in trying to write to an archive that's already at the support max size + if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) + return MZ_FALSE; + + pState = pZip->m_pState; + + if (pState->m_pFile) + { +#ifdef MINIZ_NO_STDIO + pFilename; return MZ_FALSE; +#else + // Archive is being read from stdio - try to reopen as writable. + if (pZip->m_pIO_opaque != pZip) + return MZ_FALSE; + if (!pFilename) + return MZ_FALSE; + pZip->m_pWrite = mz_zip_file_write_func; + if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) + { + // The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. + mz_zip_reader_end(pZip); + return MZ_FALSE; + } +#endif // #ifdef MINIZ_NO_STDIO + } + else if (pState->m_pMem) + { + // Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. + if (pZip->m_pIO_opaque != pZip) + return MZ_FALSE; + pState->m_mem_capacity = pState->m_mem_size; + pZip->m_pWrite = mz_zip_heap_write_func; + } + // Archive is being read via a user provided read function - make sure the user has specified a write function too. + else if (!pZip->m_pWrite) + return MZ_FALSE; + + // Start writing new files at the archive's current central directory location. + pZip->m_archive_size = pZip->m_central_directory_file_ofs; + pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; + pZip->m_central_directory_file_ofs = 0; + + return MZ_TRUE; +} + +mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags) +{ + return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0); +} + +typedef struct +{ + mz_zip_archive *m_pZip; + mz_uint64 m_cur_archive_file_ofs; + mz_uint64 m_comp_size; +} mz_zip_writer_add_state; + +static mz_bool mz_zip_writer_add_put_buf_callback(const void* pBuf, int len, void *pUser) +{ + mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser; + if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len) + return MZ_FALSE; + pState->m_cur_archive_file_ofs += len; + pState->m_comp_size += len; + return MZ_TRUE; +} + +static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date) +{ + (void)pZip; + memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size); + MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size); + return MZ_TRUE; +} + +static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes) +{ + (void)pZip; + memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size); + MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes); + MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs); + return MZ_TRUE; +} + +static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size, const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes) +{ + mz_zip_internal_state *pState = pZip->m_pState; + mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size; + size_t orig_central_dir_size = pState->m_central_dir.m_size; + mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; + + // No zip64 support yet + if ((local_header_ofs > 0xFFFFFFFF) || (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + comment_size) > 0xFFFFFFFF)) + return MZ_FALSE; + + if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes)) + return MZ_FALSE; + + if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) || + (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, ¢ral_dir_ofs, 1))) + { + // Try to push the central directory array back into its original state. + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return MZ_FALSE; + } + + return MZ_TRUE; +} + +static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name) +{ + // Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes. + if (*pArchive_name == '/') + return MZ_FALSE; + while (*pArchive_name) + { + if ((*pArchive_name == '\\') || (*pArchive_name == ':')) + return MZ_FALSE; + pArchive_name++; + } + return MZ_TRUE; +} + +static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) +{ + mz_uint32 n; + if (!pZip->m_file_offset_alignment) + return 0; + n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1)); + return (pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1); +} + +static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n) +{ + char buf[4096]; + memset(buf, 0, MZ_MIN(sizeof(buf), n)); + while (n) + { + mz_uint32 s = MZ_MIN(sizeof(buf), n); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s) + return MZ_FALSE; + cur_file_ofs += s; n -= s; + } + return MZ_TRUE; +} + +mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32) +{ + mz_uint16 method = 0, dos_time = 0, dos_date = 0; + mz_uint level, ext_attributes = 0, num_alignment_padding_bytes; + mz_uint64 local_dir_header_ofs, cur_archive_file_ofs, comp_size = 0; + size_t archive_name_size; + mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; + tdefl_compressor *pComp = NULL; + mz_bool store_data_uncompressed; + mz_zip_internal_state *pState; + + if ((int)level_and_flags < 0) + level_and_flags = MZ_DEFAULT_LEVEL; + level = level_and_flags & 0xF; + store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)); + + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION)) + return MZ_FALSE; + + local_dir_header_ofs = cur_archive_file_ofs = pZip->m_archive_size; + pState = pZip->m_pState; + + if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size)) + return MZ_FALSE; + // No zip64 support yet + if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF)) + return MZ_FALSE; + if (!mz_zip_writer_validate_archive_name(pArchive_name)) + return MZ_FALSE; + +#ifndef MINIZ_NO_TIME + { + time_t cur_time; time(&cur_time); + mz_zip_time_to_dos_time(cur_time, &dos_time, &dos_date); + } +#endif // #ifndef MINIZ_NO_TIME + + archive_name_size = strlen(pArchive_name); + if (archive_name_size > 0xFFFF) + return MZ_FALSE; + + num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); + + // no zip64 support yet + if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF)) + return MZ_FALSE; + + if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) + { + // Set DOS Subdirectory attribute bit. + ext_attributes |= 0x10; + // Subdirectories cannot contain data. + if ((buf_size) || (uncomp_size)) + return MZ_FALSE; + } + + // Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.) + if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size)) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1))) + return MZ_FALSE; + + if ((!store_data_uncompressed) && (buf_size)) + { + if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)))) + return MZ_FALSE; + } + + if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header))) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return MZ_FALSE; + } + local_dir_header_ofs += num_alignment_padding_bytes; + if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } + cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header); + + MZ_CLEAR_OBJ(local_dir_header); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return MZ_FALSE; + } + cur_archive_file_ofs += archive_name_size; + + if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) + { + uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8*)pBuf, buf_size); + uncomp_size = buf_size; + if (uncomp_size <= 3) + { + level = 0; + store_data_uncompressed = MZ_TRUE; + } + } + + if (store_data_uncompressed) + { + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return MZ_FALSE; + } + + cur_archive_file_ofs += buf_size; + comp_size = buf_size; + + if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) + method = MZ_DEFLATED; + } + else if (buf_size) + { + mz_zip_writer_add_state state; + + state.m_pZip = pZip; + state.m_cur_archive_file_ofs = cur_archive_file_ofs; + state.m_comp_size = 0; + + if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) || + (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + return MZ_FALSE; + } + + comp_size = state.m_comp_size; + cur_archive_file_ofs = state.m_cur_archive_file_ofs; + + method = MZ_DEFLATED; + } + + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + pComp = NULL; + + // no zip64 support yet + if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF)) + return MZ_FALSE; + + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date)) + return MZ_FALSE; + + if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + return MZ_FALSE; + + if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes)) + return MZ_FALSE; + + pZip->m_total_files++; + pZip->m_archive_size = cur_archive_file_ofs; + + return MZ_TRUE; +} + +#ifndef MINIZ_NO_STDIO +mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) +{ + mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes; + mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0; + mz_uint64 local_dir_header_ofs, cur_archive_file_ofs, uncomp_size = 0, comp_size = 0; + size_t archive_name_size; + mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; + MZ_FILE *pSrc_file = NULL; + + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION)) + return MZ_FALSE; + + local_dir_header_ofs = cur_archive_file_ofs = pZip->m_archive_size; + + if ((int)level_and_flags < 0) + level_and_flags = MZ_DEFAULT_LEVEL; + level = level_and_flags & 0xF; + + if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) + return MZ_FALSE; + if (!mz_zip_writer_validate_archive_name(pArchive_name)) + return MZ_FALSE; + + archive_name_size = strlen(pArchive_name); + if (archive_name_size > 0xFFFF) + return MZ_FALSE; + + num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); + + // no zip64 support yet + if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF)) + return MZ_FALSE; + + if (!mz_zip_get_file_modified_time(pSrc_filename, &dos_time, &dos_date)) + return MZ_FALSE; + + pSrc_file = MZ_FOPEN(pSrc_filename, "rb"); + if (!pSrc_file) + return MZ_FALSE; + MZ_FSEEK64(pSrc_file, 0, SEEK_END); + uncomp_size = MZ_FTELL64(pSrc_file); + MZ_FSEEK64(pSrc_file, 0, SEEK_SET); + + if (uncomp_size > 0xFFFFFFFF) + { + // No zip64 support yet + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + if (uncomp_size <= 3) + level = 0; + + if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header))) + { + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + local_dir_header_ofs += num_alignment_padding_bytes; + if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } + cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header); + + MZ_CLEAR_OBJ(local_dir_header); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) + { + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + cur_archive_file_ofs += archive_name_size; + + if (uncomp_size) + { + mz_uint64 uncomp_remaining = uncomp_size; + void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE); + if (!pRead_buf) + { + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + + if (!level) + { + while (uncomp_remaining) + { + mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining); + if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n); + uncomp_remaining -= n; + cur_archive_file_ofs += n; + } + comp_size = uncomp_size; + } + else + { + mz_bool result = MZ_FALSE; + mz_zip_writer_add_state state; + tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)); + if (!pComp) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + + state.m_pZip = pZip; + state.m_cur_archive_file_ofs = cur_archive_file_ofs; + state.m_comp_size = 0; + + if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + + for ( ; ; ) + { + size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE); + tdefl_status status; + + if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size) + break; + + uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size); + uncomp_remaining -= in_buf_size; + + status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH); + if (status == TDEFL_STATUS_DONE) + { + result = MZ_TRUE; + break; + } + else if (status != TDEFL_STATUS_OKAY) + break; + } + + pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); + + if (!result) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + MZ_FCLOSE(pSrc_file); + return MZ_FALSE; + } + + comp_size = state.m_comp_size; + cur_archive_file_ofs = state.m_cur_archive_file_ofs; + + method = MZ_DEFLATED; + } + + pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); + } + + MZ_FCLOSE(pSrc_file); pSrc_file = NULL; + + // no zip64 support yet + if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF)) + return MZ_FALSE; + + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date)) + return MZ_FALSE; + + if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) + return MZ_FALSE; + + if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes)) + return MZ_FALSE; + + pZip->m_total_files++; + pZip->m_archive_size = cur_archive_file_ofs; + + return MZ_TRUE; +} +#endif // #ifndef MINIZ_NO_STDIO + +mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index) +{ + mz_uint n, bit_flags, num_alignment_padding_bytes; + mz_uint64 comp_bytes_remaining, local_dir_header_ofs; + mz_uint64 cur_src_file_ofs, cur_dst_file_ofs; + mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; + mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; + size_t orig_central_dir_size; + mz_zip_internal_state *pState; + void *pBuf; const mz_uint8 *pSrc_central_header; + + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) + return MZ_FALSE; + if (NULL == (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index))) + return MZ_FALSE; + pState = pZip->m_pState; + + num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); + + // no zip64 support yet + if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) + return MZ_FALSE; + + cur_src_file_ofs = MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS); + cur_dst_file_ofs = pZip->m_archive_size; + + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return MZ_FALSE; + if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) + return MZ_FALSE; + cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; + + if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes)) + return MZ_FALSE; + cur_dst_file_ofs += num_alignment_padding_bytes; + local_dir_header_ofs = cur_dst_file_ofs; + if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) + return MZ_FALSE; + cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; + + n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); + comp_bytes_remaining = n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); + + if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(sizeof(mz_uint32) * 4, MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining))))) + return MZ_FALSE; + + while (comp_bytes_remaining) + { + n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining); + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return MZ_FALSE; + } + cur_src_file_ofs += n; + + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return MZ_FALSE; + } + cur_dst_file_ofs += n; + + comp_bytes_remaining -= n; + } + + bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS); + if (bit_flags & 8) + { + // Copy data descriptor + if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return MZ_FALSE; + } + + n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3); + if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + return MZ_FALSE; + } + + cur_dst_file_ofs += n; + } + pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); + + // no zip64 support yet + if (cur_dst_file_ofs > 0xFFFFFFFF) + return MZ_FALSE; + + orig_central_dir_size = pState->m_central_dir.m_size; + + memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); + MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs); + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) + return MZ_FALSE; + + n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS); + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n)) + { + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return MZ_FALSE; + } + + if (pState->m_central_dir.m_size > 0xFFFFFFFF) + return MZ_FALSE; + n = (mz_uint32)orig_central_dir_size; + if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) + { + mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); + return MZ_FALSE; + } + + pZip->m_total_files++; + pZip->m_archive_size = cur_dst_file_ofs; + + return MZ_TRUE; +} + +mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) +{ + mz_zip_internal_state *pState; + mz_uint64 central_dir_ofs, central_dir_size; + mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE]; + + if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) + return MZ_FALSE; + + pState = pZip->m_pState; + + // no zip64 support yet + if ((pZip->m_total_files > 0xFFFF) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) + return MZ_FALSE; + + central_dir_ofs = 0; + central_dir_size = 0; + if (pZip->m_total_files) + { + // Write central directory + central_dir_ofs = pZip->m_archive_size; + central_dir_size = pState->m_central_dir.m_size; + pZip->m_central_directory_file_ofs = central_dir_ofs; + if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size) + return MZ_FALSE; + pZip->m_archive_size += central_dir_size; + } + + // Write end of central directory record + MZ_CLEAR_OBJ(hdr); + MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG); + MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files); + MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files); + MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size); + MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs); + + if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, sizeof(hdr)) != sizeof(hdr)) + return MZ_FALSE; +#ifndef MINIZ_NO_STDIO + if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF)) + return MZ_FALSE; +#endif // #ifndef MINIZ_NO_STDIO + + pZip->m_archive_size += sizeof(hdr); + + pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED; + return MZ_TRUE; +} + +mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize) +{ + if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize)) + return MZ_FALSE; + if (pZip->m_pWrite != mz_zip_heap_write_func) + return MZ_FALSE; + if (!mz_zip_writer_finalize_archive(pZip)) + return MZ_FALSE; + + *pBuf = pZip->m_pState->m_pMem; + *pSize = pZip->m_pState->m_mem_size; + pZip->m_pState->m_pMem = NULL; + pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0; + return MZ_TRUE; +} + +mz_bool mz_zip_writer_end(mz_zip_archive *pZip) +{ + mz_zip_internal_state *pState; + mz_bool status = MZ_TRUE; + if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))) + return MZ_FALSE; + + pState = pZip->m_pState; + pZip->m_pState = NULL; + mz_zip_array_clear(pZip, &pState->m_central_dir); + mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); + mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); + +#ifndef MINIZ_NO_STDIO + if (pState->m_pFile) + { + MZ_FCLOSE(pState->m_pFile); + pState->m_pFile = NULL; + } +#endif // #ifndef MINIZ_NO_STDIO + + if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) + { + pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem); + pState->m_pMem = NULL; + } + + pZip->m_pFree(pZip->m_pAlloc_opaque, pState); + pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; + return status; +} + +#ifndef MINIZ_NO_STDIO +mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) +{ + mz_bool status, created_new_archive = MZ_FALSE; + mz_zip_archive zip_archive; + struct MZ_FILE_STAT_STRUCT file_stat; + MZ_CLEAR_OBJ(zip_archive); + if ((int)level_and_flags < 0) + level_and_flags = MZ_DEFAULT_LEVEL; + if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION)) + return MZ_FALSE; + if (!mz_zip_writer_validate_archive_name(pArchive_name)) + return MZ_FALSE; + if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) + { + // Create a new archive. + if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0)) + return MZ_FALSE; + created_new_archive = MZ_TRUE; + } + else + { + // Append to an existing archive. + if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) + return MZ_FALSE; + if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename)) + { + mz_zip_reader_end(&zip_archive); + return MZ_FALSE; + } + } + status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0); + // Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.) + if (!mz_zip_writer_finalize_archive(&zip_archive)) + status = MZ_FALSE; + if (!mz_zip_writer_end(&zip_archive)) + status = MZ_FALSE; + if ((!status) && (created_new_archive)) + { + // It's a new archive and something went wrong, so just delete it. + int ignoredStatus = MZ_DELETE_FILE(pZip_filename); + (void)ignoredStatus; + } + return status; +} + +void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags) +{ + int file_index; + mz_zip_archive zip_archive; + void *p = NULL; + + if (pSize) + *pSize = 0; + + if ((!pZip_filename) || (!pArchive_name)) + return NULL; + + MZ_CLEAR_OBJ(zip_archive); + if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) + return NULL; + + if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL, flags)) >= 0) + p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags); + + mz_zip_reader_end(&zip_archive); + return p; +} + +#endif // #ifndef MINIZ_NO_STDIO + +#endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS + +#endif // #ifndef MINIZ_NO_ARCHIVE_APIS + +#ifdef __cplusplus +} +#endif + +#endif // MINIZ_HEADER_FILE_ONLY + +/* + This is free and unencumbered software released into the public domain. + + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this software, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. + + In jurisdictions that recognize copyright laws, the author or authors + of this software dedicate any and all copyright interest in the + software to the public domain. We make this dedication for the benefit + of the public at large and to the detriment of our heirs and + successors. We intend this dedication to be an overt act of + relinquishment in perpetuity of all present and future rights to this + software under copyright law. + + 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 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. + + For more information, please refer to +*/ diff --git a/contrib/zip/src/zip.c b/contrib/zip/src/zip.c new file mode 100644 index 000000000..80573096b --- /dev/null +++ b/contrib/zip/src/zip.c @@ -0,0 +1,640 @@ +/* + * 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 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. + */ + +#include "zip.h" +#include "miniz.h" + +#include +#include +#include + +#if defined _WIN32 || defined __WIN32__ +/* Win32, DOS */ +#include + +#define MKDIR(DIRNAME) _mkdir(DIRNAME) +#define STRCLONE(STR) ((STR) ? _strdup(STR) : NULL) +#define HAS_DEVICE(P) \ + ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) && \ + (P)[1] == ':') +#define FILESYSTEM_PREFIX_LEN(P) (HAS_DEVICE(P) ? 2 : 0) +#define ISSLASH(C) ((C) == '/' || (C) == '\\') + +#else +#define MKDIR(DIRNAME) mkdir(DIRNAME, 0755) +#define STRCLONE(STR) ((STR) ? strdup(STR) : NULL) +#endif + +#ifndef FILESYSTEM_PREFIX_LEN +#define FILESYSTEM_PREFIX_LEN(P) 0 +#endif + +#ifndef ISSLASH +#define ISSLASH(C) ((C) == '/') +#endif + +#define CLEANUP(ptr) \ + do { \ + if (ptr) { \ + free((void *)ptr); \ + ptr = NULL; \ + } \ + } while (0) + +static char *basename(const char *name) { + char const *p; + char const *base = name += FILESYSTEM_PREFIX_LEN(name); + int all_slashes = 1; + + for (p = name; *p; p++) { + if (ISSLASH(*p)) + base = p + 1; + else + all_slashes = 0; + } + + /* If NAME is all slashes, arrange to return `/'. */ + if (*base == '\0' && ISSLASH(*name) && all_slashes) --base; + + return (char *)base; +} + +static int mkpath(const char *path) { + char const *p; + char npath[MAX_PATH + 1] = {0}; + int len = 0; + + for (p = path; *p && len < MAX_PATH; p++) { + if (ISSLASH(*p) && len > 0) { + if (MKDIR(npath) == -1) + if (errno != EEXIST) return -1; + } + npath[len++] = *p; + } + + return 0; +} + +static char *strrpl(const char *str, char oldchar, char newchar) { + char *rpl = (char *)malloc(sizeof(char) * (1 + strlen(str))); + char *begin = rpl; + char c; + while((c = *str++)) { + if (c == oldchar) { + c = newchar; + } + *rpl++ = c; + } + *rpl = '\0'; + + return begin; +} + +struct zip_entry_t { + int index; + const char *name; + mz_uint64 uncomp_size; + mz_uint64 comp_size; + mz_uint32 uncomp_crc32; + mz_uint64 offset; + mz_uint8 header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; + mz_uint64 header_offset; + mz_uint16 method; + mz_zip_writer_add_state state; + tdefl_compressor comp; +}; + +struct zip_t { + mz_zip_archive archive; + mz_uint level; + struct zip_entry_t entry; + char mode; +}; + +struct zip_t *zip_open(const char *zipname, int level, char mode) { + struct zip_t *zip = NULL; + + if (!zipname || strlen(zipname) < 1) { + // zip_t archive name is empty or NULL + goto cleanup; + } + + if (level < 0) level = MZ_DEFAULT_LEVEL; + if ((level & 0xF) > MZ_UBER_COMPRESSION) { + // Wrong compression level + goto cleanup; + } + + zip = (struct zip_t *)calloc((size_t)1, sizeof(struct zip_t)); + if (!zip) goto cleanup; + + zip->level = level; + zip->mode = mode; + switch (mode) { + case 'w': + // Create a new archive. + if (!mz_zip_writer_init_file(&(zip->archive), zipname, 0)) { + // Cannot initialize zip_archive writer + goto cleanup; + } + break; + + case 'r': + case 'a': + if (!mz_zip_reader_init_file( + &(zip->archive), zipname, + level | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) { + // An archive file does not exist or cannot initialize + // zip_archive reader + goto cleanup; + } + + if (mode == 'a' && + !mz_zip_writer_init_from_reader(&(zip->archive), zipname)) { + mz_zip_reader_end(&(zip->archive)); + goto cleanup; + } + + break; + + default: + goto cleanup; + } + + return zip; + +cleanup: + CLEANUP(zip); + return NULL; +} + +void zip_close(struct zip_t *zip) { + if (zip) { + // Always finalize, even if adding failed for some reason, so we have a + // valid central directory. + mz_zip_writer_finalize_archive(&(zip->archive)); + + mz_zip_writer_end(&(zip->archive)); + mz_zip_reader_end(&(zip->archive)); + + CLEANUP(zip); + } +} + +int zip_entry_open(struct zip_t *zip, const char *entryname) { + char *locname = NULL; + size_t entrylen = 0; + mz_zip_archive *pzip = NULL; + mz_uint num_alignment_padding_bytes, level; + + if (!zip || !entryname) { + return -1; + } + + entrylen = strlen(entryname); + if (entrylen < 1) { + return -1; + } + + pzip = &(zip->archive); + /* + .ZIP File Format Specification Version: 6.3.3 + + 4.4.17.1 The name of the file, with optional relative path. + The path stored MUST not contain a drive or + device letter, or a leading slash. All slashes + MUST be forward slashes '/' as opposed to + backwards slashes '\' for compatibility with Amiga + and UNIX file systems etc. If input came from standard + input, there is no file name field. + */ + locname = strrpl(entryname, '\\', '/'); + + if (zip->mode == 'r') { + zip->entry.index = mz_zip_reader_locate_file(pzip, locname, NULL, 0); + CLEANUP(locname); + return (zip->entry.index < 0) ? -1 : 0; + } + + zip->entry.index = zip->archive.m_total_files; + zip->entry.name = locname; + if (!zip->entry.name) { + // Cannot parse zip entry name + return -1; + } + + zip->entry.comp_size = 0; + zip->entry.uncomp_size = 0; + zip->entry.uncomp_crc32 = MZ_CRC32_INIT; + zip->entry.offset = zip->archive.m_archive_size; + zip->entry.header_offset = zip->archive.m_archive_size; + memset(zip->entry.header, 0, + MZ_ZIP_LOCAL_DIR_HEADER_SIZE * sizeof(mz_uint8)); + zip->entry.method = 0; + + num_alignment_padding_bytes = + mz_zip_writer_compute_padding_needed_for_file_alignment(pzip); + + if (!pzip->m_pState || (pzip->m_zip_mode != MZ_ZIP_MODE_WRITING)) { + // Wrong zip mode + return -1; + } + if (zip->level & MZ_ZIP_FLAG_COMPRESSED_DATA) { + // Wrong zip compression level + return -1; + } + // no zip64 support yet + if ((pzip->m_total_files == 0xFFFF) || + ((pzip->m_archive_size + num_alignment_padding_bytes + + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + + entrylen) > 0xFFFFFFFF)) { + // No zip64 support yet + return -1; + } + if (!mz_zip_writer_write_zeros( + pzip, zip->entry.offset, + num_alignment_padding_bytes + sizeof(zip->entry.header))) { + // Cannot memset zip entry header + return -1; + } + + zip->entry.header_offset += num_alignment_padding_bytes; + if (pzip->m_file_offset_alignment) { + MZ_ASSERT((zip->entry.header_offset & + (pzip->m_file_offset_alignment - 1)) == 0); + } + zip->entry.offset += + num_alignment_padding_bytes + sizeof(zip->entry.header); + + if (pzip->m_pWrite(pzip->m_pIO_opaque, zip->entry.offset, zip->entry.name, + entrylen) != entrylen) { + // Cannot write data to zip entry + return -1; + } + + zip->entry.offset += entrylen; + level = zip->level & 0xF; + if (level) { + zip->entry.state.m_pZip = pzip; + zip->entry.state.m_cur_archive_file_ofs = zip->entry.offset; + zip->entry.state.m_comp_size = 0; + + if (tdefl_init(&(zip->entry.comp), mz_zip_writer_add_put_buf_callback, + &(zip->entry.state), + tdefl_create_comp_flags_from_zip_params( + level, -15, MZ_DEFAULT_STRATEGY)) != + TDEFL_STATUS_OKAY) { + // Cannot initialize the zip compressor + return -1; + } + } + + return 0; +} + +int zip_entry_close(struct zip_t *zip) { + mz_zip_archive *pzip = NULL; + mz_uint level; + tdefl_status done; + mz_uint16 entrylen; + time_t t; + struct tm *tm; + mz_uint16 dos_time, dos_date; + int status = -1; + + if (!zip) { + // zip_t handler is not initialized + return -1; + } + + if (zip->mode == 'r') { + return 0; + } + + pzip = &(zip->archive); + level = zip->level & 0xF; + if (level) { + done = tdefl_compress_buffer(&(zip->entry.comp), "", 0, TDEFL_FINISH); + if (done != TDEFL_STATUS_DONE && done != TDEFL_STATUS_OKAY) { + // Cannot flush compressed buffer + goto cleanup; + } + zip->entry.comp_size = zip->entry.state.m_comp_size; + zip->entry.offset = zip->entry.state.m_cur_archive_file_ofs; + zip->entry.method = MZ_DEFLATED; + } + + entrylen = (mz_uint16)strlen(zip->entry.name); + t = time(NULL); + tm = localtime(&t); + dos_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + + ((tm->tm_sec) >> 1)); + dos_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + + ((tm->tm_mon + 1) << 5) + tm->tm_mday); + + // no zip64 support yet + if ((zip->entry.comp_size > 0xFFFFFFFF) || + (zip->entry.offset > 0xFFFFFFFF)) { + // No zip64 support, yet + goto cleanup; + } + + if (!mz_zip_writer_create_local_dir_header( + pzip, zip->entry.header, entrylen, 0, zip->entry.uncomp_size, + zip->entry.comp_size, zip->entry.uncomp_crc32, zip->entry.method, 0, + dos_time, dos_date)) { + // Cannot create zip entry header + goto cleanup; + } + + if (pzip->m_pWrite(pzip->m_pIO_opaque, zip->entry.header_offset, + zip->entry.header, sizeof(zip->entry.header)) != + sizeof(zip->entry.header)) { + // Cannot write zip entry header + goto cleanup; + } + + if (!mz_zip_writer_add_to_central_dir( + pzip, zip->entry.name, entrylen, NULL, 0, "", 0, + zip->entry.uncomp_size, zip->entry.comp_size, + zip->entry.uncomp_crc32, zip->entry.method, 0, dos_time, dos_date, + zip->entry.header_offset, 0)) { + // Cannot write to zip central dir + goto cleanup; + } + + pzip->m_total_files++; + pzip->m_archive_size = zip->entry.offset; + status = 0; + +cleanup: + CLEANUP(zip->entry.name); + return status; +} + +int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize) { + mz_uint level; + mz_zip_archive *pzip = NULL; + tdefl_status status; + + if (!zip) { + // zip_t handler is not initialized + return -1; + } + + pzip = &(zip->archive); + if (buf && bufsize > 0) { + zip->entry.uncomp_size += bufsize; + zip->entry.uncomp_crc32 = (mz_uint32)mz_crc32( + zip->entry.uncomp_crc32, (const mz_uint8 *)buf, bufsize); + + level = zip->level & 0xF; + if (!level) { + if ((pzip->m_pWrite(pzip->m_pIO_opaque, zip->entry.offset, buf, + bufsize) != bufsize)) { + // Cannot write buffer + return -1; + } + zip->entry.offset += bufsize; + zip->entry.comp_size += bufsize; + } else { + status = tdefl_compress_buffer(&(zip->entry.comp), buf, bufsize, + TDEFL_NO_FLUSH); + if (status != TDEFL_STATUS_DONE && status != TDEFL_STATUS_OKAY) { + // Cannot compress buffer + return -1; + } + } + } + + return 0; +} + +int zip_entry_fwrite(struct zip_t *zip, const char *filename) { + int status = 0; + size_t n = 0; + FILE *stream = NULL; + mz_uint8 buf[MZ_ZIP_MAX_IO_BUF_SIZE] = {0}; + + if (!zip) { + // zip_t handler is not initialized + return -1; + } + + stream = fopen(filename, "rb"); + if (!stream) { + // Cannot open filename + return -1; + } + + while ((n = fread(buf, sizeof(mz_uint8), MZ_ZIP_MAX_IO_BUF_SIZE, stream)) > + 0) { + if (zip_entry_write(zip, buf, n) < 0) { + status = -1; + break; + } + } + fclose(stream); + + return status; +} + +int zip_entry_read(struct zip_t *zip, void **buf, size_t *bufsize) { + mz_zip_archive *pzip = NULL; + mz_uint idx; + + if (!zip) { + // zip_t handler is not initialized + return -1; + } + + if (zip->mode != 'r' || zip->entry.index < 0) { + // the entry is not found or we do not have read access + return -1; + } + + pzip = &(zip->archive); + idx = (mz_uint)zip->entry.index; + if (mz_zip_reader_is_file_a_directory(pzip, idx)) { + // the entry is a directory + return -1; + } + + *buf = mz_zip_reader_extract_to_heap(pzip, idx, bufsize, 0); + return (*buf) ? 0 : -1; +} + +int zip_entry_fread(struct zip_t *zip, const char *filename) { + mz_zip_archive *pzip = NULL; + mz_uint idx; + + if (!zip) { + // zip_t handler is not initialized + return -1; + } + + if (zip->mode != 'r' || zip->entry.index < 0) { + // the entry is not found or we do not have read access + return -1; + } + + pzip = &(zip->archive); + idx = (mz_uint)zip->entry.index; + if (mz_zip_reader_is_file_a_directory(pzip, idx)) { + // the entry is a directory + return -1; + } + + return (mz_zip_reader_extract_to_file(pzip, idx, filename, 0)) ? 0 : -1; +} + +int zip_entry_extract(struct zip_t *zip, + size_t (*on_extract)(void *arg, unsigned long long offset, + const void *buf, size_t bufsize), + void *arg) { + mz_zip_archive *pzip = NULL; + mz_uint idx; + + if (!zip) { + // zip_t handler is not initialized + return -1; + } + + if (zip->mode != 'r' || zip->entry.index < 0) { + // the entry is not found or we do not have read access + return -1; + } + + pzip = &(zip->archive); + idx = (mz_uint)zip->entry.index; + + return (mz_zip_reader_extract_to_callback(pzip, idx, on_extract, arg, 0)) + ? 0 + : -1; +} + +int zip_create(const char *zipname, const char *filenames[], size_t len) { + int status = 0; + size_t i; + mz_zip_archive zip_archive; + + if (!zipname || strlen(zipname) < 1) { + // zip_t archive name is empty or NULL + return -1; + } + + // Create a new archive. + if (!memset(&(zip_archive), 0, sizeof(zip_archive))) { + // Cannot memset zip archive + return -1; + } + + if (!mz_zip_writer_init_file(&zip_archive, zipname, 0)) { + // Cannot initialize zip_archive writer + return -1; + } + + for (i = 0; i < len; ++i) { + const char *name = filenames[i]; + if (!name) { + status = -1; + break; + } + + if (!mz_zip_writer_add_file(&zip_archive, basename(name), name, "", 0, + ZIP_DEFAULT_COMPRESSION_LEVEL)) { + // Cannot add file to zip_archive + status = -1; + break; + } + } + + mz_zip_writer_finalize_archive(&zip_archive); + mz_zip_writer_end(&zip_archive); + return status; +} + +int zip_extract(const char *zipname, const char *dir, + int (*on_extract)(const char *filename, void *arg), void *arg) { + int status = -1; + mz_uint i, n; + char path[MAX_PATH + 1] = {0}; + mz_zip_archive zip_archive; + mz_zip_archive_file_stat info; + size_t dirlen = 0; + + if (!memset(&(zip_archive), 0, sizeof(zip_archive))) { + // Cannot memset zip archive + return -1; + } + + if (!zipname || !dir) { + // Cannot parse zip archive name + return -1; + } + + dirlen = strlen(dir); + if (dirlen + 1 > MAX_PATH) { + return -1; + } + + // Now try to open the archive. + if (!mz_zip_reader_init_file(&zip_archive, zipname, 0)) { + // Cannot initialize zip_archive reader + return -1; + } + + strcpy(path, dir); + if (!ISSLASH(path[dirlen - 1])) { +#if defined _WIN32 || defined __WIN32__ + path[dirlen] = '\\'; +#else + path[dirlen] = '/'; +#endif + ++dirlen; + } + + // Get and print information about each file in the archive. + n = mz_zip_reader_get_num_files(&zip_archive); + for (i = 0; i < n; ++i) { + if (!mz_zip_reader_file_stat(&zip_archive, i, &info)) { + // Cannot get information about zip archive; + goto out; + } + strncpy(&path[dirlen], info.m_filename, MAX_PATH - dirlen); + if (mkpath(path) < 0) { + // Cannot make a path + goto out; + } + + if (!mz_zip_reader_is_file_a_directory(&zip_archive, i)) { + if (!mz_zip_reader_extract_to_file(&zip_archive, i, path, 0)) { + // Cannot extract zip archive to file + goto out; + } + } + + if (on_extract) { + if (on_extract(path, arg) < 0) { + goto out; + } + } + } + status = 0; + +out: + // Close the archive, freeing any resources it was using + if (!mz_zip_reader_end(&zip_archive)) { + // Cannot end zip reader + status = -1; + } + + return status; +} diff --git a/contrib/zip/src/zip.h b/contrib/zip/src/zip.h new file mode 100644 index 000000000..1611b5417 --- /dev/null +++ b/contrib/zip/src/zip.h @@ -0,0 +1,193 @@ +/* + * 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 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. + */ + +#pragma once +#ifndef ZIP_H +#define ZIP_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAX_PATH +#define MAX_PATH 32767 /* # chars in a path name including NULL */ +#endif + +#define ZIP_DEFAULT_COMPRESSION_LEVEL 6 + +/* + This data structure is used throughout the library to represent zip archive + - forward declaration. +*/ +struct zip_t; + +/* + Opens zip archive with compression level using the given mode. + + Args: + zipname: zip archive file name. + level: compression level (0-9 are the standard zlib-style levels). + mode: file access mode. + 'r': opens a file for reading/extracting (the file must exists). + 'w': creates an empty file for writing. + 'a': appends to an existing archive. + + Returns: + The zip archive handler or NULL on error +*/ +extern struct zip_t *zip_open(const char *zipname, int level, char mode); + +/* + Closes zip archive, releases resources - always finalize. + + Args: + zip: zip archive handler. +*/ +extern void zip_close(struct zip_t *zip); + +/* + Opens a new entry for writing in a zip archive. + + Args: + zip: zip archive handler. + entryname: an entry name in local dictionary. + + Returns: + The return code - 0 on success, negative number (< 0) on error. +*/ +extern int zip_entry_open(struct zip_t *zip, const char *entryname); + +/* + Closes a zip entry, flushes buffer and releases resources. + + Args: + zip: zip archive handler. + + Returns: + The return code - 0 on success, negative number (< 0) on error. +*/ +extern int zip_entry_close(struct zip_t *zip); + +/* + Compresses an input buffer for the current zip entry. + + Args: + zip: zip archive handler. + buf: input buffer. + bufsize: input buffer size (in bytes). + + Returns: + The return code - 0 on success, negative number (< 0) on error. +*/ +extern int zip_entry_write(struct zip_t *zip, const void *buf, size_t bufsize); + +/* + Compresses a file for the current zip entry. + + Args: + zip: zip archive handler. + filename: input file. + + Returns: + The return code - 0 on success, negative number (< 0) on error. +*/ +extern int zip_entry_fwrite(struct zip_t *zip, const char *filename); + +/* + Extracts the current zip entry into output buffer. + The function allocates sufficient memory for a output buffer. + + Args: + zip: zip archive handler. + buf: output buffer. + bufsize: output buffer size (in bytes). + + Note: + - remember to release memory allocated for a output buffer. + - for large entries, please take a look at zip_entry_extract function. + + Returns: + The return code - 0 on success, negative number (< 0) on error. +*/ +extern int zip_entry_read(struct zip_t *zip, void **buf, size_t *bufsize); + +/* + Extracts the current zip entry into output file. + + Args: + zip: zip archive handler. + filename: output file. + + Returns: + The return code - 0 on success, negative number (< 0) on error. +*/ +extern int zip_entry_fread(struct zip_t *zip, const char *filename); + +/* + Extract the current zip entry using a callback function (on_extract). + + Args: + zip: zip archive handler. + on_extract: callback function. + arg: opaque pointer (optional argument, + which you can pass to the on_extract callback) + + Returns: + The return code - 0 on success, negative number (< 0) on error. + */ +extern int zip_entry_extract(struct zip_t *zip, + size_t (*on_extract)(void *arg, + unsigned long long offset, + const void *data, + size_t size), + void *arg); + +/* + Creates a new archive and puts files into a single zip archive. + + Args: + zipname: zip archive file. + filenames: input files. + len: number of input files. + + Returns: + The return code - 0 on success, negative number (< 0) on error. +*/ +extern int zip_create(const char *zipname, const char *filenames[], size_t len); + +/* + Extracts a zip archive file into directory. + + If on_extract_entry is not NULL, the callback will be called after + successfully extracted each zip entry. + Returning a negative value from the callback will cause abort and return an + error. The last argument (void *arg) is optional, which you can use to pass + data to the on_extract_entry callback. + + Args: + zipname: zip archive file. + dir: output directory. + on_extract_entry: on extract callback. + arg: opaque pointer. + + Returns: + The return code - 0 on success, negative number (< 0) on error. +*/ +extern int zip_extract(const char *zipname, const char *dir, + int (*on_extract_entry)(const char *filename, void *arg), + void *arg); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/contrib/zip/test/CMakeLists.txt b/contrib/zip/test/CMakeLists.txt new file mode 100644 index 000000000..7734dcbe7 --- /dev/null +++ b/contrib/zip/test/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 2.8) + +# test +include_directories(../src) +add_executable(test.exe test.c ../src/zip.c) + +add_test(NAME test COMMAND test.exe) diff --git a/contrib/zip/test/test.c b/contrib/zip/test/test.c new file mode 100644 index 000000000..0b9c9f7b6 --- /dev/null +++ b/contrib/zip/test/test.c @@ -0,0 +1,105 @@ +#include + +#include +#include +#include +#include + +#define ZIPNAME "test.zip" +#define TESTDATA1 "Some test data 1...\0" +#define TESTDATA2 "Some test data 2...\0" + +static void test_write(void) { + struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w'); + assert(zip != NULL); + + assert(0 == zip_entry_open(zip, "test/test-1.txt")); + assert(0 == zip_entry_write(zip, TESTDATA1, strlen(TESTDATA1))); + assert(0 == zip_entry_close(zip)); + + zip_close(zip); +} + +static void test_append(void) { + struct zip_t *zip = zip_open(ZIPNAME, ZIP_DEFAULT_COMPRESSION_LEVEL, 'a'); + assert(zip != NULL); + + assert(0 == zip_entry_open(zip, "test\\test-2.txt")); + assert(0 == zip_entry_write(zip, TESTDATA2, strlen(TESTDATA2))); + assert(0 == zip_entry_close(zip)); + + zip_close(zip); +} + +static void test_read(void) { + char *buf = NULL; + size_t bufsize; + struct zip_t *zip = zip_open(ZIPNAME, 0, 'r'); + assert(zip != NULL); + + assert(0 == zip_entry_open(zip, "test\\test-1.txt")); + assert(0 == zip_entry_read(zip, (void **)&buf, &bufsize)); + assert(bufsize == strlen(TESTDATA1)); + assert(0 == strncmp(buf, TESTDATA1, bufsize)); + assert(0 == zip_entry_close(zip)); + free(buf); + buf = NULL; + bufsize = 0; + + assert(0 == zip_entry_open(zip, "test/test-2.txt")); + assert(0 == zip_entry_read(zip, (void **)&buf, &bufsize)); + assert(bufsize == strlen(TESTDATA2)); + assert(0 == strncmp(buf, TESTDATA2, bufsize)); + assert(0 == zip_entry_close(zip)); + free(buf); + buf = NULL; + bufsize = 0; + + zip_close(zip); +} + +struct buffer_t { + char *data; + size_t size; +}; + +static size_t on_extract(void *arg, unsigned long long offset, const void *data, + size_t size) { + struct buffer_t *buf = (struct buffer_t *)arg; + buf->data = realloc(buf->data, buf->size + size + 1); + assert(NULL != buf->data); + + memcpy(&(buf->data[buf->size]), data, size); + buf->size += size; + buf->data[buf->size] = 0; + + return size; +} + +static void test_extract(void) { + struct buffer_t buf = {0}; + + struct zip_t *zip = zip_open(ZIPNAME, 0, 'r'); + assert(zip != NULL); + + assert(0 == zip_entry_open(zip, "test/test-1.txt")); + assert(0 == zip_entry_extract(zip, on_extract, &buf)); + + assert(buf.size == strlen(TESTDATA1)); + assert(0 == strncmp(buf.data, TESTDATA1, buf.size)); + assert(0 == zip_entry_close(zip)); + free(buf.data); + buf.data = NULL; + buf.size = 0; + + zip_close(zip); +} + +int main(int argc, char *argv[]) { + test_write(); + test_append(); + test_read(); + test_extract(); + + return remove(ZIPNAME); +} diff --git a/contrib/zip/zip.png b/contrib/zip/zip.png new file mode 100644 index 000000000..244681007 Binary files /dev/null and b/contrib/zip/zip.png differ diff --git a/contrib/zlib/CMakeLists.txt b/contrib/zlib/CMakeLists.txt index 022d3dfba..5f1368adb 100644 --- a/contrib/zlib/CMakeLists.txt +++ b/contrib/zlib/CMakeLists.txt @@ -10,10 +10,10 @@ endif() project(zlib C) cmake_policy(POP) -set(VERSION "1.2.8") +set(VERSION "1.2.11.1") -option(ASM686 "Enable building i686 assembly implementation for zlib") -option(AMD64 "Enable building amd64 assembly implementation for zlib") +option(ASM686 "Enable building i686 assembly implementation") +option(AMD64 "Enable building amd64 assembly implementation") #set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") #set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") @@ -90,7 +90,6 @@ configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein ${ZLIB_PC} @ONLY) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY) - include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}) @@ -191,7 +190,11 @@ if(MINGW) set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) endif(MINGW) +add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) +set_target_properties(zlib PROPERTIES SOVERSION 1) + INSTALL( TARGETS zlibstatic LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR} ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR} diff --git a/contrib/zlib/README b/contrib/zlib/README index 5ca9d127e..41777d06d 100644 --- a/contrib/zlib/README +++ b/contrib/zlib/README @@ -1,6 +1,6 @@ ZLIB DATA COMPRESSION LIBRARY -zlib 1.2.8 is a general purpose data compression library. All the code is +zlib 1.2.11.1 is a general purpose data compression library. All the code is thread safe. The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and @@ -31,7 +31,7 @@ Mark Nelson wrote an article about zlib for the Jan. 1997 issue of Dr. Dobb's Journal; a copy of the article is available at http://marknelson.us/1997/01/01/zlib-engine/ . -The changes made in version 1.2.8 are documented in the file ChangeLog. +The changes made in version 1.2.11.1 are documented in the file ChangeLog. Unsupported third party contributions are provided in directory contrib/ . @@ -84,7 +84,7 @@ Acknowledgments: Copyright notice: - (C) 1995-2013 Jean-loup Gailly and Mark Adler + (C) 1995-2017 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/contrib/zlib/adler32.c b/contrib/zlib/adler32.c index a868f073d..d0be4380a 100644 --- a/contrib/zlib/adler32.c +++ b/contrib/zlib/adler32.c @@ -1,5 +1,5 @@ /* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2011 Mark Adler + * Copyright (C) 1995-2011, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -7,11 +7,9 @@ #include "zutil.h" -#define local static - local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); -#define BASE 65521 /* largest prime smaller than 65536 */ +#define BASE 65521U /* largest prime smaller than 65536 */ #define NMAX 5552 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ @@ -62,10 +60,10 @@ local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); #endif /* ========================================================================= */ -uLong ZEXPORT adler32(adler, buf, len) +uLong ZEXPORT adler32_z(adler, buf, len) uLong adler; const Bytef *buf; - uInt len; + z_size_t len; { unsigned long sum2; unsigned n; @@ -132,6 +130,15 @@ uLong ZEXPORT adler32(adler, buf, len) return adler | (sum2 << 16); } +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + return adler32_z(adler, buf, len); +} + /* ========================================================================= */ local uLong adler32_combine_(adler1, adler2, len2) uLong adler1; @@ -156,7 +163,7 @@ local uLong adler32_combine_(adler1, adler2, len2) sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; if (sum1 >= BASE) sum1 -= BASE; if (sum1 >= BASE) sum1 -= BASE; - if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); + if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1); if (sum2 >= BASE) sum2 -= BASE; return sum1 | (sum2 << 16); } diff --git a/contrib/zlib/compress.c b/contrib/zlib/compress.c index 6e9762676..e2db404ab 100644 --- a/contrib/zlib/compress.c +++ b/contrib/zlib/compress.c @@ -1,5 +1,5 @@ /* compress.c -- compress a memory buffer - * Copyright (C) 1995-2005 Jean-loup Gailly. + * Copyright (C) 1995-2005, 2014, 2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -28,16 +28,11 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) { z_stream stream; int err; + const uInt max = (uInt)-1; + uLong left; - stream.next_in = (z_const Bytef *)source; - stream.avail_in = (uInt)sourceLen; -#ifdef MAXSEG_64K - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; -#endif - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + left = *destLen; + *destLen = 0; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; @@ -46,15 +41,26 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) err = deflateInit(&stream, level); if (err != Z_OK) return err; - err = deflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - deflateEnd(&stream); - return err == Z_OK ? Z_BUF_ERROR : err; - } - *destLen = stream.total_out; + stream.next_out = dest; + stream.avail_out = 0; + stream.next_in = (z_const Bytef *)source; + stream.avail_in = 0; - err = deflateEnd(&stream); - return err; + do { + if (stream.avail_out == 0) { + stream.avail_out = left > (uLong)max ? max : (uInt)left; + left -= stream.avail_out; + } + if (stream.avail_in == 0) { + stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen; + sourceLen -= stream.avail_in; + } + err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH); + } while (err == Z_OK); + + *destLen = stream.total_out; + deflateEnd(&stream); + return err == Z_STREAM_END ? Z_OK : err; } /* =========================================================================== diff --git a/contrib/zlib/crc32.c b/contrib/zlib/crc32.c index 979a7190a..e72636a50 100644 --- a/contrib/zlib/crc32.c +++ b/contrib/zlib/crc32.c @@ -1,5 +1,5 @@ /* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler + * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * Thanks to Rodney Brown for his contribution of faster @@ -30,17 +30,15 @@ #include "zutil.h" /* for STDC and FAR definitions */ -#define local static - /* Definitions for doing the crc four data bytes at a time. */ #if !defined(NOBYFOUR) && defined(Z_U4) # define BYFOUR #endif #ifdef BYFOUR local unsigned long crc32_little OF((unsigned long, - const unsigned char FAR *, unsigned)); + const unsigned char FAR *, z_size_t)); local unsigned long crc32_big OF((unsigned long, - const unsigned char FAR *, unsigned)); + const unsigned char FAR *, z_size_t)); # define TBLS 8 #else # define TBLS 1 @@ -201,10 +199,10 @@ const z_crc_t FAR * ZEXPORT get_crc_table() #define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 /* ========================================================================= */ -unsigned long ZEXPORT crc32(crc, buf, len) +unsigned long ZEXPORT crc32_z(crc, buf, len) unsigned long crc; const unsigned char FAR *buf; - uInt len; + z_size_t len; { if (buf == Z_NULL) return 0UL; @@ -214,7 +212,7 @@ unsigned long ZEXPORT crc32(crc, buf, len) #endif /* DYNAMIC_CRC_TABLE */ #ifdef BYFOUR - if (sizeof(void *) == sizeof(ptrdiff_t)) { + if (sizeof(void *) == sizeof(z_size_t)) { z_crc_t endian; endian = 1; @@ -235,8 +233,29 @@ unsigned long ZEXPORT crc32(crc, buf, len) return crc ^ 0xffffffffUL; } +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + uInt len; +{ + return crc32_z(crc, buf, len); +} + #ifdef BYFOUR +/* + This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit + integer pointer type. This violates the strict aliasing rule, where a + compiler can assume, for optimization purposes, that two pointers to + fundamentally different types won't ever point to the same memory. This can + manifest as a problem only if one of the pointers is written to. This code + only reads from those pointers. So long as this code remains isolated in + this compilation unit, there won't be a problem. For this reason, this code + should not be copied and pasted into a compilation unit in which other code + writes to the buffer that is passed to these routines. + */ + /* ========================================================================= */ #define DOLIT4 c ^= *buf4++; \ c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ @@ -247,14 +266,14 @@ unsigned long ZEXPORT crc32(crc, buf, len) local unsigned long crc32_little(crc, buf, len) unsigned long crc; const unsigned char FAR *buf; - unsigned len; + z_size_t len; { register z_crc_t c; register const z_crc_t FAR *buf4; c = (z_crc_t)crc; c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { + while (len && ((z_size_t)buf & 3)) { c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); len--; } @@ -278,7 +297,7 @@ local unsigned long crc32_little(crc, buf, len) } /* ========================================================================= */ -#define DOBIG4 c ^= *++buf4; \ +#define DOBIG4 c ^= *buf4++; \ c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 @@ -287,20 +306,19 @@ local unsigned long crc32_little(crc, buf, len) local unsigned long crc32_big(crc, buf, len) unsigned long crc; const unsigned char FAR *buf; - unsigned len; + z_size_t len; { register z_crc_t c; register const z_crc_t FAR *buf4; c = ZSWAP32((z_crc_t)crc); c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { + while (len && ((z_size_t)buf & 3)) { c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); len--; } buf4 = (const z_crc_t FAR *)(const void FAR *)buf; - buf4--; while (len >= 32) { DOBIG32; len -= 32; @@ -309,7 +327,6 @@ local unsigned long crc32_big(crc, buf, len) DOBIG4; len -= 4; } - buf4++; buf = (const unsigned char FAR *)buf4; if (len) do { diff --git a/contrib/zlib/deflate.c b/contrib/zlib/deflate.c index 696957705..568eaddbe 100644 --- a/contrib/zlib/deflate.c +++ b/contrib/zlib/deflate.c @@ -1,5 +1,5 @@ /* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + * Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -52,7 +52,7 @@ #include "deflate.h" const char deflate_copyright[] = - " deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler "; + " deflate 1.2.11.1 Copyright 1995-2017 Jean-loup Gailly and Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -73,6 +73,8 @@ typedef enum { typedef block_state (*compress_func) OF((deflate_state *s, int flush)); /* Compression function. Returns the block state after the call. */ +local int deflateStateCheck OF((z_streamp strm)); +local void slide_hash OF((deflate_state *s)); local void fill_window OF((deflate_state *s)); local block_state deflate_stored OF((deflate_state *s, int flush)); local block_state deflate_fast OF((deflate_state *s, int flush)); @@ -84,15 +86,16 @@ local block_state deflate_huff OF((deflate_state *s, int flush)); local void lm_init OF((deflate_state *s)); local void putShortMSB OF((deflate_state *s, uInt b)); local void flush_pending OF((z_streamp strm)); -local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +local unsigned read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); #ifdef ASMV +# pragma message("Assembler code may have bugs -- use at your own risk") void match_init OF((void)); /* asm code initialization */ uInt longest_match OF((deflate_state *s, IPos cur_match)); #else local uInt longest_match OF((deflate_state *s, IPos cur_match)); #endif -#ifdef DEBUG +#ifdef ZLIB_DEBUG local void check_match OF((deflate_state *s, IPos start, IPos match, int length)); #endif @@ -148,21 +151,14 @@ local const config configuration_table[10] = { * meaning. */ -#define EQUAL 0 -/* result of memcmp for equal strings */ - -#ifndef NO_DUMMY_DECL -struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ -#endif - /* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ -#define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0)) +#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0)) /* =========================================================================== * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive - * input characters, so that a running hash key can be computed from the - * previous key instead of complete recalculation each time. + * IN assertion: all calls to UPDATE_HASH are made with consecutive input + * characters, so that a running hash key can be computed from the previous + * key instead of complete recalculation each time. */ #define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) @@ -173,9 +169,9 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ * the previous length of the hash chain. * If this file is compiled with -DFASTEST, the compression level is forced * to 1, and no hash chains are maintained. - * IN assertion: all calls to to INSERT_STRING are made with consecutive - * input characters and the first MIN_MATCH bytes of str are valid - * (except for the last MIN_MATCH-1 bytes of the input file). + * IN assertion: all calls to INSERT_STRING are made with consecutive input + * characters and the first MIN_MATCH bytes of str are valid (except for + * the last MIN_MATCH-1 bytes of the input file). */ #ifdef FASTEST #define INSERT_STRING(s, str, match_head) \ @@ -194,8 +190,42 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ * prev[] will be initialized on the fly. */ #define CLEAR_HASH(s) \ - s->head[s->hash_size-1] = NIL; \ - zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + do { \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, \ + (unsigned)(s->hash_size-1)*sizeof(*s->head)); \ + } while (0) + +/* =========================================================================== + * Slide the hash table when sliding the window down (could be avoided with 32 + * bit values at the expense of memory usage). We slide even when level == 0 to + * keep the hash table consistent if we switch back to level > 0 later. + */ +local void slide_hash(s) + deflate_state *s; +{ + unsigned n, m; + Posf *p; + uInt wsize = s->w_size; + + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m - wsize : NIL); + } while (--n); + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m - wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif +} /* ========================================================================= */ int ZEXPORT deflateInit_(strm, level, version, stream_size) @@ -270,7 +300,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, #endif if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED) { + strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) { return Z_STREAM_ERROR; } if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ @@ -278,14 +308,15 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, if (s == Z_NULL) return Z_MEM_ERROR; strm->state = (struct internal_state FAR *)s; s->strm = strm; + s->status = INIT_STATE; /* to pass state test in deflateReset() */ s->wrap = wrap; s->gzhead = Z_NULL; - s->w_bits = windowBits; + s->w_bits = (uInt)windowBits; s->w_size = 1 << s->w_bits; s->w_mask = s->w_size - 1; - s->hash_bits = memLevel + 7; + s->hash_bits = (uInt)memLevel + 7; s->hash_size = 1 << s->hash_bits; s->hash_mask = s->hash_size - 1; s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); @@ -319,6 +350,31 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, return deflateReset(strm); } +/* ========================================================================= + * Check for a valid deflate stream state. Return 0 if ok, 1 if not. + */ +local int deflateStateCheck (strm) + z_streamp strm; +{ + deflate_state *s; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + s = strm->state; + if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE && +#ifdef GZIP + s->status != GZIP_STATE && +#endif + s->status != EXTRA_STATE && + s->status != NAME_STATE && + s->status != COMMENT_STATE && + s->status != HCRC_STATE && + s->status != BUSY_STATE && + s->status != FINISH_STATE)) + return 1; + return 0; +} + /* ========================================================================= */ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) z_streamp strm; @@ -331,7 +387,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) unsigned avail; z_const unsigned char *next; - if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL) + if (deflateStateCheck(strm) || dictionary == Z_NULL) return Z_STREAM_ERROR; s = strm->state; wrap = s->wrap; @@ -388,14 +444,35 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) return Z_OK; } +/* ========================================================================= */ +int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength) + z_streamp strm; + Bytef *dictionary; + uInt *dictLength; +{ + deflate_state *s; + uInt len; + + if (deflateStateCheck(strm)) + return Z_STREAM_ERROR; + s = strm->state; + len = s->strstart + s->lookahead; + if (len > s->w_size) + len = s->w_size; + if (dictionary != Z_NULL && len) + zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len); + if (dictLength != Z_NULL) + *dictLength = len; + return Z_OK; +} + /* ========================================================================= */ int ZEXPORT deflateResetKeep (strm) z_streamp strm; { deflate_state *s; - if (strm == Z_NULL || strm->state == Z_NULL || - strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + if (deflateStateCheck(strm)) { return Z_STREAM_ERROR; } @@ -410,13 +487,17 @@ int ZEXPORT deflateResetKeep (strm) if (s->wrap < 0) { s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ } - s->status = s->wrap ? INIT_STATE : BUSY_STATE; + s->status = +#ifdef GZIP + s->wrap == 2 ? GZIP_STATE : +#endif + s->wrap ? INIT_STATE : BUSY_STATE; strm->adler = #ifdef GZIP s->wrap == 2 ? crc32(0L, Z_NULL, 0) : #endif adler32(0L, Z_NULL, 0); - s->last_flush = Z_NO_FLUSH; + s->last_flush = -2; _tr_init(s); @@ -440,8 +521,8 @@ int ZEXPORT deflateSetHeader (strm, head) z_streamp strm; gz_headerp head; { - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - if (strm->state->wrap != 2) return Z_STREAM_ERROR; + if (deflateStateCheck(strm) || strm->state->wrap != 2) + return Z_STREAM_ERROR; strm->state->gzhead = head; return Z_OK; } @@ -452,7 +533,7 @@ int ZEXPORT deflatePending (strm, pending, bits) int *bits; z_streamp strm; { - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; if (pending != Z_NULL) *pending = strm->state->pending; if (bits != Z_NULL) @@ -469,7 +550,7 @@ int ZEXPORT deflatePrime (strm, bits, value) deflate_state *s; int put; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) return Z_BUF_ERROR; @@ -494,9 +575,8 @@ int ZEXPORT deflateParams(strm, level, strategy) { deflate_state *s; compress_func func; - int err = Z_OK; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; #ifdef FASTEST @@ -510,13 +590,22 @@ int ZEXPORT deflateParams(strm, level, strategy) func = configuration_table[s->level].func; if ((strategy != s->strategy || func != configuration_table[level].func) && - strm->total_in != 0) { + s->last_flush != -2) { /* Flush the last buffer: */ - err = deflate(strm, Z_BLOCK); - if (err == Z_BUF_ERROR && s->pending == 0) - err = Z_OK; + int err = deflate(strm, Z_BLOCK); + if (err == Z_STREAM_ERROR) + return err; + if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead) + return Z_BUF_ERROR; } if (s->level != level) { + if (s->level == 0 && s->matches != 0) { + if (s->matches == 1) + slide_hash(s); + else + CLEAR_HASH(s); + s->matches = 0; + } s->level = level; s->max_lazy_match = configuration_table[level].max_lazy; s->good_match = configuration_table[level].good_length; @@ -524,7 +613,7 @@ int ZEXPORT deflateParams(strm, level, strategy) s->max_chain_length = configuration_table[level].max_chain; } s->strategy = strategy; - return err; + return Z_OK; } /* ========================================================================= */ @@ -537,12 +626,12 @@ int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) { deflate_state *s; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; - s->good_match = good_length; - s->max_lazy_match = max_lazy; + s->good_match = (uInt)good_length; + s->max_lazy_match = (uInt)max_lazy; s->nice_match = nice_length; - s->max_chain_length = max_chain; + s->max_chain_length = (uInt)max_chain; return Z_OK; } @@ -569,14 +658,13 @@ uLong ZEXPORT deflateBound(strm, sourceLen) { deflate_state *s; uLong complen, wraplen; - Bytef *str; /* conservative upper bound for compressed data */ complen = sourceLen + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; /* if can't get parameters, return conservative bound plus zlib wrapper */ - if (strm == Z_NULL || strm->state == Z_NULL) + if (deflateStateCheck(strm)) return complen + 6; /* compute wrapper length */ @@ -588,9 +676,11 @@ uLong ZEXPORT deflateBound(strm, sourceLen) case 1: /* zlib wrapper */ wraplen = 6 + (s->strstart ? 4 : 0); break; +#ifdef GZIP case 2: /* gzip wrapper */ wraplen = 18; if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ + Bytef *str; if (s->gzhead->extra != Z_NULL) wraplen += 2 + s->gzhead->extra_len; str = s->gzhead->name; @@ -607,6 +697,7 @@ uLong ZEXPORT deflateBound(strm, sourceLen) wraplen += 2; } break; +#endif default: /* for compiler happiness */ wraplen = 6; } @@ -634,10 +725,10 @@ local void putShortMSB (s, b) } /* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->next_out buffer and copying into it. - * (See also read_buf()). + * Flush as much pending output as possible. All deflate() output, except for + * some deflate_stored() output, goes through this function so some + * applications may wish to modify it to avoid allocating a large + * strm->next_out buffer and copying into it. (See also read_buf()). */ local void flush_pending(strm) z_streamp strm; @@ -654,13 +745,23 @@ local void flush_pending(strm) strm->next_out += len; s->pending_out += len; strm->total_out += len; - strm->avail_out -= len; - s->pending -= len; + strm->avail_out -= len; + s->pending -= len; if (s->pending == 0) { s->pending_out = s->pending_buf; } } +/* =========================================================================== + * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1]. + */ +#define HCRC_UPDATE(beg) \ + do { \ + if (s->gzhead->hcrc && s->pending > (beg)) \ + strm->adler = crc32(strm->adler, s->pending_buf + (beg), \ + s->pending - (beg)); \ + } while (0) + /* ========================================================================= */ int ZEXPORT deflate (strm, flush) z_streamp strm; @@ -669,203 +770,21 @@ int ZEXPORT deflate (strm, flush) int old_flush; /* value of flush param for previous deflate call */ deflate_state *s; - if (strm == Z_NULL || strm->state == Z_NULL || - flush > Z_BLOCK || flush < 0) { + if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) { return Z_STREAM_ERROR; } s = strm->state; if (strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0) || + (strm->avail_in != 0 && strm->next_in == Z_NULL) || (s->status == FINISH_STATE && flush != Z_FINISH)) { ERR_RETURN(strm, Z_STREAM_ERROR); } if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); - s->strm = strm; /* just in case */ old_flush = s->last_flush; s->last_flush = flush; - /* Write the header */ - if (s->status == INIT_STATE) { -#ifdef GZIP - if (s->wrap == 2) { - strm->adler = crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (s->gzhead == Z_NULL) { - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s->status = BUSY_STATE; - } - else { - put_byte(s, (s->gzhead->text ? 1 : 0) + - (s->gzhead->hcrc ? 2 : 0) + - (s->gzhead->extra == Z_NULL ? 0 : 4) + - (s->gzhead->name == Z_NULL ? 0 : 8) + - (s->gzhead->comment == Z_NULL ? 0 : 16) - ); - put_byte(s, (Byte)(s->gzhead->time & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, s->gzhead->os & 0xff); - if (s->gzhead->extra != Z_NULL) { - put_byte(s, s->gzhead->extra_len & 0xff); - put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); - } - if (s->gzhead->hcrc) - strm->adler = crc32(strm->adler, s->pending_buf, - s->pending); - s->gzindex = 0; - s->status = EXTRA_STATE; - } - } - else -#endif - { - uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; - uInt level_flags; - - if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) - level_flags = 0; - else if (s->level < 6) - level_flags = 1; - else if (s->level == 6) - level_flags = 2; - else - level_flags = 3; - header |= (level_flags << 6); - if (s->strstart != 0) header |= PRESET_DICT; - header += 31 - (header % 31); - - s->status = BUSY_STATE; - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s->strstart != 0) { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - strm->adler = adler32(0L, Z_NULL, 0); - } - } -#ifdef GZIP - if (s->status == EXTRA_STATE) { - if (s->gzhead->extra != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - - while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) - break; - } - put_byte(s, s->gzhead->extra[s->gzindex]); - s->gzindex++; - } - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (s->gzindex == s->gzhead->extra_len) { - s->gzindex = 0; - s->status = NAME_STATE; - } - } - else - s->status = NAME_STATE; - } - if (s->status == NAME_STATE) { - if (s->gzhead->name != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - int val; - - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->name[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) { - s->gzindex = 0; - s->status = COMMENT_STATE; - } - } - else - s->status = COMMENT_STATE; - } - if (s->status == COMMENT_STATE) { - if (s->gzhead->comment != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - int val; - - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->comment[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) - s->status = HCRC_STATE; - } - else - s->status = HCRC_STATE; - } - if (s->status == HCRC_STATE) { - if (s->gzhead->hcrc) { - if (s->pending + 2 > s->pending_buf_size) - flush_pending(strm); - if (s->pending + 2 <= s->pending_buf_size) { - put_byte(s, (Byte)(strm->adler & 0xff)); - put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); - strm->adler = crc32(0L, Z_NULL, 0); - s->status = BUSY_STATE; - } - } - else - s->status = BUSY_STATE; - } -#endif - /* Flush as much pending output as possible */ if (s->pending != 0) { flush_pending(strm); @@ -894,15 +813,197 @@ int ZEXPORT deflate (strm, flush) ERR_RETURN(strm, Z_BUF_ERROR); } + /* Write the header */ + if (s->status == INIT_STATE) { + /* zlib header */ + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } +#ifdef GZIP + if (s->status == GZIP_STATE) { + /* gzip header */ + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == Z_NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != Z_NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != Z_NULL) { + ulg beg = s->pending; /* start of bytes to update crc */ + uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex; + while (s->pending + left > s->pending_buf_size) { + uInt copy = s->pending_buf_size - s->pending; + zmemcpy(s->pending_buf + s->pending, + s->gzhead->extra + s->gzindex, copy); + s->pending = s->pending_buf_size; + HCRC_UPDATE(beg); + s->gzindex += copy; + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + left -= copy; + } + zmemcpy(s->pending_buf + s->pending, + s->gzhead->extra + s->gzindex, left); + s->pending += left; + HCRC_UPDATE(beg); + s->gzindex = 0; + } + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != Z_NULL) { + ulg beg = s->pending; /* start of bytes to update crc */ + int val; + do { + if (s->pending == s->pending_buf_size) { + HCRC_UPDATE(beg); + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + HCRC_UPDATE(beg); + s->gzindex = 0; + } + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != Z_NULL) { + ulg beg = s->pending; /* start of bytes to update crc */ + int val; + do { + if (s->pending == s->pending_buf_size) { + HCRC_UPDATE(beg); + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + HCRC_UPDATE(beg); + } + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) { + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + } + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } +#endif + /* Start a new block or continue the current one. */ if (strm->avail_in != 0 || s->lookahead != 0 || (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { block_state bstate; - bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : - (s->strategy == Z_RLE ? deflate_rle(s, flush) : - (*(configuration_table[s->level].func))(s, flush)); + bstate = s->level == 0 ? deflate_stored(s, flush) : + s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : + s->strategy == Z_RLE ? deflate_rle(s, flush) : + (*(configuration_table[s->level].func))(s, flush); if (bstate == finish_started || bstate == finish_done) { s->status = FINISH_STATE; @@ -944,7 +1045,6 @@ int ZEXPORT deflate (strm, flush) } } } - Assert(strm->avail_out > 0, "bug2"); if (flush != Z_FINISH) return Z_OK; if (s->wrap <= 0) return Z_STREAM_END; @@ -981,18 +1081,9 @@ int ZEXPORT deflateEnd (strm) { int status; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; status = strm->state->status; - if (status != INIT_STATE && - status != EXTRA_STATE && - status != NAME_STATE && - status != COMMENT_STATE && - status != HCRC_STATE && - status != BUSY_STATE && - status != FINISH_STATE) { - return Z_STREAM_ERROR; - } /* Deallocate in reverse order of allocations: */ TRY_FREE(strm, strm->state->pending_buf); @@ -1023,7 +1114,7 @@ int ZEXPORT deflateCopy (dest, source) ushf *overlay; - if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + if (deflateStateCheck(source) || dest == Z_NULL) { return Z_STREAM_ERROR; } @@ -1073,7 +1164,7 @@ int ZEXPORT deflateCopy (dest, source) * allocating a large strm->next_in buffer and copying from it. * (See also flush_pending()). */ -local int read_buf(strm, buf, size) +local unsigned read_buf(strm, buf, size) z_streamp strm; Bytef *buf; unsigned size; @@ -1097,7 +1188,7 @@ local int read_buf(strm, buf, size) strm->next_in += len; strm->total_in += len; - return (int)len; + return len; } /* =========================================================================== @@ -1151,9 +1242,9 @@ local uInt longest_match(s, cur_match) { unsigned chain_length = s->max_chain_length;/* max hash chain length */ register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ + register Bytef *match; /* matched string */ register int len; /* length of current match */ - int best_len = s->prev_length; /* best match length so far */ + int best_len = (int)s->prev_length; /* best match length so far */ int nice_match = s->nice_match; /* stop if match long enough */ IPos limit = s->strstart > (IPos)MAX_DIST(s) ? s->strstart - (IPos)MAX_DIST(s) : NIL; @@ -1188,7 +1279,7 @@ local uInt longest_match(s, cur_match) /* Do not look for matches beyond the end of the input. This is necessary * to make deflate deterministic. */ - if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead; Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); @@ -1349,7 +1440,11 @@ local uInt longest_match(s, cur_match) #endif /* FASTEST */ -#ifdef DEBUG +#ifdef ZLIB_DEBUG + +#define EQUAL 0 +/* result of memcmp for equal strings */ + /* =========================================================================== * Check that the match at match_start is indeed a match. */ @@ -1375,7 +1470,7 @@ local void check_match(s, start, match, length) } #else # define check_match(s, start, match, length) -#endif /* DEBUG */ +#endif /* ZLIB_DEBUG */ /* =========================================================================== * Fill the window when the lookahead becomes insufficient. @@ -1390,8 +1485,7 @@ local void check_match(s, start, match, length) local void fill_window(s) deflate_state *s; { - register unsigned n, m; - register Posf *p; + unsigned n; unsigned more; /* Amount of free space at the end of the window. */ uInt wsize = s->w_size; @@ -1418,35 +1512,13 @@ local void fill_window(s) */ if (s->strstart >= wsize+MAX_DIST(s)) { - zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + zmemcpy(s->window, s->window+wsize, (unsigned)wsize - more); s->match_start -= wsize; s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ s->block_start -= (long) wsize; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - n = s->hash_size; - p = &s->head[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - } while (--n); - - n = wsize; -#ifndef FASTEST - p = &s->prev[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); -#endif + if (s->insert > s->strstart) + s->insert = s->strstart; + slide_hash(s); more += wsize; } if (s->strm->avail_in == 0) break; @@ -1552,70 +1624,205 @@ local void fill_window(s) if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ } +/* Maximum stored block length in deflate format (not including header). */ +#define MAX_STORED 65535 + +/* Minimum of a and b. */ +#define MIN(a, b) ((a) > (b) ? (b) : (a)) + /* =========================================================================== * Copy without compression as much as possible from the input stream, return * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. + * + * In case deflateParams() is used to later switch to a non-zero compression + * level, s->matches (otherwise unused when storing) keeps track of the number + * of hash table slides to perform. If s->matches is 1, then one hash table + * slide will be done when switching. If s->matches is 2, the maximum value + * allowed here, then the hash table will be cleared, since two or more slides + * is the same as a clear. + * + * deflate_stored() is written to minimize the number of times an input byte is + * copied. It is most efficient with large input and output buffers, which + * maximizes the opportunites to have a single copy from next_in to next_out. */ local block_state deflate_stored(s, flush) deflate_state *s; int flush; { - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: + /* Smallest worthy block size when not flushing or finishing. By default + * this is 32K. This can be as small as 507 bytes for memLevel == 1. For + * large input and output buffers, the stored block size will be larger. */ - ulg max_block_size = 0xffff; - ulg max_start; + unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size); - if (max_block_size > s->pending_buf_size - 5) { - max_block_size = s->pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (;;) { - /* Fill the window as much as possible: */ - if (s->lookahead <= 1) { - - Assert(s->strstart < s->w_size+MAX_DIST(s) || - s->block_start >= (long)s->w_size, "slide too late"); - - fill_window(s); - if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; - - if (s->lookahead == 0) break; /* flush the current block */ - } - Assert(s->block_start >= 0L, "block gone"); - - s->strstart += s->lookahead; - s->lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - max_start = s->block_start + max_block_size; - if (s->strstart == 0 || (ulg)s->strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s->lookahead = (uInt)(s->strstart - max_start); - s->strstart = (uInt)max_start; - FLUSH_BLOCK(s, 0); - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: + /* Copy as many min_block or larger stored blocks directly to next_out as + * possible. If flushing, copy the remaining available input to next_out as + * stored blocks, if there is enough space. + */ + unsigned len, left, have, last = 0; + unsigned used = s->strm->avail_in; + do { + /* Set len to the maximum size block that we can copy directly with the + * available input data and output space. Set left to how much of that + * would be copied from what's left in the window. */ - if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { - FLUSH_BLOCK(s, 0); + len = MAX_STORED; /* maximum deflate stored block length */ + have = (s->bi_valid + 42) >> 3; /* number of header bytes */ + if (s->strm->avail_out < have) /* need room for header */ + break; + /* maximum stored block length that will fit in avail_out: */ + have = s->strm->avail_out - have; + left = s->strstart - s->block_start; /* bytes left in window */ + if (len > (ulg)left + s->strm->avail_in) + len = left + s->strm->avail_in; /* limit len to the input */ + if (len > have) + len = have; /* limit len to the output */ + + /* If the stored block would be less than min_block in length, or if + * unable to copy all of the available input when flushing, then try + * copying to the window and the pending buffer instead. Also don't + * write an empty block when flushing -- deflate() does that. + */ + if (len < min_block && ((len == 0 && flush != Z_FINISH) || + flush == Z_NO_FLUSH || + len != left + s->strm->avail_in)) + break; + + /* Make a dummy stored block in pending to get the header bytes, + * including any pending bits. This also updates the debugging counts. + */ + last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0; + _tr_stored_block(s, (char *)0, 0L, last); + + /* Replace the lengths in the dummy stored block with len. */ + s->pending_buf[s->pending - 4] = len; + s->pending_buf[s->pending - 3] = len >> 8; + s->pending_buf[s->pending - 2] = ~len; + s->pending_buf[s->pending - 1] = ~len >> 8; + + /* Write the stored block header bytes. */ + flush_pending(s->strm); + +#ifdef ZLIB_DEBUG + /* Update debugging counts for the data about to be copied. */ + s->compressed_len += len << 3; + s->bits_sent += len << 3; +#endif + + /* Copy uncompressed bytes from the window to next_out. */ + if (left) { + if (left > len) + left = len; + zmemcpy(s->strm->next_out, s->window + s->block_start, left); + s->strm->next_out += left; + s->strm->avail_out -= left; + s->strm->total_out += left; + s->block_start += left; + len -= left; } + + /* Copy uncompressed bytes directly from next_in to next_out, updating + * the check value. + */ + if (len) { + read_buf(s->strm, s->strm->next_out, len); + s->strm->next_out += len; + s->strm->avail_out -= len; + s->strm->total_out += len; + } + } while (last == 0); + + /* Update the sliding window with the last s->w_size bytes of the copied + * data, or append all of the copied data to the existing window if less + * than s->w_size bytes were copied. Also update the number of bytes to + * insert in the hash tables, in the event that deflateParams() switches to + * a non-zero compression level. + */ + used -= s->strm->avail_in; /* number of input bytes directly copied */ + if (used) { + /* If any input was used, then no unused input remains in the window, + * therefore s->block_start == s->strstart. + */ + if (used >= s->w_size) { /* supplant the previous history */ + s->matches = 2; /* clear hash */ + zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size); + s->strstart = s->w_size; + s->insert = s->strstart; + } + else { + if (s->window_size - s->strstart <= used) { + /* Slide the window down. */ + s->strstart -= s->w_size; + zmemcpy(s->window, s->window + s->w_size, s->strstart); + if (s->matches < 2) + s->matches++; /* add a pending slide_hash() */ + if (s->insert > s->strstart) + s->insert = s->strstart; + } + zmemcpy(s->window + s->strstart, s->strm->next_in - used, used); + s->strstart += used; + s->insert += MIN(used, s->w_size - s->insert); + } + s->block_start = s->strstart; } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); + if (s->high_water < s->strstart) + s->high_water = s->strstart; + + /* If the last block was written to next_out, then done. */ + if (last) return finish_done; + + /* If flushing and all input has been consumed, then done. */ + if (flush != Z_NO_FLUSH && flush != Z_FINISH && + s->strm->avail_in == 0 && (long)s->strstart == s->block_start) + return block_done; + + /* Fill the window with any remaining input. */ + have = s->window_size - s->strstart; + if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) { + /* Slide the window down. */ + s->block_start -= s->w_size; + s->strstart -= s->w_size; + zmemcpy(s->window, s->window + s->w_size, s->strstart); + if (s->matches < 2) + s->matches++; /* add a pending slide_hash() */ + have += s->w_size; /* more space now */ + if (s->insert > s->strstart) + s->insert = s->strstart; } - if ((long)s->strstart > s->block_start) - FLUSH_BLOCK(s, 0); - return block_done; + if (have > s->strm->avail_in) + have = s->strm->avail_in; + if (have) { + read_buf(s->strm, s->window + s->strstart, have); + s->strstart += have; + s->insert += MIN(have, s->w_size - s->insert); + } + if (s->high_water < s->strstart) + s->high_water = s->strstart; + + /* There was not enough avail_out to write a complete worthy or flushed + * stored block to next_out. Write a stored block to pending instead, if we + * have enough input for a worthy block, or if flushing and there is enough + * room for the remaining input as a stored block in the pending buffer. + */ + have = (s->bi_valid + 42) >> 3; /* number of header bytes */ + /* maximum stored block length that will fit in pending: */ + have = MIN(s->pending_buf_size - have, MAX_STORED); + min_block = MIN(have, s->w_size); + left = s->strstart - s->block_start; + if (left >= min_block || + ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH && + s->strm->avail_in == 0 && left <= have)) { + len = MIN(left, have); + last = flush == Z_FINISH && s->strm->avail_in == 0 && + len == left ? 1 : 0; + _tr_stored_block(s, (charf *)s->window + s->block_start, len, last); + s->block_start += len; + flush_pending(s->strm); + } + + /* We've done all we can with the available input and output. */ + return last ? finish_started : need_more; } /* =========================================================================== @@ -1892,7 +2099,7 @@ local block_state deflate_rle(s, flush) prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && scan < strend); - s->match_length = MAX_MATCH - (int)(strend - scan); + s->match_length = MAX_MATCH - (uInt)(strend - scan); if (s->match_length > s->lookahead) s->match_length = s->lookahead; } diff --git a/contrib/zlib/deflate.h b/contrib/zlib/deflate.h index ce0299edd..23ecdd312 100644 --- a/contrib/zlib/deflate.h +++ b/contrib/zlib/deflate.h @@ -1,5 +1,5 @@ /* deflate.h -- internal compression state - * Copyright (C) 1995-2012 Jean-loup Gailly + * Copyright (C) 1995-2016 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -51,13 +51,16 @@ #define Buf_size 16 /* size of bit buffer in bi_buf */ -#define INIT_STATE 42 -#define EXTRA_STATE 69 -#define NAME_STATE 73 -#define COMMENT_STATE 91 -#define HCRC_STATE 103 -#define BUSY_STATE 113 -#define FINISH_STATE 666 +#define INIT_STATE 42 /* zlib header -> BUSY_STATE */ +#ifdef GZIP +# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */ +#endif +#define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */ +#define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */ +#define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */ +#define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */ +#define BUSY_STATE 113 /* deflate -> FINISH_STATE */ +#define FINISH_STATE 666 /* stream complete */ /* Stream status */ @@ -83,7 +86,7 @@ typedef struct static_tree_desc_s static_tree_desc; typedef struct tree_desc_s { ct_data *dyn_tree; /* the dynamic tree */ int max_code; /* largest code with non zero frequency */ - static_tree_desc *stat_desc; /* the corresponding static tree */ + const static_tree_desc *stat_desc; /* the corresponding static tree */ } FAR tree_desc; typedef ush Pos; @@ -100,10 +103,10 @@ typedef struct internal_state { Bytef *pending_buf; /* output still pending */ ulg pending_buf_size; /* size of pending_buf */ Bytef *pending_out; /* next pending byte to output to the stream */ - uInt pending; /* nb of bytes in the pending buffer */ + ulg pending; /* nb of bytes in the pending buffer */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ gz_headerp gzhead; /* gzip header information to write */ - uInt gzindex; /* where in extra, name, or comment */ + ulg gzindex; /* where in extra, name, or comment */ Byte method; /* can only be DEFLATED */ int last_flush; /* value of flush param for previous deflate call */ @@ -249,7 +252,7 @@ typedef struct internal_state { uInt matches; /* number of string matches in current block */ uInt insert; /* bytes at end of window left to insert */ -#ifdef DEBUG +#ifdef ZLIB_DEBUG ulg compressed_len; /* total bit length of compressed file mod 2^32 */ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ #endif @@ -275,7 +278,7 @@ typedef struct internal_state { /* Output a byte on the stream. * IN assertion: there is enough room in pending_buf. */ -#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} +#define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);} #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) @@ -309,7 +312,7 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, * used. */ -#ifndef DEBUG +#ifndef ZLIB_DEBUG /* Inline versions of _tr_tally for speed: */ #if defined(GEN_TREES_H) || !defined(STDC) @@ -328,8 +331,8 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, flush = (s->last_lit == s->lit_bufsize-1); \ } # define _tr_tally_dist(s, distance, length, flush) \ - { uch len = (length); \ - ush dist = (distance); \ + { uch len = (uch)(length); \ + ush dist = (ush)(distance); \ s->d_buf[s->last_lit] = dist; \ s->l_buf[s->last_lit++] = len; \ dist--; \ diff --git a/contrib/zlib/gzguts.h b/contrib/zlib/gzguts.h index d87659d03..6378d468a 100644 --- a/contrib/zlib/gzguts.h +++ b/contrib/zlib/gzguts.h @@ -1,5 +1,5 @@ /* gzguts.h -- zlib internal header definitions for gz* operations - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler + * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -25,6 +25,10 @@ # include # include #endif + +#ifndef _POSIX_SOURCE +# define _POSIX_SOURCE +#endif #include #ifdef _WIN32 @@ -35,6 +39,10 @@ # include #endif +#if defined(_WIN32) +# define WIDECHAR +#endif + #ifdef WINAPI_FAMILY # define open _open # define read _read @@ -95,18 +103,19 @@ # endif #endif -/* unlike snprintf (which is required in C99, yet still not supported by - Microsoft more than a decade later!), _snprintf does not guarantee null - termination of the result -- however this is only used in gzlib.c where +/* unlike snprintf (which is required in C99), _snprintf does not guarantee + null termination of the result -- however this is only used in gzlib.c where the result is assured to fit in the space provided */ -#ifdef _MSC_VER +#if defined(_MSC_VER) && _MSC_VER < 1900 # define snprintf _snprintf #endif #ifndef local # define local static #endif -/* compile with -Dlocal if your debugger can't find static symbols */ +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ /* gz* functions always use library allocation functions */ #ifndef STDC @@ -170,7 +179,7 @@ typedef struct { char *path; /* path or fd for error messages */ unsigned size; /* buffer size, zero if not allocated yet */ unsigned want; /* requested buffer size, default is GZBUFSIZE */ - unsigned char *in; /* input buffer */ + unsigned char *in; /* input buffer (double-sized when writing) */ unsigned char *out; /* output buffer (double-sized when reading) */ int direct; /* 0 if processing gzip, 1 if transparent */ /* just for reading */ diff --git a/contrib/zlib/gzlib.c b/contrib/zlib/gzlib.c index fae202ef8..4838bf047 100644 --- a/contrib/zlib/gzlib.c +++ b/contrib/zlib/gzlib.c @@ -1,5 +1,5 @@ /* gzlib.c -- zlib functions common to reading and writing gzip files - * Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler + * Copyright (C) 2004-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -94,7 +94,7 @@ local gzFile gz_open(path, fd, mode) const char *mode; { gz_statep state; - size_t len; + z_size_t len; int oflag; #ifdef O_CLOEXEC int cloexec = 0; @@ -188,10 +188,10 @@ local gzFile gz_open(path, fd, mode) } /* save the path name for error messages */ -#ifdef _WIN32 +#ifdef WIDECHAR if (fd == -2) { len = wcstombs(NULL, path, 0); - if (len == (size_t)-1) + if (len == (z_size_t)-1) len = 0; } else @@ -202,7 +202,7 @@ local gzFile gz_open(path, fd, mode) free(state); return NULL; } -#ifdef _WIN32 +#ifdef WIDECHAR if (fd == -2) if (len) wcstombs(state->path, path, len + 1); @@ -211,7 +211,7 @@ local gzFile gz_open(path, fd, mode) else #endif #if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(state->path, len + 1, "%s", (const char *)path); + (void)snprintf(state->path, len + 1, "%s", (const char *)path); #else strcpy(state->path, path); #endif @@ -239,7 +239,7 @@ local gzFile gz_open(path, fd, mode) /* open the file with the appropriate flags (or just use fd) */ state->fd = fd > -1 ? fd : ( -#ifdef _WIN32 +#ifdef WIDECHAR fd == -2 ? _wopen(path, oflag, 0666) : #endif open((const char *)path, oflag, 0666)); @@ -248,8 +248,10 @@ local gzFile gz_open(path, fd, mode) free(state); return NULL; } - if (state->mode == GZ_APPEND) + if (state->mode == GZ_APPEND) { + LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */ state->mode = GZ_WRITE; /* simplify later checks */ + } /* save the current position for rewinding (only if reading) */ if (state->mode == GZ_READ) { @@ -291,7 +293,7 @@ gzFile ZEXPORT gzdopen(fd, mode) if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) return NULL; #if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(path, 7 + 3 * sizeof(int), "", fd); /* for debugging */ + (void)snprintf(path, 7 + 3 * sizeof(int), "", fd); #else sprintf(path, "", fd); /* for debugging */ #endif @@ -301,7 +303,7 @@ gzFile ZEXPORT gzdopen(fd, mode) } /* -- see zlib.h -- */ -#ifdef _WIN32 +#ifdef WIDECHAR gzFile ZEXPORT gzopen_w(path, mode) const wchar_t *path; const char *mode; @@ -329,6 +331,8 @@ int ZEXPORT gzbuffer(file, size) return -1; /* check and set requested size */ + if ((size << 1) < size) + return -1; /* need to be able to double it */ if (size < 2) size = 2; /* need two bytes to check magic header */ state->want = size; @@ -393,7 +397,7 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence) /* if within raw area while reading, just go there */ if (state->mode == GZ_READ && state->how == COPY && state->x.pos + offset >= 0) { - ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); + ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR); if (ret == -1) return -1; state->x.have = 0; @@ -604,14 +608,13 @@ void ZLIB_INTERNAL gz_error(state, err, msg) return; } #if !defined(NO_snprintf) && !defined(NO_vsnprintf) - snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, - "%s%s%s", state->path, ": ", msg); + (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, + "%s%s%s", state->path, ": ", msg); #else strcpy(state->msg, state->path); strcat(state->msg, ": "); strcat(state->msg, msg); #endif - return; } #ifndef INT_MAX diff --git a/contrib/zlib/gzread.c b/contrib/zlib/gzread.c index bf4538eb2..f94abfed3 100644 --- a/contrib/zlib/gzread.c +++ b/contrib/zlib/gzread.c @@ -1,5 +1,5 @@ /* gzread.c -- zlib functions for reading gzip files - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler + * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -12,6 +12,7 @@ local int gz_look OF((gz_statep)); local int gz_decomp OF((gz_statep)); local int gz_fetch OF((gz_statep)); local int gz_skip OF((gz_statep, z_off64_t)); +local z_size_t gz_read OF((gz_statep, voidp, z_size_t)); /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from state->fd, and update state->eof, state->err, and state->msg as appropriate. @@ -24,13 +25,17 @@ local int gz_load(state, buf, len, have) unsigned *have; { int ret; + unsigned get, max = ((unsigned)-1 >> 2) + 1; *have = 0; do { - ret = read(state->fd, buf + *have, len - *have); + get = len - *have; + if (get > max) + get = max; + ret = read(state->fd, buf + *have, get); if (ret <= 0) break; - *have += ret; + *have += (unsigned)ret; } while (*have < len); if (ret < 0) { gz_error(state, Z_ERRNO, zstrerror()); @@ -94,10 +99,8 @@ local int gz_look(state) state->in = (unsigned char *)malloc(state->want); state->out = (unsigned char *)malloc(state->want << 1); if (state->in == NULL || state->out == NULL) { - if (state->out != NULL) - free(state->out); - if (state->in != NULL) - free(state->in); + free(state->out); + free(state->in); gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } @@ -284,33 +287,17 @@ local int gz_skip(state, len) return 0; } -/* -- see zlib.h -- */ -int ZEXPORT gzread(file, buf, len) - gzFile file; - voidp buf; - unsigned len; -{ - unsigned got, n; +/* Read len bytes into buf from file, or less than len up to the end of the + input. Return the number of bytes read. If zero is returned, either the + end of file was reached, or there was an error. state->err must be + consulted in that case to determine which. */ +local z_size_t gz_read(state, buf, len) gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* since an int is returned, make sure len fits in one, otherwise return - with an error (this avoids the flaw in the interface) */ - if ((int)len < 0) { - gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); - return -1; - } + voidp buf; + z_size_t len; +{ + z_size_t got; + unsigned n; /* if len is zero, avoid unnecessary operations */ if (len == 0) @@ -320,32 +307,38 @@ int ZEXPORT gzread(file, buf, len) if (state->seek) { state->seek = 0; if (gz_skip(state, state->skip) == -1) - return -1; + return 0; } /* get len bytes to buf, or less than len if at the end */ got = 0; do { + /* set n to the maximum amount of len that fits in an unsigned int */ + n = (unsigned)-1; + if (n > len) + n = (unsigned)len; + /* first just try copying data from the output buffer */ if (state->x.have) { - n = state->x.have > len ? len : state->x.have; + if (state->x.have < n) + n = state->x.have; memcpy(buf, state->x.next, n); state->x.next += n; state->x.have -= n; } /* output buffer empty -- return if we're at the end of the input */ - else if (state->eof && strm->avail_in == 0) { + else if (state->eof && state->strm.avail_in == 0) { state->past = 1; /* tried to read past end */ break; } /* need output data -- for small len or new stream load up our output buffer */ - else if (state->how == LOOK || len < (state->size << 1)) { + else if (state->how == LOOK || n < (state->size << 1)) { /* get more output, looking for header if required */ if (gz_fetch(state) == -1) - return -1; + return 0; continue; /* no progress yet -- go back to copy above */ /* the copy above assures that we will leave with space in the output buffer, allowing at least one gzungetc() to succeed */ @@ -353,16 +346,16 @@ int ZEXPORT gzread(file, buf, len) /* large len -- read directly into user buffer */ else if (state->how == COPY) { /* read directly */ - if (gz_load(state, (unsigned char *)buf, len, &n) == -1) - return -1; + if (gz_load(state, (unsigned char *)buf, n, &n) == -1) + return 0; } /* large len -- decompress directly into user buffer */ else { /* state->how == GZIP */ - strm->avail_out = len; - strm->next_out = (unsigned char *)buf; + state->strm.avail_out = n; + state->strm.next_out = (unsigned char *)buf; if (gz_decomp(state) == -1) - return -1; + return 0; n = state->x.have; state->x.have = 0; } @@ -374,8 +367,75 @@ int ZEXPORT gzread(file, buf, len) state->x.pos += n; } while (len); - /* return number of bytes read into user buffer (will fit in int) */ - return (int)got; + /* return number of bytes read into user buffer */ + return got; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzread(file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return -1; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids a flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in an int"); + return -1; + } + + /* read len or fewer bytes to buf */ + len = (unsigned)gz_read(state, buf, len); + + /* check for an error */ + if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR) + return -1; + + /* return the number of bytes read (this is assured to fit in an int) */ + return (int)len; +} + +/* -- see zlib.h -- */ +z_size_t ZEXPORT gzfread(buf, size, nitems, file) + voidp buf; + z_size_t size; + z_size_t nitems; + gzFile file; +{ + z_size_t len; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return 0; + + /* compute bytes to read -- error on overflow */ + len = nitems * size; + if (size && len / size != nitems) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); + return 0; + } + + /* read len or fewer bytes to buf, return the number of full items read */ + return len ? gz_read(state, buf, len) / size : 0; } /* -- see zlib.h -- */ @@ -387,7 +447,6 @@ int ZEXPORT gzread(file, buf, len) int ZEXPORT gzgetc(file) gzFile file; { - int ret; unsigned char buf[1]; gz_statep state; @@ -408,9 +467,8 @@ int ZEXPORT gzgetc(file) return *(state->x.next)++; } - /* nothing there -- try gzread() */ - ret = gzread(file, buf, 1); - return ret < 1 ? -1 : buf[0]; + /* nothing there -- try gz_read() */ + return gz_read(state, buf, 1) < 1 ? -1 : buf[0]; } int ZEXPORT gzgetc_(file) @@ -451,7 +509,7 @@ int ZEXPORT gzungetc(c, file) if (state->x.have == 0) { state->x.have = 1; state->x.next = state->out + (state->size << 1) - 1; - state->x.next[0] = c; + state->x.next[0] = (unsigned char)c; state->x.pos--; state->past = 0; return c; @@ -473,7 +531,7 @@ int ZEXPORT gzungetc(c, file) } state->x.have++; state->x.next--; - state->x.next[0] = c; + state->x.next[0] = (unsigned char)c; state->x.pos--; state->past = 0; return c; diff --git a/contrib/zlib/gzwrite.c b/contrib/zlib/gzwrite.c index 3ed161f44..3560193b8 100644 --- a/contrib/zlib/gzwrite.c +++ b/contrib/zlib/gzwrite.c @@ -1,5 +1,5 @@ /* gzwrite.c -- zlib functions for writing gzip files - * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler + * Copyright (C) 2004-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,17 +9,19 @@ local int gz_init OF((gz_statep)); local int gz_comp OF((gz_statep, int)); local int gz_zero OF((gz_statep, z_off64_t)); +local z_size_t gz_write OF((gz_statep, voidpc, z_size_t)); /* Initialize state for writing a gzip file. Mark initialization by setting - state->size to non-zero. Return -1 on failure or 0 on success. */ + state->size to non-zero. Return -1 on a memory allocation failure, or 0 on + success. */ local int gz_init(state) gz_statep state; { int ret; z_streamp strm = &(state->strm); - /* allocate input buffer */ - state->in = (unsigned char *)malloc(state->want); + /* allocate input buffer (double size for gzprintf) */ + state->in = (unsigned char *)malloc(state->want << 1); if (state->in == NULL) { gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; @@ -47,6 +49,7 @@ local int gz_init(state) gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } + strm->next_in = NULL; } /* mark state as initialized */ @@ -62,17 +65,17 @@ local int gz_init(state) } /* Compress whatever is at avail_in and next_in and write to the output file. - Return -1 if there is an error writing to the output file, otherwise 0. - flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, - then the deflate() state is reset to start a new gzip stream. If gz->direct - is true, then simply write to the output file without compressing, and - ignore flush. */ + Return -1 if there is an error writing to the output file or if gz_init() + fails to allocate memory, otherwise 0. flush is assumed to be a valid + deflate() flush value. If flush is Z_FINISH, then the deflate() state is + reset to start a new gzip stream. If gz->direct is true, then simply write + to the output file without compressing, and ignore flush. */ local int gz_comp(state, flush) gz_statep state; int flush; { - int ret, got; - unsigned have; + int ret, writ; + unsigned have, put, max = ((unsigned)-1 >> 2) + 1; z_streamp strm = &(state->strm); /* allocate memory if this is the first time through */ @@ -81,12 +84,16 @@ local int gz_comp(state, flush) /* write directly if requested */ if (state->direct) { - got = write(state->fd, strm->next_in, strm->avail_in); - if (got < 0 || (unsigned)got != strm->avail_in) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; + while (strm->avail_in) { + put = strm->avail_in > max ? max : strm->avail_in; + writ = write(state->fd, strm->next_in, put); + if (writ < 0) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + strm->avail_in -= (unsigned)writ; + strm->next_in += writ; } - strm->avail_in = 0; return 0; } @@ -97,17 +104,21 @@ local int gz_comp(state, flush) doing Z_FINISH then don't write until we get to Z_STREAM_END */ if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && (flush != Z_FINISH || ret == Z_STREAM_END))) { - have = (unsigned)(strm->next_out - state->x.next); - if (have && ((got = write(state->fd, state->x.next, have)) < 0 || - (unsigned)got != have)) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; + while (strm->next_out > state->x.next) { + put = strm->next_out - state->x.next > (int)max ? max : + (unsigned)(strm->next_out - state->x.next); + writ = write(state->fd, state->x.next, put); + if (writ < 0) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + state->x.next += writ; } if (strm->avail_out == 0) { strm->avail_out = state->size; strm->next_out = state->out; + state->x.next = state->out; } - state->x.next = strm->next_out; } /* compress */ @@ -129,7 +140,8 @@ local int gz_comp(state, flush) return 0; } -/* Compress len zeros to output. Return -1 on error, 0 on success. */ +/* Compress len zeros to output. Return -1 on a write error or memory + allocation failure by gz_comp(), or 0 on success. */ local int gz_zero(state, len) gz_statep state; z_off64_t len; @@ -161,32 +173,14 @@ local int gz_zero(state, len) return 0; } -/* -- see zlib.h -- */ -int ZEXPORT gzwrite(file, buf, len) - gzFile file; - voidpc buf; - unsigned len; -{ - unsigned put = len; +/* Write len bytes from buf to file. Return the number of bytes written. If + the returned value is less than len, then there was an error. */ +local z_size_t gz_write(state, buf, len) gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return 0; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; - - /* since an int is returned, make sure len fits in one, otherwise return - with an error (this avoids the flaw in the interface) */ - if ((int)len < 0) { - gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); - return 0; - } + voidpc buf; + z_size_t len; +{ + z_size_t put = len; /* if len is zero, avoid unnecessary operations */ if (len == 0) @@ -209,14 +203,15 @@ int ZEXPORT gzwrite(file, buf, len) do { unsigned have, copy; - if (strm->avail_in == 0) - strm->next_in = state->in; - have = (unsigned)((strm->next_in + strm->avail_in) - state->in); + if (state->strm.avail_in == 0) + state->strm.next_in = state->in; + have = (unsigned)((state->strm.next_in + state->strm.avail_in) - + state->in); copy = state->size - have; if (copy > len) - copy = len; + copy = (unsigned)len; memcpy(state->in + have, buf, copy); - strm->avail_in += copy; + state->strm.avail_in += copy; state->x.pos += copy; buf = (const char *)buf + copy; len -= copy; @@ -226,19 +221,83 @@ int ZEXPORT gzwrite(file, buf, len) } else { /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return 0; /* directly compress user buffer to file */ - strm->avail_in = len; - strm->next_in = (z_const Bytef *)buf; - state->x.pos += len; - if (gz_comp(state, Z_NO_FLUSH) == -1) - return 0; + state->strm.next_in = (z_const Bytef *)buf; + do { + unsigned n = (unsigned)-1; + if (n > len) + n = (unsigned)len; + state->strm.avail_in = n; + state->x.pos += n; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + len -= n; + } while (len); } - /* input was all buffered or compressed (put will fit in int) */ - return (int)put; + /* input was all buffered or compressed */ + return put; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzwrite(file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids a flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); + return 0; + } + + /* write len bytes from buf (the return value will fit in an int) */ + return (int)gz_write(state, buf, len); +} + +/* -- see zlib.h -- */ +z_size_t ZEXPORT gzfwrite(buf, size, nitems, file) + voidpc buf; + z_size_t size; + z_size_t nitems; + gzFile file; +{ + z_size_t len; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* compute bytes to read -- error on overflow */ + len = nitems * size; + if (size && len / size != nitems) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); + return 0; + } + + /* write len bytes to buf, return the number of full items written */ + return len ? gz_write(state, buf, len) / size : 0; } /* -- see zlib.h -- */ @@ -275,7 +334,7 @@ int ZEXPORT gzputc(file, c) strm->next_in = state->in; have = (unsigned)((strm->next_in + strm->avail_in) - state->in); if (have < state->size) { - state->in[have] = c; + state->in[have] = (unsigned char)c; strm->avail_in++; state->x.pos++; return c & 0xff; @@ -283,8 +342,8 @@ int ZEXPORT gzputc(file, c) } /* no room in buffer or not initialized, use gz_write() */ - buf[0] = c; - if (gzwrite(file, buf, 1) != 1) + buf[0] = (unsigned char)c; + if (gz_write(state, buf, 1) != 1) return -1; return c & 0xff; } @@ -294,13 +353,26 @@ int ZEXPORT gzputs(file, str) gzFile file; const char *str; { - int ret; - unsigned len; + z_size_t len, put; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return -1; /* write string */ - len = (unsigned)strlen(str); - ret = gzwrite(file, str, len); - return ret == 0 && len != 0 ? -1 : ret; + len = strlen(str); + if ((int)len < 0 || (unsigned)len != len) { + gz_error(state, Z_STREAM_ERROR, "string length does not fit in int"); + return -1; + } + put = gz_write(state, str, len); + return put < len ? -1 : (int)len; } #if defined(STDC) || defined(Z_HAVE_STDARG_H) @@ -309,63 +381,73 @@ int ZEXPORT gzputs(file, str) /* -- see zlib.h -- */ int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) { - int size, len; + int len; + unsigned left; + char *next; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) - return -1; + return Z_STREAM_ERROR; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; + return Z_STREAM_ERROR; /* make sure we have some buffer space */ if (state->size == 0 && gz_init(state) == -1) - return 0; + return state->err; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) - return 0; + return state->err; } - /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - - /* do the printf() into the input buffer, put length in len */ - size = (int)(state->size); - state->in[size - 1] = 0; + /* do the printf() into the input buffer, put length in len -- the input + buffer is double-sized just for this function, so there is guaranteed to + be state->size bytes available after the current contents */ + if (strm->avail_in == 0) + strm->next_in = state->in; + next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in); + next[state->size - 1] = 0; #ifdef NO_vsnprintf # ifdef HAS_vsprintf_void - (void)vsprintf((char *)(state->in), format, va); - for (len = 0; len < size; len++) - if (state->in[len] == 0) break; + (void)vsprintf(next, format, va); + for (len = 0; len < state->size; len++) + if (next[len] == 0) break; # else - len = vsprintf((char *)(state->in), format, va); + len = vsprintf(next, format, va); # endif #else # ifdef HAS_vsnprintf_void - (void)vsnprintf((char *)(state->in), size, format, va); - len = strlen((char *)(state->in)); + (void)vsnprintf(next, state->size, format, va); + len = strlen(next); # else - len = vsnprintf((char *)(state->in), size, format, va); + len = vsnprintf(next, state->size, format, va); # endif #endif /* check that printf() results fit in buffer */ - if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0) return 0; - /* update buffer and position, defer compression until needed */ - strm->avail_in = (unsigned)len; - strm->next_in = state->in; + /* update buffer and position, compress first half if past that */ + strm->avail_in += (unsigned)len; state->x.pos += len; + if (strm->avail_in >= state->size) { + left = strm->avail_in - state->size; + strm->avail_in = state->size; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return state->err; + memcpy(state->in, state->in + state->size, left); + strm->next_in = state->in; + strm->avail_in = left; + } return len; } @@ -390,73 +472,82 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; { - int size, len; + unsigned len, left; + char *next; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) - return -1; + return Z_STREAM_ERROR; state = (gz_statep)file; strm = &(state->strm); /* check that can really pass pointer in ints */ if (sizeof(int) != sizeof(void *)) - return 0; + return Z_STREAM_ERROR; /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; + return Z_STREAM_ERROR; /* make sure we have some buffer space */ if (state->size == 0 && gz_init(state) == -1) - return 0; + return state->error; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) - return 0; + return state->error; } - /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - - /* do the printf() into the input buffer, put length in len */ - size = (int)(state->size); - state->in[size - 1] = 0; + /* do the printf() into the input buffer, put length in len -- the input + buffer is double-sized just for this function, so there is guaranteed to + be state->size bytes available after the current contents */ + if (strm->avail_in == 0) + strm->next_in = state->in; + next = (char *)(strm->next_in + strm->avail_in); + next[state->size - 1] = 0; #ifdef NO_snprintf # ifdef HAS_sprintf_void - sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, + a13, a14, a15, a16, a17, a18, a19, a20); for (len = 0; len < size; len++) - if (state->in[len] == 0) break; + if (next[len] == 0) + break; # else - len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, + a12, a13, a14, a15, a16, a17, a18, a19, a20); # endif #else # ifdef HAS_snprintf_void - snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); - len = strlen((char *)(state->in)); + snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(next); # else - len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, - a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, - a19, a20); + len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); # endif #endif /* check that printf() results fit in buffer */ - if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + if (len == 0 || len >= state->size || next[state->size - 1] != 0) return 0; - /* update buffer and position, defer compression until needed */ - strm->avail_in = (unsigned)len; - strm->next_in = state->in; + /* update buffer and position, compress first half if past that */ + strm->avail_in += len; state->x.pos += len; - return len; + if (strm->avail_in >= state->size) { + left = strm->avail_in - state->size; + strm->avail_in = state->size; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return state->err; + memcpy(state->in, state->in + state->size, left); + strm->next_in = state->in; + strm->avail_in = left; + } + return (int)len; } #endif @@ -470,7 +561,7 @@ int ZEXPORT gzflush(file, flush) /* get internal structure */ if (file == NULL) - return -1; + return Z_STREAM_ERROR; state = (gz_statep)file; /* check that we're writing and that there's no error */ @@ -485,11 +576,11 @@ int ZEXPORT gzflush(file, flush) if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) - return -1; + return state->err; } /* compress remaining data with requested flush */ - gz_comp(state, flush); + (void)gz_comp(state, flush); return state->err; } @@ -520,13 +611,13 @@ int ZEXPORT gzsetparams(file, level, strategy) if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) - return -1; + return state->err; } /* change compression parameters for subsequent input */ if (state->size) { /* flush previous input with previous parameters before changing */ - if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) + if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1) return state->err; deflateParams(strm, level, strategy); } diff --git a/contrib/zlib/infback.c b/contrib/zlib/infback.c index f3833c2e4..59679ecbf 100644 --- a/contrib/zlib/infback.c +++ b/contrib/zlib/infback.c @@ -1,5 +1,5 @@ /* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2011 Mark Adler + * Copyright (C) 1995-2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -61,7 +61,7 @@ int stream_size; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; state->dmax = 32768U; - state->wbits = windowBits; + state->wbits = (uInt)windowBits; state->wsize = 1U << windowBits; state->window = window; state->wnext = 0; diff --git a/contrib/zlib/inffast.c b/contrib/zlib/inffast.c index bda59ceb6..1fec7f363 100644 --- a/contrib/zlib/inffast.c +++ b/contrib/zlib/inffast.c @@ -1,5 +1,5 @@ /* inffast.c -- fast decoding - * Copyright (C) 1995-2008, 2010, 2013 Mark Adler + * Copyright (C) 1995-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -8,26 +8,9 @@ #include "inflate.h" #include "inffast.h" -#ifndef ASMINF - -/* Allow machine dependent optimization for post-increment or pre-increment. - Based on testing to date, - Pre-increment preferred for: - - PowerPC G3 (Adler) - - MIPS R5000 (Randers-Pehrson) - Post-increment preferred for: - - none - No measurable difference: - - Pentium III (Anderson) - - M68060 (Nikl) - */ -#ifdef POSTINC -# define OFF 0 -# define PUP(a) *(a)++ +#ifdef ASMINF +# pragma message("Assembler code may have bugs -- use at your own risk") #else -# define OFF 1 -# define PUP(a) *++(a) -#endif /* Decode literal, length, and distance codes and write out the resulting @@ -87,7 +70,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ code const FAR *dcode; /* local strm->distcode */ unsigned lmask; /* mask for first level of length codes */ unsigned dmask; /* mask for first level of distance codes */ - code here; /* retrieved table entry */ + code const *here; /* retrieved table entry */ unsigned op; /* code bits, operation, extra bits, or */ /* window position, window bytes to copy */ unsigned len; /* match length, unused bytes */ @@ -96,9 +79,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ /* copy state to local variables */ state = (struct inflate_state FAR *)strm->state; - in = strm->next_in - OFF; + in = strm->next_in; last = in + (strm->avail_in - 5); - out = strm->next_out - OFF; + out = strm->next_out; beg = out - (start - strm->avail_out); end = out + (strm->avail_out - 257); #ifdef INFLATE_STRICT @@ -119,29 +102,29 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ input data or output space */ do { if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } - here = lcode[hold & lmask]; + here = lcode + (hold & lmask); dolen: - op = (unsigned)(here.bits); + op = (unsigned)(here->bits); hold >>= op; bits -= op; - op = (unsigned)(here.op); + op = (unsigned)(here->op); if (op == 0) { /* literal */ - Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ? "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", here.val)); - PUP(out) = (unsigned char)(here.val); + "inflate: literal 0x%02x\n", here->val)); + *out++ = (unsigned char)(here->val); } else if (op & 16) { /* length base */ - len = (unsigned)(here.val); + len = (unsigned)(here->val); op &= 15; /* number of extra bits */ if (op) { if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } len += (unsigned)hold & ((1U << op) - 1); @@ -150,25 +133,25 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ } Tracevv((stderr, "inflate: length %u\n", len)); if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } - here = dcode[hold & dmask]; + here = dcode + (hold & dmask); dodist: - op = (unsigned)(here.bits); + op = (unsigned)(here->bits); hold >>= op; bits -= op; - op = (unsigned)(here.op); + op = (unsigned)(here->op); if (op & 16) { /* distance base */ - dist = (unsigned)(here.val); + dist = (unsigned)(here->val); op &= 15; /* number of extra bits */ if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } } @@ -196,30 +179,30 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR if (len <= op - whave) { do { - PUP(out) = 0; + *out++ = 0; } while (--len); continue; } len -= op - whave; do { - PUP(out) = 0; + *out++ = 0; } while (--op > whave); if (op == 0) { from = out - dist; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--len); continue; } #endif } - from = window - OFF; + from = window; if (wnext == 0) { /* very common case */ from += wsize - op; if (op < len) { /* some from window */ len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } @@ -230,14 +213,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ if (op < len) { /* some from end of window */ len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); - from = window - OFF; + from = window; if (wnext < len) { /* some from start of window */ op = wnext; len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } @@ -248,40 +231,40 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ if (op < len) { /* some from window */ len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } } while (len > 2) { - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; len -= 3; } if (len) { - PUP(out) = PUP(from); + *out++ = *from++; if (len > 1) - PUP(out) = PUP(from); + *out++ = *from++; } } else { from = out - dist; /* copy direct from output */ do { /* minimum length is three */ - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; len -= 3; } while (len > 2); if (len) { - PUP(out) = PUP(from); + *out++ = *from++; if (len > 1) - PUP(out) = PUP(from); + *out++ = *from++; } } } else if ((op & 64) == 0) { /* 2nd level distance code */ - here = dcode[here.val + (hold & ((1U << op) - 1))]; + here = dcode + here->val + (hold & ((1U << op) - 1)); goto dodist; } else { @@ -291,7 +274,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ } } else if ((op & 64) == 0) { /* 2nd level length code */ - here = lcode[here.val + (hold & ((1U << op) - 1))]; + here = lcode + here->val + (hold & ((1U << op) - 1)); goto dolen; } else if (op & 32) { /* end-of-block */ @@ -313,8 +296,8 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ hold &= (1U << bits) - 1; /* update state and return */ - strm->next_in = in + OFF; - strm->next_out = out + OFF; + strm->next_in = in; + strm->next_out = out; strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); strm->avail_out = (unsigned)(out < end ? 257 + (end - out) : 257 - (out - end)); diff --git a/contrib/zlib/inflate.c b/contrib/zlib/inflate.c index 870f89bb4..575fcdf82 100644 --- a/contrib/zlib/inflate.c +++ b/contrib/zlib/inflate.c @@ -1,5 +1,5 @@ /* inflate.c -- zlib decompression - * Copyright (C) 1995-2012 Mark Adler + * Copyright (C) 1995-2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -92,6 +92,7 @@ #endif /* function prototypes */ +local int inflateStateCheck OF((z_streamp strm)); local void fixedtables OF((struct inflate_state FAR *state)); local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, unsigned copy)); @@ -101,12 +102,26 @@ local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, unsigned len)); +local int inflateStateCheck(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + state = (struct inflate_state FAR *)strm->state; + if (state == Z_NULL || state->strm != strm || + state->mode < HEAD || state->mode > SYNC) + return 1; + return 0; +} + int ZEXPORT inflateResetKeep(strm) z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; strm->total_in = strm->total_out = state->total = 0; strm->msg = Z_NULL; @@ -131,7 +146,7 @@ z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; state->wsize = 0; state->whave = 0; @@ -147,7 +162,7 @@ int windowBits; struct inflate_state FAR *state; /* get the state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* extract wrap request from windowBits parameter */ @@ -156,7 +171,7 @@ int windowBits; windowBits = -windowBits; } else { - wrap = (windowBits >> 4) + 1; + wrap = (windowBits >> 4) + 5; #ifdef GUNZIP if (windowBits < 48) windowBits &= 15; @@ -210,7 +225,9 @@ int stream_size; if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; + state->strm = strm; state->window = Z_NULL; + state->mode = HEAD; /* to pass state test in inflateReset2() */ ret = inflateReset2(strm, windowBits); if (ret != Z_OK) { ZFREE(strm, state); @@ -234,17 +251,17 @@ int value; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (bits < 0) { state->hold = 0; state->bits = 0; return Z_OK; } - if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; value &= (1L << bits) - 1; - state->hold += value << state->bits; - state->bits += bits; + state->hold += (unsigned)value << state->bits; + state->bits += (uInt)bits; return Z_OK; } @@ -625,7 +642,7 @@ int flush; static const unsigned short order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + if (inflateStateCheck(strm) || strm->next_out == Z_NULL || (strm->next_in == Z_NULL && strm->avail_in != 0)) return Z_STREAM_ERROR; @@ -645,6 +662,8 @@ int flush; NEEDBITS(16); #ifdef GUNZIP if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + if (state->wbits == 0) + state->wbits = 15; state->check = crc32(0L, Z_NULL, 0); CRC2(state->check, hold); INITBITS(); @@ -672,7 +691,7 @@ int flush; len = BITS(4) + 8; if (state->wbits == 0) state->wbits = len; - else if (len > state->wbits) { + if (len > 15 || len > state->wbits) { strm->msg = (char *)"invalid window size"; state->mode = BAD; break; @@ -699,14 +718,16 @@ int flush; } if (state->head != Z_NULL) state->head->text = (int)((hold >> 8) & 1); - if (state->flags & 0x0200) CRC2(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); INITBITS(); state->mode = TIME; case TIME: NEEDBITS(32); if (state->head != Z_NULL) state->head->time = hold; - if (state->flags & 0x0200) CRC4(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC4(state->check, hold); INITBITS(); state->mode = OS; case OS: @@ -715,7 +736,8 @@ int flush; state->head->xflags = (int)(hold & 0xff); state->head->os = (int)(hold >> 8); } - if (state->flags & 0x0200) CRC2(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); INITBITS(); state->mode = EXLEN; case EXLEN: @@ -724,7 +746,8 @@ int flush; state->length = (unsigned)(hold); if (state->head != Z_NULL) state->head->extra_len = (unsigned)hold; - if (state->flags & 0x0200) CRC2(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); INITBITS(); } else if (state->head != Z_NULL) @@ -742,7 +765,7 @@ int flush; len + copy > state->head->extra_max ? state->head->extra_max - len : copy); } - if (state->flags & 0x0200) + if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; @@ -761,9 +784,9 @@ int flush; if (state->head != Z_NULL && state->head->name != Z_NULL && state->length < state->head->name_max) - state->head->name[state->length++] = len; + state->head->name[state->length++] = (Bytef)len; } while (len && copy < have); - if (state->flags & 0x0200) + if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; @@ -782,9 +805,9 @@ int flush; if (state->head != Z_NULL && state->head->comment != Z_NULL && state->length < state->head->comm_max) - state->head->comment[state->length++] = len; + state->head->comment[state->length++] = (Bytef)len; } while (len && copy < have); - if (state->flags & 0x0200) + if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; @@ -796,7 +819,7 @@ int flush; case HCRC: if (state->flags & 0x0200) { NEEDBITS(16); - if (hold != (state->check & 0xffff)) { + if ((state->wrap & 4) && hold != (state->check & 0xffff)) { strm->msg = (char *)"header crc mismatch"; state->mode = BAD; break; @@ -1177,11 +1200,11 @@ int flush; out -= left; strm->total_out += out; state->total += out; - if (out) + if ((state->wrap & 4) && out) strm->adler = state->check = UPDATE(state->check, put - out, out); out = left; - if (( + if ((state->wrap & 4) && ( #ifdef GUNZIP state->flags ? hold : #endif @@ -1240,10 +1263,10 @@ int flush; strm->total_in += in; strm->total_out += out; state->total += out; - if (state->wrap && out) + if ((state->wrap & 4) && out) strm->adler = state->check = UPDATE(state->check, strm->next_out - out, out); - strm->data_type = state->bits + (state->last ? 64 : 0) + + strm->data_type = (int)state->bits + (state->last ? 64 : 0) + (state->mode == TYPE ? 128 : 0) + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) @@ -1255,7 +1278,7 @@ int ZEXPORT inflateEnd(strm) z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->window != Z_NULL) ZFREE(strm, state->window); @@ -1273,7 +1296,7 @@ uInt *dictLength; struct inflate_state FAR *state; /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* copy dictionary */ @@ -1298,7 +1321,7 @@ uInt dictLength; int ret; /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->wrap != 0 && state->mode != DICT) return Z_STREAM_ERROR; @@ -1330,7 +1353,7 @@ gz_headerp head; struct inflate_state FAR *state; /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; @@ -1383,7 +1406,7 @@ z_streamp strm; struct inflate_state FAR *state; /* check parameters */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; @@ -1410,6 +1433,8 @@ z_streamp strm; /* return no joy or set up to restart inflate() on a new block */ if (state->have != 4) return Z_DATA_ERROR; + if (state->mode == HEAD) + state->wrap = 0; /* never processed header, so assume raw */ in = strm->total_in; out = strm->total_out; inflateReset(strm); strm->total_in = in; strm->total_out = out; @@ -1430,7 +1455,7 @@ z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; return state->mode == STORED && state->bits == 0; } @@ -1445,8 +1470,7 @@ z_streamp source; unsigned wsize; /* check input */ - if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || - source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + if (inflateStateCheck(source) || dest == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)source->state; @@ -1467,6 +1491,7 @@ z_streamp source; /* copy state */ zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); + copy->strm = dest; if (state->lencode >= state->codes && state->lencode <= state->codes + ENOUGH - 1) { copy->lencode = copy->codes + (state->lencode - state->codes); @@ -1488,25 +1513,51 @@ int subvert; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; - state->sane = !subvert; #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + state->sane = !subvert; return Z_OK; #else + (void)subvert; state->sane = 1; return Z_DATA_ERROR; #endif } +int ZEXPORT inflateValidate(strm, check) +z_streamp strm; +int check; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (check && state->wrap) + state->wrap |= 4; + else + state->wrap &= ~4; + return Z_OK; +} + long ZEXPORT inflateMark(strm) z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; + if (inflateStateCheck(strm)) + return -(1L << 16); state = (struct inflate_state FAR *)strm->state; - return ((long)(state->back) << 16) + + return (long)(((unsigned long)((long)state->back)) << 16) + (state->mode == COPY ? state->length : (state->mode == MATCH ? state->was - state->length : 0)); } + +unsigned long ZEXPORT inflateCodesUsed(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) return (unsigned long)-1; + state = (struct inflate_state FAR *)strm->state; + return (unsigned long)(state->next - state->codes); +} diff --git a/contrib/zlib/inflate.h b/contrib/zlib/inflate.h index 95f4986d4..a46cce6b6 100644 --- a/contrib/zlib/inflate.h +++ b/contrib/zlib/inflate.h @@ -1,5 +1,5 @@ /* inflate.h -- internal inflate state definition - * Copyright (C) 1995-2009 Mark Adler + * Copyright (C) 1995-2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -18,7 +18,7 @@ /* Possible inflate modes between inflate() calls */ typedef enum { - HEAD, /* i: waiting for magic header */ + HEAD = 16180, /* i: waiting for magic header */ FLAGS, /* i: waiting for method and flags (gzip) */ TIME, /* i: waiting for modification time (gzip) */ OS, /* i: waiting for extra flags and operating system (gzip) */ @@ -77,11 +77,14 @@ typedef enum { CHECK -> LENGTH -> DONE */ -/* state maintained between inflate() calls. Approximately 10K bytes. */ +/* State maintained between inflate() calls -- approximately 7K bytes, not + including the allocated sliding window, which is up to 32K bytes. */ struct inflate_state { + z_streamp strm; /* pointer back to this zlib stream */ inflate_mode mode; /* current inflate mode */ int last; /* true if processing last block */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip, + bit 2 true to validate check value */ int havedict; /* true if dictionary provided */ int flags; /* gzip header method and flags (0 if zlib) */ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ diff --git a/contrib/zlib/inftrees.c b/contrib/zlib/inftrees.c index 44d89cf24..716c98842 100644 --- a/contrib/zlib/inftrees.c +++ b/contrib/zlib/inftrees.c @@ -1,5 +1,5 @@ /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2013 Mark Adler + * Copyright (C) 1995-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,7 +9,7 @@ #define MAXBITS 15 const char inflate_copyright[] = - " inflate 1.2.8 Copyright 1995-2013 Mark Adler "; + " inflate 1.2.11.1 Copyright 1995-2017 Mark Adler "; /* If you use the zlib library in a product, an acknowledgment is welcome in the documentation of your product. If for some reason you cannot @@ -54,7 +54,7 @@ unsigned short FAR *work; code FAR *next; /* next available space in table */ const unsigned short FAR *base; /* base value table to use */ const unsigned short FAR *extra; /* extra bits table to use */ - int end; /* use base and extra for symbol > end */ + unsigned match; /* use base and extra for symbol >= match */ unsigned short count[MAXBITS+1]; /* number of codes of each length */ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ static const unsigned short lbase[31] = { /* Length codes 257..285 base */ @@ -62,7 +62,7 @@ unsigned short FAR *work; 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; static const unsigned short lext[31] = { /* Length codes 257..285 extra */ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78}; + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 198, 196}; static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, @@ -181,19 +181,17 @@ unsigned short FAR *work; switch (type) { case CODES: base = extra = work; /* dummy value--not used */ - end = 19; + match = 20; break; case LENS: base = lbase; - base -= 257; extra = lext; - extra -= 257; - end = 256; + match = 257; break; - default: /* DISTS */ + default: /* DISTS */ base = dbase; extra = dext; - end = -1; + match = 0; } /* initialize state for loop */ @@ -216,13 +214,13 @@ unsigned short FAR *work; for (;;) { /* create table entry */ here.bits = (unsigned char)(len - drop); - if ((int)(work[sym]) < end) { + if (work[sym] + 1U < match) { here.op = (unsigned char)0; here.val = work[sym]; } - else if ((int)(work[sym]) > end) { - here.op = (unsigned char)(extra[work[sym]]); - here.val = base[work[sym]]; + else if (work[sym] >= match) { + here.op = (unsigned char)(extra[work[sym] - match]); + here.val = base[work[sym] - match]; } else { here.op = (unsigned char)(32 + 64); /* end of block */ diff --git a/contrib/zlib/trees.c b/contrib/zlib/trees.c index 1fd7759ef..50cf4b457 100644 --- a/contrib/zlib/trees.c +++ b/contrib/zlib/trees.c @@ -1,5 +1,5 @@ /* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2012 Jean-loup Gailly + * Copyright (C) 1995-2017 Jean-loup Gailly * detect_data_type() function provided freely by Cosmin Truta, 2006 * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -36,7 +36,7 @@ #include "deflate.h" -#ifdef DEBUG +#ifdef ZLIB_DEBUG # include #endif @@ -122,13 +122,13 @@ struct static_tree_desc_s { int max_length; /* max bit length for the codes */ }; -local static_tree_desc static_l_desc = +local const static_tree_desc static_l_desc = {static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; -local static_tree_desc static_d_desc = +local const static_tree_desc static_d_desc = {static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; -local static_tree_desc static_bl_desc = +local const static_tree_desc static_bl_desc = {(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; /* =========================================================================== @@ -152,18 +152,16 @@ local int detect_data_type OF((deflate_state *s)); local unsigned bi_reverse OF((unsigned value, int length)); local void bi_windup OF((deflate_state *s)); local void bi_flush OF((deflate_state *s)); -local void copy_block OF((deflate_state *s, charf *buf, unsigned len, - int header)); #ifdef GEN_TREES_H local void gen_trees_header OF((void)); #endif -#ifndef DEBUG +#ifndef ZLIB_DEBUG # define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) /* Send a code of the given tree. c and tree must not have side effects */ -#else /* DEBUG */ +#else /* !ZLIB_DEBUG */ # define send_code(s, c, tree) \ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ send_bits(s, tree[c].Code, tree[c].Len); } @@ -182,7 +180,7 @@ local void gen_trees_header OF((void)); * Send a value on a given number of bits. * IN assertion: length <= 16 and value fits in length bits. */ -#ifdef DEBUG +#ifdef ZLIB_DEBUG local void send_bits OF((deflate_state *s, int value, int length)); local void send_bits(s, value, length) @@ -208,12 +206,12 @@ local void send_bits(s, value, length) s->bi_valid += length; } } -#else /* !DEBUG */ +#else /* !ZLIB_DEBUG */ #define send_bits(s, value, length) \ { int len = length;\ if (s->bi_valid > (int)Buf_size - len) {\ - int val = value;\ + int val = (int)value;\ s->bi_buf |= (ush)val << s->bi_valid;\ put_short(s, s->bi_buf);\ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ @@ -223,7 +221,7 @@ local void send_bits(s, value, length) s->bi_valid += len;\ }\ } -#endif /* DEBUG */ +#endif /* ZLIB_DEBUG */ /* the arguments must not have side effects */ @@ -317,7 +315,7 @@ local void tr_static_init() * Genererate the file trees.h describing the static trees. */ #ifdef GEN_TREES_H -# ifndef DEBUG +# ifndef ZLIB_DEBUG # include # endif @@ -394,7 +392,7 @@ void ZLIB_INTERNAL _tr_init(s) s->bi_buf = 0; s->bi_valid = 0; -#ifdef DEBUG +#ifdef ZLIB_DEBUG s->compressed_len = 0L; s->bits_sent = 0L; #endif @@ -522,12 +520,12 @@ local void gen_bitlen(s, desc) xbits = 0; if (n >= base) xbits = extra[n-base]; f = tree[n].Freq; - s->opt_len += (ulg)f * (bits + xbits); - if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + s->opt_len += (ulg)f * (unsigned)(bits + xbits); + if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits); } if (overflow == 0) return; - Trace((stderr,"\nbit length overflow\n")); + Tracev((stderr,"\nbit length overflow\n")); /* This happens for example on obj2 and pic of the Calgary corpus */ /* Find the first bit length which could increase: */ @@ -554,9 +552,8 @@ local void gen_bitlen(s, desc) m = s->heap[--h]; if (m > max_code) continue; if ((unsigned) tree[m].Len != (unsigned) bits) { - Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s->opt_len += ((long)bits - (long)tree[m].Len) - *(long)tree[m].Freq; + Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((ulg)bits - tree[m].Len) * tree[m].Freq; tree[m].Len = (ush)bits; } n--; @@ -578,7 +575,7 @@ local void gen_codes (tree, max_code, bl_count) ushf *bl_count; /* number of codes at each bit length */ { ush next_code[MAX_BITS+1]; /* next code value for each bit length */ - ush code = 0; /* running code value */ + unsigned code = 0; /* running code value */ int bits; /* bit index */ int n; /* code index */ @@ -586,7 +583,8 @@ local void gen_codes (tree, max_code, bl_count) * without bit reversal. */ for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits-1]) << 1; + code = (code + bl_count[bits-1]) << 1; + next_code[bits] = (ush)code; } /* Check that the bit counts in bl_count are consistent. The last code * must be all ones. @@ -599,7 +597,7 @@ local void gen_codes (tree, max_code, bl_count) int len = tree[n].Len; if (len == 0) continue; /* Now reverse the bits */ - tree[n].Code = bi_reverse(next_code[len]++, len); + tree[n].Code = (ush)bi_reverse(next_code[len]++, len); Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); @@ -821,7 +819,7 @@ local int build_bl_tree(s) if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; } /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*(max_blindex+1) + 5+5+4; + s->opt_len += 3*((ulg)max_blindex+1) + 5+5+4; Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", s->opt_len, s->static_len)); @@ -869,11 +867,17 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) int last; /* one if this is the last block for a file */ { send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ -#ifdef DEBUG + bi_windup(s); /* align on byte boundary */ + put_short(s, (ush)stored_len); + put_short(s, (ush)~stored_len); + zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len); + s->pending += stored_len; +#ifdef ZLIB_DEBUG s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; s->compressed_len += (stored_len + 4) << 3; + s->bits_sent += 2*16; + s->bits_sent += stored_len<<3; #endif - copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ } /* =========================================================================== @@ -894,7 +898,7 @@ void ZLIB_INTERNAL _tr_align(s) { send_bits(s, STATIC_TREES<<1, 3); send_code(s, END_BLOCK, static_ltree); -#ifdef DEBUG +#ifdef ZLIB_DEBUG s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ #endif bi_flush(s); @@ -902,7 +906,7 @@ void ZLIB_INTERNAL _tr_align(s) /* =========================================================================== * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. + * trees or store, and write out the encoded block. */ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) deflate_state *s; @@ -974,7 +978,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) send_bits(s, (STATIC_TREES<<1)+last, 3); compress_block(s, (const ct_data *)static_ltree, (const ct_data *)static_dtree); -#ifdef DEBUG +#ifdef ZLIB_DEBUG s->compressed_len += 3 + s->static_len; #endif } else { @@ -983,7 +987,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) max_blindex+1); compress_block(s, (const ct_data *)s->dyn_ltree, (const ct_data *)s->dyn_dtree); -#ifdef DEBUG +#ifdef ZLIB_DEBUG s->compressed_len += 3 + s->opt_len; #endif } @@ -995,7 +999,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) if (last) { bi_windup(s); -#ifdef DEBUG +#ifdef ZLIB_DEBUG s->compressed_len += 7; /* align on byte boundary */ #endif } @@ -1090,7 +1094,7 @@ local void compress_block(s, ltree, dtree) send_code(s, code, dtree); /* send the distance code */ extra = extra_dbits[code]; if (extra != 0) { - dist -= base_dist[code]; + dist -= (unsigned)base_dist[code]; send_bits(s, dist, extra); /* send the extra distance bits */ } } /* literal or match pair ? */ @@ -1193,34 +1197,7 @@ local void bi_windup(s) } s->bi_buf = 0; s->bi_valid = 0; -#ifdef DEBUG +#ifdef ZLIB_DEBUG s->bits_sent = (s->bits_sent+7) & ~7; #endif } - -/* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ -local void copy_block(s, buf, len, header) - deflate_state *s; - charf *buf; /* the input data */ - unsigned len; /* its length */ - int header; /* true if block header must be written */ -{ - bi_windup(s); /* align on byte boundary */ - - if (header) { - put_short(s, (ush)len); - put_short(s, (ush)~len); -#ifdef DEBUG - s->bits_sent += 2*16; -#endif - } -#ifdef DEBUG - s->bits_sent += (ulg)len<<3; -#endif - while (len--) { - put_byte(s, *buf++); - } -} diff --git a/contrib/zlib/uncompr.c b/contrib/zlib/uncompr.c index 242e9493d..f03a1a865 100644 --- a/contrib/zlib/uncompr.c +++ b/contrib/zlib/uncompr.c @@ -1,5 +1,5 @@ /* uncompr.c -- decompress a memory buffer - * Copyright (C) 1995-2003, 2010 Jean-loup Gailly. + * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,51 +9,85 @@ #include "zlib.h" /* =========================================================================== - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. + Decompresses the source buffer into the destination buffer. *sourceLen is + the byte length of the source buffer. Upon entry, *destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, + *destLen is the size of the decompressed data and *sourceLen is the number + of source bytes consumed. Upon return, source + *sourceLen points to the + first unused input byte. - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted. + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, or + Z_DATA_ERROR if the input data was corrupted, including if the input data is + an incomplete zlib stream. */ +int ZEXPORT uncompress2 (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong *sourceLen; +{ + z_stream stream; + int err; + const uInt max = (uInt)-1; + uLong len, left; + Byte buf[1]; /* for detection of incomplete stream when *destLen == 0 */ + + len = *sourceLen; + if (*destLen) { + left = *destLen; + *destLen = 0; + } + else { + left = 1; + dest = buf; + } + + stream.next_in = (z_const Bytef *)source; + stream.avail_in = 0; + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + stream.next_out = dest; + stream.avail_out = 0; + + do { + if (stream.avail_out == 0) { + stream.avail_out = left > (uLong)max ? max : (uInt)left; + left -= stream.avail_out; + } + if (stream.avail_in == 0) { + stream.avail_in = len > (uLong)max ? max : (uInt)len; + len -= stream.avail_in; + } + err = inflate(&stream, Z_NO_FLUSH); + } while (err == Z_OK); + + *sourceLen -= len + stream.avail_in; + if (dest != buf) + *destLen = stream.total_out; + else if (stream.total_out && err == Z_BUF_ERROR) + left = 1; + + inflateEnd(&stream); + return err == Z_STREAM_END ? Z_OK : + err == Z_NEED_DICT ? Z_DATA_ERROR : + err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR : + err; +} + int ZEXPORT uncompress (dest, destLen, source, sourceLen) Bytef *dest; uLongf *destLen; const Bytef *source; uLong sourceLen; { - z_stream stream; - int err; - - stream.next_in = (z_const Bytef *)source; - stream.avail_in = (uInt)sourceLen; - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; - - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; - - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - - err = inflateInit(&stream); - if (err != Z_OK) return err; - - err = inflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - inflateEnd(&stream); - if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) - return Z_DATA_ERROR; - return err; - } - *destLen = stream.total_out; - - err = inflateEnd(&stream); - return err; + return uncompress2(dest, destLen, source, &sourceLen); } diff --git a/contrib/zlib/win32/Makefile.gcc b/contrib/zlib/win32/Makefile.gcc index 6d1ded622..305be50af 100644 --- a/contrib/zlib/win32/Makefile.gcc +++ b/contrib/zlib/win32/Makefile.gcc @@ -39,7 +39,7 @@ IMPLIB = libz.dll.a SHARED_MODE=0 #LOC = -DASMV -#LOC = -DDEBUG -g +#LOC = -DZLIB_DEBUG -g PREFIX = CC = $(PREFIX)gcc diff --git a/contrib/zlib/win32/Makefile.msc b/contrib/zlib/win32/Makefile.msc index 67b773171..6831882de 100644 --- a/contrib/zlib/win32/Makefile.msc +++ b/contrib/zlib/win32/Makefile.msc @@ -1,5 +1,5 @@ # Makefile for zlib using Microsoft (Visual) C -# zlib is copyright (C) 1995-2006 Jean-loup Gailly and Mark Adler +# zlib is copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler # # Usage: # nmake -f win32/Makefile.msc (standard build) diff --git a/contrib/zlib/win32/README-WIN32.txt b/contrib/zlib/win32/README-WIN32.txt index 3d77d521e..a1de359a3 100644 --- a/contrib/zlib/win32/README-WIN32.txt +++ b/contrib/zlib/win32/README-WIN32.txt @@ -1,6 +1,6 @@ ZLIB DATA COMPRESSION LIBRARY -zlib 1.2.8 is a general purpose data compression library. All the code is +zlib 1.2.11.1 is a general purpose data compression library. All the code is thread safe. The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) @@ -22,7 +22,7 @@ before asking for help. Manifest: -The package zlib-1.2.8-win32-x86.zip will contain the following files: +The package zlib-1.2.11.1-win32-x86.zip will contain the following files: README-WIN32.txt This document ChangeLog Changes since previous zlib packages @@ -72,7 +72,7 @@ are too numerous to cite here. Copyright notice: - (C) 1995-2012 Jean-loup Gailly and Mark Adler + (C) 1995-2017 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/contrib/zlib/win32/VisualC.txt b/contrib/zlib/win32/VisualC.txt index 579a5fc9e..1005b2194 100644 --- a/contrib/zlib/win32/VisualC.txt +++ b/contrib/zlib/win32/VisualC.txt @@ -1,3 +1,3 @@ To build zlib using the Microsoft Visual C++ environment, -use the appropriate project from the projects/ directory. +use the appropriate project from the contrib/vstudio/ directory. diff --git a/contrib/zlib/win32/zlib.def b/contrib/zlib/win32/zlib.def index face65518..a2188b000 100644 --- a/contrib/zlib/win32/zlib.def +++ b/contrib/zlib/win32/zlib.def @@ -8,6 +8,7 @@ EXPORTS inflateEnd ; advanced functions deflateSetDictionary + deflateGetDictionary deflateCopy deflateReset deflateParams @@ -33,12 +34,15 @@ EXPORTS compress2 compressBound uncompress + uncompress2 gzopen gzdopen gzbuffer gzsetparams gzread + gzfread gzwrite + gzfwrite gzprintf gzvprintf gzputs @@ -67,7 +71,9 @@ EXPORTS crc32_combine64 ; checksum functions adler32 + adler32_z crc32 + crc32_z adler32_combine crc32_combine ; various hacks, don't look :) @@ -81,6 +87,8 @@ EXPORTS inflateSyncPoint get_crc_table inflateUndermine + inflateValidate + inflateCodesUsed inflateResetKeep deflateResetKeep gzopen_w diff --git a/contrib/zlib/win32/zlib1.rc b/contrib/zlib/win32/zlib1.rc index 5c0feed1b..234e641c3 100644 --- a/contrib/zlib/win32/zlib1.rc +++ b/contrib/zlib/win32/zlib1.rc @@ -26,7 +26,7 @@ BEGIN VALUE "FileDescription", "zlib data compression library\0" VALUE "FileVersion", ZLIB_VERSION "\0" VALUE "InternalName", "zlib1.dll\0" - VALUE "LegalCopyright", "(C) 1995-2013 Jean-loup Gailly & Mark Adler\0" + VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" VALUE "OriginalFilename", "zlib1.dll\0" VALUE "ProductName", "zlib\0" VALUE "ProductVersion", ZLIB_VERSION "\0" diff --git a/contrib/zlib/zconf.h.cmakein b/contrib/zlib/zconf.h.cmakein index 043019cda..a7f24cce6 100644 --- a/contrib/zlib/zconf.h.cmakein +++ b/contrib/zlib/zconf.h.cmakein @@ -1,5 +1,5 @@ /* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2013 Jean-loup Gailly. + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -19,7 +19,7 @@ #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ # define Z_PREFIX_SET -/* all linked symbols */ +/* all linked symbols and init macros */ # define _dist_code z__dist_code # define _length_code z__length_code # define _tr_align z__tr_align @@ -31,6 +31,7 @@ # define adler32 z_adler32 # define adler32_combine z_adler32_combine # define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z # ifndef Z_SOLO # define compress z_compress # define compress2 z_compress2 @@ -39,10 +40,14 @@ # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z # define deflate z_deflate # define deflateBound z_deflateBound # define deflateCopy z_deflateCopy # define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 # define deflateInit2_ z_deflateInit2_ # define deflateInit_ z_deflateInit_ # define deflateParams z_deflateParams @@ -69,6 +74,8 @@ # define gzeof z_gzeof # define gzerror z_gzerror # define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite # define gzgetc z_gzgetc # define gzgetc_ z_gzgetc_ # define gzgets z_gzgets @@ -80,7 +87,6 @@ # define gzopen_w z_gzopen_w # endif # define gzprintf z_gzprintf -# define gzvprintf z_gzvprintf # define gzputc z_gzputc # define gzputs z_gzputs # define gzread z_gzread @@ -91,32 +97,39 @@ # define gztell z_gztell # define gztell64 z_gztell64 # define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf # define gzwrite z_gzwrite # endif # define inflate z_inflate # define inflateBack z_inflateBack # define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit # define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed # define inflateCopy z_inflateCopy # define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary # define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 # define inflateInit2_ z_inflateInit2_ # define inflateInit_ z_inflateInit_ # define inflateMark z_inflateMark # define inflatePrime z_inflatePrime # define inflateReset z_inflateReset # define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep # define inflateSetDictionary z_inflateSetDictionary -# define inflateGetDictionary z_inflateGetDictionary # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint # define inflateUndermine z_inflateUndermine -# define inflateResetKeep z_inflateResetKeep +# define inflateValidate z_inflateValidate # define inflate_copyright z_inflate_copyright # define inflate_fast z_inflate_fast # define inflate_table z_inflate_table # ifndef Z_SOLO # define uncompress z_uncompress +# define uncompress2 z_uncompress2 # endif # define zError z_zError # ifndef Z_SOLO @@ -226,9 +239,19 @@ # define z_const #endif -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) -# define NO_DUMMY_DECL +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong #endif /* Maximum value for memLevel in deflateInit2 */ @@ -258,7 +281,7 @@ Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes for small objects. */ diff --git a/contrib/zlib/zconf.in.h b/contrib/zlib/zconf.h.in similarity index 50% rename from contrib/zlib/zconf.in.h rename to contrib/zlib/zconf.h.in index 03a9431c8..5e1d68a00 100644 --- a/contrib/zlib/zconf.in.h +++ b/contrib/zlib/zconf.h.in @@ -1,5 +1,5 @@ /* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2005 Jean-loup Gailly. + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -11,52 +11,158 @@ /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". */ -#ifdef Z_PREFIX -# define deflateInit_ z_deflateInit_ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z # define deflate z_deflate -# define deflateEnd z_deflateEnd -# define inflateInit_ z_inflateInit_ -# define inflate z_inflate -# define inflateEnd z_inflateEnd -# define deflateInit2_ z_deflateInit2_ -# define deflateSetDictionary z_deflateSetDictionary -# define deflateCopy z_deflateCopy -# define deflateReset z_deflateReset -# define deflateParams z_deflateParams # define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending # define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 # define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep # define inflateSetDictionary z_inflateSetDictionary # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint -# define inflateCopy z_inflateCopy -# define inflateReset z_inflateReset -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# define uncompress z_uncompress -# define adler32 z_adler32 -# define crc32 z_crc32 -# define get_crc_table z_get_crc_table +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif # define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion -# define alloc_func z_alloc_func -# define free_func z_free_func -# define in_func z_in_func -# define out_func z_out_func +/* all zlib typedefs in zlib.h and zconf.h */ # define Byte z_Byte -# define uInt z_uInt -# define uLong z_uLong # define Bytef z_Bytef +# define alloc_func z_alloc_func # define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func # define intf z_intf +# define out_func z_out_func +# define uInt z_uInt # define uIntf z_uIntf +# define uLong z_uLong # define uLongf z_uLongf -# define voidpf z_voidpf # define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + #endif #if defined(__MSDOS__) && !defined(MSDOS) @@ -125,9 +231,25 @@ # endif #endif -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) -# define NO_DUMMY_DECL +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong #endif /* Maximum value for memLevel in deflateInit2 */ @@ -157,7 +279,7 @@ Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes for small objects. */ @@ -171,6 +293,14 @@ # endif #endif +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + /* The following definitions for FAR are needed only for MSDOS mixed * model programming (small or medium model with some far allocations). * This was tested only with MSC; for other MSDOS compilers you may have @@ -284,49 +414,121 @@ typedef uLong FAR uLongf; typedef Byte *voidp; #endif -#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ -# include /* for off_t */ -# include /* for SEEK_* and off_t */ -# ifdef VMS -# include /* for off_t */ +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short # endif -# define z_off_t off_t #endif -#ifndef SEEK_SET + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) # define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ #endif + #ifndef z_off_t # define z_off_t long #endif -#if defined(__OS400__) -# define NO_vsnprintf -#endif - -#if defined(__MVS__) -# define NO_vsnprintf -# ifdef FAR -# undef FAR +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t # endif #endif /* MVS linker does not support external names larger than 8 bytes */ #if defined(__MVS__) -# pragma map(deflateInit_,"DEIN") -# pragma map(deflateInit2_,"DEIN2") -# pragma map(deflateEnd,"DEEND") -# pragma map(deflateBound,"DEBND") -# pragma map(inflateInit_,"ININ") -# pragma map(inflateInit2_,"ININ2") -# pragma map(inflateEnd,"INEND") -# pragma map(inflateSync,"INSY") -# pragma map(inflateSetDictionary,"INSEDI") -# pragma map(compressBound,"CMBND") -# pragma map(inflate_table,"INTABL") -# pragma map(inflate_fast,"INFA") -# pragma map(inflate_copyright,"INCOPY") + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") #endif #endif /* ZCONF_H */ diff --git a/contrib/zlib/zconf.h.included b/contrib/zlib/zconf.h.included index 9ccbb0a6f..352f552b8 100644 --- a/contrib/zlib/zconf.h.included +++ b/contrib/zlib/zconf.h.included @@ -1,5 +1,5 @@ /* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2013 Jean-loup Gailly. + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -19,7 +19,7 @@ #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ # define Z_PREFIX_SET -/* all linked symbols */ +/* all linked symbols and init macros */ # define _dist_code z__dist_code # define _length_code z__length_code # define _tr_align z__tr_align @@ -31,6 +31,7 @@ # define adler32 z_adler32 # define adler32_combine z_adler32_combine # define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z # ifndef Z_SOLO # define compress z_compress # define compress2 z_compress2 @@ -39,10 +40,14 @@ # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z # define deflate z_deflate # define deflateBound z_deflateBound # define deflateCopy z_deflateCopy # define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 # define deflateInit2_ z_deflateInit2_ # define deflateInit_ z_deflateInit_ # define deflateParams z_deflateParams @@ -69,6 +74,8 @@ # define gzeof z_gzeof # define gzerror z_gzerror # define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite # define gzgetc z_gzgetc # define gzgetc_ z_gzgetc_ # define gzgets z_gzgets @@ -80,7 +87,6 @@ # define gzopen_w z_gzopen_w # endif # define gzprintf z_gzprintf -# define gzvprintf z_gzvprintf # define gzputc z_gzputc # define gzputs z_gzputs # define gzread z_gzread @@ -91,32 +97,39 @@ # define gztell z_gztell # define gztell64 z_gztell64 # define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf # define gzwrite z_gzwrite # endif # define inflate z_inflate # define inflateBack z_inflateBack # define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit # define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed # define inflateCopy z_inflateCopy # define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary # define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 # define inflateInit2_ z_inflateInit2_ # define inflateInit_ z_inflateInit_ # define inflateMark z_inflateMark # define inflatePrime z_inflatePrime # define inflateReset z_inflateReset # define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep # define inflateSetDictionary z_inflateSetDictionary -# define inflateGetDictionary z_inflateGetDictionary # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint # define inflateUndermine z_inflateUndermine -# define inflateResetKeep z_inflateResetKeep +# define inflateValidate z_inflateValidate # define inflate_copyright z_inflate_copyright # define inflate_fast z_inflate_fast # define inflate_table z_inflate_table # ifndef Z_SOLO # define uncompress z_uncompress +# define uncompress2 z_uncompress2 # endif # define zError z_zError # ifndef Z_SOLO @@ -226,9 +239,19 @@ # define z_const #endif -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) -# define NO_DUMMY_DECL +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong #endif /* Maximum value for memLevel in deflateInit2 */ @@ -258,7 +281,7 @@ Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes for small objects. */ diff --git a/contrib/zlib/zlib.h b/contrib/zlib/zlib.h index 3e0c7672a..577d81e3b 100644 --- a/contrib/zlib/zlib.h +++ b/contrib/zlib/zlib.h @@ -1,7 +1,7 @@ /* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.8, April 28th, 2013 + version 1.2.11.1, January xxth, 2017 - Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -37,12 +37,12 @@ extern "C" { #endif -#define ZLIB_VERSION "1.2.8" -#define ZLIB_VERNUM 0x1280 +#define ZLIB_VERSION "1.2.11.1-motley" +#define ZLIB_VERNUM 0x12b1 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 8 -#define ZLIB_VER_SUBREVISION 0 +#define ZLIB_VER_REVISION 11 +#define ZLIB_VER_SUBREVISION 1 /* The 'zlib' compression library provides in-memory compression and @@ -65,7 +65,8 @@ extern "C" { with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - This library can optionally read and write gzip streams in memory as well. + This library can optionally read and write gzip and raw deflate streams in + memory as well. The zlib format was designed to be compact and fast for use in memory and on communications channels. The gzip format was designed for single- @@ -74,7 +75,7 @@ extern "C" { The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash - even in case of corrupted input. + even in the case of corrupted input. */ typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); @@ -87,7 +88,7 @@ typedef struct z_stream_s { uInt avail_in; /* number of bytes available at next_in */ uLong total_in; /* total number of input bytes read so far */ - Bytef *next_out; /* next output byte should be put there */ + Bytef *next_out; /* next output byte will go here */ uInt avail_out; /* remaining free space at next_out */ uLong total_out; /* total number of bytes output so far */ @@ -98,8 +99,9 @@ typedef struct z_stream_s { free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ - int data_type; /* best guess about the data type: binary or text */ - uLong adler; /* adler32 value of the uncompressed data */ + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream; @@ -142,7 +144,9 @@ typedef gz_header FAR *gz_headerp; zalloc must return Z_NULL if there is not enough memory for the object. If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). On 16-bit systems, the functions zalloc and zfree must be able to allocate exactly 65536 bytes, but will not be required to allocate more than this if @@ -155,7 +159,7 @@ typedef gz_header FAR *gz_headerp; The fields total_in and total_out can be used for statistics or progress reports. After compression, total_in holds the total size of the - uncompressed data and may be saved for use in the decompressor (particularly + uncompressed data and may be saved for use by the decompressor (particularly if the decompressor wants to decompress everything in a single step). */ @@ -200,7 +204,7 @@ typedef gz_header FAR *gz_headerp; #define Z_TEXT 1 #define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ #define Z_UNKNOWN 2 -/* Possible values of the data_type field (though see inflate()) */ +/* Possible values of the data_type field for deflate() */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */ @@ -258,11 +262,11 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); enough room in the output buffer), next_in and avail_in are updated and processing will resume at this point for the next call of deflate(). - - Provide more output starting at next_out and update next_out and avail_out + - Generate more output starting at next_out and update next_out and avail_out accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). Some - output may be provided even if flush is not set. + should be set only when necessary. Some output may be provided even if + flush is zero. Before the call of deflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more @@ -271,7 +275,9 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output - buffer because there might be more output pending. + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more ouput + in that case. Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to decide how much data to accumulate before producing output, in order to @@ -292,8 +298,8 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. This completes the current deflate block and follows it with an empty fixed codes block that is 10 bits long. This assures that enough bytes are output - in order for the decompressor to finish the block before the empty fixed code - block. + in order for the decompressor to finish the block before the empty fixed + codes block. If flush is set to Z_BLOCK, a deflate block is completed and emitted, as for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to @@ -319,34 +325,38 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was - enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the stream - are deflateReset or deflateEnd. + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least the - value returned by deflateBound (see below). Then deflate is guaranteed to - return Z_STREAM_END. If not enough output space is provided, deflate will - not return Z_STREAM_END, and it must be called again as described above. + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered - binary. This field is only for information purposes and does not affect the - compression algorithm in any manner. + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. deflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if all input has been consumed and all output has been produced (only when flush is set to Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not - fatal, and deflate() can be called again with more input and more output - space to continue compressing. + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. */ @@ -369,23 +379,21 @@ ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the - exact value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit() does not process any header information -- that is deferred - until inflate() is called. + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. */ @@ -401,17 +409,20 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); - Decompress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing will - resume at this point for the next call of inflate(). + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). - - Provide more output starting at next_out and update next_out and avail_out + - Generate more output starting at next_out and update next_out and avail_out accordingly. inflate() provides as much output as possible, until there is no more input data or no more space in the output buffer (see below about the flush parameter). Before the call of inflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more - output, and updating the next_* and avail_* values accordingly. The + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The application can consume the uncompressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of inflate(). If inflate returns Z_OK and with zero avail_out, it must be @@ -428,7 +439,7 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); gets to the end of that block, or when it runs out of data. The Z_BLOCK option assists in appending to or combining deflate streams. - Also to assist in this, on return inflate() will set strm->data_type to the + To assist in this, on return inflate() always sets strm->data_type to the number of unused bits in the last byte taken from strm->next_in, plus 64 if inflate() is currently decoding the last block in the deflate stream, plus 128 if inflate() returned immediately after decoding an end-of-block code or @@ -454,7 +465,7 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); this case all pending input is processed and all pending output is flushed; avail_out must be large enough to hold all of the uncompressed data for the operation to complete. (The size of the uncompressed data may have been - saved by the compressor for this purpose.) The use of Z_FINISH is not + saved by the compressor for this purpose.) The use of Z_FINISH is not required to perform an inflation in one step. However it may be used to inform inflate that a faster approach can be used for the single inflate() call. Z_FINISH also informs inflate to not maintain a sliding window if the @@ -476,32 +487,33 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); chosen by the compressor and returns Z_NEED_DICT; otherwise it sets strm->adler to the Adler-32 checksum of all output produced so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed adler32 + below. At the end of the stream, inflate() checks that its computed Adler-32 checksum is equal to that saved by the compressor and returns Z_STREAM_END only if the checksum is correct. inflate() can decompress and check either zlib-wrapped or gzip-wrapped deflate data. The header type is detected automatically, if requested when initializing with inflateInit2(). Any information contained in the gzip - header is not retained, so applications that need that information should - instead use raw inflate, see inflateInit2() below, or inflateBack() and - perform their own processing of the gzip header and trailer. When processing + header is not retained unless inflateGetHeader() is used. When processing gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output - producted so far. The CRC-32 is checked against the gzip trailer. + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has been reached and all uncompressed output has been produced, Z_NEED_DICT if a preset dictionary is needed at this point, Z_DATA_ERROR if the input data was corrupted (input stream not conforming to the zlib format or incorrect check - value), Z_STREAM_ERROR if the stream structure was inconsistent (for example - next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, - Z_BUF_ERROR if no progress is possible or if there was not enough room in the - output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and inflate() can be called again with more input and more output space to continue decompressing. If Z_DATA_ERROR is returned, the application may then call inflateSync() to look for a good compression block if a partial - recovery of the data is desired. + recovery of the data is to be attempted. */ @@ -511,9 +523,8 @@ ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); This function discards any unprocessed input and does not flush any pending output. - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. */ @@ -544,16 +555,29 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, compression at the expense of memory usage. The default value is 15 if deflateInit is used instead. + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute an adler32 check value. + with no zlib header or trailer, and will not compute a check value. windowBits can also be greater than 15 for optional gzip encoding. Add 16 to windowBits to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper. The gzip header will have no file name, no extra data, no comment, no modification time (set to zero), no - header crc, and the operating system will be set to 255 (unknown). If a - gzip stream is being written, strm->adler is a crc32 instead of an adler32. + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. The memLevel parameter specifies how much memory should be allocated for the internal compression state. memLevel=1 uses minimum memory but is @@ -614,12 +638,12 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, addition, the current implementation of deflate will use at most the window size minus 262 bytes of the provided dictionary. - Upon return of this function, strm->adler is set to the adler32 value + Upon return of this function, strm->adler is set to the Adler-32 value of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The adler32 value + which dictionary has been used by the compressor. (The Adler-32 value applies to the whole dictionary even if only a subset of the dictionary is actually used by the compressor.) If a raw deflate was requested, then the - adler32 value is not computed and strm->adler is not set. + Adler-32 value is not computed and strm->adler is not set. deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is @@ -628,6 +652,28 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, not perform any compression: this will be done by deflate(). */ +ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, z_streamp source)); /* @@ -648,10 +694,10 @@ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); /* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. The - stream will keep the same compression level and any other attributes that - may have been set by deflateInit2. + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). @@ -662,20 +708,37 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, int strategy)); /* Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be + interpretation of level and strategy is as in deflateInit2(). This can be used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. - If the compression level is changed, the input available so far is - compressed with the old level (and may be flushed); the new level will take - effect only at the next call of deflate(). + If the compression approach (which is a function of the level) or the + strategy is changed, and if there have been any deflate() calls since the + state was initialized or reset, then the input available so far is + compressed with the old level and strategy using deflate(strm, Z_BLOCK). + There are three approaches for the compression levels 0, 1..3, and 4..9 + respectively. The new level and strategy will take effect at the next call + of deflate(). - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to be - compressed and flushed. In particular, strm->avail_out must be non-zero. + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if - strm->avail_out was zero. + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. */ ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, @@ -793,7 +856,7 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, is for use with other formats that use the deflate compressed data format such as zip. Those formats provide their own check values. If a custom format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an adler32 or a crc32 be applied to + recommended that a check value such as an Adler-32 or a CRC-32 be applied to the uncompressed data as is done in the zlib, gzip, and zip formats. For most applications, the zlib format should be used as is. Note that comments above on the use in deflateInit2() applies to the magnitude of windowBits. @@ -802,7 +865,10 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, 32 to windowBits to enable zlib and gzip decoding with automatic header detection, or add 16 to decode only the gzip format (the zlib format will return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a - crc32 instead of an adler32. + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will not automatically decode concatenated gzip streams. + inflate() will return Z_STREAM_END at the end of the gzip stream. The state + would need to be reset to continue decoding a subsequent gzip stream. inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the @@ -823,7 +889,7 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, Initializes the decompression dictionary from the given uncompressed byte sequence. This function must be called immediately after a call of inflate, if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the adler32 value returned by that call of inflate. + can be determined from the Adler-32 value returned by that call of inflate. The compressor and decompressor must use exactly the same dictionary (see deflateSetDictionary). For raw inflate, this function can be called at any time to set the dictionary. If the provided dictionary is smaller than the @@ -834,7 +900,7 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect adler32 value). inflateSetDictionary does not + expected one (incorrect Adler-32 value). inflateSetDictionary does not perform any decompression: this will be done by subsequent calls of inflate(). */ @@ -892,7 +958,7 @@ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); /* This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. The + but does not free and reallocate the internal decompression state. The stream will keep attributes that may have been set by inflateInit2. inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source @@ -904,7 +970,9 @@ ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, /* This function is the same as inflateReset, but it also permits changing the wrap and window size requests. The windowBits parameter is interpreted - the same as it is for inflateInit2. + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL), or if @@ -956,7 +1024,7 @@ ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); location in the input stream can be determined from avail_in and data_type as noted in the description for the Z_BLOCK flush parameter for inflate. - inflateMark returns the value noted above or -1 << 16 if the provided + inflateMark returns the value noted above, or -65536 if the provided source stream state was inconsistent. */ @@ -1048,9 +1116,9 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, This routine would normally be used in a utility that reads zip or gzip files and writes out uncompressed files. The utility would decode the header and process the trailer on its own, hence this routine expects only - the raw deflate stream to decompress. This is different from the normal - behavior of inflate(), which expects either a zlib or gzip header and - trailer around the deflate stream. + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. inflateBack() uses two subroutines supplied by the caller that are then called by inflateBack() for input and output. inflateBack() calls those @@ -1059,12 +1127,12 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, parameters and return types are defined above in the in_func and out_func typedefs. inflateBack() will call in(in_desc, &buf) which should return the number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero--buf is ignored in that - case--and inflateBack() will return a buffer error. inflateBack() will call - out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() - should return zero on success, or non-zero on failure. If out() returns - non-zero, inflateBack() will return with an error. Neither in() nor out() - are permitted to change the contents of the window provided to + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to inflateBackInit(), which is also the buffer that out() uses to write from. The length written by out() will be at most the window size. Any non-zero amount of input may be provided by in(). @@ -1092,7 +1160,7 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, using strm->next_in which will be Z_NULL only if in() returned an error. If strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning non-zero. (in() will always be called before out(), so strm->next_in is - assured to be defined if out() returns non-zero.) Note that inflateBack() + assured to be defined if out() returns non-zero.) Note that inflateBack() cannot return Z_OK. */ @@ -1114,7 +1182,7 @@ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); 7.6: size of z_off_t Compiler, assembler, and debug options: - 8: DEBUG + 8: ZLIB_DEBUG 9: ASMV or ASMINF -- use ASM code 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention 11: 0 (reserved) @@ -1164,7 +1232,8 @@ ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. compress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output @@ -1180,7 +1249,7 @@ ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. + compressed data. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, @@ -1203,7 +1272,7 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.) Upon exit, destLen - is the actual size of the uncompressed buffer. + is the actual size of the uncompressed data. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output @@ -1212,6 +1281,14 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, buffer with the uncompressed data up to that point. */ +ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen)); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + /* gzip file access functions */ /* @@ -1290,10 +1367,9 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); default buffer size is 8192 bytes. This function must be called after gzopen() or gzdopen(), and before any other calls that read or write the file. The buffer memory allocation is always deferred to the first read or - write. Two buffers are allocated, either both of the specified size when - writing, or one of the specified size and the other twice that size when - reading. A larger buffer size of, for example, 64K or 128K bytes will - noticeably increase the speed of decompression (reading). + write. Three times that size in buffer space is allocated. A larger buffer + size of, for example, 64K or 128K bytes will noticeably increase the speed + of decompression (reading). The new buffer size also affects the maximum length for gzprintf(). @@ -1304,10 +1380,12 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); /* Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. + of deflateInit2 for the meaning of these parameters. Previously provided + data is flushed before the parameter change. - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. */ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); @@ -1335,7 +1413,35 @@ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); case. gzread returns the number of uncompressed bytes actually read, less than - len for end of file, or -1 for error. + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, + gzFile file)); +/* + Read up to nitems items of size size from file to buf, otherwise operating + as gzread() does. This duplicates the interface of stdio's fread(), with + size_t request and return types. If the library defines size_t, then + z_size_t is identical to size_t. If not, then z_size_t is an unsigned + integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevetheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, reseting and retrying on end-of-file, when size is not 1. */ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, @@ -1346,19 +1452,33 @@ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, error. */ +ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, + z_size_t nitems, gzFile file)); +/* + gzfwrite() writes nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); /* Converts, formats, and writes the arguments to the compressed file under control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written, or 0 in case of error. The number of - uncompressed bytes written is limited to 8191, or one less than the buffer - size given to gzbuffer(). The caller should assure that this limit is not - exceeded. If it is exceeded, then gzprintf() will return an error (0) with - nothing written. In this case, there may also be a buffer overflow with - unpredictable consequences, which is possible only if zlib was compiled with - the insecure functions sprintf() or vsprintf() because the secure snprintf() - or vsnprintf() functions were not available. This can be determined using - zlibCompileFlags(). + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). */ ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); @@ -1418,7 +1538,7 @@ ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); If the flush parameter is Z_FINISH, the remaining data is written and the gzip stream is completed in the output. If gzwrite() is called again, a new gzip stream will be started in the output. gzread() is able to read such - concatented gzip streams. + concatenated gzip streams. gzflush should be called only when strictly necessary because it will degrade compression if called too often. @@ -1572,7 +1692,7 @@ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); return the updated checksum. If buf is Z_NULL, this function returns the required initial value for the checksum. - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed much faster. Usage example: @@ -1585,6 +1705,12 @@ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); if (adler != original_adler) error(); */ +ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as adler32(), but with a size_t length. +*/ + /* ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, z_off_t len2)); @@ -1614,6 +1740,12 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); if (crc != original_crc) error(); */ +ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as crc32(), but with a size_t length. +*/ + /* ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); @@ -1644,19 +1776,35 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size)); -#define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ - (int)sizeof(z_stream)) -#define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, (int)sizeof(z_stream)) +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif #ifndef Z_SOLO @@ -1676,10 +1824,10 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ #ifdef Z_PREFIX_SET # undef z_gzgetc # define z_gzgetc(g) \ - ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) #else # define gzgetc(g) \ - ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g)) + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) #endif /* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or @@ -1737,16 +1885,13 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ #endif /* !Z_SOLO */ -/* hack for buggy compilers */ -#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; -#endif - /* undocumented functions */ ZEXTERN const char * ZEXPORT zError OF((int)); ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); #if defined(_WIN32) && !defined(Z_SOLO) diff --git a/contrib/zlib/zutil.c b/contrib/zlib/zutil.c index 23d2ebef0..dcab28a0d 100644 --- a/contrib/zlib/zutil.c +++ b/contrib/zlib/zutil.c @@ -1,5 +1,5 @@ /* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2005, 2010, 2011, 2012 Jean-loup Gailly. + * Copyright (C) 1995-2017 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -10,21 +10,18 @@ # include "gzguts.h" #endif -#ifndef NO_DUMMY_DECL -struct internal_state {int dummy;}; /* for buggy compilers */ -#endif - z_const char * const z_errmsg[10] = { -"need dictionary", /* Z_NEED_DICT 2 */ -"stream end", /* Z_STREAM_END 1 */ -"", /* Z_OK 0 */ -"file error", /* Z_ERRNO (-1) */ -"stream error", /* Z_STREAM_ERROR (-2) */ -"data error", /* Z_DATA_ERROR (-3) */ -"insufficient memory", /* Z_MEM_ERROR (-4) */ -"buffer error", /* Z_BUF_ERROR (-5) */ -"incompatible version",/* Z_VERSION_ERROR (-6) */ -""}; + (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ + (z_const char *)"stream end", /* Z_STREAM_END 1 */ + (z_const char *)"", /* Z_OK 0 */ + (z_const char *)"file error", /* Z_ERRNO (-1) */ + (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */ + (z_const char *)"data error", /* Z_DATA_ERROR (-3) */ + (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */ + (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */ + (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */ + (z_const char *)"" +}; const char * ZEXPORT zlibVersion() @@ -61,7 +58,7 @@ uLong ZEXPORT zlibCompileFlags() case 8: flags += 2 << 6; break; default: flags += 3 << 6; } -#ifdef DEBUG +#ifdef ZLIB_DEBUG flags += 1 << 8; #endif #if defined(ASMV) || defined(ASMINF) @@ -115,8 +112,8 @@ uLong ZEXPORT zlibCompileFlags() return flags; } -#ifdef DEBUG - +#ifdef ZLIB_DEBUG +#include # ifndef verbose # define verbose 0 # endif @@ -139,8 +136,8 @@ const char * ZEXPORT zError(err) return ERR_MSG(err); } -#if defined(_WIN32_WCE) - /* The Microsoft C Run-Time Library for Windows CE doesn't have +#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800 + /* The older Microsoft C Run-Time Library for Windows CE doesn't have * errno. We define it as a global variable to simplify porting. * Its value is always 0 and should not be used. */ @@ -219,9 +216,11 @@ local ptr_table table[MAX_PTR]; voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) { - voidpf buf = opaque; /* just to make some compilers happy */ + voidpf buf; ulg bsize = (ulg)items*size; + (void)opaque; + /* If we allocate less than 65520 bytes, we assume that farmalloc * will return a usable pointer which doesn't have to be normalized. */ @@ -244,6 +243,9 @@ voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) { int n; + + (void)opaque; + if (*(ush*)&ptr != 0) { /* object < 64K */ farfree(ptr); return; @@ -259,7 +261,6 @@ void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) next_ptr--; return; } - ptr = opaque; /* just to make some compilers happy */ Assert(0, "zcfree: ptr not found"); } @@ -278,13 +279,13 @@ void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) { - if (opaque) opaque = 0; /* to make compiler happy */ + (void)opaque; return _halloc((long)items, size); } void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) { - if (opaque) opaque = 0; /* to make compiler happy */ + (void)opaque; _hfree(ptr); } @@ -306,7 +307,7 @@ voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) unsigned items; unsigned size; { - if (opaque) items += size - size; /* make compiler happy */ + (void)opaque; return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : (voidpf)calloc(items, size); } @@ -315,8 +316,8 @@ void ZLIB_INTERNAL zcfree (opaque, ptr) voidpf opaque; voidpf ptr; { + (void)opaque; free(ptr); - if (opaque) return; /* make compiler happy */ } #endif /* MY_ZCALLOC */ diff --git a/contrib/zlib/zutil.h b/contrib/zlib/zutil.h index 24ab06b1c..60a0bca79 100644 --- a/contrib/zlib/zutil.h +++ b/contrib/zlib/zutil.h @@ -1,5 +1,5 @@ /* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2013 Jean-loup Gailly. + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -29,14 +29,12 @@ # include #endif -#ifdef Z_SOLO - typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ -#endif - #ifndef local # define local static #endif -/* compile with -Dlocal if your debugger can't find static symbols */ +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ typedef unsigned char uch; typedef uch FAR uchf; @@ -98,28 +96,38 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #endif #ifdef AMIGA -# define OS_CODE 0x01 +# define OS_CODE 1 #endif #if defined(VAXC) || defined(VMS) -# define OS_CODE 0x02 +# define OS_CODE 2 # define F_OPEN(name, mode) \ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") #endif +#ifdef __370__ +# if __TARGET_LIB__ < 0x20000000 +# define OS_CODE 4 +# elif __TARGET_LIB__ < 0x40000000 +# define OS_CODE 11 +# else +# define OS_CODE 8 +# endif +#endif + #if defined(ATARI) || defined(atarist) -# define OS_CODE 0x05 +# define OS_CODE 5 #endif #ifdef OS2 -# define OS_CODE 0x06 +# define OS_CODE 6 # if defined(M_I86) && !defined(Z_SOLO) # include # endif #endif #if defined(MACOS) || defined(TARGET_OS_MAC) -# define OS_CODE 0x07 +# define OS_CODE 7 # ifndef Z_SOLO # if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os # include /* for fdopen */ @@ -131,18 +139,24 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ # endif #endif -#ifdef TOPS20 -# define OS_CODE 0x0a +#ifdef __acorn +# define OS_CODE 13 #endif -#ifdef WIN32 -# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ -# define OS_CODE 0x0b -# endif +#if defined(WIN32) && !defined(__CYGWIN__) +# define OS_CODE 10 #endif -#ifdef __50SERIES /* Prime/PRIMOS */ -# define OS_CODE 0x0f +#ifdef _BEOS_ +# define OS_CODE 16 +#endif + +#ifdef __TOS_OS400__ +# define OS_CODE 18 +#endif + +#ifdef __APPLE__ +# define OS_CODE 19 #endif #if defined(_BEOS_) || defined(RISCOS) @@ -152,10 +166,6 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX # if defined(_WIN32_WCE) # define fdopen(fd,mode) NULL /* No fdopen() */ -# ifndef _PTRDIFF_T_DEFINED - typedef int ptrdiff_t; -# define _PTRDIFF_T_DEFINED -# endif # else # define fdopen(fd,type) _fdopen(fd,type) # endif @@ -177,7 +187,7 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ /* common defaults */ #ifndef OS_CODE -# define OS_CODE 0x03 /* assume Unix */ +# define OS_CODE 3 /* assume Unix */ #endif #ifndef F_OPEN @@ -216,7 +226,7 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ #endif /* Diagnostic functions */ -#ifdef DEBUG +#ifdef ZLIB_DEBUG # include extern int ZLIB_INTERNAL z_verbose; extern void ZLIB_INTERNAL z_error OF((char *m)); diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 000000000..f7ce7b726 --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,42 @@ +find_package( Doxygen REQUIRED ) + +set( HTML_OUTPUT "AssimpDoc_Html" CACHE STRING "Output directory for generated HTML documentation. Defaults to AssimpDoc_Html." ) + +# Enable Microsoft CHM help style only on Windows +set( MICROSOFT_HELP_WORKSHOP "NO") +if( MSVC ) + set( MICROSOFT_HELP_WORKSHOP "YES" ) +endif( MSVC ) + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in + ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + @ONLY +) + +add_custom_target( + docs ALL + DEPENDS docs.done +) + +add_custom_command( + OUTPUT docs.done + COMMAND ${DOXYGEN_EXECUTABLE} + COMMAND ${CMAKE_COMMAND} -E touch docs.done + COMMENT "Generating assimp documentation" + VERBATIM + ) + +if( DEFINED CMAKE_INSTALL_DOCDIR ) + install( + DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${HTML_OUTPUT} + DESTINATION ${CMAKE_INSTALL_DOCDIR} + ) + install(FILES + ${CMAKE_CURRENT_SOURCE_DIR}/AssimpDoc_Html/AnimationOverview.png + ${CMAKE_CURRENT_SOURCE_DIR}/AssimpDoc_Html/AnimationOverview.svg + ${CMAKE_CURRENT_SOURCE_DIR}/AssimpDoc_Html/dragonsplash.png + DESTINATION ${CMAKE_INSTALL_DOCDIR}/${HTML_OUTPUT} + ) +endif( DEFINED CMAKE_INSTALL_DOCDIR ) + diff --git a/doc/Doxyfile b/doc/Doxyfile.in similarity index 97% rename from doc/Doxyfile rename to doc/Doxyfile.in index 64dd5d2cc..ffe39f9f7 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile.in @@ -32,7 +32,7 @@ PROJECT_NAME = Assimp # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = "v3.1.1 (June 2014)" +PROJECT_NUMBER = "v4.1. (December 2018)" # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer @@ -140,7 +140,8 @@ FULL_PATH_NAMES = NO # relative paths, which will be relative from the directory where doxygen is # started. -STRIP_FROM_PATH = +STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@ \ + @PROJECT_BINARY_DIR@ # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells @@ -339,22 +340,6 @@ INLINE_SIMPLE_STRUCTS = NO TYPEDEF_HIDES_STRUCT = YES -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penalty. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will roughly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols. - -SYMBOL_CACHE_SIZE = 0 - # Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be # set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given # their name and scope. Since this can be an expensive process and often the @@ -677,9 +662,12 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../include/ \ - ../doc/dox.h \ - ../code/BaseImporter.h +INPUT = @doxy_main_page@ \ + @PROJECT_SOURCE_DIR@ \ + @PROJECT_BINARY_DIR@ \ + @PROJECT_SOURCE_DIR@/include/ \ + @PROJECT_SOURCE_DIR@/doc/dox.h \ + @PROJECT_SOURCE_DIR@/code/BaseImporter.h # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -737,7 +725,7 @@ RECURSIVE = YES # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = +EXCLUDE = irrXML.h # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded @@ -919,7 +907,7 @@ GENERATE_HTML = YES # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. -HTML_OUTPUT = AssimpDoc_Html +HTML_OUTPUT = @HTML_OUTPUT@ # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank @@ -953,7 +941,7 @@ HTML_FOOTER = # HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this # tag will in the future become obsolete. -HTML_STYLESHEET = style.css +# HTML_STYLESHEET = @CMAKE_CURRENT_SOURCE_DIR@/style.css # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional # user-defined cascading style sheet that is included after the standard @@ -1064,7 +1052,7 @@ DOCSET_PUBLISHER_NAME = Publisher # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. -GENERATE_HTMLHELP = YES +GENERATE_HTMLHELP = @MICROSOFT_HELP_WORKSHOP@ # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You @@ -1504,18 +1492,6 @@ GENERATE_XML = NO XML_OUTPUT = xml -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that @@ -1766,7 +1742,7 @@ UML_LOOK = NO # the class node. If there are many fields or methods and many nodes the # graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS # threshold limits the number of items for each type to make the size more -# managable. Set this to 0 for no limit. Note that the threshold may be +# manageable. Set this to 0 for no limit. Note that the threshold may be # exceeded by 50% before the limit is enforced. UML_LIMIT_NUM_FIELDS = 10 diff --git a/doc/Preamble.txt b/doc/Preamble.txt index 0722a48e1..102b2792d 100644 --- a/doc/Preamble.txt +++ b/doc/Preamble.txt @@ -3,12 +3,12 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2012, assimp team +Copyright (c) 2006-2017, 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 +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 @@ -25,16 +25,16 @@ conditions are met: 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 +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 +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 +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 +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. --------------------------------------------------------------------------- -*/ \ No newline at end of file +*/ diff --git a/doc/architecture/Assimp_Arch_Import.class.violet.html b/doc/architecture/Assimp_Arch_Import.class.violet.html index a7ed8c6ce..264468f98 100644 --- a/doc/architecture/Assimp_Arch_Import.class.violet.html +++ b/doc/architecture/Assimp_Arch_Import.class.violet.html @@ -20,8 +20,8 @@ - - + + 1 255 @@ -37,620 +37,318 @@ - Assimpo::Exporter + Importer - aiScene* mScene; -IOSystem* mIOHandler; -struct ExportFormatEntry { - aiExportFormatDesc mDescription; - fpExportFunc mExportFunction; -}; - + - const aiExportDataBlob* ExportToBlob( const aiScene* pScene, ... ); -const aiExportDataBlob* ExportToBlob( const aiScene* pScene, ...); -aiReturn Export( const aiScene* pScene, ... ); -aiReturn Export( const aiScene* pScene, ...); - - + RegisterLoader() +UnregisterLoader() +ReadFile() - - - 1 - - 255 - 255 - 255 - 255 - - - 0 - 0 - 0 - 255 - - - - IOSystem - - - - - - bool Exists( const std::string& pFile) const; -bool Exists( const char* pFile) const; -virtual char getOsSeparator() const; - -virtual IOStream* Open(const char* pFile, - const char* pMode = "rb"); -IOStream* Open(const std::string& pFile, const std::string& pMode = std::string("rb")); -void Close( IOStream* pFile); - - - - - - - - + + 1 - - ObjExporter + + IOSystem - - File contains function pointer: -ExportSceneObj + + - + + + + + + 1 + + + + + BaseImporter + + + + + + CanRead() +InternRead() + + + + + + + 1 + + + + + ObjImporter + + + + + + CanRead() +InternRead() + + + + + + + 1 + + + + + glTFImporter + + + + + + CanRead() +InternRead() + + - - - - - - - - - 1 - - - - - - - - - 1 - - - - - - - - - 1 - - - - - - + + + + + + - + 1 - - - - - - - - + + + + + + + + + + + + 1 - - - - - - + + + + + + + + + + - + 1 - - - - - - - + + + + + + + 1 - - - - - - - - + + + + + + + + + + + + 1 - - - - - - - - - 1 - + + + + + ]]>

- embedded diagram image + embedded diagram image \ No newline at end of file diff --git a/doc/architecture/Assimp_Arch_export.class.violet.html b/doc/architecture/Assimp_Arch_export.class.violet.html new file mode 100644 index 000000000..85f68d68d --- /dev/null +++ b/doc/architecture/Assimp_Arch_export.class.violet.html @@ -0,0 +1,648 @@ + + + + + + + + + This file was generated with Violet UML Editor 2.1.0. +   ( View Source / Download Violet ) +
+
+ +
+
+ embedded diagram image + + \ No newline at end of file diff --git a/doc/architecture/assimp-process.png b/doc/architecture/assimp-process.png new file mode 100644 index 000000000..6507cb34c Binary files /dev/null and b/doc/architecture/assimp-process.png differ diff --git a/doc/architecture/assimp_usecase.ucase.violet.html b/doc/architecture/assimp_usecase.ucase.violet.html new file mode 100644 index 000000000..3045add42 --- /dev/null +++ b/doc/architecture/assimp_usecase.ucase.violet.html @@ -0,0 +1,875 @@ + + + + + + + + + This file was generated with Violet UML Editor 2.1.0. +   ( View Source / Download Violet ) +
+
+ +
+
+ embedded diagram image + + \ No newline at end of file diff --git a/doc/architecture/exporter.png b/doc/architecture/exporter.png new file mode 100644 index 000000000..b2e5b3d93 Binary files /dev/null and b/doc/architecture/exporter.png differ diff --git a/doc/architecture/process.class.violet.html b/doc/architecture/process.class.violet.html new file mode 100644 index 000000000..d4f77d909 --- /dev/null +++ b/doc/architecture/process.class.violet.html @@ -0,0 +1,337 @@ + + + + + + + + + This file was generated with Violet UML Editor 2.1.0. +   ( View Source / Download Violet ) +
+
+ +
+
+ embedded diagram image + + \ No newline at end of file diff --git a/doc/architecture/usecases.png b/doc/architecture/usecases.png new file mode 100644 index 000000000..584ebc890 Binary files /dev/null and b/doc/architecture/usecases.png differ diff --git a/doc/dox.h b/doc/dox.h index f051e5c00..2672adcb5 100644 --- a/doc/dox.h +++ b/doc/dox.h @@ -60,7 +60,7 @@ that it has not been implemented yet and some (most ...) formats lack proper spe Stanford Ply ( *.ply )
TrueSpace ( *.cob, *.scn )2

-See the @link importer_notes Importer Notes Page @endlink for informations, what a specific importer can do and what not. +See the @link importer_notes Importer Notes Page @endlink for information, what a specific importer can do and what not. Note that although this paper claims to be the official documentation, http://assimp.sourceforge.net/main_features_formats.html
is usually the most up-to-date list of file formats supported by the library.
@@ -81,7 +81,7 @@ formats handle the required endian conversion correctly, so large parts of the l The assimp linker library and viewer application are provided under the BSD 3-clause license. This basically means that you are free to use it in open- or closed-source projects, for commercial or non-commercial purposes as you like -as long as you retain the license informations and take own responsibility for what you do with it. For details see +as long as you retain the license information and take own responsibility for what you do with it. For details see the LICENSE file. You can find test models for almost all formats in the /test/models directory. Beware, they're *free*, @@ -453,7 +453,7 @@ by calling it as a singleton with the requested logging-type. To see how this wo using namespace Assimp; // Create a logger instance -DefaultLogger::create("",Logger::VERBOSE); +DefaultLogger::create("", Logger::VERBOSE); // Now I am ready for logging my stuff DefaultLogger::get()->info("this is my info-call"); @@ -472,22 +472,9 @@ Just derivate your own logger from the abstract base class LogStream and overwri @code // Example stream -class myStream : - public LogStream +class myStream : public LogStream { public: - // Constructor - myStream() - { - // empty - } - - // Destructor - ~myStream() - { - // empty - } - // Write womethink using your own functionality void write(const char* message) { @@ -496,10 +483,10 @@ public: }; // Select the kinds of messages you want to receive on this log stream -const unsigned int severity = Logger::DEBUGGING|Logger::INFO|Logger::ERR|Logger::WARN; +const unsigned int severity = Logger::Debugging|Logger::Info|Logger::Err|Logger::Warn; // Attaching it to the default logger -Assimp::DefaultLogger::get()->attachStream( new myStream(), severity ); +Assimp::DefaultLogger::get()->attachStream( new myStream, severity ); @endcode @@ -512,10 +499,10 @@ flag set: @code unsigned int severity = 0; -severity |= Logger::DEBUGGING; +severity |= Logger::Debugging; // Detach debug messages from you self defined stream -Assimp::DefaultLogger::get()->attachStream( new myStream(), severity ); +Assimp::DefaultLogger::get()->attachStream( new myStream, severity ); @endcode @@ -743,6 +730,8 @@ need them at all. Normally textures used by assets are stored in separate files, however, there are file formats embedding their textures directly into the model file. Such textures are loaded into an aiTexture structure. +For embedded textures, the value of `AI_MATKEY_TEXTURE(textureType, index)` will be `*` where +`` is the index of the texture in aiScene::mTextures.
There are two cases:
@@ -930,7 +919,7 @@ All material key constants start with 'AI_MATKEY' (it's an ugly macro for histor TEXTURE(t,n) aiString n/a - Defines the path to the n'th texture on the stack 't', where 'n' is any value >= 0 and 't' is one of the #aiTextureType enumerated values. + Defines the path of the n'th texture on the stack 't', where 'n' is any value >= 0 and 't' is one of the #aiTextureType enumerated values. Either a filepath or `*`, where `` is the index of an embedded texture in aiScene::mTextures. See the 'Textures' section above. @@ -1431,7 +1420,7 @@ IFC file properties (IfcPropertySet) are kept as per-node metadata, see aiNode:: This section contains implementations notes for the OgreXML importer. @subsection overview Overview -Ogre importer is currently optimized for the Blender Ogre exporter, because thats the only one that I use. You can find the Blender Ogre exporter at: http://www.ogre3d.org/forums/viewtopic.php?f=8&t=45922 +Ogre importer is currently optimized for the Blender Ogre exporter, because that's the only one that I use. You can find the Blender Ogre exporter at: http://www.ogre3d.org/forums/viewtopic.php?f=8&t=45922 @subsection what What will be loaded? @@ -1445,7 +1434,7 @@ Skeleton: Skeleton with Bone hierarchy (Position and Rotation, but no Scaling in animations with rotation, translation and scaling keys. @subsection export_Blender How to export Files from Blender -You can find informations about how to use the Ogreexporter by your own, so here are just some options that you need, so the assimp +You can find information about how to use the Ogreexporter by your own, so here are just some options that you need, so the assimp importer will load everything correctly: - Use either "Rendering Material" or "Custom Material" see @ref material - do not use "Flip Up Axies to Y" @@ -1554,7 +1543,7 @@ Done! Please, share your loader that everyone can profit from it! @section properties Properties -You can use properties to chance the behavior of you importer. In order to do so, you have to overide BaseImporter::SetupProperties, and specify +You can use properties to chance the behavior of you importer. In order to do so, you have to override BaseImporter::SetupProperties, and specify you custom properties in config.h. Just have a look to the other AI_CONFIG_IMPORT_* defines and you will understand, how it works. The properties can be set with Importer::SetProperty***() and can be accessed in your SetupProperties function with Importer::GetProperty***(). You can diff --git a/code/DefaultIOStream.h b/include/assimp/DefaultIOStream.h similarity index 98% rename from code/DefaultIOStream.h rename to include/assimp/DefaultIOStream.h index 294c5b797..3668b27ec 100644 --- a/code/DefaultIOStream.h +++ b/include/assimp/DefaultIOStream.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -45,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include -#include "Defines.h" +#include namespace Assimp { diff --git a/code/DefaultIOSystem.h b/include/assimp/DefaultIOSystem.h similarity index 97% rename from code/DefaultIOSystem.h rename to include/assimp/DefaultIOSystem.h index 49960a847..d7cf031cf 100644 --- a/code/DefaultIOSystem.h +++ b/include/assimp/DefaultIOSystem.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -48,7 +49,7 @@ namespace Assimp { // --------------------------------------------------------------------------- /** Default implementation of IOSystem using the standard C file functions */ -class DefaultIOSystem : public IOSystem +class ASSIMP_API DefaultIOSystem : public IOSystem { public: /** Constructor. */ diff --git a/include/assimp/DefaultLogger.hpp b/include/assimp/DefaultLogger.hpp index 52574d5ea..4f1a7e1f4 100644 --- a/include/assimp/DefaultLogger.hpp +++ b/include/assimp/DefaultLogger.hpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/Defines.h b/include/assimp/Defines.h similarity index 100% rename from code/Defines.h rename to include/assimp/Defines.h diff --git a/include/assimp/Exporter.hpp b/include/assimp/Exporter.hpp index c2531420b..c6a6f684a 100644 --- a/include/assimp/Exporter.hpp +++ b/include/assimp/Exporter.hpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -170,7 +171,7 @@ public: * Any IO handlers set via #SetIOHandler are ignored here. * @note Use aiCopyScene() to get a modifiable copy of a previously * imported scene. */ - const aiExportDataBlob* ExportToBlob( const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL); + const aiExportDataBlob* ExportToBlob(const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing = 0u, const ExportProperties* = NULL); const aiExportDataBlob* ExportToBlob( const aiScene* pScene, const std::string& pFormatId, unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = NULL); // ------------------------------------------------------------------- @@ -296,8 +297,7 @@ protected: ExporterPimpl* pimpl; }; -class ASSIMP_API ExportProperties -{ +class ASSIMP_API ExportProperties { public: // Data type to store the key hash typedef unsigned int KeyType; diff --git a/include/assimp/IOStream.hpp b/include/assimp/IOStream.hpp index b0bc5ebb6..ce5907a47 100644 --- a/include/assimp/IOStream.hpp +++ b/include/assimp/IOStream.hpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/include/assimp/IOSystem.hpp b/include/assimp/IOSystem.hpp index 83d927453..f4fbb6023 100644 --- a/include/assimp/IOSystem.hpp +++ b/include/assimp/IOSystem.hpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -55,10 +56,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "types.h" +#ifdef _WIN32 +# include +# include +# include +#else +# include +# include +# include +#endif // _WIN32 + #include namespace Assimp { -class IOStream; + + class IOStream; // --------------------------------------------------------------------------- /** @brief CPP-API: Interface to the file system. @@ -197,20 +209,37 @@ public: */ virtual bool PopDirectory(); + // ------------------------------------------------------------------- + /** @brief CReates an new directory at the given path. + * @param path [in] The path to create. + * @return True, when a directory was created. False if the directory + * cannot be created. + */ + virtual bool CreateDirectory( const std::string &path ); + + // ------------------------------------------------------------------- + /** @brief Will change the current directory to the given path. + * @param path [in] The path to change to. + * @return True, when the directory has changed successfully. + */ + virtual bool ChangeDirectory( const std::string &path ); + + virtual bool DeleteFile( const std::string &file ); + private: std::vector m_pathStack; }; // ---------------------------------------------------------------------------- -AI_FORCE_INLINE IOSystem::IOSystem() : - m_pathStack() -{ +AI_FORCE_INLINE +IOSystem::IOSystem() +: m_pathStack() { // empty } // ---------------------------------------------------------------------------- -AI_FORCE_INLINE IOSystem::~IOSystem() -{ +AI_FORCE_INLINE +IOSystem::~IOSystem() { // empty } @@ -221,9 +250,8 @@ AI_FORCE_INLINE IOSystem::~IOSystem() // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- -AI_FORCE_INLINE IOStream* IOSystem::Open(const std::string& pFile, - const std::string& pMode) -{ +AI_FORCE_INLINE +IOStream* IOSystem::Open(const std::string& pFile, const std::string& pMode) { // NOTE: // For compatibility, interface was changed to const char* to // avoid crashes between binary incompatible STL versions @@ -231,8 +259,8 @@ AI_FORCE_INLINE IOStream* IOSystem::Open(const std::string& pFile, } // ---------------------------------------------------------------------------- -AI_FORCE_INLINE bool IOSystem::Exists( const std::string& pFile) const -{ +AI_FORCE_INLINE +bool IOSystem::Exists( const std::string& pFile) const { // NOTE: // For compatibility, interface was changed to const char* to // avoid crashes between binary incompatible STL versions @@ -240,9 +268,8 @@ AI_FORCE_INLINE bool IOSystem::Exists( const std::string& pFile) const } // ---------------------------------------------------------------------------- -inline bool IOSystem::ComparePaths (const std::string& one, - const std::string& second) const -{ +AI_FORCE_INLINE +bool IOSystem::ComparePaths (const std::string& one, const std::string& second) const { // NOTE: // For compatibility, interface was changed to const char* to // avoid crashes between binary incompatible STL versions @@ -250,7 +277,8 @@ inline bool IOSystem::ComparePaths (const std::string& one, } // ---------------------------------------------------------------------------- -inline bool IOSystem::PushDirectory( const std::string &path ) { +AI_FORCE_INLINE +bool IOSystem::PushDirectory( const std::string &path ) { if ( path.empty() ) { return false; } @@ -261,7 +289,8 @@ inline bool IOSystem::PushDirectory( const std::string &path ) { } // ---------------------------------------------------------------------------- -inline const std::string &IOSystem::CurrentDirectory() const { +AI_FORCE_INLINE +const std::string &IOSystem::CurrentDirectory() const { if ( m_pathStack.empty() ) { static const std::string Dummy(""); return Dummy; @@ -270,12 +299,14 @@ inline const std::string &IOSystem::CurrentDirectory() const { } // ---------------------------------------------------------------------------- -inline size_t IOSystem::StackSize() const { +AI_FORCE_INLINE +size_t IOSystem::StackSize() const { return m_pathStack.size(); } // ---------------------------------------------------------------------------- -inline bool IOSystem::PopDirectory() { +AI_FORCE_INLINE +bool IOSystem::PopDirectory() { if ( m_pathStack.empty() ) { return false; } @@ -286,7 +317,43 @@ inline bool IOSystem::PopDirectory() { } // ---------------------------------------------------------------------------- +AI_FORCE_INLINE +bool IOSystem::CreateDirectory( const std::string &path ) { + if ( path.empty() ) { + return false; + } +#ifdef _WIN32 + return 0 != ::_mkdir( path.c_str() ); +#else + return 0 != ::mkdir( path.c_str(), 0777 ); +#endif // _WIN32 +} + +// ---------------------------------------------------------------------------- +AI_FORCE_INLINE +bool IOSystem::ChangeDirectory( const std::string &path ) { + if ( path.empty() ) { + return false; + } + +#ifdef _WIN32 + return 0 != ::_chdir( path.c_str() ); +#else + return 0 != ::chdir( path.c_str() ); +#endif // _WIN32 +} + + +// ---------------------------------------------------------------------------- +AI_FORCE_INLINE +bool IOSystem::DeleteFile( const std::string &file ) { + if ( file.empty() ) { + return false; + } + const int retCode( ::remove( file.c_str() ) ); + return ( 0 == retCode ); +} } //!ns Assimp #endif //AI_IOSYSTEM_H_INC diff --git a/include/assimp/Importer.hpp b/include/assimp/Importer.hpp index 810a5fff5..f42a2deaf 100644 --- a/include/assimp/Importer.hpp +++ b/include/assimp/Importer.hpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -52,13 +53,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Public ASSIMP data structures #include -#include namespace Assimp { // ======================================================================= // Public interface to Assimp class Importer; - class Exporter; // export.hpp class IOStream; class IOSystem; class ProgressHandler; @@ -77,7 +76,6 @@ namespace Assimp { // ======================================================================= // Holy stuff, only for members of the high council of the Jedi. class ImporterPimpl; - class ExporterPimpl; // export.hpp } //! namespace Assimp #define AI_PROPERTY_WAS_NOT_EXISTING 0xffffffff diff --git a/include/assimp/LogStream.hpp b/include/assimp/LogStream.hpp index 477fe5321..1052f1fda 100644 --- a/include/assimp/LogStream.hpp +++ b/include/assimp/LogStream.hpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -43,8 +44,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef INCLUDED_AI_LOGSTREAM_H #define INCLUDED_AI_LOGSTREAM_H + #include "types.h" + namespace Assimp { + class IOSystem; // ------------------------------------------------------------------------------------ @@ -60,12 +64,11 @@ class ASSIMP_API LogStream { protected: /** @brief Default constructor */ - LogStream() { - } + LogStream(); + public: /** @brief Virtual destructor */ - virtual ~LogStream() { - } + virtual ~LogStream(); // ------------------------------------------------------------------- /** @brief Overwrite this for your own output methods @@ -90,6 +93,17 @@ public: IOSystem* io = NULL); }; // !class LogStream + +inline +LogStream::LogStream() { + // empty +} + +inline +LogStream::~LogStream() { + // empty +} + // ------------------------------------------------------------------------------------ } // Namespace Assimp diff --git a/include/assimp/Logger.hpp b/include/assimp/Logger.hpp index 7f355b5bf..0875b6d7d 100644 --- a/include/assimp/Logger.hpp +++ b/include/assimp/Logger.hpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -45,7 +46,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_LOGGER_H #include "types.h" -namespace Assimp { + +namespace Assimp { + class LogStream; // Maximum length of a log message. Longer messages are rejected. diff --git a/include/assimp/NullLogger.hpp b/include/assimp/NullLogger.hpp index 64b59a4a0..191db1aaa 100644 --- a/include/assimp/NullLogger.hpp +++ b/include/assimp/NullLogger.hpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -46,7 +47,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_NULLLOGGER_H #include "Logger.hpp" -namespace Assimp { + +namespace Assimp { + // --------------------------------------------------------------------------- /** @brief CPP-API: Empty logging implementation. * diff --git a/include/assimp/ProgressHandler.hpp b/include/assimp/ProgressHandler.hpp index 1ac016efb..2c5b2f4c5 100644 --- a/include/assimp/ProgressHandler.hpp +++ b/include/assimp/ProgressHandler.hpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/code/SceneCombiner.h b/include/assimp/SceneCombiner.h similarity index 97% rename from code/SceneCombiner.h rename to include/assimp/SceneCombiner.h index a6ba06768..aa57406b9 100644 --- a/code/SceneCombiner.h +++ b/include/assimp/SceneCombiner.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -46,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#include "Defines.h" +#include #include #include #include @@ -142,7 +143,6 @@ struct NodeAttachmentInfo */ #define AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY 0x10 - typedef std::pair BoneSrcIndex; // --------------------------------------------------------------------------- @@ -152,7 +152,6 @@ struct BoneWithHash : public std::pair { std::vector pSrcBones; }; - // --------------------------------------------------------------------------- /** @brief Utility for SceneCombiner */ @@ -198,13 +197,17 @@ struct SceneHelper * The class is currently being used by various postprocessing steps * and loaders (ie. LWS). */ -class ASSIMP_API SceneCombiner -{ +class ASSIMP_API SceneCombiner { // class cannot be instanced - SceneCombiner() {} + SceneCombiner() { + // empty + } + + ~SceneCombiner() { + // empty + } public: - // ------------------------------------------------------------------- /** Merges two or more scenes. * @@ -218,10 +221,9 @@ public: static void MergeScenes(aiScene** dest,std::vector& src, unsigned int flags = 0); - // ------------------------------------------------------------------- - /** Merges two or more scenes and attaches all sceenes to a specific - * position in the node graph of the masteer scene. + /** Merges two or more scenes and attaches all scenes to a specific + * position in the node graph of the master scene. * * @param dest Receives a pointer to the destination scene. If the * pointer doesn't point to NULL when the function is called, the @@ -237,7 +239,6 @@ public: std::vector& src, unsigned int flags = 0); - // ------------------------------------------------------------------- /** Merges two or more meshes * @@ -256,7 +257,6 @@ public: std::vector::const_iterator begin, std::vector::const_iterator end); - // ------------------------------------------------------------------- /** Merges two or more bones * diff --git a/include/assimp/ai_assert.h b/include/assimp/ai_assert.h index fa63c329c..d8dbac8d2 100644 --- a/include/assimp/ai_assert.h +++ b/include/assimp/ai_assert.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/include/assimp/anim.h b/include/assimp/anim.h index 2a0b0e06e..f8774b8fd 100644 --- a/include/assimp/anim.h +++ b/include/assimp/anim.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -190,6 +191,39 @@ struct aiMeshKey #endif }; +// --------------------------------------------------------------------------- +/** Binds a morph anim mesh to a specific point in time. */ +struct aiMeshMorphKey +{ + /** The time of this key */ + double mTime; + + /** The values and weights at the time of this key */ + unsigned int *mValues; + double *mWeights; + + /** The number of values and weights */ + unsigned int mNumValuesAndWeights; +#ifdef __cplusplus + aiMeshMorphKey() + : mTime(0.0) + , mValues(NULL) + , mWeights(NULL) + , mNumValuesAndWeights(0) + { + + } + + ~aiMeshMorphKey() + { + if (mNumValuesAndWeights && mValues && mWeights) { + delete [] mValues; + delete [] mWeights; + } + } +#endif +}; + // --------------------------------------------------------------------------- /** Defines how an animation channel behaves outside the defined time * range. This corresponds to aiNodeAnim::mPreState and @@ -340,6 +374,37 @@ struct aiMeshAnim #endif }; +// --------------------------------------------------------------------------- +/** Describes a morphing animation of a given mesh. */ +struct aiMeshMorphAnim +{ + /** Name of the mesh to be animated. An empty string is not allowed, + * animated meshes need to be named (not necessarily uniquely, + * the name can basically serve as wildcard to select a group + * of meshes with similar animation setup)*/ + C_STRUCT aiString mName; + + /** Size of the #mKeys array. Must be 1, at least. */ + unsigned int mNumKeys; + + /** Key frames of the animation. May not be NULL. */ + C_STRUCT aiMeshMorphKey* mKeys; + +#ifdef __cplusplus + + aiMeshMorphAnim() + : mNumKeys() + , mKeys() + {} + + ~aiMeshMorphAnim() + { + delete[] mKeys; + } + +#endif +}; + // --------------------------------------------------------------------------- /** An animation consists of key-frame data for a number of nodes. For * each node affected by the animation a separate series of data is given.*/ @@ -372,14 +437,24 @@ struct aiAnimation { * The array is mNumMeshChannels in size. */ C_STRUCT aiMeshAnim** mMeshChannels; + /** The number of mesh animation channels. Each channel affects + * a single mesh and defines morphing animation. */ + unsigned int mNumMorphMeshChannels; + + /** The morph mesh animation channels. Each channel affects a single mesh. + * The array is mNumMorphMeshChannels in size. */ + C_STRUCT aiMeshMorphAnim **mMorphMeshChannels; + #ifdef __cplusplus aiAnimation() : mDuration(-1.) , mTicksPerSecond(0.) , mNumChannels(0) - , mChannels(nullptr) + , mChannels(NULL) , mNumMeshChannels(0) - , mMeshChannels(nullptr) { + , mMeshChannels(NULL) + , mNumMorphMeshChannels(0) + , mMorphMeshChannels(NULL) { // empty } @@ -399,6 +474,13 @@ struct aiAnimation { delete [] mMeshChannels; } + if (mNumMorphMeshChannels && mMorphMeshChannels) { + for( unsigned int a = 0; a < mNumMorphMeshChannels; a++) { + delete mMorphMeshChannels[a]; + } + + delete [] mMorphMeshChannels; + } } #endif // __cplusplus }; diff --git a/include/assimp/camera.h b/include/assimp/camera.h index 6b9fbbea5..7b7bd0922 100644 --- a/include/assimp/camera.h +++ b/include/assimp/camera.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/include/assimp/cexport.h b/include/assimp/cexport.h index f77d23c05..44b06fb3c 100644 --- a/include/assimp/cexport.h +++ b/include/assimp/cexport.h @@ -49,7 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_NO_EXPORT // Public ASSIMP data structures -#include #include #ifdef __cplusplus diff --git a/include/assimp/cfileio.h b/include/assimp/cfileio.h index 5f46f7c4c..63eeb59b0 100644 --- a/include/assimp/cfileio.h +++ b/include/assimp/cfileio.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/include/assimp/cimport.h b/include/assimp/cimport.h index 6d3fa4aea..8aa125c67 100644 --- a/include/assimp/cimport.h +++ b/include/assimp/cimport.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -46,7 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_ASSIMP_H_INC #define AI_ASSIMP_H_INC -#include #include #include "importerdesc.h" @@ -417,7 +417,7 @@ ASSIMP_API void aiSetImportPropertyInteger( ASSIMP_API void aiSetImportPropertyFloat( C_STRUCT aiPropertyStore* store, const char* szName, - float value); + ai_real value); // -------------------------------------------------------------------------------- /** Set a string property. diff --git a/include/assimp/color4.h b/include/assimp/color4.h index 6cd6a35b3..48e7aad30 100644 --- a/include/assimp/color4.h +++ b/include/assimp/color4.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -45,7 +46,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_COLOR4D_H_INC #define AI_COLOR4D_H_INC -#include "./Compiler/pushpack1.h" #include "defs.h" #ifdef __cplusplus @@ -89,7 +89,7 @@ public: // Red, green, blue and alpha color values TReal r, g, b, a; -} PACK_STRUCT; // !struct aiColor4D +}; // !struct aiColor4D typedef aiColor4t aiColor4D; @@ -97,10 +97,8 @@ typedef aiColor4t aiColor4D; struct aiColor4D { ai_real r, g, b, a; -} PACK_STRUCT; +}; #endif // __cplusplus -#include "./Compiler/poppack1.h" - #endif // AI_COLOR4D_H_INC diff --git a/include/assimp/color4.inl b/include/assimp/color4.inl index 219372ef2..b242c4e77 100644 --- a/include/assimp/color4.inl +++ b/include/assimp/color4.inl @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -76,12 +77,32 @@ AI_FORCE_INLINE const aiColor4t& aiColor4t::operator /= (TReal f) // ------------------------------------------------------------------------------------------------ template AI_FORCE_INLINE TReal aiColor4t::operator[](unsigned int i) const { - return *(&r + i); + switch ( i ) { + case 0: + return r; + case 1: + return g; + case 2: + return b; + default: + break; + } + return r; } // ------------------------------------------------------------------------------------------------ template AI_FORCE_INLINE TReal& aiColor4t::operator[](unsigned int i) { - return *(&r + i); + switch ( i ) { + case 0: + return r; + case 1: + return g; + case 2: + return b; + default: + break; + } + return r; } // ------------------------------------------------------------------------------------------------ template diff --git a/include/assimp/config.h.in b/include/assimp/config.h.in index 148a68868..1dabae7cf 100644 --- a/include/assimp/config.h.in +++ b/include/assimp/config.h.in @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team All rights reserved. @@ -266,6 +266,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_CONFIG_PP_FD_REMOVE \ "PP_FD_REMOVE" +// --------------------------------------------------------------------------- +/** + * @brief Configures the #aiProcess_FindDegenerates to check the area of a + * trinagle to be greates than e-6. If this is not the case the triangle will + * be removed if #AI_CONFIG_PP_FD_REMOVE is set to true. + */ +#define AI_CONFIG_PP_FD_CHECKAREA \ + "PP_FD_CHECKAREA" + // --------------------------------------------------------------------------- /** @brief Configures the #aiProcess_OptimizeGraph step to preserve nodes * matching a name in a given list. @@ -323,7 +332,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @brief Set the maximum number of bones affecting a single vertex * * This is used by the #aiProcess_LimitBoneWeights PostProcess-Step. - * @note The default value is AI_LBW_MAX_WEIGHTS + * @note The default value is AI_LMW_MAX_WEIGHTS * Property type: integer.*/ #define AI_CONFIG_PP_LBW_MAX_WEIGHTS \ "PP_LBW_MAX_WEIGHTS" @@ -632,8 +641,15 @@ enum aiComponent #define AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES \ "IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES" - - +// --------------------------------------------------------------------------- +/** @brief Set whether the fbx importer will search for embedded loaded textures, where no embedded texture data is provided. +* +* The default value is false (0) +* Property type: bool +*/ +#define AI_CONFIG_IMPORT_FBX_SEARCH_EMBEDDED_TEXTURES \ + "IMPORT_FBX_SEARCH_EMBEDDED_TEXTURES" + // --------------------------------------------------------------------------- /** @brief Set the vertex animation keyframe to be imported * @@ -844,14 +860,6 @@ enum aiComponent #define AI_CONFIG_IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME \ "IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME" -/** @brief Specifies whether the IFC loader skips over IfcSpace elements. - * - * IfcSpace elements (and their geometric representations) are used to - * represent, well, free space in a building storey.
- * Property type: Bool. Default value: true. - */ -#define AI_CONFIG_IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS "IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS" - /** @brief Specifies whether the Android JNI asset extraction is supported. * * Turn on this option if you want to manage assets in native @@ -860,17 +868,14 @@ enum aiComponent */ #define AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT "AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT" - // --------------------------------------------------------------------------- -/** @brief Specifies whether the IFC loader skips over - * shape representations of type 'Curve2D'. +/** @brief Specifies whether the IFC loader skips over IfcSpace elements. * - * A lot of files contain both a faceted mesh representation and a outline - * with a presentation type of 'Curve2D'. Currently Assimp doesn't convert those, - * so turning this option off just clutters the log with errors.
+ * IfcSpace elements (and their geometric representations) are used to + * represent, well, free space in a building storey.
* Property type: Bool. Default value: true. */ -#define AI_CONFIG_IMPORT_IFC_SKIP_CURVE_REPRESENTATIONS "IMPORT_IFC_SKIP_CURVE_REPRESENTATIONS" +#define AI_CONFIG_IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS "IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS" // --------------------------------------------------------------------------- /** @brief Specifies whether the IFC loader will use its own, custom triangulation @@ -887,6 +892,38 @@ enum aiComponent */ #define AI_CONFIG_IMPORT_IFC_CUSTOM_TRIANGULATION "IMPORT_IFC_CUSTOM_TRIANGULATION" +// --------------------------------------------------------------------------- +/** @brief Set the tessellation conic angle for IFC smoothing curves. + * + * This is used by the IFC importer to determine the tessellation parameter + * for smoothing curves. + * @note The default value is AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE and the + * accepted values are in range [5.0, 120.0]. + * Property type: Float. + */ +#define AI_CONFIG_IMPORT_IFC_SMOOTHING_ANGLE "IMPORT_IFC_SMOOTHING_ANGLE" + +// default value for AI_CONFIG_IMPORT_IFC_SMOOTHING_ANGLE +#if (!defined AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE) +# define AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE 10.0f +#endif + +// --------------------------------------------------------------------------- +/** @brief Set the tessellation for IFC cylindrical shapes. + * + * This is used by the IFC importer to determine the tessellation parameter + * for cylindrical shapes, i.e. the number of segments used to approximate a circle. + * @note The default value is AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION and the + * accepted values are in range [3, 180]. + * Property type: Integer. + */ +#define AI_CONFIG_IMPORT_IFC_CYLINDRICAL_TESSELLATION "IMPORT_IFC_CYLINDRICAL_TESSELLATION" + +// default value for AI_CONFIG_IMPORT_IFC_CYLINDRICAL_TESSELLATION +#if (!defined AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION) +# define AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION 32 +#endif + // --------------------------------------------------------------------------- /** @brief Specifies whether the Collada loader will ignore the provided up direction. * @@ -905,6 +942,14 @@ enum aiComponent #define AI_CONFIG_EXPORT_XFILE_64BIT "EXPORT_XFILE_64BIT" +/** + * @brief Specifies a gobal key factor for scale, float value + */ +#define AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY "GLOBAL_SCALE_FACTOR" + +#if (!defined AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT) +# define AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT 1.0f +#endif // !! AI_DEBONE_THRESHOLD // ---------- All the Build/Compile-time defines ------------ diff --git a/include/assimp/defs.h b/include/assimp/defs.h index f68d69cc1..20b234f90 100644 --- a/include/assimp/defs.h +++ b/include/assimp/defs.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -212,7 +213,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #if (defined(__BORLANDC__) || defined (__BCPLUSPLUS__)) #error Currently, Borland is unsupported. Feel free to port Assimp. -// "W8059 Packgr��e der Struktur ge�ndert" +// "W8059 Packgröße der Struktur geändert" #endif diff --git a/include/assimp/importerdesc.h b/include/assimp/importerdesc.h index 455f83cce..6b83b8aa2 100644 --- a/include/assimp/importerdesc.h +++ b/include/assimp/importerdesc.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/include/assimp/light.h b/include/assimp/light.h index 9a7893b52..324339a97 100644 --- a/include/assimp/light.h +++ b/include/assimp/light.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/include/assimp/material.h b/include/assimp/material.h index 23a45878e..a12e7d076 100644 --- a/include/assimp/material.h +++ b/include/assimp/material.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/include/assimp/material.inl b/include/assimp/material.inl index cd610fd58..2c31fd571 100644 --- a/include/assimp/material.inl +++ b/include/assimp/material.inl @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -47,6 +48,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_MATERIAL_INL_INC #define AI_MATERIAL_INL_INC +// --------------------------------------------------------------------------- +inline aiPropertyTypeInfo ai_real_to_property_type_info(float) +{ + return aiPTI_Float; +} + +inline aiPropertyTypeInfo ai_real_to_property_type_info(double) +{ + return aiPTI_Double; +} +// --------------------------------------------------------------------------- + //! @cond never // --------------------------------------------------------------------------- @@ -222,7 +235,7 @@ inline aiReturn aiMaterial::AddProperty(const aiUVTransform* pInput, { return AddBinaryProperty((const void*)pInput, pNumValues * sizeof(aiUVTransform), - pKey,type,index,aiPTI_Float); //TODO could be Double ... + pKey,type,index,ai_real_to_property_type_info(pInput->mRotation)); } // --------------------------------------------------------------------------- @@ -234,7 +247,7 @@ inline aiReturn aiMaterial::AddProperty(const aiColor4D* pInput, { return AddBinaryProperty((const void*)pInput, pNumValues * sizeof(aiColor4D), - pKey,type,index,aiPTI_Float); //TODO could be Double ... + pKey,type,index,ai_real_to_property_type_info(pInput->a)); } // --------------------------------------------------------------------------- @@ -246,7 +259,7 @@ inline aiReturn aiMaterial::AddProperty(const aiColor3D* pInput, { return AddBinaryProperty((const void*)pInput, pNumValues * sizeof(aiColor3D), - pKey,type,index,aiPTI_Float); //TODO could be Double ... + pKey,type,index,ai_real_to_property_type_info(pInput->b)); } // --------------------------------------------------------------------------- @@ -258,7 +271,7 @@ inline aiReturn aiMaterial::AddProperty(const aiVector3D* pInput, { return AddBinaryProperty((const void*)pInput, pNumValues * sizeof(aiVector3D), - pKey,type,index,aiPTI_Float); //TODO could be Double ... + pKey,type,index,ai_real_to_property_type_info(pInput->x)); } // --------------------------------------------------------------------------- diff --git a/include/assimp/matrix3x3.h b/include/assimp/matrix3x3.h index f6c151aa5..3cf575e38 100644 --- a/include/assimp/matrix3x3.h +++ b/include/assimp/matrix3x3.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -46,7 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_MATRIX3X3_H_INC #define AI_MATRIX3X3_H_INC -#include "./Compiler/pushpack1.h" #include "defs.h" #ifdef __cplusplus @@ -153,8 +153,8 @@ public: /** @brief A function for creating a rotation matrix that rotates a * vector called "from" into another vector called "to". * Input : from[3], to[3] which both must be *normalized* non-zero vectors - * Output: mtx[3][3] -- a 3x3 matrix in colum-major form - * Authors: Tomas M�ller, John Hughes + * Output: mtx[3][3] -- a 3x3 matrix in column-major form + * Authors: Tomas Möller, John Hughes * "Efficiently Building a Matrix to Rotate One Vector to Another" * Journal of Graphics Tools, 4(4):1-4, 1999 */ @@ -165,7 +165,7 @@ public: TReal a1, a2, a3; TReal b1, b2, b3; TReal c1, c2, c3; -} PACK_STRUCT; +}; typedef aiMatrix3x3t aiMatrix3x3; @@ -175,10 +175,8 @@ struct aiMatrix3x3 { ai_real a1, a2, a3; ai_real b1, b2, b3; ai_real c1, c2, c3; -} PACK_STRUCT; +}; #endif // __cplusplus -#include "./Compiler/poppack1.h" - #endif // AI_MATRIX3X3_H_INC diff --git a/include/assimp/matrix3x3.inl b/include/assimp/matrix3x3.inl index 2ef0141e8..14f2cd2fc 100644 --- a/include/assimp/matrix3x3.inl +++ b/include/assimp/matrix3x3.inl @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -101,16 +102,34 @@ inline aiMatrix3x3t aiMatrix3x3t::operator* (const aiMatrix3x3t -inline TReal* aiMatrix3x3t::operator[] (unsigned int p_iIndex) -{ - return &this->a1 + p_iIndex * 3; +inline TReal* aiMatrix3x3t::operator[] (unsigned int p_iIndex) { + switch ( p_iIndex ) { + case 0: + return &a1; + case 1: + return &b1; + case 2: + return &c1; + default: + break; + } + return &a1; } // ------------------------------------------------------------------------------------------------ template -inline const TReal* aiMatrix3x3t::operator[] (unsigned int p_iIndex) const -{ - return &this->a1 + p_iIndex * 3; +inline const TReal* aiMatrix3x3t::operator[] (unsigned int p_iIndex) const { + switch ( p_iIndex ) { + case 0: + return &a1; + case 1: + return &b1; + case 2: + return &c1; + default: + break; + } + return &a1; } // ------------------------------------------------------------------------------------------------ @@ -242,7 +261,7 @@ inline aiMatrix3x3t& aiMatrix3x3t::Translation( const aiVector2t operator aiMatrix4x4t () const; @@ -222,7 +224,7 @@ public: * @return Reference to the output matrix */ static aiMatrix4x4t& Rotation(TReal a, const aiVector3t& axis, - aiMatrix4x4t& out); + aiMatrix4x4t& out); // ------------------------------------------------------------------- /** @brief Returns a translation matrix @@ -230,7 +232,8 @@ public: * @param out Receives the output matrix * @return Reference to the output matrix */ - static aiMatrix4x4t& Translation( const aiVector3t& v, aiMatrix4x4t& out); + static aiMatrix4x4t& Translation( const aiVector3t& v, + aiMatrix4x4t& out); // ------------------------------------------------------------------- /** @brief Returns a scaling matrix @@ -250,14 +253,14 @@ public: * Journal of Graphics Tools, 4(4):1-4, 1999 */ static aiMatrix4x4t& FromToMatrix(const aiVector3t& from, - const aiVector3t& to, aiMatrix4x4t& out); + const aiVector3t& to, aiMatrix4x4t& out); public: TReal a1, a2, a3, a4; TReal b1, b2, b3, b4; TReal c1, c2, c3, c4; TReal d1, d2, d3, d4; -} PACK_STRUCT; +}; typedef aiMatrix4x4t aiMatrix4x4; @@ -268,11 +271,9 @@ struct aiMatrix4x4 { ai_real b1, b2, b3, b4; ai_real c1, c2, c3, c4; ai_real d1, d2, d3, d4; -} PACK_STRUCT; +}; #endif // __cplusplus -#include "./Compiler/poppack1.h" - #endif // AI_MATRIX4X4_H_INC diff --git a/include/assimp/matrix4x4.inl b/include/assimp/matrix4x4.inl index a7977cd2c..b15d50a09 100644 --- a/include/assimp/matrix4x4.inl +++ b/include/assimp/matrix4x4.inl @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -155,6 +156,54 @@ inline aiMatrix4x4t& aiMatrix4x4t::operator *= (const aiMatrix4x4t return *this; } +// ---------------------------------------------------------------------------------------- +template +inline aiMatrix4x4t aiMatrix4x4t::operator* (const TReal& aFloat) const +{ + aiMatrix4x4t temp( + a1 * aFloat, + a2 * aFloat, + a3 * aFloat, + a4 * aFloat, + b1 * aFloat, + b2 * aFloat, + b3 * aFloat, + b4 * aFloat, + c1 * aFloat, + c2 * aFloat, + c3 * aFloat, + c4 * aFloat, + d1 * aFloat, + d2 * aFloat, + d3 * aFloat, + d4 * aFloat); + return temp; +} + +// ---------------------------------------------------------------------------------------- +template +inline aiMatrix4x4t aiMatrix4x4t::operator+ (const aiMatrix4x4t& m) const +{ + aiMatrix4x4t temp( + m.a1 + a1, + m.a2 + a2, + m.a3 + a3, + m.a4 + a4, + m.b1 + b1, + m.b2 + b2, + m.b3 + b3, + m.b4 + b4, + m.c1 + c1, + m.c2 + c2, + m.c3 + c3, + m.c4 + c4, + m.d1 + d1, + m.d2 + d2, + m.d3 + d3, + m.d4 + d4); + return temp; +} + // ---------------------------------------------------------------------------------------- template inline aiMatrix4x4t aiMatrix4x4t::operator* (const aiMatrix4x4t& m) const @@ -243,9 +292,19 @@ inline TReal* aiMatrix4x4t::operator[](unsigned int p_iIndex) { if (p_iIndex > 3) { return NULL; } - - // XXX this is UB. Has been for years. The fact that it works now does not make it better. - return &this->a1 + p_iIndex * 4; + switch ( p_iIndex ) { + case 0: + return &a1; + case 1: + return &b1; + case 2: + return &c1; + case 3: + return &d1; + default: + break; + } + return &a1; } // ---------------------------------------------------------------------------------------- @@ -255,8 +314,19 @@ inline const TReal* aiMatrix4x4t::operator[](unsigned int p_iIndex) const return NULL; } - // XXX same - return &this->a1 + p_iIndex * 4; + switch ( p_iIndex ) { + case 0: + return &a1; + case 1: + return &b1; + case 2: + return &c1; + case 3: + return &d1; + default: + break; + } + return &a1; } // ---------------------------------------------------------------------------------------- @@ -592,7 +662,7 @@ inline aiMatrix4x4t& aiMatrix4x4t::Scaling( const aiVector3t + inline void Add(const std::string& key, const T& value) + { + aiString* new_keys = new aiString[mNumProperties + 1]; + aiMetadataEntry* new_values = new aiMetadataEntry[mNumProperties + 1]; + + for(unsigned int i = 0; i < mNumProperties; ++i) + { + new_keys[i] = mKeys[i]; + new_values[i] = mValues[i]; + } + + delete mKeys; + delete mValues; + + mKeys = new_keys; + mValues = new_values; + + mNumProperties++; + + Set(mNumProperties - 1, key, value); + } + template inline bool Set( unsigned index, const std::string& key, const T& value ) { diff --git a/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h b/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h index 6f806f922..41d800487 100644 --- a/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h +++ b/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h @@ -45,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef AI_ANDROIDJNIIOSYSTEM_H_INC #define AI_ANDROIDJNIIOSYSTEM_H_INC -#include "../code/DefaultIOSystem.h" +#include #include #include #include diff --git a/include/assimp/postprocess.h b/include/assimp/postprocess.h index 53c22da13..970df8e8a 100644 --- a/include/assimp/postprocess.h +++ b/include/assimp/postprocess.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, @@ -524,7 +525,17 @@ enum aiPostProcessSteps * Use #AI_CONFIG_PP_DB_ALL_OR_NONE if you want bones removed if and * only if all bones within the scene qualify for removal. */ - aiProcess_Debone = 0x4000000 + aiProcess_Debone = 0x4000000, + + // ------------------------------------------------------------------------- + /**
This step will perform a global scale of the model. + * + * Some importers are providing a mechanism to define a scaling unit for the + * model. This post processing step can be used to do so. + * + * Use #AI_CONFIG_GLOBAL_SCALE_FACTOR_KEY to control this. + */ + aiProcess_GlobalScale = 0x8000000 // aiProcess_GenEntityMeshes = 0x100000, // aiProcess_OptimizeAnimations = 0x200000 diff --git a/include/assimp/quaternion.h b/include/assimp/quaternion.h index fdc4d266b..a5cb67a9a 100644 --- a/include/assimp/quaternion.h +++ b/include/assimp/quaternion.h @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. Redistribution and use of this software in source and binary forms, diff --git a/include/assimp/quaternion.inl b/include/assimp/quaternion.inl index 68cb5a236..d0bf5831c 100644 --- a/include/assimp/quaternion.inl +++ b/include/assimp/quaternion.inl @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/include/assimp/scene.h b/include/assimp/scene.h index d9799db99..342c316d6 100644 --- a/include/assimp/scene.h +++ b/include/assimp/scene.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -59,6 +60,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. extern "C" { #endif +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wattributes" +#endif + // ------------------------------------------------------------------------------- /** * A node in the imported hierarchy. @@ -69,7 +75,7 @@ extern "C" { * the imported scene does consist of only a single root node without children. */ // ------------------------------------------------------------------------------- -struct aiNode +struct ASSIMP_API aiNode { /** The name of the node. * @@ -124,47 +130,13 @@ struct aiNode #ifdef __cplusplus /** Constructor */ - aiNode() - // set all members to zero by default - : mName("") - , mParent(NULL) - , mNumChildren(0) - , mChildren(NULL) - , mNumMeshes(0) - , mMeshes(NULL) - , mMetaData(NULL) - { - } - + aiNode(); /** Construction from a specific name */ - explicit aiNode(const std::string& name) - // set all members to zero by default - : mName(name) - , mParent(NULL) - , mNumChildren(0) - , mChildren(NULL) - , mNumMeshes(0) - , mMeshes(NULL) - , mMetaData(NULL) - { - } + explicit aiNode(const std::string& name); /** Destructor */ - ~aiNode() - { - // delete all children recursively - // to make sure we won't crash if the data is invalid ... - if (mChildren && mNumChildren) - { - for( unsigned int a = 0; a < mNumChildren; a++) - delete mChildren[a]; - } - delete [] mChildren; - delete [] mMeshes; - delete mMetaData; - } - + ~aiNode(); /** Searches for a node with a specific name, beginning at this * nodes. Normally you will call this method on the root node @@ -173,49 +145,32 @@ struct aiNode * @param name Name to search for * @return NULL or a valid Node if the search was successful. */ - inline const aiNode* FindNode(const aiString& name) const - { + inline + const aiNode* FindNode(const aiString& name) const { return FindNode(name.data); } - - inline aiNode* FindNode(const aiString& name) - { + inline + aiNode* FindNode(const aiString& name) { return FindNode(name.data); } + const aiNode* FindNode(const char* name) const; - inline const aiNode* FindNode(const char* name) const - { - if (!::strcmp( mName.data,name))return this; - for (unsigned int i = 0; i < mNumChildren;++i) - { - const aiNode* const p = mChildren[i]->FindNode(name); - if (p) { - return p; - } - } - // there is definitely no sub-node with this name - return NULL; - } - - inline aiNode* FindNode(const char* name) - { - if (!::strcmp( mName.data,name))return this; - for (unsigned int i = 0; i < mNumChildren;++i) - { - aiNode* const p = mChildren[i]->FindNode(name); - if (p) { - return p; - } - } - // there is definitely no sub-node with this name - return NULL; - } + aiNode* FindNode(const char* name); + /** + * @brief Will add new children. + * @param numChildren Number of children to add. + * @param children The array with pointers showing to the children. + */ + void addChildren(unsigned int numChildren, aiNode **children); #endif // __cplusplus }; +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif // ------------------------------------------------------------------------------- /** diff --git a/include/assimp/texture.h b/include/assimp/texture.h index ab52c79a2..c09ef2cbe 100644 --- a/include/assimp/texture.h +++ b/include/assimp/texture.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/include/assimp/types.h b/include/assimp/types.h index 7904413b0..0012a0bba 100644 --- a/include/assimp/types.h +++ b/include/assimp/types.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -115,8 +116,6 @@ const size_t MAXLEN = 1024; # define MAXLEN 1024 #endif -#include "./Compiler/pushpack1.h" - // ---------------------------------------------------------------------------------- /** Represents a plane in a three-dimensional, euclidean space */ @@ -133,7 +132,7 @@ struct aiPlane //! Plane equation ai_real a,b,c,d; -} PACK_STRUCT; // !struct aiPlane +}; // !struct aiPlane // ---------------------------------------------------------------------------------- /** Represents a ray @@ -151,7 +150,7 @@ struct aiRay //! Position and direction of the ray C_STRUCT aiVector3D pos, dir; -} PACK_STRUCT; // !struct aiRay +}; // !struct aiRay // ---------------------------------------------------------------------------------- /** Represents a color in Red-Green-Blue space. @@ -227,8 +226,7 @@ struct aiColor3D //! Red, green and blue color values ai_real r, g, b; -} /*PACK_STRUCT*/; // !struct aiColor3D -#include "./Compiler/poppack1.h" +}; // !struct aiColor3D // ---------------------------------------------------------------------------------- /** Represents an UTF-8 string, zero byte terminated. diff --git a/include/assimp/vector2.h b/include/assimp/vector2.h index 4122273c5..564d1f8b5 100644 --- a/include/assimp/vector2.h +++ b/include/assimp/vector2.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/include/assimp/vector2.inl b/include/assimp/vector2.inl index ce6521139..5ce13eece 100644 --- a/include/assimp/vector2.inl +++ b/include/assimp/vector2.inl @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/include/assimp/vector3.h b/include/assimp/vector3.h index 891beb28c..641dab795 100644 --- a/include/assimp/vector3.h +++ b/include/assimp/vector3.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -51,7 +52,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # include #endif -#include "./Compiler/pushpack1.h" #include "defs.h" #ifdef __cplusplus @@ -65,11 +65,10 @@ template class aiVector3t { public: - - aiVector3t () : x(), y(), z() {} - aiVector3t (TReal _x, TReal _y, TReal _z) : x(_x), y(_y), z(_z) {} - explicit aiVector3t (TReal _xyz) : x(_xyz), y(_xyz), z(_xyz) {} - aiVector3t (const aiVector3t& o) : x(o.x), y(o.y), z(o.z) {} + aiVector3t() : x(), y(), z() {} + aiVector3t(TReal _x, TReal _y, TReal _z) : x(_x), y(_y), z(_z) {} + explicit aiVector3t (TReal _xyz ) : x(_xyz), y(_xyz), z(_xyz) {} + aiVector3t( const aiVector3t& o ) : x(o.x), y(o.y), z(o.z) {} public: @@ -126,7 +125,7 @@ public: const aiVector3t SymMul(const aiVector3t& o); TReal x, y, z; -} PACK_STRUCT; +}; typedef aiVector3t aiVector3D; @@ -135,16 +134,12 @@ typedef aiVector3t aiVector3D; struct aiVector3D { ai_real x, y, z; -} PACK_STRUCT; +}; #endif // __cplusplus -#include "./Compiler/poppack1.h" - #ifdef __cplusplus - - #endif // __cplusplus #endif // AI_VECTOR3D_H_INC diff --git a/include/assimp/vector3.inl b/include/assimp/vector3.inl index 22b5bca03..a074bb23a 100644 --- a/include/assimp/vector3.inl +++ b/include/assimp/vector3.inl @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -141,12 +142,34 @@ AI_FORCE_INLINE aiVector3t& aiVector3t::operator *= (const aiMatri // ------------------------------------------------------------------------------------------------ template AI_FORCE_INLINE TReal aiVector3t::operator[](unsigned int i) const { - return *(&x + i); +// return *(&x + i); + switch (i) { + case 0: + return x; + case 1: + return y; + case 2: + return z; + default: + break; + } + return x; } // ------------------------------------------------------------------------------------------------ template AI_FORCE_INLINE TReal& aiVector3t::operator[](unsigned int i) { - return *(&x + i); +// return *(&x + i); + switch (i) { + case 0: + return x; + case 1: + return y; + case 2: + return z; + default: + break; + } + return x; } // ------------------------------------------------------------------------------------------------ template diff --git a/include/assimp/version.h b/include/assimp/version.h index a9b2beb5b..d1821fa2b 100644 --- a/include/assimp/version.h +++ b/include/assimp/version.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -104,3 +105,4 @@ ASSIMP_API unsigned int aiGetCompileFlags (void); #endif #endif // !! #ifndef AI_VERSION_H_INC + diff --git a/packaging/windows-innosetup/script.iss b/packaging/windows-innosetup/script.iss index d8e0d082a..f301bc4eb 100644 --- a/packaging/windows-innosetup/script.iss +++ b/packaging/windows-innosetup/script.iss @@ -19,35 +19,32 @@ VersionInfoCompany=Assimp Development Team ArchitecturesInstallIn64BitMode=x64 [Types] -Name: "full"; Description: "Full installation" +Name: "full"; Description: "Full installation" Name: "compact"; Description: "Compact installation, no test models or language bindings" -Name: "custom"; Description: "Custom installation"; Flags: iscustom +Name: "custom"; Description: "Custom installation"; Flags: iscustom [Components] -Name: "main"; Description: "Main Files (32 and 64 Bit)"; Types: full compact custom; Flags: fixed -Name: "tools"; Description: "Asset Viewer & Command Line Tools (32 and 64 Bit)"; Types: full compact -Name: "help"; Description: "Help Files"; Types: full compact -Name: "samples"; Description: "Samples"; Types: full -;Name: "wsource"; Description: "Source Code"; Types: full -Name: "test"; Description: "Test Models (BSD-licensed)"; Types: full +Name: "main"; Description: "Main Files (32 and 64 Bit)"; Types: full compact custom; Flags: fixed +Name: "tools"; Description: "Asset Viewer & Command Line Tools (32 and 64 Bit)"; Types: full compact +Name: "help"; Description: "Help Files"; Types: full compact +Name: "samples"; Description: "Samples"; Types: full +Name: "test"; Description: "Test Models (BSD-licensed)"; Types: full Name: "test_nonbsd"; Description: "Test Models (other (free) licenses)"; Types: full -Name: "pyassimp"; Description: "Python Bindings"; Types: full -Name: "dassimp"; Description: "D Bindings"; Types: full -Name: "assimp_net"; Description: "C#/.NET Bindings"; Types: full -;Name: "vc8"; Description: "VC8 project files"; Types: full -;Name: "vc9"; Description: "VC9 project files"; Types: full +Name: "pyassimp"; Description: "Python Bindings"; Types: full +Name: "dassimp"; Description: "D Bindings"; Types: full +Name: "assimp_net"; Description: "C#/.NET Bindings"; Types: full [Run] -Filename: "{app}\stub\vcredist_x86.exe"; Parameters: "/qb"; StatusMsg: "Installing VS2012 SP1 redistributable package (32 Bit)"; Check: not IsWin64 -Filename: "{app}\stub\vcredist_x64.exe"; Parameters: "/qb"; StatusMsg: "Installing VS2012 SP1 redistributable package (64 Bit)"; Check: IsWin64 +Filename: "{app}\stub\vc_redist.x86.exe"; Parameters: "/qb"; StatusMsg: "Installing VS2015 redistributable package (32 Bit)"; Check: not IsWin64 +Filename: "{app}\stub\vc_redist.x64.exe"; Parameters: "/qb"; StatusMsg: "Installing VS2015 redistributable package (64 Bit)"; Check: IsWin64 [Files] Source: "readme_installer.txt"; DestDir: "{app}"; Flags: isreadme ; Installer stub -Source: "vcredist_x86.exe"; DestDir: "{app}\stub\"; Check: not IsWin64 -Source: "vcredist_x64.exe"; DestDir: "{app}\stub\"; Check: IsWin64 +Source: "vc_redist.x86.exe"; DestDir: "{app}\stub\"; Check: not IsWin64 +Source: "vc_redist.x64.exe"; DestDir: "{app}\stub\"; Check: IsWin64 ; Common stuff Source: "..\..\CREDITS"; DestDir: "{app}" @@ -58,18 +55,18 @@ Source: "WEB"; DestDir: "{app}" Source: "..\..\scripts\*"; DestDir: "{app}\scripts"; Flags: recursesubdirs ; x86 binaries -Source: "..\..\bin\assimp_release-dll_Win32\Assimp32.dll"; DestDir: "{app}\bin\x86" -Source: "..\..\bin\assimpview_release-dll_Win32\assimp_view.exe"; DestDir: "{app}\bin\x86"; Components: tools -Source: "D3DCompiler_42.dll"; DestDir: "{app}\bin\x86"; Components: tools -Source: "D3DX9_42.dll"; DestDir: "{app}\bin\x86"; Components: tools -Source: "..\..\bin\assimpcmd_release-dll_Win32\assimp.exe"; DestDir: "{app}\bin\x86"; Components: tools +Source: "..\..\bin\release\x86\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x86" +Source: "..\..\bin\release\x86\assimp_viewer.exe"; DestDir: "{app}\bin\x86"; Components: tools +Source: "D3DCompiler_42.dll"; DestDir: "{app}\bin\x86"; Components: tools +Source: "D3DX9_42.dll"; DestDir: "{app}\bin\x86"; Components: tools +Source: "..\..\bin\release\x86\assimp.exe"; DestDir: "{app}\bin\x86"; Components: tools ; x64 binaries -Source: "..\..\bin\assimp_release-dll_x64\Assimp64.dll"; DestDir: "{app}\bin\x64" -Source: "..\..\bin\assimpview_release-dll_x64\assimp_view.exe"; DestDir: "{app}\bin\x64"; Components: tools -Source: "D3DCompiler_42_x64.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DCompiler_42.dll"; Components: tools -Source: "D3DX9_42_x64.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DX9_42.dll"; Components: tools -Source: "..\..\bin\assimpcmd_release-dll_x64\assimp.exe"; DestDir: "{app}\bin\x64"; Components: tools +Source: "..\..\bin\release\x64\assimp-vc140-mt.dll"; DestDir: "{app}\bin\x64" +Source: "..\..\bin\release\x64\assimp_viewer.exe"; DestDir: "{app}\bin\x64"; Components: tools +Source: "D3DCompiler_42_x64.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DCompiler_42.dll"; Components: tools +Source: "D3DX9_42_x64.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DX9_42.dll"; Components: tools +Source: "..\..\bin\release\x64\assimp.exe"; DestDir: "{app}\bin\x64"; Components: tools ; Documentation Source: "..\..\doc\AssimpDoc_Html\AssimpDoc.chm"; DestDir: "{app}\doc"; Components: help @@ -77,8 +74,8 @@ Source: "..\..\doc\AssimpCmdDoc_Html\AssimpCmdDoc.chm"; DestDir: "{app}\doc"; Co Source: "..\..\doc\datastructure.xml"; DestDir: "{app}\doc"; Components: help ; Import libraries -Source: "..\..\lib\assimp_release-dll_Win32\assimp.lib"; DestDir: "{app}\lib\x86" -Source: "..\..\lib\assimp_release-dll_x64\assimp.lib"; DestDir: "{app}\lib\x64" +Source: "..\..\lib\release\x86\assimp.lib"; DestDir: "{app}\lib\x86" +Source: "..\..\lib\release\x64\assimp.lib"; DestDir: "{app}\lib\x64" ; Samples Source: "..\..\samples\*"; DestDir: "{app}\samples"; Flags: recursesubdirs; Components: samples @@ -90,15 +87,15 @@ Source: "..\..\include\*"; DestDir: "{app}\include"; Flags: recursesubdirs Source: "..\..\port\dAssimp\*"; DestDir: "{app}\port\D"; Flags: recursesubdirs; Components: dassimp ; Assimp.NET -Source: "..\..\port\Assimp.NET\*"; DestDir: "{app}\port\C#"; Flags: recursesubdirs; Components: assimp_net +;Source: "..\..\port\Assimp.NET\*"; DestDir: "{app}\port\C#"; Flags: recursesubdirs; Components: assimp_net ; PyAssimp -Source: "..\..\port\PyAssimp\*"; DestDir: "{app}\port\Python"; Excludes: "*.pyc,*.dll"; Flags: recursesubdirs; Components: pyassimp +;Source: "..\..\port\PyAssimp\*"; DestDir: "{app}\port\Python"; Excludes: "*.pyc,*.dll"; Flags: recursesubdirs; Components: pyassimp ; Test repository -Source: "..\..\test\models\*"; DestDir: "{app}\test\models"; Flags: recursesubdirs; Components: test -Source: "..\..\test\regression\*"; DestDir: "{app}\test\regression"; Flags: recursesubdirs; Components: test -Source: "..\..\test\models-nonbsd\*"; DestDir: "{app}\test\models-nonbsd"; Flags: recursesubdirs; Components: test_nonbsd +;Source: "..\..\test\models\*"; DestDir: "{app}\test\models"; Flags: recursesubdirs; Components: test +;Source: "..\..\test\regression\*"; DestDir: "{app}\test\regression"; Flags: recursesubdirs; Components: test +;Source: "..\..\test\models-nonbsd\*"; DestDir: "{app}\test\models-nonbsd"; Flags: recursesubdirs; Components: test_nonbsd ; Source Code & Workspaces ;Source: "..\..\code\*"; Excludes: "*.o"; DestDir: "{app}\code"; Flags: recursesubdirs; Components: wsource diff --git a/port/AndroidJNI/AndroidJNIIOSystem.cpp b/port/AndroidJNI/AndroidJNIIOSystem.cpp index 43bb9213d..e276ea59f 100644 --- a/port/AndroidJNI/AndroidJNIIOSystem.cpp +++ b/port/AndroidJNI/AndroidJNIIOSystem.cpp @@ -46,14 +46,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #if __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) +#include #include +#include #include #include #include #include #include #include -#include +#include #include using namespace Assimp; @@ -100,6 +102,27 @@ void AndroidJNIIOSystem::AndroidActivityInit(ANativeActivity* activity) mApkAssetManager = activity->assetManager; } +// ------------------------------------------------------------------------------------------------ +// Create the directory for the extracted resource +static int mkpath(std::string path, mode_t mode) +{ + if (mkdir(path.c_str(), mode) == -1) { + switch(errno) { + case ENOENT: + if (mkpath(path.substr(0, path.find_last_of('/')), mode) == -1) + return -1; + else + return mkdir(path.c_str(), mode); + case EEXIST: + return 0; + default: + return -1; + } + } + + return 0; +} + // ------------------------------------------------------------------------------------------------ // Extracts android asset bool AndroidJNIIOSystem::AndroidExtractAsset(std::string name) @@ -131,6 +154,15 @@ bool AndroidJNIIOSystem::AndroidExtractAsset(std::string name) // Close AAsset_close(asset); + // Prepare directory for output buffer + std::string directoryNewPath = newPath; + directoryNewPath = dirname(&directoryNewPath[0]); + + if (mkpath(directoryNewPath, S_IRUSR | S_IWUSR | S_IXUSR) == -1) { + __android_log_print(ANDROID_LOG_ERROR, "assimp", + "Can not create the directory for the output file"); + } + // Prepare output buffer std::ofstream assetExtracted(newPath.c_str(), std::ios::out | std::ios::binary); diff --git a/port/PyAssimp/3d_viewer_screenshot.png b/port/PyAssimp/3d_viewer_screenshot.png new file mode 100644 index 000000000..2031faf5a Binary files /dev/null and b/port/PyAssimp/3d_viewer_screenshot.png differ diff --git a/port/PyAssimp/README.md b/port/PyAssimp/README.md index 201d3ed7d..37ecdb65d 100644 --- a/port/PyAssimp/README.md +++ b/port/PyAssimp/README.md @@ -1,73 +1,94 @@ -PyAssimp Readme -=============== - -A simple Python wrapper for Assimp using `ctypes` to access the library. -Requires Python >= 2.6. - -Python 3 support is mostly here, but not well tested. - -Note that pyassimp is not complete. Many ASSIMP features are missing. - -USAGE ------ - -To get started with pyAssimp, examine the `sample.py` script in `scripts/`, -which illustrates the basic usage. All Assimp data structures are wrapped using -ctypes. All the data+length fields in Assimp's data structures (such as -`aiMesh::mNumVertices`, `aiMesh::mVertices`) are replaced by simple python -lists, so you can call len() on them to get their respective size and access -members using []. - -For example, to load a file named 'hello.3ds' and print the first -vertex of the first mesh, you would do (proper error handling -substituted by assertions ...): - -```python - -from pyassimp import * -scene = load('hello.3ds') - -assert len(scene.meshes) -mesh = scene.meshes[0] - -assert len(mesh.vertices) -print(mesh.vertices[0]) - -# don't forget this one, or you will leak! -release(scene) - -``` - -Another example to list the 'top nodes' in a -scene: - -```python - -from pyassimp import * -scene = load('hello.3ds') - -for c in scene.rootnode.children: - print(str(c)) - -release(scene) - -``` - -INSTALL -------- - -Install `pyassimp` by running: - -> python setup.py install - -PyAssimp requires a assimp dynamic library (`DLL` on windows, -`.so` on linux :-) in order to work. The default search directories -are: - -- the current directory -- on linux additionally: `/usr/lib` and `/usr/local/lib` - -To build that library, refer to the Assimp master INSTALL -instructions. To look in more places, edit `./pyassimp/helper.py`. -There's an `additional_dirs` list waiting for your entries. - +PyAssimp Readme +=============== + +A simple Python wrapper for Assimp using `ctypes` to access the library. +Requires Python >= 2.6. + +Python 3 support is mostly here, but not well tested. + +Note that pyassimp is not complete. Many ASSIMP features are missing. + +USAGE +----- + +### Complete example: 3D viewer + +`pyassimp` comes with a simple 3D viewer that shows how to load and display a 3D +model using a shader-based OpenGL pipeline. + +![Screenshot](3d_viewer_screenshot.png) + +To use it, from within `/port/PyAssimp`: + +``` +$ cd scripts +$ python ./3D-viewer +``` + +You can use this code as starting point in your applications. + +### Writing your own code + +To get started with `pyassimp`, examine the simpler `sample.py` script in `scripts/`, +which illustrates the basic usage. All Assimp data structures are wrapped using +`ctypes`. All the data+length fields in Assimp's data structures (such as +`aiMesh::mNumVertices`, `aiMesh::mVertices`) are replaced by simple python +lists, so you can call `len()` on them to get their respective size and access +members using `[]`. + +For example, to load a file named `hello.3ds` and print the first +vertex of the first mesh, you would do (proper error handling +substituted by assertions ...): + +```python + +from pyassimp import * +scene = load('hello.3ds') + +assert len(scene.meshes) +mesh = scene.meshes[0] + +assert len(mesh.vertices) +print(mesh.vertices[0]) + +# don't forget this one, or you will leak! +release(scene) + +``` + +Another example to list the 'top nodes' in a +scene: + +```python + +from pyassimp import * +scene = load('hello.3ds') + +for c in scene.rootnode.children: + print(str(c)) + +release(scene) + +``` + +INSTALL +------- + +Install `pyassimp` by running: + +``` +$ python setup.py install +``` + +PyAssimp requires a assimp dynamic library (`DLL` on windows, +`.so` on linux, `.dynlib` on macOS) in order to work. The default search directories +are: + +- the current directory +- on linux additionally: `/usr/lib`, `/usr/local/lib`, + `/usr/lib/x86_64-linux-gnu` + +To build that library, refer to the Assimp master `INSTALL` +instructions. To look in more places, edit `./pyassimp/helper.py`. +There's an `additional_dirs` list waiting for your entries. + diff --git a/port/PyAssimp/pyassimp/core.py b/port/PyAssimp/pyassimp/core.py index 27ec44c97..573ce27b1 100644 --- a/port/PyAssimp/pyassimp/core.py +++ b/port/PyAssimp/pyassimp/core.py @@ -70,7 +70,7 @@ def make_tuple(ai_obj, type = None): def _init_face(aiFace): aiFace.indices = [aiFace.mIndices[i] for i in range(aiFace.mNumIndices)] assimp_struct_inits = { structs.Face : _init_face } - + def call_init(obj, caller = None): if helper.hasattr_silent(obj,'contents'): #pointer _init(obj.contents, obj, caller) @@ -85,12 +85,12 @@ def _is_init_type(obj): # so it breaks the 'is iterable' check. # Basically: # FIXME! - elif not bool(obj): + elif not bool(obj): return False tname = obj.__class__.__name__ return not (tname[:2] == 'c_' or tname == 'Structure' \ or tname == 'POINTER') and not isinstance(obj,int) - + def _init(self, target = None, parent = None): """ Custom initialize() for C structs, adds safely accessible member functionality. @@ -100,8 +100,8 @@ def _init(self, target = None, parent = None): """ if not target: target = self - - dirself = dir(self) + + dirself = dir(self) for m in dirself: if m.startswith("_"): @@ -119,11 +119,15 @@ def _init(self, target = None, parent = None): if m == 'mName': obj = self.mName - target.name = str(obj.data.decode("utf-8")) + try: + uni = unicode(obj.data, errors='ignore') + except: + uni = str(obj.data, errors='ignore') + target.name = str( uni ) target.__class__.__repr__ = lambda x: str(x.__class__) + "(" + x.name + ")" target.__class__.__str__ = lambda x: x.name continue - + name = m[1:].lower() obj = getattr(self, m) @@ -144,7 +148,7 @@ def _init(self, target = None, parent = None): if helper.hasattr_silent(self, 'mNum' + m[1:]): length = getattr(self, 'mNum' + m[1:]) - + # -> special case: properties are # stored as a dict. if m == 'mProperties': @@ -156,7 +160,7 @@ def _init(self, target = None, parent = None): setattr(target, name, []) logger.debug(str(self) + ": " + name + " is an empty list.") continue - + try: if obj._type_ in structs.assimp_structs_as_tuple: @@ -166,7 +170,7 @@ def _init(self, target = None, parent = None): logger.debug(str(self) + ": Added an array of numpy arrays (type "+ str(type(obj)) + ") as self." + name) else: setattr(target, name, [make_tuple(obj[i]) for i in range(length)]) - + logger.debug(str(self) + ": Added a list of lists (type "+ str(type(obj)) + ") as self." + name) else: @@ -191,7 +195,7 @@ def _init(self, target = None, parent = None): sys.exit(1) except ValueError as e: - + logger.error("In " + str(self) + "->" + name + ": " + str(e) + ". Quitting now.") if "setting an array element with a sequence" in str(e): logger.error("Note that pyassimp does not currently " @@ -200,13 +204,13 @@ def _init(self, target = None, parent = None): " a post-processing to triangulate your" " faces.") raise e - + else: # starts with 'm' but not iterable setattr(target, name, obj) logger.debug("Added " + name + " as self." + name + " (type: " + str(type(obj)) + ")") - + if _is_init_type(obj): call_init(obj, target) @@ -265,34 +269,34 @@ def recur_pythonize(node, scene): for c in node.children: recur_pythonize(c, scene) -def load(filename, +def load(filename, file_type = None, processing = postprocess.aiProcess_Triangulate): ''' Load a model into a scene. On failure throws AssimpError. - + Arguments --------- filename: Either a filename or a file object to load model from. If a file object is passed, file_type MUST be specified Otherwise Assimp has no idea which importer to use. - This is named 'filename' so as to not break legacy code. + This is named 'filename' so as to not break legacy code. processing: assimp postprocessing parameters. Verbose keywords are imported from postprocessing, and the parameters can be combined bitwise to generate the final processing value. Note that the default value will triangulate quad faces. Example of generating other possible values: - processing = (pyassimp.postprocess.aiProcess_Triangulate | + processing = (pyassimp.postprocess.aiProcess_Triangulate | pyassimp.postprocess.aiProcess_OptimizeMeshes) file_type: string of file extension, such as 'stl' - + Returns --------- Scene object with model data ''' - + if hasattr(filename, 'read'): ''' - This is the case where a file object has been passed to load. + This is the case where a file object has been passed to load. It is calling the following function: const aiScene* aiImportFileFromMemory(const char* pBuffer, unsigned int pLength, @@ -302,14 +306,14 @@ def load(filename, if file_type == None: raise AssimpError('File type must be specified when passing file objects!') data = filename.read() - model = _assimp_lib.load_mem(data, - len(data), - processing, + model = _assimp_lib.load_mem(data, + len(data), + processing, file_type) else: # a filename string has been passed model = _assimp_lib.load(filename.encode("ascii"), processing) - + if not model: raise AssimpError('Could not import file!') scene = _init(model.contents) @@ -317,22 +321,22 @@ def load(filename, return scene def export(scene, - filename, + filename, file_type = None, processing = postprocess.aiProcess_Triangulate): ''' Export a scene. On failure throws AssimpError. - + Arguments --------- scene: scene to export. - filename: Filename that the scene should be exported to. + filename: Filename that the scene should be exported to. file_type: string of file exporter to use. For example "collada". processing: assimp postprocessing parameters. Verbose keywords are imported from postprocessing, and the parameters can be combined bitwise to generate the final processing value. Note that the default value will triangulate quad faces. Example of generating other possible values: - processing = (pyassimp.postprocess.aiProcess_Triangulate | + processing = (pyassimp.postprocess.aiProcess_Triangulate | pyassimp.postprocess.aiProcess_OptimizeMeshes) ''' @@ -400,7 +404,7 @@ def _finalize_mesh(mesh, target): fillarray("mColors") fillarray("mTextureCoords") - + # prepare faces if numpy: faces = numpy.array([f.indices for f in target.faces], dtype=numpy.int32) @@ -429,7 +433,7 @@ class PropertyGetter(dict): yield k[0], v -def _get_properties(properties, length): +def _get_properties(properties, length): """ Convenience Function to get the material properties as a dict and values in a python format. @@ -439,7 +443,11 @@ def _get_properties(properties, length): for p in [properties[i] for i in range(length)]: #the name p = p.contents - key = (str(p.mKey.data.decode("utf-8")).split('.')[1], p.mSemantic) + try: + uni = unicode(p.mKey.data, errors='ignore') + except: + uni = str(p.mKey.data, errors='ignore') + key = (str(uni).split('.')[1], p.mSemantic) #the data from ctypes import POINTER, cast, c_int, c_float, sizeof @@ -447,7 +455,12 @@ def _get_properties(properties, length): arr = cast(p.mData, POINTER(c_float * int(p.mDataLength/sizeof(c_float)) )).contents value = [x for x in arr] elif p.mType == 3: #string can't be an array - value = cast(p.mData, POINTER(structs.MaterialPropertyString)).contents.data.decode("utf-8") + try: + uni = unicode(cast(p.mData, POINTER(structs.MaterialPropertyString)).contents.data, errors='ignore') + except: + uni = str(cast(p.mData, POINTER(structs.MaterialPropertyString)).contents.data, errors='ignore') + value = uni + elif p.mType == 4: arr = cast(p.mData, POINTER(c_int * int(p.mDataLength/sizeof(c_int)) )).contents value = [x for x in arr] @@ -464,11 +477,12 @@ def _get_properties(properties, length): def decompose_matrix(matrix): if not isinstance(matrix, structs.Matrix4x4): raise AssimpError("pyassimp.decompose_matrix failed: Not a Matrix4x4!") - + scaling = structs.Vector3D() rotation = structs.Quaternion() position = structs.Vector3D() - + from ctypes import byref, pointer _assimp_lib.dll.aiDecomposeMatrix(pointer(matrix), byref(scaling), byref(rotation), byref(position)) return scaling._init(), rotation._init(), position._init() + diff --git a/port/PyAssimp/pyassimp/helper.py b/port/PyAssimp/pyassimp/helper.py index 2e1ae50b9..85bb53add 100644 --- a/port/PyAssimp/pyassimp/helper.py +++ b/port/PyAssimp/pyassimp/helper.py @@ -9,6 +9,10 @@ import ctypes from ctypes import POINTER import operator +from distutils.sysconfig import get_python_lib +import re +import sys + try: import numpy except: numpy = None @@ -23,9 +27,21 @@ additional_dirs, ext_whitelist = [],[] if os.name=='posix': additional_dirs.append('./') additional_dirs.append('/usr/lib/') + additional_dirs.append('/usr/lib/x86_64-linux-gnu') additional_dirs.append('/usr/local/lib/') - # note - this won't catch libassimp.so.N.n, but + if 'LD_LIBRARY_PATH' in os.environ: + additional_dirs.extend([item for item in os.environ['LD_LIBRARY_PATH'].split(':') if item]) + + # check if running from anaconda. + if "conda" or "continuum" in sys.version.lower(): + cur_path = get_python_lib() + pattern = re.compile('.*\/lib\/') + conda_lib = pattern.match(cur_path).group() + logger.info("Adding Anaconda lib path:"+ conda_lib) + additional_dirs.append(conda_lib) + + # note - this won't catch libassimp.so.N.n, but # currently there's always a symlink called # libassimp.so in /usr/local/lib. ext_whitelist.append('.so') @@ -38,7 +54,7 @@ elif os.name=='nt': for dir_candidate in path_dirs: if 'assimp' in dir_candidate.lower(): additional_dirs.append(dir_candidate) - + #print(additional_dirs) def vec2tuple(x): """ Converts a VECTOR3D to a Tuple """ @@ -60,10 +76,10 @@ def transform(vector3, matrix4x4): m2[0]*x + m2[1]*y + m2[2]*z + m2[3], m3[0]*x + m3[1]*y + m3[2]*z + m3[3] ] - + def _inv(matrix4x4): m0,m1,m2,m3 = matrix4x4 - + det = m0[3]*m1[2]*m2[1]*m3[0] - m0[2]*m1[3]*m2[1]*m3[0] - \ m0[3]*m1[1]*m2[2]*m3[0] + m0[1]*m1[3]*m2[2]*m3[0] + \ m0[2]*m1[1]*m2[3]*m3[0] - m0[1]*m1[2]*m2[3]*m3[0] - \ @@ -76,7 +92,7 @@ def _inv(matrix4x4): m0[2]*m1[1]*m2[0]*m3[3] + m0[1]*m1[2]*m2[0]*m3[3] + \ m0[2]*m1[0]*m2[1]*m3[3] - m0[0]*m1[2]*m2[1]*m3[3] - \ m0[1]*m1[0]*m2[2]*m3[3] + m0[0]*m1[1]*m2[2]*m3[3] - + return[[( m1[2]*m2[3]*m3[1] - m1[3]*m2[2]*m3[1] + m1[3]*m2[1]*m3[2] - m1[1]*m2[3]*m3[2] - m1[2]*m2[1]*m3[3] + m1[1]*m2[2]*m3[3]) /det, ( m0[3]*m2[2]*m3[1] - m0[2]*m2[3]*m3[1] - m0[3]*m2[1]*m3[2] + m0[1]*m2[3]*m3[2] + m0[2]*m2[1]*m3[3] - m0[1]*m2[2]*m3[3]) /det, ( m0[2]*m1[3]*m3[1] - m0[3]*m1[2]*m3[1] + m0[3]*m1[1]*m3[2] - m0[1]*m1[3]*m3[2] - m0[2]*m1[1]*m3[3] + m0[1]*m1[2]*m3[3]) /det, @@ -93,7 +109,7 @@ def _inv(matrix4x4): ( m0[1]*m2[2]*m3[0] - m0[2]*m2[1]*m3[0] + m0[2]*m2[0]*m3[1] - m0[0]*m2[2]*m3[1] - m0[1]*m2[0]*m3[2] + m0[0]*m2[1]*m3[2]) /det, ( m0[2]*m1[1]*m3[0] - m0[1]*m1[2]*m3[0] - m0[2]*m1[0]*m3[1] + m0[0]*m1[2]*m3[1] + m0[1]*m1[0]*m3[2] - m0[0]*m1[1]*m3[2]) /det, ( m0[1]*m1[2]*m2[0] - m0[2]*m1[1]*m2[0] + m0[2]*m1[0]*m2[1] - m0[0]*m1[2]*m2[1] - m0[1]*m1[0]*m2[2] + m0[0]*m1[1]*m2[2]) /det]] - + def get_bounding_box(scene): bb_min = [1e10, 1e10, 1e10] # x,y,z bb_max = [-1e10, -1e10, -1e10] # x,y,z @@ -128,7 +144,7 @@ def get_bounding_box_for_node(node, bb_min, bb_max, transformation): t3[0]*T0[2] + t3[1]*T1[2] + t3[2]*T2[2] + t3[3]*T3[2], t3[0]*T0[3] + t3[1]*T1[3] + t3[2]*T2[3] + t3[3]*T3[3] ] ] - + for mesh in node.meshes: for v in mesh.vertices: v = transform(v, transformation) @@ -148,25 +164,25 @@ def get_bounding_box_for_node(node, bb_min, bb_max, transformation): def try_load_functions(library_path, dll): ''' Try to bind to aiImportFile and aiReleaseImport - + Arguments --------- library_path: path to current lib dll: ctypes handle to library - + Returns --------- If unsuccessful: None If successful: - Tuple containing (library_path, + Tuple containing (library_path, load from filename function, load from memory function, export to filename function, - release function, + release function, ctypes handle to assimp library) ''' - + try: load = dll.aiImportFile release = dll.aiReleaseImport @@ -175,7 +191,7 @@ def try_load_functions(library_path, dll): except AttributeError: #OK, this is a library, but it doesn't have the functions we need return None - + # library found! from .structs import Scene load.restype = POINTER(Scene) @@ -184,13 +200,13 @@ def try_load_functions(library_path, dll): def search_library(): ''' - Loads the assimp library. + Loads the assimp library. Throws exception AssimpError if no library_path is found - - Returns: tuple, (load from filename function, + + Returns: tuple, (load from filename function, load from memory function, export to filename function, - release function, + release function, dll) ''' #this path @@ -200,7 +216,7 @@ def search_library(): try: ctypes.windll.kernel32.SetErrorMode(0x8007) except AttributeError: - pass + pass candidates = [] # test every file @@ -208,7 +224,7 @@ def search_library(): if os.path.isdir(curfolder): for filename in os.listdir(curfolder): # our minimum requirement for candidates is that - # they should contain 'assimp' somewhere in + # they should contain 'assimp' somewhere in # their name if filename.lower().find('assimp')==-1 or\ os.path.splitext(filename)[-1].lower() not in ext_whitelist: @@ -247,10 +263,10 @@ def hasattr_silent(object, name): """ Calls hasttr() with the given parameters and preserves the legacy (pre-Python 3.2) functionality of silently catching exceptions. - + Returns the result of hasatter() or False if an exception was raised. """ - + try: return hasattr(object, name) except: diff --git a/port/PyAssimp/pyassimp/material.py b/port/PyAssimp/pyassimp/material.py new file mode 100644 index 000000000..97b143a62 --- /dev/null +++ b/port/PyAssimp/pyassimp/material.py @@ -0,0 +1,89 @@ +##
Dummy value. +# +# No texture, but the value to be used as 'texture semantic' +# (#aiMaterialProperty::mSemantic) for all material properties +# *not* related to textures. +# +aiTextureType_NONE = 0x0 + +##
The texture is combined with the result of the diffuse +# lighting equation. +# +aiTextureType_DIFFUSE = 0x1 + +##
The texture is combined with the result of the specular +# lighting equation. +# +aiTextureType_SPECULAR = 0x2 + +##
The texture is combined with the result of the ambient +# lighting equation. +# +aiTextureType_AMBIENT = 0x3 + +##
The texture is added to the result of the lighting +# calculation. It isn't influenced by incoming light. +# +aiTextureType_EMISSIVE = 0x4 + +##
The texture is a height map. +# +# By convention, higher gray-scale values stand for +# higher elevations from the base height. +# +aiTextureType_HEIGHT = 0x5 + +##
The texture is a (tangent space) normal-map. +# +# Again, there are several conventions for tangent-space +# normal maps. Assimp does (intentionally) not +# distinguish here. +# +aiTextureType_NORMALS = 0x6 + +##
The texture defines the glossiness of the material. +# +# The glossiness is in fact the exponent of the specular +# (phong) lighting equation. Usually there is a conversion +# function defined to map the linear color values in the +# texture to a suitable exponent. Have fun. +# +aiTextureType_SHININESS = 0x7 + +##
The texture defines per-pixel opacity. +# +# Usually 'white' means opaque and 'black' means +# 'transparency'. Or quite the opposite. Have fun. +# +aiTextureType_OPACITY = 0x8 + +##
Displacement texture +# +# The exact purpose and format is application-dependent. +# Higher color values stand for higher vertex displacements. +# +aiTextureType_DISPLACEMENT = 0x9 + +##
Lightmap texture (aka Ambient Occlusion) +# +# Both 'Lightmaps' and dedicated 'ambient occlusion maps' are +# covered by this material property. The texture contains a +# scaling value for the final color value of a pixel. Its +# intensity is not affected by incoming light. +# +aiTextureType_LIGHTMAP = 0xA + +##
Reflection texture +# +#Contains the color of a perfect mirror reflection. +#Rarely used, almost never for real-time applications. +# +aiTextureType_REFLECTION = 0xB + +##
Unknown texture +# +# A texture reference that does not match any of the definitions +# above is considered to be 'unknown'. It is still imported +# but is excluded from any further postprocessing. +# +aiTextureType_UNKNOWN = 0xC diff --git a/port/PyAssimp/pyassimp/structs.py b/port/PyAssimp/pyassimp/structs.py index 84fcfb7a0..edae77d8d 100644 --- a/port/PyAssimp/pyassimp/structs.py +++ b/port/PyAssimp/pyassimp/structs.py @@ -206,7 +206,7 @@ class MeshKey(Structure): ("mTime", c_double), # Index into the aiMesh::mAnimMeshes array of the - # mesh coresponding to the + # mesh corresponding to the #aiMeshAnim hosting this # key frame. The referenced anim mesh is evaluated # according to the rules defined in the docs for diff --git a/port/PyAssimp/scripts/3d_viewer.py b/port/PyAssimp/scripts/3d_viewer.py index b6c131817..08a62660b 100755 --- a/port/PyAssimp/scripts/3d_viewer.py +++ b/port/PyAssimp/scripts/3d_viewer.py @@ -1,168 +1,597 @@ #!/usr/bin/env python -#-*- coding: UTF-8 -*- +# -*- coding: UTF-8 -*- """ This program loads a model with PyASSIMP, and display it. -It make a large use of shaders to illustrate a 'modern' OpenGL pipeline. - Based on: - - pygame + mouselook code from http://3dengine.org/Spectator_%28PyOpenGL%29 - - http://www.lighthouse3d.com/tutorials - - http://www.songho.ca/opengl/gl_transform.html - - http://code.activestate.com/recipes/325391/ - - ASSIMP's C++ SimpleOpenGL viewer +- pygame code from http://3dengine.org/Spectator_%28PyOpenGL%29 +- http://www.lighthouse3d.com/tutorials +- http://www.songho.ca/opengl/gl_transform.html +- http://code.activestate.com/recipes/325391/ +- ASSIMP's C++ SimpleOpenGL viewer -Authors: Séverin Lemaignan, 2012-2013 +Authors: Séverin Lemaignan, 2012-2016 """ import sys - import logging + logger = logging.getLogger("pyassimp") gllogger = logging.getLogger("OpenGL") gllogger.setLevel(logging.WARNING) logging.basicConfig(level=logging.INFO) import OpenGL -OpenGL.ERROR_CHECKING=False + +OpenGL.ERROR_CHECKING = False OpenGL.ERROR_LOGGING = False -#OpenGL.ERROR_ON_COPY = True -#OpenGL.FULL_LOGGING = True +# OpenGL.ERROR_ON_COPY = True +# OpenGL.FULL_LOGGING = True from OpenGL.GL import * -from OpenGL.error import GLError -from OpenGL.GLU import * -from OpenGL.GLUT import * from OpenGL.arrays import vbo from OpenGL.GL import shaders import pygame +import pygame.font +import pygame.image import math, random -import numpy from numpy import linalg import pyassimp from pyassimp.postprocess import * from pyassimp.helper import * +import transformations + +ROTATION_180_X = numpy.array([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]], dtype=numpy.float32) + +# rendering mode +BASE = "BASE" +COLORS = "COLORS" +SILHOUETTE = "SILHOUETTE" +HELPERS = "HELPERS" + +# Entities type +ENTITY = "entity" +CAMERA = "camera" +MESH = "mesh" + +FLAT_VERTEX_SHADER_120 = """ +#version 120 + +uniform mat4 u_viewProjectionMatrix; +uniform mat4 u_modelMatrix; + +uniform vec4 u_materialDiffuse; + +attribute vec3 a_vertex; + +varying vec4 v_color; + +void main(void) +{ + v_color = u_materialDiffuse; + gl_Position = u_viewProjectionMatrix * u_modelMatrix * vec4(a_vertex, 1.0); +} +""" + +FLAT_VERTEX_SHADER_130 = """ +#version 130 + +uniform mat4 u_viewProjectionMatrix; +uniform mat4 u_modelMatrix; + +uniform vec4 u_materialDiffuse; + +in vec3 a_vertex; + +out vec4 v_color; + +void main(void) +{ + v_color = u_materialDiffuse; + gl_Position = u_viewProjectionMatrix * u_modelMatrix * vec4(a_vertex, 1.0); +} +""" + +BASIC_VERTEX_SHADER_120 = """ +#version 120 + +uniform mat4 u_viewProjectionMatrix; +uniform mat4 u_modelMatrix; +uniform mat3 u_normalMatrix; +uniform vec3 u_lightPos; + +uniform vec4 u_materialDiffuse; + +attribute vec3 a_vertex; +attribute vec3 a_normal; + +varying vec4 v_color; + +void main(void) +{ + // Now the normal is in world space, as we pass the light in world space. + vec3 normal = u_normalMatrix * a_normal; + + float dist = distance(a_vertex, u_lightPos); + + // go to https://www.desmos.com/calculator/nmnaud1hrw to play with the parameters + // att is not used for now + float att=1.0/(1.0+0.8*dist*dist); + + vec3 surf2light = normalize(u_lightPos - a_vertex); + vec3 norm = normalize(normal); + float dcont=max(0.0,dot(norm,surf2light)); + + float ambient = 0.3; + float intensity = dcont + 0.3 + ambient; + + v_color = u_materialDiffuse * intensity; + + gl_Position = u_viewProjectionMatrix * u_modelMatrix * vec4(a_vertex, 1.0); +} +""" + +BASIC_VERTEX_SHADER_130 = """ +#version 130 + +uniform mat4 u_viewProjectionMatrix; +uniform mat4 u_modelMatrix; +uniform mat3 u_normalMatrix; +uniform vec3 u_lightPos; + +uniform vec4 u_materialDiffuse; + +in vec3 a_vertex; +in vec3 a_normal; + +out vec4 v_color; + +void main(void) +{ + // Now the normal is in world space, as we pass the light in world space. + vec3 normal = u_normalMatrix * a_normal; + + float dist = distance(a_vertex, u_lightPos); + + // go to https://www.desmos.com/calculator/nmnaud1hrw to play with the parameters + // att is not used for now + float att=1.0/(1.0+0.8*dist*dist); + + vec3 surf2light = normalize(u_lightPos - a_vertex); + vec3 norm = normalize(normal); + float dcont=max(0.0,dot(norm,surf2light)); + + float ambient = 0.3; + float intensity = dcont + 0.3 + ambient; + + v_color = u_materialDiffuse * intensity; + + gl_Position = u_viewProjectionMatrix * u_modelMatrix * vec4(a_vertex, 1.0); +} +""" + +BASIC_FRAGMENT_SHADER_120 = """ +#version 120 + +varying vec4 v_color; + +void main() { + gl_FragColor = v_color; +} +""" + +BASIC_FRAGMENT_SHADER_130 = """ +#version 130 + +in vec4 v_color; + +void main() { + gl_FragColor = v_color; +} +""" + +GOOCH_VERTEX_SHADER_120 = """ +#version 120 + +// attributes +attribute vec3 a_vertex; // xyz - position +attribute vec3 a_normal; // xyz - normal + +// uniforms +uniform mat4 u_modelMatrix; +uniform mat4 u_viewProjectionMatrix; +uniform mat3 u_normalMatrix; +uniform vec3 u_lightPos; +uniform vec3 u_camPos; + +// output data from vertex to fragment shader +varying vec3 o_normal; +varying vec3 o_lightVector; + +/////////////////////////////////////////////////////////////////// + +void main(void) +{ + // transform position and normal to world space + vec4 positionWorld = u_modelMatrix * vec4(a_vertex, 1.0); + vec3 normalWorld = u_normalMatrix * a_normal; + + // calculate and pass vectors required for lighting + o_lightVector = u_lightPos - positionWorld.xyz; + o_normal = normalWorld; + + // project world space position to the screen and output it + gl_Position = u_viewProjectionMatrix * positionWorld; +} +""" + +GOOCH_VERTEX_SHADER_130 = """ +#version 130 + +// attributes +in vec3 a_vertex; // xyz - position +in vec3 a_normal; // xyz - normal + +// uniforms +uniform mat4 u_modelMatrix; +uniform mat4 u_viewProjectionMatrix; +uniform mat3 u_normalMatrix; +uniform vec3 u_lightPos; +uniform vec3 u_camPos; + +// output data from vertex to fragment shader +out vec3 o_normal; +out vec3 o_lightVector; + +/////////////////////////////////////////////////////////////////// + +void main(void) +{ + // transform position and normal to world space + vec4 positionWorld = u_modelMatrix * vec4(a_vertex, 1.0); + vec3 normalWorld = u_normalMatrix * a_normal; + + // calculate and pass vectors required for lighting + o_lightVector = u_lightPos - positionWorld.xyz; + o_normal = normalWorld; + + // project world space position to the screen and output it + gl_Position = u_viewProjectionMatrix * positionWorld; +} +""" + +GOOCH_FRAGMENT_SHADER_120 = """ +#version 120 + +// data from vertex shader +varying vec3 o_normal; +varying vec3 o_lightVector; + +// diffuse color of the object +uniform vec4 u_materialDiffuse; +// cool color of gooch shading +uniform vec3 u_coolColor; +// warm color of gooch shading +uniform vec3 u_warmColor; +// how much to take from object color in final cool color +uniform float u_alpha; +// how much to take from object color in final warm color +uniform float u_beta; + +/////////////////////////////////////////////////////////// + +void main(void) +{ + // normlize vectors for lighting + vec3 normalVector = normalize(o_normal); + vec3 lightVector = normalize(o_lightVector); + // intensity of diffuse lighting [-1, 1] + float diffuseLighting = dot(lightVector, normalVector); + // map intensity of lighting from range [-1; 1] to [0, 1] + float interpolationValue = (1.0 + diffuseLighting)/2; + + ////////////////////////////////////////////////////////////////// + + // cool color mixed with color of the object + vec3 coolColorMod = u_coolColor + vec3(u_materialDiffuse) * u_alpha; + // warm color mixed with color of the object + vec3 warmColorMod = u_warmColor + vec3(u_materialDiffuse) * u_beta; + // interpolation of cool and warm colors according + // to lighting intensity. The lower the light intensity, + // the larger part of the cool color is used + vec3 colorOut = mix(coolColorMod, warmColorMod, interpolationValue); + + ////////////////////////////////////////////////////////////////// + + // save color + gl_FragColor.rgb = colorOut; + gl_FragColor.a = 1; +} +""" + +GOOCH_FRAGMENT_SHADER_130 = """ +#version 130 + +// data from vertex shader +in vec3 o_normal; +in vec3 o_lightVector; + +// diffuse color of the object +uniform vec4 u_materialDiffuse; +// cool color of gooch shading +uniform vec3 u_coolColor; +// warm color of gooch shading +uniform vec3 u_warmColor; +// how much to take from object color in final cool color +uniform float u_alpha; +// how much to take from object color in final warm color +uniform float u_beta; + +// output to framebuffer +out vec4 resultingColor; + +/////////////////////////////////////////////////////////// + +void main(void) +{ + // normlize vectors for lighting + vec3 normalVector = normalize(o_normal); + vec3 lightVector = normalize(o_lightVector); + // intensity of diffuse lighting [-1, 1] + float diffuseLighting = dot(lightVector, normalVector); + // map intensity of lighting from range [-1; 1] to [0, 1] + float interpolationValue = (1.0 + diffuseLighting)/2; + + ////////////////////////////////////////////////////////////////// + + // cool color mixed with color of the object + vec3 coolColorMod = u_coolColor + vec3(u_materialDiffuse) * u_alpha; + // warm color mixed with color of the object + vec3 warmColorMod = u_warmColor + vec3(u_materialDiffuse) * u_beta; + // interpolation of cool and warm colors according + // to lighting intensity. The lower the light intensity, + // the larger part of the cool color is used + vec3 colorOut = mix(coolColorMod, warmColorMod, interpolationValue); + + ////////////////////////////////////////////////////////////////// + + // save color + resultingColor.rgb = colorOut; + resultingColor.a = 1; +} +""" + +SILHOUETTE_VERTEX_SHADER_120 = """ +#version 120 + +attribute vec3 a_vertex; // xyz - position +attribute vec3 a_normal; // xyz - normal + +uniform mat4 u_modelMatrix; +uniform mat4 u_viewProjectionMatrix; +uniform mat4 u_modelViewMatrix; +uniform vec4 u_materialDiffuse; +uniform float u_bordersize; // width of the border + +varying vec4 v_color; + +void main(void){ + v_color = u_materialDiffuse; + float distToCamera = -(u_modelViewMatrix * vec4(a_vertex, 1.0)).z; + vec4 tPos = vec4(a_vertex + a_normal * u_bordersize * distToCamera, 1.0); + gl_Position = u_viewProjectionMatrix * u_modelMatrix * tPos; +} +""" + +SILHOUETTE_VERTEX_SHADER_130 = """ +#version 130 + +in vec3 a_vertex; // xyz - position +in vec3 a_normal; // xyz - normal + +uniform mat4 u_modelMatrix; +uniform mat4 u_viewProjectionMatrix; +uniform mat4 u_modelViewMatrix; +uniform vec4 u_materialDiffuse; +uniform float u_bordersize; // width of the border + +out vec4 v_color; + +void main(void){ + v_color = u_materialDiffuse; + float distToCamera = -(u_modelViewMatrix * vec4(a_vertex, 1.0)).z; + vec4 tPos = vec4(a_vertex + a_normal * u_bordersize * distToCamera, 1.0); + gl_Position = u_viewProjectionMatrix * u_modelMatrix * tPos; +} +""" +DEFAULT_CLIP_PLANE_NEAR = 0.001 +DEFAULT_CLIP_PLANE_FAR = 1000.0 + + +def get_world_transform(scene, node): + if node == scene.rootnode: + return numpy.identity(4, dtype=numpy.float32) + + parents = reversed(_get_parent_chain(scene, node, [])) + parent_transform = reduce(numpy.dot, [p.transformation for p in parents]) + return numpy.dot(parent_transform, node.transformation) + + +def _get_parent_chain(scene, node, parents): + parent = node.parent + + parents.append(parent) + + if parent == scene.rootnode: + return parents + + return _get_parent_chain(scene, parent, parents) + class DefaultCamera: def __init__(self, w, h, fov): - self.clipplanenear = 0.001 - self.clipplanefar = 100000.0 - self.aspect = w/h - self.horizontalfov = fov * math.pi/180 - self.transformation = [[ 0.68, -0.32, 0.65, 7.48], - [ 0.73, 0.31, -0.61, -6.51], - [-0.01, 0.89, 0.44, 5.34], - [ 0., 0., 0., 1. ]] - self.lookat = [0.0,0.0,-1.0] + self.name = "default camera" + self.type = CAMERA + self.clipplanenear = DEFAULT_CLIP_PLANE_NEAR + self.clipplanefar = DEFAULT_CLIP_PLANE_FAR + self.aspect = w / h + self.horizontalfov = fov * math.pi / 180 + self.transformation = numpy.array([[0.68, -0.32, 0.65, 7.48], + [0.73, 0.31, -0.61, -6.51], + [-0.01, 0.89, 0.44, 5.34], + [0., 0., 0., 1.]], dtype=numpy.float32) + + self.transformation = numpy.dot(self.transformation, ROTATION_180_X) def __str__(self): - return "Default camera" + return self.name + class PyAssimp3DViewer: - base_name = "PyASSIMP 3D viewer" - def __init__(self, model, w=1024, h=768, fov=75): + def __init__(self, model, w=1024, h=768): + + self.w = w + self.h = h pygame.init() pygame.display.set_caption(self.base_name) - pygame.display.set_mode((w,h), pygame.OPENGL | pygame.DOUBLEBUF) - glutInit() - self.prepare_shaders() + pygame.display.set_mode((w, h), pygame.OPENGL | pygame.DOUBLEBUF) + + glClearColor(0.18, 0.18, 0.18, 1.0) + + shader_compilation_succeeded = False + try: + self.set_shaders_v130() + self.prepare_shaders() + except RuntimeError, message: + sys.stderr.write("%s\n" % message) + sys.stdout.write("Could not compile shaders in version 1.30, trying version 1.20\n") + + if not shader_compilation_succeeded: + self.set_shaders_v120() + self.prepare_shaders() + + self.scene = None + self.meshes = {} # stores the OpenGL vertex/faces/normals buffers pointers + + self.node2colorid = {} # stores a color ID for each node. Useful for mouse picking and visibility checking + self.colorid2node = {} # reverse dict of node2colorid + + self.currently_selected = None + self.moving = False + self.moving_situation = None + + self.default_camera = DefaultCamera(self.w, self.h, fov=70) + self.cameras = [self.default_camera] - self.cameras = [DefaultCamera(w,h,fov)] self.current_cam_index = 0 + self.current_cam = self.default_camera + self.set_camera_projection() self.load_model(model) - # for FPS computation - self.frames = 0 - self.last_fps_time = glutGet(GLUT_ELAPSED_TIME) + # user interactions + self.focal_point = [0, 0, 0] + self.is_rotating = False + self.is_panning = False + self.is_zooming = False + def set_shaders_v120(self): + self.BASIC_VERTEX_SHADER = BASIC_VERTEX_SHADER_120 + self.FLAT_VERTEX_SHADER = FLAT_VERTEX_SHADER_120 + self.SILHOUETTE_VERTEX_SHADER = SILHOUETTE_VERTEX_SHADER_120 + self.GOOCH_VERTEX_SHADER = GOOCH_VERTEX_SHADER_120 - self.cycle_cameras() + self.BASIC_FRAGMENT_SHADER = BASIC_FRAGMENT_SHADER_120 + self.GOOCH_FRAGMENT_SHADER = GOOCH_FRAGMENT_SHADER_120 + + def set_shaders_v130(self): + self.BASIC_VERTEX_SHADER = BASIC_VERTEX_SHADER_130 + self.FLAT_VERTEX_SHADER = FLAT_VERTEX_SHADER_130 + self.SILHOUETTE_VERTEX_SHADER = SILHOUETTE_VERTEX_SHADER_130 + self.GOOCH_VERTEX_SHADER = GOOCH_VERTEX_SHADER_130 + + self.BASIC_FRAGMENT_SHADER = BASIC_FRAGMENT_SHADER_130 + self.GOOCH_FRAGMENT_SHADER = GOOCH_FRAGMENT_SHADER_130 def prepare_shaders(self): - phong_weightCalc = """ - float phong_weightCalc( - in vec3 light_pos, // light position - in vec3 frag_normal // geometry normal - ) { - // returns vec2( ambientMult, diffuseMult ) - float n_dot_pos = max( 0.0, dot( - frag_normal, light_pos - )); - return n_dot_pos; - } - """ + ### Base shader + vertex = shaders.compileShader(self.BASIC_VERTEX_SHADER, GL_VERTEX_SHADER) + fragment = shaders.compileShader(self.BASIC_FRAGMENT_SHADER, GL_FRAGMENT_SHADER) - vertex = shaders.compileShader( phong_weightCalc + - """ - uniform vec4 Global_ambient; - uniform vec4 Light_ambient; - uniform vec4 Light_diffuse; - uniform vec3 Light_location; - uniform vec4 Material_ambient; - uniform vec4 Material_diffuse; - attribute vec3 Vertex_position; - attribute vec3 Vertex_normal; - varying vec4 baseColor; - void main() { - gl_Position = gl_ModelViewProjectionMatrix * vec4( - Vertex_position, 1.0 - ); - vec3 EC_Light_location = gl_NormalMatrix * Light_location; - float diffuse_weight = phong_weightCalc( - normalize(EC_Light_location), - normalize(gl_NormalMatrix * Vertex_normal) - ); - baseColor = clamp( - ( - // global component - (Global_ambient * Material_ambient) - // material's interaction with light's contribution - // to the ambient lighting... - + (Light_ambient * Material_ambient) - // material's interaction with the direct light from - // the light. - + (Light_diffuse * Material_diffuse * diffuse_weight) - ), 0.0, 1.0); - }""", GL_VERTEX_SHADER) + self.shader = shaders.compileProgram(vertex, fragment) - fragment = shaders.compileShader(""" - varying vec4 baseColor; - void main() { - gl_FragColor = baseColor; - } - """, GL_FRAGMENT_SHADER) + self.set_shader_accessors(('u_modelMatrix', + 'u_viewProjectionMatrix', + 'u_normalMatrix', + 'u_lightPos', + 'u_materialDiffuse'), + ('a_vertex', + 'a_normal'), self.shader) - self.shader = shaders.compileProgram(vertex,fragment) - self.set_shader_accessors( ( - 'Global_ambient', - 'Light_ambient','Light_diffuse','Light_location', - 'Material_ambient','Material_diffuse', - ), ( - 'Vertex_position','Vertex_normal', - ), self.shader) + ### Flat shader + flatvertex = shaders.compileShader(self.FLAT_VERTEX_SHADER, GL_VERTEX_SHADER) + self.flatshader = shaders.compileProgram(flatvertex, fragment) - def set_shader_accessors(self, uniforms, attributes, shader): + self.set_shader_accessors(('u_modelMatrix', + 'u_viewProjectionMatrix', + 'u_materialDiffuse',), + ('a_vertex',), self.flatshader) + + ### Silhouette shader + silh_vertex = shaders.compileShader(self.SILHOUETTE_VERTEX_SHADER, GL_VERTEX_SHADER) + self.silhouette_shader = shaders.compileProgram(silh_vertex, fragment) + + self.set_shader_accessors(('u_modelMatrix', + 'u_viewProjectionMatrix', + 'u_modelViewMatrix', + 'u_materialDiffuse', + 'u_bordersize' # width of the silhouette + ), + ('a_vertex', + 'a_normal'), self.silhouette_shader) + + ### Gooch shader + gooch_vertex = shaders.compileShader(self.GOOCH_VERTEX_SHADER, GL_VERTEX_SHADER) + gooch_fragment = shaders.compileShader(self.GOOCH_FRAGMENT_SHADER, GL_FRAGMENT_SHADER) + self.gooch_shader = shaders.compileProgram(gooch_vertex, gooch_fragment) + + self.set_shader_accessors(('u_modelMatrix', + 'u_viewProjectionMatrix', + 'u_normalMatrix', + 'u_lightPos', + 'u_materialDiffuse', + 'u_coolColor', + 'u_warmColor', + 'u_alpha', + 'u_beta' + ), + ('a_vertex', + 'a_normal'), self.gooch_shader) + + @staticmethod + def set_shader_accessors(uniforms, attributes, shader): # add accessors to the shaders uniforms and attributes for uniform in uniforms: - location = glGetUniformLocation( shader, uniform ) - if location in (None,-1): - logger.warning('No uniform: %s'%( uniform )) - setattr( shader, uniform, location ) + location = glGetUniformLocation(shader, uniform) + if location in (None, -1): + raise RuntimeError('No uniform: %s (maybe it is not used ' + 'anymore and has been optimized out by' + ' the shader compiler)' % uniform) + setattr(shader, uniform, location) for attribute in attributes: - location = glGetAttribLocation( shader, attribute ) - if location in (None,-1): - logger.warning('No attribute: %s'%( attribute )) - setattr( shader, attribute, location ) + location = glGetAttribLocation(shader, attribute) + if location in (None, -1): + raise RuntimeError('No attribute: %s' % attribute) + setattr(shader, attribute, location) - - def prepare_gl_buffers(self, mesh): + @staticmethod + def prepare_gl_buffers(mesh): mesh.gl = {} @@ -170,28 +599,93 @@ class PyAssimp3DViewer: v = numpy.array(mesh.vertices, 'f') n = numpy.array(mesh.normals, 'f') - mesh.gl["vbo"] = vbo.VBO(numpy.hstack((v,n))) + mesh.gl["vbo"] = vbo.VBO(numpy.hstack((v, n))) # Fill the buffer for vertex positions mesh.gl["faces"] = glGenBuffers(1) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.gl["faces"]) - glBufferData(GL_ELEMENT_ARRAY_BUFFER, - mesh.faces, - GL_STATIC_DRAW) - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0) + glBufferData(GL_ELEMENT_ARRAY_BUFFER, + numpy.array(mesh.faces, dtype=numpy.int32), + GL_STATIC_DRAW) - - def load_model(self, path, postprocess = aiProcessPreset_TargetRealtime_MaxQuality): + mesh.gl["nbfaces"] = len(mesh.faces) + + # Unbind buffers + glBindBuffer(GL_ARRAY_BUFFER, 0) + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) + + @staticmethod + def get_rgb_from_colorid(colorid): + r = (colorid >> 0) & 0xff + g = (colorid >> 8) & 0xff + b = (colorid >> 16) & 0xff + + return r, g, b + + def get_color_id(self): + id = random.randint(0, 256 * 256 * 256) + if id not in self.colorid2node: + return id + else: + return self.get_color_id() + + def glize(self, scene, node): + + logger.info("Loading node <%s>" % node) + node.selected = True if self.currently_selected and self.currently_selected == node else False + + node.transformation = node.transformation.astype(numpy.float32) + + if node.meshes: + node.type = MESH + colorid = self.get_color_id() + self.colorid2node[colorid] = node + self.node2colorid[node.name] = colorid + + elif node.name in [c.name for c in scene.cameras]: + + # retrieve the ASSIMP camera object + [cam] = [c for c in scene.cameras if c.name == node.name] + node.type = CAMERA + logger.info("Added camera <%s>" % node.name) + logger.info("Camera position: %.3f, %.3f, %.3f" % tuple(node.transformation[:, 3][:3].tolist())) + self.cameras.append(node) + node.clipplanenear = cam.clipplanenear + node.clipplanefar = cam.clipplanefar + + if numpy.allclose(cam.lookat, [0, 0, -1]) and numpy.allclose(cam.up, [0, 1, 0]): # Cameras in .blend files + + # Rotate by 180deg around X to have Z pointing forward + node.transformation = numpy.dot(node.transformation, ROTATION_180_X) + else: + raise RuntimeError( + "I do not know how to normalize this camera orientation: lookat=%s, up=%s" % (cam.lookat, cam.up)) + + if cam.aspect == 0.0: + logger.warning("Camera aspect not set. Setting to default 4:3") + node.aspect = 1.333 + else: + node.aspect = cam.aspect + + node.horizontalfov = cam.horizontalfov + + else: + node.type = ENTITY + + for child in node.children: + self.glize(scene, child) + + def load_model(self, path, postprocess=aiProcessPreset_TargetRealtime_MaxQuality): logger.info("Loading model:" + path + "...") if postprocess: - self.scene = pyassimp.load(path, postprocess) + self.scene = pyassimp.load(path, processing=postprocess) else: self.scene = pyassimp.load(path) logger.info("Done.") scene = self.scene - #log some statistics + # log some statistics logger.info(" meshes: %d" % len(scene.meshes)) logger.info(" total faces: %d" % sum([len(mesh.faces) for mesh in scene.meshes])) logger.info(" materials: %d" % len(scene.materials)) @@ -203,27 +697,34 @@ class PyAssimp3DViewer: for index, mesh in enumerate(scene.meshes): self.prepare_gl_buffers(mesh) + self.glize(scene, scene.rootnode) + # Finally release the model pyassimp.release(scene) - logger.info("Ready for 3D rendering!") def cycle_cameras(self): - if not self.cameras: - logger.info("No camera in the scene") - return None + self.current_cam_index = (self.current_cam_index + 1) % len(self.cameras) self.current_cam = self.cameras[self.current_cam_index] - self.set_camera(self.current_cam) + self.set_camera_projection(self.current_cam) logger.info("Switched to camera <%s>" % self.current_cam) - def set_camera_projection(self, camera = None): + def set_overlay_projection(self): + glViewport(0, 0, self.w, self.h) + glMatrixMode(GL_PROJECTION) + glLoadIdentity() + glOrtho(0.0, self.w - 1.0, 0.0, self.h - 1.0, -1.0, 1.0) + glMatrixMode(GL_MODELVIEW) + glLoadIdentity() + + def set_camera_projection(self, camera=None): if not camera: - camera = self.cameras[self.current_cam_index] + camera = self.current_cam - znear = camera.clipplanenear - zfar = camera.clipplanefar + znear = camera.clipplanenear or DEFAULT_CLIP_PLANE_NEAR + zfar = camera.clipplanefar or DEFAULT_CLIP_PLANE_FAR aspect = camera.aspect fov = camera.horizontalfov @@ -231,185 +732,587 @@ class PyAssimp3DViewer: glLoadIdentity() # Compute gl frustrum - tangent = math.tan(fov/2.) + tangent = math.tan(fov / 2.) h = znear * tangent w = h * aspect # params: left, right, bottom, top, near, far glFrustum(-w, w, -h, h, znear, zfar) # equivalent to: - #gluPerspective(fov * 180/math.pi, aspect, znear, zfar) - glMatrixMode(GL_MODELVIEW) - glLoadIdentity() + # gluPerspective(fov * 180/math.pi, aspect, znear, zfar) - - def set_camera(self, camera): - - self.set_camera_projection(camera) + self.projection_matrix = glGetFloatv(GL_PROJECTION_MATRIX).transpose() glMatrixMode(GL_MODELVIEW) glLoadIdentity() - cam = transform([0.0, 0.0, 0.0], camera.transformation) - at = transform(camera.lookat, camera.transformation) - gluLookAt(cam[0], cam[2], -cam[1], - at[0], at[2], -at[1], - 0, 1, 0) - - def render(self, wireframe = False, twosided = False): + def render_colors(self): glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LEQUAL) + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) + glEnable(GL_CULL_FACE) + + glUseProgram(self.flatshader) + + glUniformMatrix4fv(self.flatshader.u_viewProjectionMatrix, 1, GL_TRUE, + numpy.dot(self.projection_matrix, self.view_matrix)) + + self.recursive_render(self.scene.rootnode, self.flatshader, mode=COLORS) + + glUseProgram(0) + + def get_hovered_node(self, mousex, mousey): + """ + Attention: The performances of this method relies heavily on the size of the display! + """ + + # mouse out of the window? + if mousex < 0 or mousex >= self.w or mousey < 0 or mousey >= self.h: + return None + + self.render_colors() + # Capture image from the OpenGL buffer + buf = (GLubyte * (3 * self.w * self.h))(0) + glReadPixels(0, 0, self.w, self.h, GL_RGB, GL_UNSIGNED_BYTE, buf) + + # Reinterpret the RGB pixel buffer as a 1-D array of 24bits colors + a = numpy.ndarray(len(buf), numpy.dtype('>u1'), buf) + colors = numpy.zeros(len(buf) / 3, numpy.dtype('u1')[i::3] + + colorid = colors[mousex + mousey * self.w] + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) + + if colorid in self.colorid2node: + return self.colorid2node[colorid] + + def render(self, wireframe=False, twosided=False): + + glEnable(GL_DEPTH_TEST) + glDepthFunc(GL_LEQUAL) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE if wireframe else GL_FILL) glDisable(GL_CULL_FACE) if twosided else glEnable(GL_CULL_FACE) - shader = self.shader + self.render_grid() - glUseProgram(shader) - glUniform4f( shader.Global_ambient, .4,.2,.2,.1 ) - glUniform4f( shader.Light_ambient, .4,.4,.4, 1.0 ) - glUniform4f( shader.Light_diffuse, 1,1,1,1 ) - glUniform3f( shader.Light_location, 2,2,10 ) + self.recursive_render(self.scene.rootnode, None, mode=HELPERS) + + ### First, the silhouette + + if False: + shader = self.silhouette_shader + + # glDepthMask(GL_FALSE) + glCullFace(GL_FRONT) # cull front faces + + glUseProgram(shader) + glUniform1f(shader.u_bordersize, 0.01) + + glUniformMatrix4fv(shader.u_viewProjectionMatrix, 1, GL_TRUE, + numpy.dot(self.projection_matrix, self.view_matrix)) + + self.recursive_render(self.scene.rootnode, shader, mode=SILHOUETTE) + + glUseProgram(0) + + ### Then, inner shading + # glDepthMask(GL_TRUE) + glCullFace(GL_BACK) + + use_gooch = False + if use_gooch: + shader = self.gooch_shader + + glUseProgram(shader) + glUniform3f(shader.u_lightPos, -.5, -.5, .5) + + ##### GOOCH specific + glUniform3f(shader.u_coolColor, 159.0 / 255, 148.0 / 255, 255.0 / 255) + glUniform3f(shader.u_warmColor, 255.0 / 255, 75.0 / 255, 75.0 / 255) + glUniform1f(shader.u_alpha, .25) + glUniform1f(shader.u_beta, .25) + ######### + else: + shader = self.shader + glUseProgram(shader) + glUniform3f(shader.u_lightPos, -.5, -.5, .5) + + glUniformMatrix4fv(shader.u_viewProjectionMatrix, 1, GL_TRUE, + numpy.dot(self.projection_matrix, self.view_matrix)) self.recursive_render(self.scene.rootnode, shader) + glUseProgram(0) - glUseProgram( 0 ) + def render_axis(self, + transformation=numpy.identity(4, dtype=numpy.float32), + label=None, + size=0.2, + selected=False): + m = transformation.transpose() # OpenGL row major - def recursive_render(self, node, shader): - """ Main recursive rendering method. - """ - - # save model matrix and apply node transformation glPushMatrix() - m = node.transformation.transpose() # OpenGL row major glMultMatrixf(m) - for mesh in node.meshes: + glLineWidth(3 if selected else 1) - stride = 24 # 6 * 4 bytes + size = 2 * size if selected else size - diffuse = mesh.material.properties["diffuse"] - if len(diffuse) == 3: diffuse.append(1.0) - ambient = mesh.material.properties["ambient"] - if len(ambient) == 3: ambient.append(1.0) + glBegin(GL_LINES) - glUniform4f( shader.Material_diffuse, *diffuse ) - glUniform4f( shader.Material_ambient, *ambient ) + # draw line for x axis + glColor3f(1.0, 0.0, 0.0) + glVertex3f(0.0, 0.0, 0.0) + glVertex3f(size, 0.0, 0.0) - vbo = mesh.gl["vbo"] - vbo.bind() + # draw line for y axis + glColor3f(0.0, 1.0, 0.0) + glVertex3f(0.0, 0.0, 0.0) + glVertex3f(0.0, size, 0.0) - glEnableVertexAttribArray( shader.Vertex_position ) - glEnableVertexAttribArray( shader.Vertex_normal ) + # draw line for Z axis + glColor3f(0.0, 0.0, 1.0) + glVertex3f(0.0, 0.0, 0.0) + glVertex3f(0.0, 0.0, size) - glVertexAttribPointer( - shader.Vertex_position, - 3, GL_FLOAT,False, stride, vbo - ) + glEnd() - glVertexAttribPointer( - shader.Vertex_normal, - 3, GL_FLOAT,False, stride, vbo+12 - ) - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.gl["faces"]) - glDrawElements(GL_TRIANGLES, len(mesh.faces) * 3, GL_UNSIGNED_INT, None) - - - vbo.unbind() - glDisableVertexAttribArray( shader.Vertex_position ) - - glDisableVertexAttribArray( shader.Vertex_normal ) - - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) - - for child in node.children: - self.recursive_render(child, shader) + if label: + self.showtext(label) glPopMatrix() + @staticmethod + def render_camera(camera, transformation): + + m = transformation.transpose() # OpenGL row major + + aspect = camera.aspect + + u = 0.1 # unit size (in m) + l = 3 * u # length of the camera cone + f = 3 * u # aperture of the camera cone + + glPushMatrix() + glMultMatrixf(m) + + glLineWidth(2) + glBegin(GL_LINE_STRIP) + + glColor3f(.2, .2, .2) + + glVertex3f(u, u, -u) + glVertex3f(u, -u, -u) + glVertex3f(-u, -u, -u) + glVertex3f(-u, u, -u) + glVertex3f(u, u, -u) + + glVertex3f(u, u, 0.0) + glVertex3f(u, -u, 0.0) + glVertex3f(-u, -u, 0.0) + glVertex3f(-u, u, 0.0) + glVertex3f(u, u, 0.0) + + glVertex3f(f * aspect, f, l) + glVertex3f(f * aspect, -f, l) + glVertex3f(-f * aspect, -f, l) + glVertex3f(-f * aspect, f, l) + glVertex3f(f * aspect, f, l) + + glEnd() + + glBegin(GL_LINE_STRIP) + glVertex3f(u, -u, -u) + glVertex3f(u, -u, 0.0) + glVertex3f(f * aspect, -f, l) + glEnd() + + glBegin(GL_LINE_STRIP) + glVertex3f(-u, -u, -u) + glVertex3f(-u, -u, 0.0) + glVertex3f(-f * aspect, -f, l) + glEnd() + + glBegin(GL_LINE_STRIP) + glVertex3f(-u, u, -u) + glVertex3f(-u, u, 0.0) + glVertex3f(-f * aspect, f, l) + glEnd() + + glPopMatrix() + + @staticmethod + def render_grid(): + + glLineWidth(1) + glColor3f(0.5, 0.5, 0.5) + glBegin(GL_LINES) + for i in range(-10, 11): + glVertex3f(i, -10.0, 0.0) + glVertex3f(i, 10.0, 0.0) + + for i in range(-10, 11): + glVertex3f(-10.0, i, 0.0) + glVertex3f(10.0, i, 0.0) + glEnd() + + def recursive_render(self, node, shader, mode=BASE, with_normals=True): + """ Main recursive rendering method. + """ + + normals = with_normals + + if mode == COLORS: + normals = False + + + if not hasattr(node, "selected"): + node.selected = False + + m = get_world_transform(self.scene, node) + + # HELPERS mode + ### + if mode == HELPERS: + # if node.type == ENTITY: + self.render_axis(m, + label=node.name if node != self.scene.rootnode else None, + selected=node.selected if hasattr(node, "selected") else False) + + if node.type == CAMERA: + self.render_camera(node, m) + + for child in node.children: + self.recursive_render(child, shader, mode) + + return + + # Mesh rendering modes + ### + if node.type == MESH: + + for mesh in node.meshes: + + stride = 24 # 6 * 4 bytes + + if node.selected and mode == SILHOUETTE: + glUniform4f(shader.u_materialDiffuse, 1.0, 0.0, 0.0, 1.0) + glUniformMatrix4fv(shader.u_modelViewMatrix, 1, GL_TRUE, + numpy.dot(self.view_matrix, m)) + + else: + if mode == COLORS: + colorid = self.node2colorid[node.name] + r, g, b = self.get_rgb_from_colorid(colorid) + glUniform4f(shader.u_materialDiffuse, r / 255.0, g / 255.0, b / 255.0, 1.0) + elif mode == SILHOUETTE: + glUniform4f(shader.u_materialDiffuse, .0, .0, .0, 1.0) + else: + if node.selected: + diffuse = (1.0, 0.0, 0.0, 1.0) # selected nodes in red + else: + diffuse = mesh.material.properties["diffuse"] + if len(diffuse) == 3: # RGB instead of expected RGBA + diffuse.append(1.0) + glUniform4f(shader.u_materialDiffuse, *diffuse) + # if ambient: + # glUniform4f( shader.Material_ambient, *mat["ambient"] ) + + if mode == BASE: # not in COLORS or SILHOUETTE + normal_matrix = linalg.inv(numpy.dot(self.view_matrix, m)[0:3, 0:3]).transpose() + glUniformMatrix3fv(shader.u_normalMatrix, 1, GL_TRUE, normal_matrix) + + glUniformMatrix4fv(shader.u_modelMatrix, 1, GL_TRUE, m) + + vbo = mesh.gl["vbo"] + vbo.bind() + + glEnableVertexAttribArray(shader.a_vertex) + if normals: + glEnableVertexAttribArray(shader.a_normal) + + glVertexAttribPointer( + shader.a_vertex, + 3, GL_FLOAT, False, stride, vbo + ) + + if normals: + glVertexAttribPointer( + shader.a_normal, + 3, GL_FLOAT, False, stride, vbo + 12 + ) + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.gl["faces"]) + glDrawElements(GL_TRIANGLES, mesh.gl["nbfaces"] * 3, GL_UNSIGNED_INT, None) + + vbo.unbind() + glDisableVertexAttribArray(shader.a_vertex) + + if normals: + glDisableVertexAttribArray(shader.a_normal) + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) + + for child in node.children: + self.recursive_render(child, shader, mode) + + + def switch_to_overlay(self): + glPushMatrix() + self.set_overlay_projection() + + def switch_from_overlay(self): + self.set_camera_projection() + glPopMatrix() + + def select_node(self, node): + self.currently_selected = node + self.update_node_select(self.scene.rootnode) + + def update_node_select(self, node): + if node is self.currently_selected: + node.selected = True + else: + node.selected = False + + for child in node.children: + self.update_node_select(child) def loop(self): pygame.display.flip() - pygame.event.pump() - self.keys = [k for k, pressed in enumerate(pygame.key.get_pressed()) if pressed] + + if not self.process_events(): + return False # ESC has been pressed glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) - # Compute FPS - gl_time = glutGet(GLUT_ELAPSED_TIME) - self.frames += 1 - if gl_time - self.last_fps_time >= 1000: - current_fps = self.frames * 1000 / (gl_time - self.last_fps_time) - pygame.display.set_caption(self.base_name + " - %.0f fps" % current_fps) - self.frames = 0 - self.last_fps_time = gl_time + return True + def process_events(self): + + LEFT_BUTTON = 1 + MIDDLE_BUTTON = 2 + RIGHT_BUTTON = 3 + WHEEL_UP = 4 + WHEEL_DOWN = 5 + + dx, dy = pygame.mouse.get_rel() + mousex, mousey = pygame.mouse.get_pos() + + zooming_one_shot = False + + ok = True + + for evt in pygame.event.get(): + if evt.type == pygame.MOUSEBUTTONDOWN and evt.button == LEFT_BUTTON: + hovered = self.get_hovered_node(mousex, self.h - mousey) + if hovered: + if self.currently_selected and self.currently_selected == hovered: + self.select_node(None) + else: + logger.info("Node %s selected" % hovered) + self.select_node(hovered) + else: + self.is_rotating = True + if evt.type == pygame.MOUSEBUTTONUP and evt.button == LEFT_BUTTON: + self.is_rotating = False + + if evt.type == pygame.MOUSEBUTTONDOWN and evt.button == MIDDLE_BUTTON: + self.is_panning = True + if evt.type == pygame.MOUSEBUTTONUP and evt.button == MIDDLE_BUTTON: + self.is_panning = False + + if evt.type == pygame.MOUSEBUTTONDOWN and evt.button == RIGHT_BUTTON: + self.is_zooming = True + if evt.type == pygame.MOUSEBUTTONUP and evt.button == RIGHT_BUTTON: + self.is_zooming = False + + if evt.type == pygame.MOUSEBUTTONDOWN and evt.button in [WHEEL_UP, WHEEL_DOWN]: + zooming_one_shot = True + self.is_zooming = True + dy = -10 if evt.button == WHEEL_UP else 10 + + if evt.type == pygame.KEYDOWN: + ok = (ok and self.process_keystroke(evt.key, evt.mod)) + + self.controls_3d(dx, dy, zooming_one_shot) + + return ok + + def process_keystroke(self, key, mod): + + # process arrow keys if an object is selected + if self.currently_selected: + up = 0 + strafe = 0 + + if key == pygame.K_UP: + up = 1 + if key == pygame.K_DOWN: + up = -1 + if key == pygame.K_LEFT: + strafe = -1 + if key == pygame.K_RIGHT: + strafe = 1 + + self.move_selected_node(up, strafe) + + if key == pygame.K_f: + pygame.display.toggle_fullscreen() + + if key == pygame.K_TAB: + self.cycle_cameras() + + if key in [pygame.K_ESCAPE, pygame.K_q]: + return False return True - def controls_3d(self, - mouse_button=1, \ - up_key=pygame.K_UP, \ - down_key=pygame.K_DOWN, \ - left_key=pygame.K_LEFT, \ - right_key=pygame.K_RIGHT): - """ The actual camera setting cycle """ - mouse_dx,mouse_dy = pygame.mouse.get_rel() - if pygame.mouse.get_pressed()[mouse_button]: - look_speed = .2 - buffer = glGetDoublev(GL_MODELVIEW_MATRIX) - c = (-1 * numpy.mat(buffer[:3,:3]) * \ - numpy.mat(buffer[3,:3]).T).reshape(3,1) - # c is camera center in absolute coordinates, - # we need to move it back to (0,0,0) - # before rotating the camera - glTranslate(c[0],c[1],c[2]) - m = buffer.flatten() - glRotate(mouse_dx * look_speed, m[1],m[5],m[9]) - glRotate(mouse_dy * look_speed, m[0],m[4],m[8]) - - # compensate roll - glRotated(-math.atan2(-m[4],m[5]) * \ - 57.295779513082320876798154814105 ,m[2],m[6],m[10]) - glTranslate(-c[0],-c[1],-c[2]) + def controls_3d(self, dx, dy, zooming_one_shot=False): - # move forward-back or right-left - if up_key in self.keys: - fwd = .1 - elif down_key in self.keys: - fwd = -.1 - else: - fwd = 0 + CAMERA_TRANSLATION_FACTOR = 0.01 + CAMERA_ROTATION_FACTOR = 0.01 - if left_key in self.keys: - strafe = .1 - elif right_key in self.keys: - strafe = -.1 - else: - strafe = 0 + if not (self.is_rotating or self.is_panning or self.is_zooming): + return - if abs(fwd) or abs(strafe): - m = glGetDoublev(GL_MODELVIEW_MATRIX).flatten() - glTranslate(fwd*m[2],fwd*m[6],fwd*m[10]) - glTranslate(strafe*m[0],strafe*m[4],strafe*m[8]) + current_pos = self.current_cam.transformation[:3, 3].copy() + distance = numpy.linalg.norm(self.focal_point - current_pos) + + if self.is_rotating: + """ Orbiting the camera is implemented the following way: + + - the rotation is split into a rotation around the *world* Z axis + (controlled by the horizontal mouse motion along X) and a + rotation around the *X* axis of the camera (pitch) *shifted to + the focal origin* (the world origin for now). This is controlled + by the vertical motion of the mouse (Y axis). + + - as a result, the resulting transformation of the camera in the + world frame C' is: + C' = (T · Rx · T⁻¹ · (Rz · C)⁻¹)⁻¹ + + where: + - C is the original camera transformation in the world frame, + - Rz is the rotation along the Z axis (in the world frame) + - T is the translation camera -> world (ie, the inverse of the + translation part of C + - Rx is the rotation around X in the (translated) camera frame + """ + + rotation_camera_x = dy * CAMERA_ROTATION_FACTOR + rotation_world_z = dx * CAMERA_ROTATION_FACTOR + world_z_rotation = transformations.euler_matrix(0, 0, rotation_world_z) + cam_x_rotation = transformations.euler_matrix(rotation_camera_x, 0, 0) + + after_world_z_rotation = numpy.dot(world_z_rotation, self.current_cam.transformation) + + inverse_transformation = transformations.inverse_matrix(after_world_z_rotation) + + translation = transformations.translation_matrix( + transformations.decompose_matrix(inverse_transformation)[3]) + inverse_translation = transformations.inverse_matrix(translation) + + new_inverse = numpy.dot(inverse_translation, inverse_transformation) + new_inverse = numpy.dot(cam_x_rotation, new_inverse) + new_inverse = numpy.dot(translation, new_inverse) + + self.current_cam.transformation = transformations.inverse_matrix(new_inverse).astype(numpy.float32) + + if self.is_panning: + tx = -dx * CAMERA_TRANSLATION_FACTOR * distance + ty = dy * CAMERA_TRANSLATION_FACTOR * distance + cam_transform = transformations.translation_matrix((tx, ty, 0)).astype(numpy.float32) + self.current_cam.transformation = numpy.dot(self.current_cam.transformation, cam_transform) + + if self.is_zooming: + tz = dy * CAMERA_TRANSLATION_FACTOR * distance + cam_transform = transformations.translation_matrix((0, 0, tz)).astype(numpy.float32) + self.current_cam.transformation = numpy.dot(self.current_cam.transformation, cam_transform) + + if zooming_one_shot: + self.is_zooming = False + + self.update_view_camera() + + def update_view_camera(self): + + self.view_matrix = linalg.inv(self.current_cam.transformation) + + # Rotate by 180deg around X to have Z pointing backward (OpenGL convention) + self.view_matrix = numpy.dot(ROTATION_180_X, self.view_matrix) + + glMatrixMode(GL_MODELVIEW) + glLoadIdentity() + glMultMatrixf(self.view_matrix.transpose()) + + def move_selected_node(self, up, strafe): + self.currently_selected.transformation[0][3] += strafe + self.currently_selected.transformation[2][3] += up + + @staticmethod + def showtext(text, x=0, y=0, z=0, size=20): + + # TODO: alpha blending does not work... + # glEnable(GL_BLEND) + # glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) + + font = pygame.font.Font(None, size) + text_surface = font.render(text, True, (10, 10, 10, 255), + (255 * 0.18, 255 * 0.18, 255 * 0.18, 0)) + text_data = pygame.image.tostring(text_surface, "RGBA", True) + glRasterPos3d(x, y, z) + glDrawPixels(text_surface.get_width(), + text_surface.get_height(), + GL_RGBA, GL_UNSIGNED_BYTE, + text_data) + + # glDisable(GL_BLEND) + + +def main(model, width, height): + app = PyAssimp3DViewer(model, w=width, h=height) + + clock = pygame.time.Clock() + + while app.loop(): + + app.update_view_camera() + + ## Main rendering + app.render() + + ## GUI text display + app.switch_to_overlay() + app.showtext("Active camera: %s" % str(app.current_cam), 10, app.h - 30) + if app.currently_selected: + app.showtext("Selected node: %s" % app.currently_selected, 10, app.h - 50) + pos = app.h - 70 + + app.showtext("(%sm, %sm, %sm)" % (app.currently_selected.transformation[0, 3], + app.currently_selected.transformation[1, 3], + app.currently_selected.transformation[2, 3]), 30, pos) + + app.switch_from_overlay() + + # Make sure we do not go over 30fps + clock.tick(30) + + logger.info("Quitting! Bye bye!") + + +######################################################################### +######################################################################### if __name__ == '__main__': if not len(sys.argv) > 1: print("Usage: " + __file__ + " ") sys.exit(2) - app = PyAssimp3DViewer(model = sys.argv[1], w = 1024, h = 768, fov = 75) - - while app.loop(): - app.render() - app.controls_3d(0) - if pygame.K_f in app.keys: pygame.display.toggle_fullscreen() - if pygame.K_TAB in app.keys: app.cycle_cameras() - if pygame.K_ESCAPE in app.keys: - break + main(model=sys.argv[1], width=1024, height=768) diff --git a/port/PyAssimp/scripts/3d_viewer_py3.py b/port/PyAssimp/scripts/3d_viewer_py3.py new file mode 100755 index 000000000..4c88edc7b --- /dev/null +++ b/port/PyAssimp/scripts/3d_viewer_py3.py @@ -0,0 +1,1320 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +""" This program loads a model with PyASSIMP, and display it. + +Based on: +- pygame code from http://3dengine.org/Spectator_%28PyOpenGL%29 +- http://www.lighthouse3d.com/tutorials +- http://www.songho.ca/opengl/gl_transform.html +- http://code.activestate.com/recipes/325391/ +- ASSIMP's C++ SimpleOpenGL viewer + +Authors: Séverin Lemaignan, 2012-2016 +""" +import sys +import logging + +from functools import reduce + +logger = logging.getLogger("pyassimp") +gllogger = logging.getLogger("OpenGL") +gllogger.setLevel(logging.WARNING) +logging.basicConfig(level=logging.INFO) + +import OpenGL + +OpenGL.ERROR_CHECKING = False +OpenGL.ERROR_LOGGING = False +# OpenGL.ERROR_ON_COPY = True +# OpenGL.FULL_LOGGING = True +from OpenGL.GL import * +from OpenGL.arrays import vbo +from OpenGL.GL import shaders + +import pygame +import pygame.font +import pygame.image + +import math, random +from numpy import linalg + +import pyassimp +from pyassimp.postprocess import * +from pyassimp.helper import * +import transformations + +ROTATION_180_X = numpy.array([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]], dtype=numpy.float32) + +# rendering mode +BASE = "BASE" +COLORS = "COLORS" +SILHOUETTE = "SILHOUETTE" +HELPERS = "HELPERS" + +# Entities type +ENTITY = "entity" +CAMERA = "camera" +MESH = "mesh" + +FLAT_VERTEX_SHADER_120 = """ +#version 120 + +uniform mat4 u_viewProjectionMatrix; +uniform mat4 u_modelMatrix; + +uniform vec4 u_materialDiffuse; + +attribute vec3 a_vertex; + +varying vec4 v_color; + +void main(void) +{ + v_color = u_materialDiffuse; + gl_Position = u_viewProjectionMatrix * u_modelMatrix * vec4(a_vertex, 1.0); +} +""" + +FLAT_VERTEX_SHADER_130 = """ +#version 130 + +uniform mat4 u_viewProjectionMatrix; +uniform mat4 u_modelMatrix; + +uniform vec4 u_materialDiffuse; + +in vec3 a_vertex; + +out vec4 v_color; + +void main(void) +{ + v_color = u_materialDiffuse; + gl_Position = u_viewProjectionMatrix * u_modelMatrix * vec4(a_vertex, 1.0); +} +""" + +BASIC_VERTEX_SHADER_120 = """ +#version 120 + +uniform mat4 u_viewProjectionMatrix; +uniform mat4 u_modelMatrix; +uniform mat3 u_normalMatrix; +uniform vec3 u_lightPos; + +uniform vec4 u_materialDiffuse; + +attribute vec3 a_vertex; +attribute vec3 a_normal; + +varying vec4 v_color; + +void main(void) +{ + // Now the normal is in world space, as we pass the light in world space. + vec3 normal = u_normalMatrix * a_normal; + + float dist = distance(a_vertex, u_lightPos); + + // go to https://www.desmos.com/calculator/nmnaud1hrw to play with the parameters + // att is not used for now + float att=1.0/(1.0+0.8*dist*dist); + + vec3 surf2light = normalize(u_lightPos - a_vertex); + vec3 norm = normalize(normal); + float dcont=max(0.0,dot(norm,surf2light)); + + float ambient = 0.3; + float intensity = dcont + 0.3 + ambient; + + v_color = u_materialDiffuse * intensity; + + gl_Position = u_viewProjectionMatrix * u_modelMatrix * vec4(a_vertex, 1.0); +} +""" + +BASIC_VERTEX_SHADER_130 = """ +#version 130 + +uniform mat4 u_viewProjectionMatrix; +uniform mat4 u_modelMatrix; +uniform mat3 u_normalMatrix; +uniform vec3 u_lightPos; + +uniform vec4 u_materialDiffuse; + +in vec3 a_vertex; +in vec3 a_normal; + +out vec4 v_color; + +void main(void) +{ + // Now the normal is in world space, as we pass the light in world space. + vec3 normal = u_normalMatrix * a_normal; + + float dist = distance(a_vertex, u_lightPos); + + // go to https://www.desmos.com/calculator/nmnaud1hrw to play with the parameters + // att is not used for now + float att=1.0/(1.0+0.8*dist*dist); + + vec3 surf2light = normalize(u_lightPos - a_vertex); + vec3 norm = normalize(normal); + float dcont=max(0.0,dot(norm,surf2light)); + + float ambient = 0.3; + float intensity = dcont + 0.3 + ambient; + + v_color = u_materialDiffuse * intensity; + + gl_Position = u_viewProjectionMatrix * u_modelMatrix * vec4(a_vertex, 1.0); +} +""" + +BASIC_FRAGMENT_SHADER_120 = """ +#version 120 + +varying vec4 v_color; + +void main() { + gl_FragColor = v_color; +} +""" + +BASIC_FRAGMENT_SHADER_130 = """ +#version 130 + +in vec4 v_color; + +void main() { + gl_FragColor = v_color; +} +""" + +GOOCH_VERTEX_SHADER_120 = """ +#version 120 + +// attributes +attribute vec3 a_vertex; // xyz - position +attribute vec3 a_normal; // xyz - normal + +// uniforms +uniform mat4 u_modelMatrix; +uniform mat4 u_viewProjectionMatrix; +uniform mat3 u_normalMatrix; +uniform vec3 u_lightPos; +uniform vec3 u_camPos; + +// output data from vertex to fragment shader +varying vec3 o_normal; +varying vec3 o_lightVector; + +/////////////////////////////////////////////////////////////////// + +void main(void) +{ + // transform position and normal to world space + vec4 positionWorld = u_modelMatrix * vec4(a_vertex, 1.0); + vec3 normalWorld = u_normalMatrix * a_normal; + + // calculate and pass vectors required for lighting + o_lightVector = u_lightPos - positionWorld.xyz; + o_normal = normalWorld; + + // project world space position to the screen and output it + gl_Position = u_viewProjectionMatrix * positionWorld; +} +""" + +GOOCH_VERTEX_SHADER_130 = """ +#version 130 + +// attributes +in vec3 a_vertex; // xyz - position +in vec3 a_normal; // xyz - normal + +// uniforms +uniform mat4 u_modelMatrix; +uniform mat4 u_viewProjectionMatrix; +uniform mat3 u_normalMatrix; +uniform vec3 u_lightPos; +uniform vec3 u_camPos; + +// output data from vertex to fragment shader +out vec3 o_normal; +out vec3 o_lightVector; + +/////////////////////////////////////////////////////////////////// + +void main(void) +{ + // transform position and normal to world space + vec4 positionWorld = u_modelMatrix * vec4(a_vertex, 1.0); + vec3 normalWorld = u_normalMatrix * a_normal; + + // calculate and pass vectors required for lighting + o_lightVector = u_lightPos - positionWorld.xyz; + o_normal = normalWorld; + + // project world space position to the screen and output it + gl_Position = u_viewProjectionMatrix * positionWorld; +} +""" + +GOOCH_FRAGMENT_SHADER_120 = """ +#version 120 + +// data from vertex shader +varying vec3 o_normal; +varying vec3 o_lightVector; + +// diffuse color of the object +uniform vec4 u_materialDiffuse; +// cool color of gooch shading +uniform vec3 u_coolColor; +// warm color of gooch shading +uniform vec3 u_warmColor; +// how much to take from object color in final cool color +uniform float u_alpha; +// how much to take from object color in final warm color +uniform float u_beta; + +/////////////////////////////////////////////////////////// + +void main(void) +{ + // normlize vectors for lighting + vec3 normalVector = normalize(o_normal); + vec3 lightVector = normalize(o_lightVector); + // intensity of diffuse lighting [-1, 1] + float diffuseLighting = dot(lightVector, normalVector); + // map intensity of lighting from range [-1; 1] to [0, 1] + float interpolationValue = (1.0 + diffuseLighting)/2; + + ////////////////////////////////////////////////////////////////// + + // cool color mixed with color of the object + vec3 coolColorMod = u_coolColor + vec3(u_materialDiffuse) * u_alpha; + // warm color mixed with color of the object + vec3 warmColorMod = u_warmColor + vec3(u_materialDiffuse) * u_beta; + // interpolation of cool and warm colors according + // to lighting intensity. The lower the light intensity, + // the larger part of the cool color is used + vec3 colorOut = mix(coolColorMod, warmColorMod, interpolationValue); + + ////////////////////////////////////////////////////////////////// + + // save color + gl_FragColor.rgb = colorOut; + gl_FragColor.a = 1; +} +""" + +GOOCH_FRAGMENT_SHADER_130 = """ +#version 130 + +// data from vertex shader +in vec3 o_normal; +in vec3 o_lightVector; + +// diffuse color of the object +uniform vec4 u_materialDiffuse; +// cool color of gooch shading +uniform vec3 u_coolColor; +// warm color of gooch shading +uniform vec3 u_warmColor; +// how much to take from object color in final cool color +uniform float u_alpha; +// how much to take from object color in final warm color +uniform float u_beta; + +// output to framebuffer +out vec4 resultingColor; + +/////////////////////////////////////////////////////////// + +void main(void) +{ + // normlize vectors for lighting + vec3 normalVector = normalize(o_normal); + vec3 lightVector = normalize(o_lightVector); + // intensity of diffuse lighting [-1, 1] + float diffuseLighting = dot(lightVector, normalVector); + // map intensity of lighting from range [-1; 1] to [0, 1] + float interpolationValue = (1.0 + diffuseLighting)/2; + + ////////////////////////////////////////////////////////////////// + + // cool color mixed with color of the object + vec3 coolColorMod = u_coolColor + vec3(u_materialDiffuse) * u_alpha; + // warm color mixed with color of the object + vec3 warmColorMod = u_warmColor + vec3(u_materialDiffuse) * u_beta; + // interpolation of cool and warm colors according + // to lighting intensity. The lower the light intensity, + // the larger part of the cool color is used + vec3 colorOut = mix(coolColorMod, warmColorMod, interpolationValue); + + ////////////////////////////////////////////////////////////////// + + // save color + resultingColor.rgb = colorOut; + resultingColor.a = 1; +} +""" + +SILHOUETTE_VERTEX_SHADER_120 = """ +#version 120 + +attribute vec3 a_vertex; // xyz - position +attribute vec3 a_normal; // xyz - normal + +uniform mat4 u_modelMatrix; +uniform mat4 u_viewProjectionMatrix; +uniform mat4 u_modelViewMatrix; +uniform vec4 u_materialDiffuse; +uniform float u_bordersize; // width of the border + +varying vec4 v_color; + +void main(void){ + v_color = u_materialDiffuse; + float distToCamera = -(u_modelViewMatrix * vec4(a_vertex, 1.0)).z; + vec4 tPos = vec4(a_vertex + a_normal * u_bordersize * distToCamera, 1.0); + gl_Position = u_viewProjectionMatrix * u_modelMatrix * tPos; +} +""" + +SILHOUETTE_VERTEX_SHADER_130 = """ +#version 130 + +in vec3 a_vertex; // xyz - position +in vec3 a_normal; // xyz - normal + +uniform mat4 u_modelMatrix; +uniform mat4 u_viewProjectionMatrix; +uniform mat4 u_modelViewMatrix; +uniform vec4 u_materialDiffuse; +uniform float u_bordersize; // width of the border + +out vec4 v_color; + +void main(void){ + v_color = u_materialDiffuse; + float distToCamera = -(u_modelViewMatrix * vec4(a_vertex, 1.0)).z; + vec4 tPos = vec4(a_vertex + a_normal * u_bordersize * distToCamera, 1.0); + gl_Position = u_viewProjectionMatrix * u_modelMatrix * tPos; +} +""" +DEFAULT_CLIP_PLANE_NEAR = 0.001 +DEFAULT_CLIP_PLANE_FAR = 1000.0 + + +def get_world_transform(scene, node): + if node == scene.rootnode: + return numpy.identity(4, dtype=numpy.float32) + + parents = reversed(_get_parent_chain(scene, node, [])) + parent_transform = reduce(numpy.dot, [p.transformation for p in parents]) + return numpy.dot(parent_transform, node.transformation) + + +def _get_parent_chain(scene, node, parents): + parent = node.parent + + parents.append(parent) + + if parent == scene.rootnode: + return parents + + return _get_parent_chain(scene, parent, parents) + + +class DefaultCamera: + def __init__(self, w, h, fov): + self.name = "default camera" + self.type = CAMERA + self.clipplanenear = DEFAULT_CLIP_PLANE_NEAR + self.clipplanefar = DEFAULT_CLIP_PLANE_FAR + self.aspect = w / h + self.horizontalfov = fov * math.pi / 180 + self.transformation = numpy.array([[0.68, -0.32, 0.65, 7.48], + [0.73, 0.31, -0.61, -6.51], + [-0.01, 0.89, 0.44, 5.34], + [0., 0., 0., 1.]], dtype=numpy.float32) + + self.transformation = numpy.dot(self.transformation, ROTATION_180_X) + + def __str__(self): + return self.name + + +class PyAssimp3DViewer: + base_name = "PyASSIMP 3D viewer" + + def __init__(self, model, w=1024, h=768): + + self.w = w + self.h = h + + pygame.init() + pygame.display.set_caption(self.base_name) + pygame.display.set_mode((w, h), pygame.OPENGL | pygame.DOUBLEBUF) + + glClearColor(0.18, 0.18, 0.18, 1.0) + + shader_compilation_succeeded = False + try: + self.set_shaders_v130() + self.prepare_shaders() + except RuntimeError, message: + sys.stderr.write("%s\n" % message) + sys.stdout.write("Could not compile shaders in version 1.30, trying version 1.20\n") + + if not shader_compilation_succeeded: + self.set_shaders_v120() + self.prepare_shaders() + + self.scene = None + self.meshes = {} # stores the OpenGL vertex/faces/normals buffers pointers + + self.node2colorid = {} # stores a color ID for each node. Useful for mouse picking and visibility checking + self.colorid2node = {} # reverse dict of node2colorid + + self.currently_selected = None + self.moving = False + self.moving_situation = None + + self.default_camera = DefaultCamera(self.w, self.h, fov=70) + self.cameras = [self.default_camera] + + self.current_cam_index = 0 + self.current_cam = self.default_camera + self.set_camera_projection() + + self.load_model(model) + + # user interactions + self.focal_point = [0, 0, 0] + self.is_rotating = False + self.is_panning = False + self.is_zooming = False + + def set_shaders_v120(self): + self.BASIC_VERTEX_SHADER = BASIC_VERTEX_SHADER_120 + self.FLAT_VERTEX_SHADER = FLAT_VERTEX_SHADER_120 + self.SILHOUETTE_VERTEX_SHADER = SILHOUETTE_VERTEX_SHADER_120 + self.GOOCH_VERTEX_SHADER = GOOCH_VERTEX_SHADER_120 + + self.BASIC_FRAGMENT_SHADER = BASIC_FRAGMENT_SHADER_120 + self.GOOCH_FRAGMENT_SHADER = GOOCH_FRAGMENT_SHADER_120 + + def set_shaders_v130(self): + self.BASIC_VERTEX_SHADER = BASIC_VERTEX_SHADER_130 + self.FLAT_VERTEX_SHADER = FLAT_VERTEX_SHADER_130 + self.SILHOUETTE_VERTEX_SHADER = SILHOUETTE_VERTEX_SHADER_130 + self.GOOCH_VERTEX_SHADER = GOOCH_VERTEX_SHADER_130 + + self.BASIC_FRAGMENT_SHADER = BASIC_FRAGMENT_SHADER_130 + self.GOOCH_FRAGMENT_SHADER = GOOCH_FRAGMENT_SHADER_130 + + def prepare_shaders(self): + + ### Base shader + vertex = shaders.compileShader(self.BASIC_VERTEX_SHADER, GL_VERTEX_SHADER) + fragment = shaders.compileShader(self.BASIC_FRAGMENT_SHADER, GL_FRAGMENT_SHADER) + + self.shader = shaders.compileProgram(vertex, fragment) + + self.set_shader_accessors(('u_modelMatrix', + 'u_viewProjectionMatrix', + 'u_normalMatrix', + 'u_lightPos', + 'u_materialDiffuse'), + ('a_vertex', + 'a_normal'), self.shader) + + ### Flat shader + flatvertex = shaders.compileShader(self.FLAT_VERTEX_SHADER, GL_VERTEX_SHADER) + self.flatshader = shaders.compileProgram(flatvertex, fragment) + + self.set_shader_accessors(('u_modelMatrix', + 'u_viewProjectionMatrix', + 'u_materialDiffuse',), + ('a_vertex',), self.flatshader) + + ### Silhouette shader + silh_vertex = shaders.compileShader(self.SILHOUETTE_VERTEX_SHADER, GL_VERTEX_SHADER) + self.silhouette_shader = shaders.compileProgram(silh_vertex, fragment) + + self.set_shader_accessors(('u_modelMatrix', + 'u_viewProjectionMatrix', + 'u_modelViewMatrix', + 'u_materialDiffuse', + 'u_bordersize' # width of the silhouette + ), + ('a_vertex', + 'a_normal'), self.silhouette_shader) + + ### Gooch shader + gooch_vertex = shaders.compileShader(self.GOOCH_VERTEX_SHADER, GL_VERTEX_SHADER) + gooch_fragment = shaders.compileShader(self.GOOCH_FRAGMENT_SHADER, GL_FRAGMENT_SHADER) + self.gooch_shader = shaders.compileProgram(gooch_vertex, gooch_fragment) + + self.set_shader_accessors(('u_modelMatrix', + 'u_viewProjectionMatrix', + 'u_normalMatrix', + 'u_lightPos', + 'u_materialDiffuse', + 'u_coolColor', + 'u_warmColor', + 'u_alpha', + 'u_beta' + ), + ('a_vertex', + 'a_normal'), self.gooch_shader) + + @staticmethod + def set_shader_accessors(uniforms, attributes, shader): + # add accessors to the shaders uniforms and attributes + for uniform in uniforms: + location = glGetUniformLocation(shader, uniform) + if location in (None, -1): + raise RuntimeError('No uniform: %s (maybe it is not used ' + 'anymore and has been optimized out by' + ' the shader compiler)' % uniform) + setattr(shader, uniform, location) + + for attribute in attributes: + location = glGetAttribLocation(shader, attribute) + if location in (None, -1): + raise RuntimeError('No attribute: %s' % attribute) + setattr(shader, attribute, location) + + @staticmethod + def prepare_gl_buffers(mesh): + + mesh.gl = {} + + # Fill the buffer for vertex and normals positions + v = numpy.array(mesh.vertices, 'f') + n = numpy.array(mesh.normals, 'f') + + mesh.gl["vbo"] = vbo.VBO(numpy.hstack((v, n))) + + # Fill the buffer for vertex positions + mesh.gl["faces"] = glGenBuffers(1) + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.gl["faces"]) + glBufferData(GL_ELEMENT_ARRAY_BUFFER, + numpy.array(mesh.faces, dtype=numpy.int32), + GL_STATIC_DRAW) + + mesh.gl["nbfaces"] = len(mesh.faces) + + # Unbind buffers + glBindBuffer(GL_ARRAY_BUFFER, 0) + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) + + @staticmethod + def get_rgb_from_colorid(colorid): + r = (colorid >> 0) & 0xff + g = (colorid >> 8) & 0xff + b = (colorid >> 16) & 0xff + + return r, g, b + + def get_color_id(self): + id = random.randint(0, 256 * 256 * 256) + if id not in self.colorid2node: + return id + else: + return self.get_color_id() + + def glize(self, scene, node): + + logger.info("Loading node <%s>" % node) + node.selected = True if self.currently_selected and self.currently_selected == node else False + + node.transformation = node.transformation.astype(numpy.float32) + + if node.meshes: + node.type = MESH + colorid = self.get_color_id() + self.colorid2node[colorid] = node + self.node2colorid[node.name] = colorid + + elif node.name in [c.name for c in scene.cameras]: + + # retrieve the ASSIMP camera object + [cam] = [c for c in scene.cameras if c.name == node.name] + node.type = CAMERA + logger.info("Added camera <%s>" % node.name) + logger.info("Camera position: %.3f, %.3f, %.3f" % tuple(node.transformation[:, 3][:3].tolist())) + self.cameras.append(node) + node.clipplanenear = cam.clipplanenear + node.clipplanefar = cam.clipplanefar + + if numpy.allclose(cam.lookat, [0, 0, -1]) and numpy.allclose(cam.up, [0, 1, 0]): # Cameras in .blend files + + # Rotate by 180deg around X to have Z pointing forward + node.transformation = numpy.dot(node.transformation, ROTATION_180_X) + else: + raise RuntimeError( + "I do not know how to normalize this camera orientation: lookat=%s, up=%s" % (cam.lookat, cam.up)) + + if cam.aspect == 0.0: + logger.warning("Camera aspect not set. Setting to default 4:3") + node.aspect = 1.333 + else: + node.aspect = cam.aspect + + node.horizontalfov = cam.horizontalfov + + else: + node.type = ENTITY + + for child in node.children: + self.glize(scene, child) + + def load_model(self, path, postprocess=aiProcessPreset_TargetRealtime_MaxQuality): + logger.info("Loading model:" + path + "...") + + if postprocess: + self.scene = pyassimp.load(path, processing=postprocess) + else: + self.scene = pyassimp.load(path) + logger.info("Done.") + + scene = self.scene + # log some statistics + logger.info(" meshes: %d" % len(scene.meshes)) + logger.info(" total faces: %d" % sum([len(mesh.faces) for mesh in scene.meshes])) + logger.info(" materials: %d" % len(scene.materials)) + self.bb_min, self.bb_max = get_bounding_box(self.scene) + logger.info(" bounding box:" + str(self.bb_min) + " - " + str(self.bb_max)) + + self.scene_center = [(a + b) / 2. for a, b in zip(self.bb_min, self.bb_max)] + + for index, mesh in enumerate(scene.meshes): + self.prepare_gl_buffers(mesh) + + self.glize(scene, scene.rootnode) + + # Finally release the model + pyassimp.release(scene) + logger.info("Ready for 3D rendering!") + + def cycle_cameras(self): + + self.current_cam_index = (self.current_cam_index + 1) % len(self.cameras) + self.current_cam = self.cameras[self.current_cam_index] + self.set_camera_projection(self.current_cam) + logger.info("Switched to camera <%s>" % self.current_cam) + + def set_overlay_projection(self): + glViewport(0, 0, self.w, self.h) + glMatrixMode(GL_PROJECTION) + glLoadIdentity() + glOrtho(0.0, self.w - 1.0, 0.0, self.h - 1.0, -1.0, 1.0) + glMatrixMode(GL_MODELVIEW) + glLoadIdentity() + + def set_camera_projection(self, camera=None): + + if not camera: + camera = self.current_cam + + znear = camera.clipplanenear or DEFAULT_CLIP_PLANE_NEAR + zfar = camera.clipplanefar or DEFAULT_CLIP_PLANE_FAR + aspect = camera.aspect + fov = camera.horizontalfov + + glMatrixMode(GL_PROJECTION) + glLoadIdentity() + + # Compute gl frustrum + tangent = math.tan(fov / 2.) + h = znear * tangent + w = h * aspect + + # params: left, right, bottom, top, near, far + glFrustum(-w, w, -h, h, znear, zfar) + # equivalent to: + # gluPerspective(fov * 180/math.pi, aspect, znear, zfar) + + self.projection_matrix = glGetFloatv(GL_PROJECTION_MATRIX).transpose() + + glMatrixMode(GL_MODELVIEW) + glLoadIdentity() + + def render_colors(self): + + glEnable(GL_DEPTH_TEST) + glDepthFunc(GL_LEQUAL) + + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) + glEnable(GL_CULL_FACE) + + glUseProgram(self.flatshader) + + glUniformMatrix4fv(self.flatshader.u_viewProjectionMatrix, 1, GL_TRUE, + numpy.dot(self.projection_matrix, self.view_matrix)) + + self.recursive_render(self.scene.rootnode, self.flatshader, mode=COLORS) + + glUseProgram(0) + + def get_hovered_node(self, mousex, mousey): + """ + Attention: The performances of this method relies heavily on the size of the display! + """ + + # mouse out of the window? + if mousex < 0 or mousex >= self.w or mousey < 0 or mousey >= self.h: + return None + + self.render_colors() + # Capture image from the OpenGL buffer + buf = (GLubyte * (3 * self.w * self.h))(0) + glReadPixels(0, 0, self.w, self.h, GL_RGB, GL_UNSIGNED_BYTE, buf) + + # Reinterpret the RGB pixel buffer as a 1-D array of 24bits colors + a = numpy.ndarray(len(buf), numpy.dtype('>u1'), buf) + colors = numpy.zeros(len(buf) // 3, numpy.dtype('u1')[i::3] + + colorid = colors[mousex + mousey * self.w] + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) + + if colorid in self.colorid2node: + return self.colorid2node[colorid] + + def render(self, wireframe=False, twosided=False): + + glEnable(GL_DEPTH_TEST) + glDepthFunc(GL_LEQUAL) + + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE if wireframe else GL_FILL) + glDisable(GL_CULL_FACE) if twosided else glEnable(GL_CULL_FACE) + + self.render_grid() + + self.recursive_render(self.scene.rootnode, None, mode=HELPERS) + + ### First, the silhouette + + if False: + shader = self.silhouette_shader + + # glDepthMask(GL_FALSE) + glCullFace(GL_FRONT) # cull front faces + + glUseProgram(shader) + glUniform1f(shader.u_bordersize, 0.01) + + glUniformMatrix4fv(shader.u_viewProjectionMatrix, 1, GL_TRUE, + numpy.dot(self.projection_matrix, self.view_matrix)) + + self.recursive_render(self.scene.rootnode, shader, mode=SILHOUETTE) + + glUseProgram(0) + + ### Then, inner shading + # glDepthMask(GL_TRUE) + glCullFace(GL_BACK) + + use_gooch = False + if use_gooch: + shader = self.gooch_shader + + glUseProgram(shader) + glUniform3f(shader.u_lightPos, -.5, -.5, .5) + + ##### GOOCH specific + glUniform3f(shader.u_coolColor, 159.0 / 255, 148.0 / 255, 255.0 / 255) + glUniform3f(shader.u_warmColor, 255.0 / 255, 75.0 / 255, 75.0 / 255) + glUniform1f(shader.u_alpha, .25) + glUniform1f(shader.u_beta, .25) + ######### + else: + shader = self.shader + glUseProgram(shader) + glUniform3f(shader.u_lightPos, -.5, -.5, .5) + + glUniformMatrix4fv(shader.u_viewProjectionMatrix, 1, GL_TRUE, + numpy.dot(self.projection_matrix, self.view_matrix)) + + self.recursive_render(self.scene.rootnode, shader) + + glUseProgram(0) + + def render_axis(self, + transformation=numpy.identity(4, dtype=numpy.float32), + label=None, + size=0.2, + selected=False): + m = transformation.transpose() # OpenGL row major + + glPushMatrix() + glMultMatrixf(m) + + glLineWidth(3 if selected else 1) + + size = 2 * size if selected else size + + glBegin(GL_LINES) + + # draw line for x axis + glColor3f(1.0, 0.0, 0.0) + glVertex3f(0.0, 0.0, 0.0) + glVertex3f(size, 0.0, 0.0) + + # draw line for y axis + glColor3f(0.0, 1.0, 0.0) + glVertex3f(0.0, 0.0, 0.0) + glVertex3f(0.0, size, 0.0) + + # draw line for Z axis + glColor3f(0.0, 0.0, 1.0) + glVertex3f(0.0, 0.0, 0.0) + glVertex3f(0.0, 0.0, size) + + glEnd() + + if label: + self.showtext(label) + + glPopMatrix() + + @staticmethod + def render_camera(camera, transformation): + + m = transformation.transpose() # OpenGL row major + + aspect = camera.aspect + + u = 0.1 # unit size (in m) + l = 3 * u # length of the camera cone + f = 3 * u # aperture of the camera cone + + glPushMatrix() + glMultMatrixf(m) + + glLineWidth(2) + glBegin(GL_LINE_STRIP) + + glColor3f(.2, .2, .2) + + glVertex3f(u, u, -u) + glVertex3f(u, -u, -u) + glVertex3f(-u, -u, -u) + glVertex3f(-u, u, -u) + glVertex3f(u, u, -u) + + glVertex3f(u, u, 0.0) + glVertex3f(u, -u, 0.0) + glVertex3f(-u, -u, 0.0) + glVertex3f(-u, u, 0.0) + glVertex3f(u, u, 0.0) + + glVertex3f(f * aspect, f, l) + glVertex3f(f * aspect, -f, l) + glVertex3f(-f * aspect, -f, l) + glVertex3f(-f * aspect, f, l) + glVertex3f(f * aspect, f, l) + + glEnd() + + glBegin(GL_LINE_STRIP) + glVertex3f(u, -u, -u) + glVertex3f(u, -u, 0.0) + glVertex3f(f * aspect, -f, l) + glEnd() + + glBegin(GL_LINE_STRIP) + glVertex3f(-u, -u, -u) + glVertex3f(-u, -u, 0.0) + glVertex3f(-f * aspect, -f, l) + glEnd() + + glBegin(GL_LINE_STRIP) + glVertex3f(-u, u, -u) + glVertex3f(-u, u, 0.0) + glVertex3f(-f * aspect, f, l) + glEnd() + + glPopMatrix() + + @staticmethod + def render_grid(): + + glLineWidth(1) + glColor3f(0.5, 0.5, 0.5) + glBegin(GL_LINES) + for i in range(-10, 11): + glVertex3f(i, -10.0, 0.0) + glVertex3f(i, 10.0, 0.0) + + for i in range(-10, 11): + glVertex3f(-10.0, i, 0.0) + glVertex3f(10.0, i, 0.0) + glEnd() + + def recursive_render(self, node, shader, mode=BASE, with_normals=True): + """ Main recursive rendering method. + """ + + normals = with_normals + + if mode == COLORS: + normals = False + + + if not hasattr(node, "selected"): + node.selected = False + + m = get_world_transform(self.scene, node) + + # HELPERS mode + ### + if mode == HELPERS: + # if node.type == ENTITY: + self.render_axis(m, + label=node.name if node != self.scene.rootnode else None, + selected=node.selected if hasattr(node, "selected") else False) + + if node.type == CAMERA: + self.render_camera(node, m) + + for child in node.children: + self.recursive_render(child, shader, mode) + + return + + # Mesh rendering modes + ### + if node.type == MESH: + + for mesh in node.meshes: + + stride = 24 # 6 * 4 bytes + + if node.selected and mode == SILHOUETTE: + glUniform4f(shader.u_materialDiffuse, 1.0, 0.0, 0.0, 1.0) + glUniformMatrix4fv(shader.u_modelViewMatrix, 1, GL_TRUE, + numpy.dot(self.view_matrix, m)) + + else: + if mode == COLORS: + colorid = self.node2colorid[node.name] + r, g, b = self.get_rgb_from_colorid(colorid) + glUniform4f(shader.u_materialDiffuse, r / 255.0, g / 255.0, b / 255.0, 1.0) + elif mode == SILHOUETTE: + glUniform4f(shader.u_materialDiffuse, .0, .0, .0, 1.0) + else: + if node.selected: + diffuse = (1.0, 0.0, 0.0, 1.0) # selected nodes in red + else: + diffuse = mesh.material.properties["diffuse"] + if len(diffuse) == 3: # RGB instead of expected RGBA + diffuse.append(1.0) + glUniform4f(shader.u_materialDiffuse, *diffuse) + # if ambient: + # glUniform4f( shader.Material_ambient, *mat["ambient"] ) + + if mode == BASE: # not in COLORS or SILHOUETTE + normal_matrix = linalg.inv(numpy.dot(self.view_matrix, m)[0:3, 0:3]).transpose() + glUniformMatrix3fv(shader.u_normalMatrix, 1, GL_TRUE, normal_matrix) + + glUniformMatrix4fv(shader.u_modelMatrix, 1, GL_TRUE, m) + + vbo = mesh.gl["vbo"] + vbo.bind() + + glEnableVertexAttribArray(shader.a_vertex) + if normals: + glEnableVertexAttribArray(shader.a_normal) + + glVertexAttribPointer( + shader.a_vertex, + 3, GL_FLOAT, False, stride, vbo + ) + + if normals: + glVertexAttribPointer( + shader.a_normal, + 3, GL_FLOAT, False, stride, vbo + 12 + ) + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.gl["faces"]) + glDrawElements(GL_TRIANGLES, mesh.gl["nbfaces"] * 3, GL_UNSIGNED_INT, None) + + vbo.unbind() + glDisableVertexAttribArray(shader.a_vertex) + + if normals: + glDisableVertexAttribArray(shader.a_normal) + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) + + for child in node.children: + self.recursive_render(child, shader, mode) + + + def switch_to_overlay(self): + glPushMatrix() + self.set_overlay_projection() + + def switch_from_overlay(self): + self.set_camera_projection() + glPopMatrix() + + def select_node(self, node): + self.currently_selected = node + self.update_node_select(self.scene.rootnode) + + def update_node_select(self, node): + if node is self.currently_selected: + node.selected = True + else: + node.selected = False + + for child in node.children: + self.update_node_select(child) + + def loop(self): + + pygame.display.flip() + + if not self.process_events(): + return False # ESC has been pressed + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) + + return True + + def process_events(self): + + LEFT_BUTTON = 1 + MIDDLE_BUTTON = 2 + RIGHT_BUTTON = 3 + WHEEL_UP = 4 + WHEEL_DOWN = 5 + + dx, dy = pygame.mouse.get_rel() + mousex, mousey = pygame.mouse.get_pos() + + zooming_one_shot = False + + ok = True + + for evt in pygame.event.get(): + if evt.type == pygame.MOUSEBUTTONDOWN and evt.button == LEFT_BUTTON: + hovered = self.get_hovered_node(mousex, self.h - mousey) + if hovered: + if self.currently_selected and self.currently_selected == hovered: + self.select_node(None) + else: + logger.info("Node %s selected" % hovered) + self.select_node(hovered) + else: + self.is_rotating = True + if evt.type == pygame.MOUSEBUTTONUP and evt.button == LEFT_BUTTON: + self.is_rotating = False + + if evt.type == pygame.MOUSEBUTTONDOWN and evt.button == MIDDLE_BUTTON: + self.is_panning = True + if evt.type == pygame.MOUSEBUTTONUP and evt.button == MIDDLE_BUTTON: + self.is_panning = False + + if evt.type == pygame.MOUSEBUTTONDOWN and evt.button == RIGHT_BUTTON: + self.is_zooming = True + if evt.type == pygame.MOUSEBUTTONUP and evt.button == RIGHT_BUTTON: + self.is_zooming = False + + if evt.type == pygame.MOUSEBUTTONDOWN and evt.button in [WHEEL_UP, WHEEL_DOWN]: + zooming_one_shot = True + self.is_zooming = True + dy = -10 if evt.button == WHEEL_UP else 10 + + if evt.type == pygame.KEYDOWN: + ok = (ok and self.process_keystroke(evt.key, evt.mod)) + + self.controls_3d(dx, dy, zooming_one_shot) + + return ok + + def process_keystroke(self, key, mod): + + # process arrow keys if an object is selected + if self.currently_selected: + up = 0 + strafe = 0 + + if key == pygame.K_UP: + up = 1 + if key == pygame.K_DOWN: + up = -1 + if key == pygame.K_LEFT: + strafe = -1 + if key == pygame.K_RIGHT: + strafe = 1 + + self.move_selected_node(up, strafe) + + if key == pygame.K_f: + pygame.display.toggle_fullscreen() + + if key == pygame.K_TAB: + self.cycle_cameras() + + if key in [pygame.K_ESCAPE, pygame.K_q]: + return False + + return True + + def controls_3d(self, dx, dy, zooming_one_shot=False): + + CAMERA_TRANSLATION_FACTOR = 0.01 + CAMERA_ROTATION_FACTOR = 0.01 + + if not (self.is_rotating or self.is_panning or self.is_zooming): + return + + current_pos = self.current_cam.transformation[:3, 3].copy() + distance = numpy.linalg.norm(self.focal_point - current_pos) + + if self.is_rotating: + """ Orbiting the camera is implemented the following way: + + - the rotation is split into a rotation around the *world* Z axis + (controlled by the horizontal mouse motion along X) and a + rotation around the *X* axis of the camera (pitch) *shifted to + the focal origin* (the world origin for now). This is controlled + by the vertical motion of the mouse (Y axis). + + - as a result, the resulting transformation of the camera in the + world frame C' is: + C' = (T · Rx · T⁻¹ · (Rz · C)⁻¹)⁻¹ + + where: + - C is the original camera transformation in the world frame, + - Rz is the rotation along the Z axis (in the world frame) + - T is the translation camera -> world (ie, the inverse of the + translation part of C + - Rx is the rotation around X in the (translated) camera frame + """ + + rotation_camera_x = dy * CAMERA_ROTATION_FACTOR + rotation_world_z = dx * CAMERA_ROTATION_FACTOR + world_z_rotation = transformations.euler_matrix(0, 0, rotation_world_z) + cam_x_rotation = transformations.euler_matrix(rotation_camera_x, 0, 0) + + after_world_z_rotation = numpy.dot(world_z_rotation, self.current_cam.transformation) + + inverse_transformation = transformations.inverse_matrix(after_world_z_rotation) + + translation = transformations.translation_matrix( + transformations.decompose_matrix(inverse_transformation)[3]) + inverse_translation = transformations.inverse_matrix(translation) + + new_inverse = numpy.dot(inverse_translation, inverse_transformation) + new_inverse = numpy.dot(cam_x_rotation, new_inverse) + new_inverse = numpy.dot(translation, new_inverse) + + self.current_cam.transformation = transformations.inverse_matrix(new_inverse).astype(numpy.float32) + + if self.is_panning: + tx = -dx * CAMERA_TRANSLATION_FACTOR * distance + ty = dy * CAMERA_TRANSLATION_FACTOR * distance + cam_transform = transformations.translation_matrix((tx, ty, 0)).astype(numpy.float32) + self.current_cam.transformation = numpy.dot(self.current_cam.transformation, cam_transform) + + if self.is_zooming: + tz = dy * CAMERA_TRANSLATION_FACTOR * distance + cam_transform = transformations.translation_matrix((0, 0, tz)).astype(numpy.float32) + self.current_cam.transformation = numpy.dot(self.current_cam.transformation, cam_transform) + + if zooming_one_shot: + self.is_zooming = False + + self.update_view_camera() + + def update_view_camera(self): + + self.view_matrix = linalg.inv(self.current_cam.transformation) + + # Rotate by 180deg around X to have Z pointing backward (OpenGL convention) + self.view_matrix = numpy.dot(ROTATION_180_X, self.view_matrix) + + glMatrixMode(GL_MODELVIEW) + glLoadIdentity() + glMultMatrixf(self.view_matrix.transpose()) + + def move_selected_node(self, up, strafe): + self.currently_selected.transformation[0][3] += strafe + self.currently_selected.transformation[2][3] += up + + @staticmethod + def showtext(text, x=0, y=0, z=0, size=20): + + # TODO: alpha blending does not work... + # glEnable(GL_BLEND) + # glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) + + font = pygame.font.Font(None, size) + text_surface = font.render(text, True, (10, 10, 10, 255), + (255 * 0.18, 255 * 0.18, 255 * 0.18, 0)) + text_data = pygame.image.tostring(text_surface, "RGBA", True) + glRasterPos3d(x, y, z) + glDrawPixels(text_surface.get_width(), + text_surface.get_height(), + GL_RGBA, GL_UNSIGNED_BYTE, + text_data) + + # glDisable(GL_BLEND) + + +def main(model, width, height): + app = PyAssimp3DViewer(model, w=width, h=height) + + clock = pygame.time.Clock() + + while app.loop(): + + app.update_view_camera() + + ## Main rendering + app.render() + + ## GUI text display + app.switch_to_overlay() + app.showtext("Active camera: %s" % str(app.current_cam), 10, app.h - 30) + if app.currently_selected: + app.showtext("Selected node: %s" % app.currently_selected, 10, app.h - 50) + pos = app.h - 70 + + app.showtext("(%sm, %sm, %sm)" % (app.currently_selected.transformation[0, 3], + app.currently_selected.transformation[1, 3], + app.currently_selected.transformation[2, 3]), 30, pos) + + app.switch_from_overlay() + + # Make sure we do not go over 30fps + clock.tick(30) + + logger.info("Quitting! Bye bye!") + + +######################################################################### +######################################################################### + +if __name__ == '__main__': + if not len(sys.argv) > 1: + print("Usage: " + __file__ + " ") + sys.exit(2) + + main(model=sys.argv[1], width=1024, height=768) diff --git a/port/PyAssimp/scripts/fixed_pipeline_3d_viewer.py b/port/PyAssimp/scripts/fixed_pipeline_3d_viewer.py index 48c157917..7f98b9004 100755 --- a/port/PyAssimp/scripts/fixed_pipeline_3d_viewer.py +++ b/port/PyAssimp/scripts/fixed_pipeline_3d_viewer.py @@ -98,7 +98,7 @@ class GLRenderer(): logger.info("Loading model:" + path + "...") if postprocess: - self.scene = pyassimp.load(path, postprocess) + self.scene = pyassimp.load(path, processing=postprocess) else: self.scene = pyassimp.load(path) logger.info("Done.") diff --git a/port/PyAssimp/scripts/sample.py b/port/PyAssimp/scripts/sample.py index 5153a9bab..9012eb374 100755 --- a/port/PyAssimp/scripts/sample.py +++ b/port/PyAssimp/scripts/sample.py @@ -20,7 +20,7 @@ def recur_node(node,level = 0): def main(filename=None): - scene = pyassimp.load(filename, pyassimp.postprocess.aiProcess_Triangulate) + scene = pyassimp.load(filename, processing=pyassimp.postprocess.aiProcess_Triangulate) #the model we load print("MODEL:" + filename) diff --git a/port/PyAssimp/scripts/transformations.py b/port/PyAssimp/scripts/transformations.py new file mode 100644 index 000000000..bf0cac9e3 --- /dev/null +++ b/port/PyAssimp/scripts/transformations.py @@ -0,0 +1,1705 @@ +# -*- coding: utf-8 -*- +# transformations.py + +# Copyright (c) 2006, Christoph Gohlke +# Copyright (c) 2006-2009, The Regents of the University of California +# All rights reserved. +# +# Redistribution and use 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 copyright holders nor the names of any +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# 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. + +"""Homogeneous Transformation Matrices and Quaternions. + +A library for calculating 4x4 matrices for translating, rotating, reflecting, +scaling, shearing, projecting, orthogonalizing, and superimposing arrays of +3D homogeneous coordinates as well as for converting between rotation matrices, +Euler angles, and quaternions. Also includes an Arcball control object and +functions to decompose transformation matrices. + +:Authors: + `Christoph Gohlke `__, + Laboratory for Fluorescence Dynamics, University of California, Irvine + +:Version: 20090418 + +Requirements +------------ + +* `Python 2.6 `__ +* `Numpy 1.3 `__ +* `transformations.c 20090418 `__ + (optional implementation of some functions in C) + +Notes +----- + +Matrices (M) can be inverted using numpy.linalg.inv(M), concatenated using +numpy.dot(M0, M1), or used to transform homogeneous coordinates (v) using +numpy.dot(M, v) for shape (4, \*) "point of arrays", respectively +numpy.dot(v, M.T) for shape (\*, 4) "array of points". + +Calculations are carried out with numpy.float64 precision. + +This Python implementation is not optimized for speed. + +Vector, point, quaternion, and matrix function arguments are expected to be +"array like", i.e. tuple, list, or numpy arrays. + +Return types are numpy arrays unless specified otherwise. + +Angles are in radians unless specified otherwise. + +Quaternions ix+jy+kz+w are represented as [x, y, z, w]. + +Use the transpose of transformation matrices for OpenGL glMultMatrixd(). + +A triple of Euler angles can be applied/interpreted in 24 ways, which can +be specified using a 4 character string or encoded 4-tuple: + + *Axes 4-string*: e.g. 'sxyz' or 'ryxy' + + - first character : rotations are applied to 's'tatic or 'r'otating frame + - remaining characters : successive rotation axis 'x', 'y', or 'z' + + *Axes 4-tuple*: e.g. (0, 0, 0, 0) or (1, 1, 1, 1) + + - inner axis: code of axis ('x':0, 'y':1, 'z':2) of rightmost matrix. + - parity : even (0) if inner axis 'x' is followed by 'y', 'y' is followed + by 'z', or 'z' is followed by 'x'. Otherwise odd (1). + - repetition : first and last axis are same (1) or different (0). + - frame : rotations are applied to static (0) or rotating (1) frame. + +References +---------- + +(1) Matrices and transformations. Ronald Goldman. + In "Graphics Gems I", pp 472-475. Morgan Kaufmann, 1990. +(2) More matrices and transformations: shear and pseudo-perspective. + Ronald Goldman. In "Graphics Gems II", pp 320-323. Morgan Kaufmann, 1991. +(3) Decomposing a matrix into simple transformations. Spencer Thomas. + In "Graphics Gems II", pp 320-323. Morgan Kaufmann, 1991. +(4) Recovering the data from the transformation matrix. Ronald Goldman. + In "Graphics Gems II", pp 324-331. Morgan Kaufmann, 1991. +(5) Euler angle conversion. Ken Shoemake. + In "Graphics Gems IV", pp 222-229. Morgan Kaufmann, 1994. +(6) Arcball rotation control. Ken Shoemake. + In "Graphics Gems IV", pp 175-192. Morgan Kaufmann, 1994. +(7) Representing attitude: Euler angles, unit quaternions, and rotation + vectors. James Diebel. 2006. +(8) A discussion of the solution for the best rotation to relate two sets + of vectors. W Kabsch. Acta Cryst. 1978. A34, 827-828. +(9) Closed-form solution of absolute orientation using unit quaternions. + BKP Horn. J Opt Soc Am A. 1987. 4(4), 629-642. +(10) Quaternions. Ken Shoemake. + http://www.sfu.ca/~jwa3/cmpt461/files/quatut.pdf +(11) From quaternion to matrix and back. JMP van Waveren. 2005. + http://www.intel.com/cd/ids/developer/asmo-na/eng/293748.htm +(12) Uniform random rotations. Ken Shoemake. + In "Graphics Gems III", pp 124-132. Morgan Kaufmann, 1992. + + +Examples +-------- + +>>> alpha, beta, gamma = 0.123, -1.234, 2.345 +>>> origin, xaxis, yaxis, zaxis = (0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1) +>>> I = identity_matrix() +>>> Rx = rotation_matrix(alpha, xaxis) +>>> Ry = rotation_matrix(beta, yaxis) +>>> Rz = rotation_matrix(gamma, zaxis) +>>> R = concatenate_matrices(Rx, Ry, Rz) +>>> euler = euler_from_matrix(R, 'rxyz') +>>> numpy.allclose([alpha, beta, gamma], euler) +True +>>> Re = euler_matrix(alpha, beta, gamma, 'rxyz') +>>> is_same_transform(R, Re) +True +>>> al, be, ga = euler_from_matrix(Re, 'rxyz') +>>> is_same_transform(Re, euler_matrix(al, be, ga, 'rxyz')) +True +>>> qx = quaternion_about_axis(alpha, xaxis) +>>> qy = quaternion_about_axis(beta, yaxis) +>>> qz = quaternion_about_axis(gamma, zaxis) +>>> q = quaternion_multiply(qx, qy) +>>> q = quaternion_multiply(q, qz) +>>> Rq = quaternion_matrix(q) +>>> is_same_transform(R, Rq) +True +>>> S = scale_matrix(1.23, origin) +>>> T = translation_matrix((1, 2, 3)) +>>> Z = shear_matrix(beta, xaxis, origin, zaxis) +>>> R = random_rotation_matrix(numpy.random.rand(3)) +>>> M = concatenate_matrices(T, R, Z, S) +>>> scale, shear, angles, trans, persp = decompose_matrix(M) +>>> numpy.allclose(scale, 1.23) +True +>>> numpy.allclose(trans, (1, 2, 3)) +True +>>> numpy.allclose(shear, (0, math.tan(beta), 0)) +True +>>> is_same_transform(R, euler_matrix(axes='sxyz', *angles)) +True +>>> M1 = compose_matrix(scale, shear, angles, trans, persp) +>>> is_same_transform(M, M1) +True + +""" + +from __future__ import division + +import warnings +import math + +import numpy + +# Documentation in HTML format can be generated with Epydoc +__docformat__ = "restructuredtext en" + + +def identity_matrix(): + """Return 4x4 identity/unit matrix. + + >>> I = identity_matrix() + >>> numpy.allclose(I, numpy.dot(I, I)) + True + >>> numpy.sum(I), numpy.trace(I) + (4.0, 4.0) + >>> numpy.allclose(I, numpy.identity(4, dtype=numpy.float64)) + True + + """ + return numpy.identity(4, dtype=numpy.float64) + + +def translation_matrix(direction): + """Return matrix to translate by direction vector. + + >>> v = numpy.random.random(3) - 0.5 + >>> numpy.allclose(v, translation_matrix(v)[:3, 3]) + True + + """ + M = numpy.identity(4) + M[:3, 3] = direction[:3] + return M + + +def translation_from_matrix(matrix): + """Return translation vector from translation matrix. + + >>> v0 = numpy.random.random(3) - 0.5 + >>> v1 = translation_from_matrix(translation_matrix(v0)) + >>> numpy.allclose(v0, v1) + True + + """ + return numpy.array(matrix, copy=False)[:3, 3].copy() + + +def reflection_matrix(point, normal): + """Return matrix to mirror at plane defined by point and normal vector. + + >>> v0 = numpy.random.random(4) - 0.5 + >>> v0[3] = 1.0 + >>> v1 = numpy.random.random(3) - 0.5 + >>> R = reflection_matrix(v0, v1) + >>> numpy.allclose(2., numpy.trace(R)) + True + >>> numpy.allclose(v0, numpy.dot(R, v0)) + True + >>> v2 = v0.copy() + >>> v2[:3] += v1 + >>> v3 = v0.copy() + >>> v2[:3] -= v1 + >>> numpy.allclose(v2, numpy.dot(R, v3)) + True + + """ + normal = unit_vector(normal[:3]) + M = numpy.identity(4) + M[:3, :3] -= 2.0 * numpy.outer(normal, normal) + M[:3, 3] = (2.0 * numpy.dot(point[:3], normal)) * normal + return M + + +def reflection_from_matrix(matrix): + """Return mirror plane point and normal vector from reflection matrix. + + >>> v0 = numpy.random.random(3) - 0.5 + >>> v1 = numpy.random.random(3) - 0.5 + >>> M0 = reflection_matrix(v0, v1) + >>> point, normal = reflection_from_matrix(M0) + >>> M1 = reflection_matrix(point, normal) + >>> is_same_transform(M0, M1) + True + + """ + M = numpy.array(matrix, dtype=numpy.float64, copy=False) + # normal: unit eigenvector corresponding to eigenvalue -1 + l, V = numpy.linalg.eig(M[:3, :3]) + i = numpy.where(abs(numpy.real(l) + 1.0) < 1e-8)[0] + if not len(i): + raise ValueError("no unit eigenvector corresponding to eigenvalue -1") + normal = numpy.real(V[:, i[0]]).squeeze() + # point: any unit eigenvector corresponding to eigenvalue 1 + l, V = numpy.linalg.eig(M) + i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-8)[0] + if not len(i): + raise ValueError("no unit eigenvector corresponding to eigenvalue 1") + point = numpy.real(V[:, i[-1]]).squeeze() + point /= point[3] + return point, normal + + +def rotation_matrix(angle, direction, point=None): + """Return matrix to rotate about axis defined by point and direction. + + >>> angle = (random.random() - 0.5) * (2*math.pi) + >>> direc = numpy.random.random(3) - 0.5 + >>> point = numpy.random.random(3) - 0.5 + >>> R0 = rotation_matrix(angle, direc, point) + >>> R1 = rotation_matrix(angle-2*math.pi, direc, point) + >>> is_same_transform(R0, R1) + True + >>> R0 = rotation_matrix(angle, direc, point) + >>> R1 = rotation_matrix(-angle, -direc, point) + >>> is_same_transform(R0, R1) + True + >>> I = numpy.identity(4, numpy.float64) + >>> numpy.allclose(I, rotation_matrix(math.pi*2, direc)) + True + >>> numpy.allclose(2., numpy.trace(rotation_matrix(math.pi/2, + ... direc, point))) + True + + """ + sina = math.sin(angle) + cosa = math.cos(angle) + direction = unit_vector(direction[:3]) + # rotation matrix around unit vector + R = numpy.array(((cosa, 0.0, 0.0), + (0.0, cosa, 0.0), + (0.0, 0.0, cosa)), dtype=numpy.float64) + R += numpy.outer(direction, direction) * (1.0 - cosa) + direction *= sina + R += numpy.array((( 0.0, -direction[2], direction[1]), + ( direction[2], 0.0, -direction[0]), + (-direction[1], direction[0], 0.0)), + dtype=numpy.float64) + M = numpy.identity(4) + M[:3, :3] = R + if point is not None: + # rotation not around origin + point = numpy.array(point[:3], dtype=numpy.float64, copy=False) + M[:3, 3] = point - numpy.dot(R, point) + return M + + +def rotation_from_matrix(matrix): + """Return rotation angle and axis from rotation matrix. + + >>> angle = (random.random() - 0.5) * (2*math.pi) + >>> direc = numpy.random.random(3) - 0.5 + >>> point = numpy.random.random(3) - 0.5 + >>> R0 = rotation_matrix(angle, direc, point) + >>> angle, direc, point = rotation_from_matrix(R0) + >>> R1 = rotation_matrix(angle, direc, point) + >>> is_same_transform(R0, R1) + True + + """ + R = numpy.array(matrix, dtype=numpy.float64, copy=False) + R33 = R[:3, :3] + # direction: unit eigenvector of R33 corresponding to eigenvalue of 1 + l, W = numpy.linalg.eig(R33.T) + i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-8)[0] + if not len(i): + raise ValueError("no unit eigenvector corresponding to eigenvalue 1") + direction = numpy.real(W[:, i[-1]]).squeeze() + # point: unit eigenvector of R33 corresponding to eigenvalue of 1 + l, Q = numpy.linalg.eig(R) + i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-8)[0] + if not len(i): + raise ValueError("no unit eigenvector corresponding to eigenvalue 1") + point = numpy.real(Q[:, i[-1]]).squeeze() + point /= point[3] + # rotation angle depending on direction + cosa = (numpy.trace(R33) - 1.0) / 2.0 + if abs(direction[2]) > 1e-8: + sina = (R[1, 0] + (cosa-1.0)*direction[0]*direction[1]) / direction[2] + elif abs(direction[1]) > 1e-8: + sina = (R[0, 2] + (cosa-1.0)*direction[0]*direction[2]) / direction[1] + else: + sina = (R[2, 1] + (cosa-1.0)*direction[1]*direction[2]) / direction[0] + angle = math.atan2(sina, cosa) + return angle, direction, point + + +def scale_matrix(factor, origin=None, direction=None): + """Return matrix to scale by factor around origin in direction. + + Use factor -1 for point symmetry. + + >>> v = (numpy.random.rand(4, 5) - 0.5) * 20.0 + >>> v[3] = 1.0 + >>> S = scale_matrix(-1.234) + >>> numpy.allclose(numpy.dot(S, v)[:3], -1.234*v[:3]) + True + >>> factor = random.random() * 10 - 5 + >>> origin = numpy.random.random(3) - 0.5 + >>> direct = numpy.random.random(3) - 0.5 + >>> S = scale_matrix(factor, origin) + >>> S = scale_matrix(factor, origin, direct) + + """ + if direction is None: + # uniform scaling + M = numpy.array(((factor, 0.0, 0.0, 0.0), + (0.0, factor, 0.0, 0.0), + (0.0, 0.0, factor, 0.0), + (0.0, 0.0, 0.0, 1.0)), dtype=numpy.float64) + if origin is not None: + M[:3, 3] = origin[:3] + M[:3, 3] *= 1.0 - factor + else: + # nonuniform scaling + direction = unit_vector(direction[:3]) + factor = 1.0 - factor + M = numpy.identity(4) + M[:3, :3] -= factor * numpy.outer(direction, direction) + if origin is not None: + M[:3, 3] = (factor * numpy.dot(origin[:3], direction)) * direction + return M + + +def scale_from_matrix(matrix): + """Return scaling factor, origin and direction from scaling matrix. + + >>> factor = random.random() * 10 - 5 + >>> origin = numpy.random.random(3) - 0.5 + >>> direct = numpy.random.random(3) - 0.5 + >>> S0 = scale_matrix(factor, origin) + >>> factor, origin, direction = scale_from_matrix(S0) + >>> S1 = scale_matrix(factor, origin, direction) + >>> is_same_transform(S0, S1) + True + >>> S0 = scale_matrix(factor, origin, direct) + >>> factor, origin, direction = scale_from_matrix(S0) + >>> S1 = scale_matrix(factor, origin, direction) + >>> is_same_transform(S0, S1) + True + + """ + M = numpy.array(matrix, dtype=numpy.float64, copy=False) + M33 = M[:3, :3] + factor = numpy.trace(M33) - 2.0 + try: + # direction: unit eigenvector corresponding to eigenvalue factor + l, V = numpy.linalg.eig(M33) + i = numpy.where(abs(numpy.real(l) - factor) < 1e-8)[0][0] + direction = numpy.real(V[:, i]).squeeze() + direction /= vector_norm(direction) + except IndexError: + # uniform scaling + factor = (factor + 2.0) / 3.0 + direction = None + # origin: any eigenvector corresponding to eigenvalue 1 + l, V = numpy.linalg.eig(M) + i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-8)[0] + if not len(i): + raise ValueError("no eigenvector corresponding to eigenvalue 1") + origin = numpy.real(V[:, i[-1]]).squeeze() + origin /= origin[3] + return factor, origin, direction + + +def projection_matrix(point, normal, direction=None, + perspective=None, pseudo=False): + """Return matrix to project onto plane defined by point and normal. + + Using either perspective point, projection direction, or none of both. + + If pseudo is True, perspective projections will preserve relative depth + such that Perspective = dot(Orthogonal, PseudoPerspective). + + >>> P = projection_matrix((0, 0, 0), (1, 0, 0)) + >>> numpy.allclose(P[1:, 1:], numpy.identity(4)[1:, 1:]) + True + >>> point = numpy.random.random(3) - 0.5 + >>> normal = numpy.random.random(3) - 0.5 + >>> direct = numpy.random.random(3) - 0.5 + >>> persp = numpy.random.random(3) - 0.5 + >>> P0 = projection_matrix(point, normal) + >>> P1 = projection_matrix(point, normal, direction=direct) + >>> P2 = projection_matrix(point, normal, perspective=persp) + >>> P3 = projection_matrix(point, normal, perspective=persp, pseudo=True) + >>> is_same_transform(P2, numpy.dot(P0, P3)) + True + >>> P = projection_matrix((3, 0, 0), (1, 1, 0), (1, 0, 0)) + >>> v0 = (numpy.random.rand(4, 5) - 0.5) * 20.0 + >>> v0[3] = 1.0 + >>> v1 = numpy.dot(P, v0) + >>> numpy.allclose(v1[1], v0[1]) + True + >>> numpy.allclose(v1[0], 3.0-v1[1]) + True + + """ + M = numpy.identity(4) + point = numpy.array(point[:3], dtype=numpy.float64, copy=False) + normal = unit_vector(normal[:3]) + if perspective is not None: + # perspective projection + perspective = numpy.array(perspective[:3], dtype=numpy.float64, + copy=False) + M[0, 0] = M[1, 1] = M[2, 2] = numpy.dot(perspective-point, normal) + M[:3, :3] -= numpy.outer(perspective, normal) + if pseudo: + # preserve relative depth + M[:3, :3] -= numpy.outer(normal, normal) + M[:3, 3] = numpy.dot(point, normal) * (perspective+normal) + else: + M[:3, 3] = numpy.dot(point, normal) * perspective + M[3, :3] = -normal + M[3, 3] = numpy.dot(perspective, normal) + elif direction is not None: + # parallel projection + direction = numpy.array(direction[:3], dtype=numpy.float64, copy=False) + scale = numpy.dot(direction, normal) + M[:3, :3] -= numpy.outer(direction, normal) / scale + M[:3, 3] = direction * (numpy.dot(point, normal) / scale) + else: + # orthogonal projection + M[:3, :3] -= numpy.outer(normal, normal) + M[:3, 3] = numpy.dot(point, normal) * normal + return M + + +def projection_from_matrix(matrix, pseudo=False): + """Return projection plane and perspective point from projection matrix. + + Return values are same as arguments for projection_matrix function: + point, normal, direction, perspective, and pseudo. + + >>> point = numpy.random.random(3) - 0.5 + >>> normal = numpy.random.random(3) - 0.5 + >>> direct = numpy.random.random(3) - 0.5 + >>> persp = numpy.random.random(3) - 0.5 + >>> P0 = projection_matrix(point, normal) + >>> result = projection_from_matrix(P0) + >>> P1 = projection_matrix(*result) + >>> is_same_transform(P0, P1) + True + >>> P0 = projection_matrix(point, normal, direct) + >>> result = projection_from_matrix(P0) + >>> P1 = projection_matrix(*result) + >>> is_same_transform(P0, P1) + True + >>> P0 = projection_matrix(point, normal, perspective=persp, pseudo=False) + >>> result = projection_from_matrix(P0, pseudo=False) + >>> P1 = projection_matrix(*result) + >>> is_same_transform(P0, P1) + True + >>> P0 = projection_matrix(point, normal, perspective=persp, pseudo=True) + >>> result = projection_from_matrix(P0, pseudo=True) + >>> P1 = projection_matrix(*result) + >>> is_same_transform(P0, P1) + True + + """ + M = numpy.array(matrix, dtype=numpy.float64, copy=False) + M33 = M[:3, :3] + l, V = numpy.linalg.eig(M) + i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-8)[0] + if not pseudo and len(i): + # point: any eigenvector corresponding to eigenvalue 1 + point = numpy.real(V[:, i[-1]]).squeeze() + point /= point[3] + # direction: unit eigenvector corresponding to eigenvalue 0 + l, V = numpy.linalg.eig(M33) + i = numpy.where(abs(numpy.real(l)) < 1e-8)[0] + if not len(i): + raise ValueError("no eigenvector corresponding to eigenvalue 0") + direction = numpy.real(V[:, i[0]]).squeeze() + direction /= vector_norm(direction) + # normal: unit eigenvector of M33.T corresponding to eigenvalue 0 + l, V = numpy.linalg.eig(M33.T) + i = numpy.where(abs(numpy.real(l)) < 1e-8)[0] + if len(i): + # parallel projection + normal = numpy.real(V[:, i[0]]).squeeze() + normal /= vector_norm(normal) + return point, normal, direction, None, False + else: + # orthogonal projection, where normal equals direction vector + return point, direction, None, None, False + else: + # perspective projection + i = numpy.where(abs(numpy.real(l)) > 1e-8)[0] + if not len(i): + raise ValueError( + "no eigenvector not corresponding to eigenvalue 0") + point = numpy.real(V[:, i[-1]]).squeeze() + point /= point[3] + normal = - M[3, :3] + perspective = M[:3, 3] / numpy.dot(point[:3], normal) + if pseudo: + perspective -= normal + return point, normal, None, perspective, pseudo + + +def clip_matrix(left, right, bottom, top, near, far, perspective=False): + """Return matrix to obtain normalized device coordinates from frustrum. + + The frustrum bounds are axis-aligned along x (left, right), + y (bottom, top) and z (near, far). + + Normalized device coordinates are in range [-1, 1] if coordinates are + inside the frustrum. + + If perspective is True the frustrum is a truncated pyramid with the + perspective point at origin and direction along z axis, otherwise an + orthographic canonical view volume (a box). + + Homogeneous coordinates transformed by the perspective clip matrix + need to be dehomogenized (divided by w coordinate). + + >>> frustrum = numpy.random.rand(6) + >>> frustrum[1] += frustrum[0] + >>> frustrum[3] += frustrum[2] + >>> frustrum[5] += frustrum[4] + >>> M = clip_matrix(*frustrum, perspective=False) + >>> numpy.dot(M, [frustrum[0], frustrum[2], frustrum[4], 1.0]) + array([-1., -1., -1., 1.]) + >>> numpy.dot(M, [frustrum[1], frustrum[3], frustrum[5], 1.0]) + array([ 1., 1., 1., 1.]) + >>> M = clip_matrix(*frustrum, perspective=True) + >>> v = numpy.dot(M, [frustrum[0], frustrum[2], frustrum[4], 1.0]) + >>> v / v[3] + array([-1., -1., -1., 1.]) + >>> v = numpy.dot(M, [frustrum[1], frustrum[3], frustrum[4], 1.0]) + >>> v / v[3] + array([ 1., 1., -1., 1.]) + + """ + if left >= right or bottom >= top or near >= far: + raise ValueError("invalid frustrum") + if perspective: + if near <= _EPS: + raise ValueError("invalid frustrum: near <= 0") + t = 2.0 * near + M = ((-t/(right-left), 0.0, (right+left)/(right-left), 0.0), + (0.0, -t/(top-bottom), (top+bottom)/(top-bottom), 0.0), + (0.0, 0.0, -(far+near)/(far-near), t*far/(far-near)), + (0.0, 0.0, -1.0, 0.0)) + else: + M = ((2.0/(right-left), 0.0, 0.0, (right+left)/(left-right)), + (0.0, 2.0/(top-bottom), 0.0, (top+bottom)/(bottom-top)), + (0.0, 0.0, 2.0/(far-near), (far+near)/(near-far)), + (0.0, 0.0, 0.0, 1.0)) + return numpy.array(M, dtype=numpy.float64) + + +def shear_matrix(angle, direction, point, normal): + """Return matrix to shear by angle along direction vector on shear plane. + + The shear plane is defined by a point and normal vector. The direction + vector must be orthogonal to the plane's normal vector. + + A point P is transformed by the shear matrix into P" such that + the vector P-P" is parallel to the direction vector and its extent is + given by the angle of P-P'-P", where P' is the orthogonal projection + of P onto the shear plane. + + >>> angle = (random.random() - 0.5) * 4*math.pi + >>> direct = numpy.random.random(3) - 0.5 + >>> point = numpy.random.random(3) - 0.5 + >>> normal = numpy.cross(direct, numpy.random.random(3)) + >>> S = shear_matrix(angle, direct, point, normal) + >>> numpy.allclose(1.0, numpy.linalg.det(S)) + True + + """ + normal = unit_vector(normal[:3]) + direction = unit_vector(direction[:3]) + if abs(numpy.dot(normal, direction)) > 1e-6: + raise ValueError("direction and normal vectors are not orthogonal") + angle = math.tan(angle) + M = numpy.identity(4) + M[:3, :3] += angle * numpy.outer(direction, normal) + M[:3, 3] = -angle * numpy.dot(point[:3], normal) * direction + return M + + +def shear_from_matrix(matrix): + """Return shear angle, direction and plane from shear matrix. + + >>> angle = (random.random() - 0.5) * 4*math.pi + >>> direct = numpy.random.random(3) - 0.5 + >>> point = numpy.random.random(3) - 0.5 + >>> normal = numpy.cross(direct, numpy.random.random(3)) + >>> S0 = shear_matrix(angle, direct, point, normal) + >>> angle, direct, point, normal = shear_from_matrix(S0) + >>> S1 = shear_matrix(angle, direct, point, normal) + >>> is_same_transform(S0, S1) + True + + """ + M = numpy.array(matrix, dtype=numpy.float64, copy=False) + M33 = M[:3, :3] + # normal: cross independent eigenvectors corresponding to the eigenvalue 1 + l, V = numpy.linalg.eig(M33) + i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-4)[0] + if len(i) < 2: + raise ValueError("No two linear independent eigenvectors found %s" % l) + V = numpy.real(V[:, i]).squeeze().T + lenorm = -1.0 + for i0, i1 in ((0, 1), (0, 2), (1, 2)): + n = numpy.cross(V[i0], V[i1]) + l = vector_norm(n) + if l > lenorm: + lenorm = l + normal = n + normal /= lenorm + # direction and angle + direction = numpy.dot(M33 - numpy.identity(3), normal) + angle = vector_norm(direction) + direction /= angle + angle = math.atan(angle) + # point: eigenvector corresponding to eigenvalue 1 + l, V = numpy.linalg.eig(M) + i = numpy.where(abs(numpy.real(l) - 1.0) < 1e-8)[0] + if not len(i): + raise ValueError("no eigenvector corresponding to eigenvalue 1") + point = numpy.real(V[:, i[-1]]).squeeze() + point /= point[3] + return angle, direction, point, normal + + +def decompose_matrix(matrix): + """Return sequence of transformations from transformation matrix. + + matrix : array_like + Non-degenerative homogeneous transformation matrix + + Return tuple of: + scale : vector of 3 scaling factors + shear : list of shear factors for x-y, x-z, y-z axes + angles : list of Euler angles about static x, y, z axes + translate : translation vector along x, y, z axes + perspective : perspective partition of matrix + + Raise ValueError if matrix is of wrong type or degenerative. + + >>> T0 = translation_matrix((1, 2, 3)) + >>> scale, shear, angles, trans, persp = decompose_matrix(T0) + >>> T1 = translation_matrix(trans) + >>> numpy.allclose(T0, T1) + True + >>> S = scale_matrix(0.123) + >>> scale, shear, angles, trans, persp = decompose_matrix(S) + >>> scale[0] + 0.123 + >>> R0 = euler_matrix(1, 2, 3) + >>> scale, shear, angles, trans, persp = decompose_matrix(R0) + >>> R1 = euler_matrix(*angles) + >>> numpy.allclose(R0, R1) + True + + """ + M = numpy.array(matrix, dtype=numpy.float64, copy=True).T + if abs(M[3, 3]) < _EPS: + raise ValueError("M[3, 3] is zero") + M /= M[3, 3] + P = M.copy() + P[:, 3] = 0, 0, 0, 1 + if not numpy.linalg.det(P): + raise ValueError("Matrix is singular") + + scale = numpy.zeros((3, ), dtype=numpy.float64) + shear = [0, 0, 0] + angles = [0, 0, 0] + + if any(abs(M[:3, 3]) > _EPS): + perspective = numpy.dot(M[:, 3], numpy.linalg.inv(P.T)) + M[:, 3] = 0, 0, 0, 1 + else: + perspective = numpy.array((0, 0, 0, 1), dtype=numpy.float64) + + translate = M[3, :3].copy() + M[3, :3] = 0 + + row = M[:3, :3].copy() + scale[0] = vector_norm(row[0]) + row[0] /= scale[0] + shear[0] = numpy.dot(row[0], row[1]) + row[1] -= row[0] * shear[0] + scale[1] = vector_norm(row[1]) + row[1] /= scale[1] + shear[0] /= scale[1] + shear[1] = numpy.dot(row[0], row[2]) + row[2] -= row[0] * shear[1] + shear[2] = numpy.dot(row[1], row[2]) + row[2] -= row[1] * shear[2] + scale[2] = vector_norm(row[2]) + row[2] /= scale[2] + shear[1:] /= scale[2] + + if numpy.dot(row[0], numpy.cross(row[1], row[2])) < 0: + scale *= -1 + row *= -1 + + angles[1] = math.asin(-row[0, 2]) + if math.cos(angles[1]): + angles[0] = math.atan2(row[1, 2], row[2, 2]) + angles[2] = math.atan2(row[0, 1], row[0, 0]) + else: + #angles[0] = math.atan2(row[1, 0], row[1, 1]) + angles[0] = math.atan2(-row[2, 1], row[1, 1]) + angles[2] = 0.0 + + return scale, shear, angles, translate, perspective + + +def compose_matrix(scale=None, shear=None, angles=None, translate=None, + perspective=None): + """Return transformation matrix from sequence of transformations. + + This is the inverse of the decompose_matrix function. + + Sequence of transformations: + scale : vector of 3 scaling factors + shear : list of shear factors for x-y, x-z, y-z axes + angles : list of Euler angles about static x, y, z axes + translate : translation vector along x, y, z axes + perspective : perspective partition of matrix + + >>> scale = numpy.random.random(3) - 0.5 + >>> shear = numpy.random.random(3) - 0.5 + >>> angles = (numpy.random.random(3) - 0.5) * (2*math.pi) + >>> trans = numpy.random.random(3) - 0.5 + >>> persp = numpy.random.random(4) - 0.5 + >>> M0 = compose_matrix(scale, shear, angles, trans, persp) + >>> result = decompose_matrix(M0) + >>> M1 = compose_matrix(*result) + >>> is_same_transform(M0, M1) + True + + """ + M = numpy.identity(4) + if perspective is not None: + P = numpy.identity(4) + P[3, :] = perspective[:4] + M = numpy.dot(M, P) + if translate is not None: + T = numpy.identity(4) + T[:3, 3] = translate[:3] + M = numpy.dot(M, T) + if angles is not None: + R = euler_matrix(angles[0], angles[1], angles[2], 'sxyz') + M = numpy.dot(M, R) + if shear is not None: + Z = numpy.identity(4) + Z[1, 2] = shear[2] + Z[0, 2] = shear[1] + Z[0, 1] = shear[0] + M = numpy.dot(M, Z) + if scale is not None: + S = numpy.identity(4) + S[0, 0] = scale[0] + S[1, 1] = scale[1] + S[2, 2] = scale[2] + M = numpy.dot(M, S) + M /= M[3, 3] + return M + + +def orthogonalization_matrix(lengths, angles): + """Return orthogonalization matrix for crystallographic cell coordinates. + + Angles are expected in degrees. + + The de-orthogonalization matrix is the inverse. + + >>> O = orthogonalization_matrix((10., 10., 10.), (90., 90., 90.)) + >>> numpy.allclose(O[:3, :3], numpy.identity(3, float) * 10) + True + >>> O = orthogonalization_matrix([9.8, 12.0, 15.5], [87.2, 80.7, 69.7]) + >>> numpy.allclose(numpy.sum(O), 43.063229) + True + + """ + a, b, c = lengths + angles = numpy.radians(angles) + sina, sinb, _ = numpy.sin(angles) + cosa, cosb, cosg = numpy.cos(angles) + co = (cosa * cosb - cosg) / (sina * sinb) + return numpy.array(( + ( a*sinb*math.sqrt(1.0-co*co), 0.0, 0.0, 0.0), + (-a*sinb*co, b*sina, 0.0, 0.0), + ( a*cosb, b*cosa, c, 0.0), + ( 0.0, 0.0, 0.0, 1.0)), + dtype=numpy.float64) + + +def superimposition_matrix(v0, v1, scaling=False, usesvd=True): + """Return matrix to transform given vector set into second vector set. + + v0 and v1 are shape (3, \*) or (4, \*) arrays of at least 3 vectors. + + If usesvd is True, the weighted sum of squared deviations (RMSD) is + minimized according to the algorithm by W. Kabsch [8]. Otherwise the + quaternion based algorithm by B. Horn [9] is used (slower when using + this Python implementation). + + The returned matrix performs rotation, translation and uniform scaling + (if specified). + + >>> v0 = numpy.random.rand(3, 10) + >>> M = superimposition_matrix(v0, v0) + >>> numpy.allclose(M, numpy.identity(4)) + True + >>> R = random_rotation_matrix(numpy.random.random(3)) + >>> v0 = ((1,0,0), (0,1,0), (0,0,1), (1,1,1)) + >>> v1 = numpy.dot(R, v0) + >>> M = superimposition_matrix(v0, v1) + >>> numpy.allclose(v1, numpy.dot(M, v0)) + True + >>> v0 = (numpy.random.rand(4, 100) - 0.5) * 20.0 + >>> v0[3] = 1.0 + >>> v1 = numpy.dot(R, v0) + >>> M = superimposition_matrix(v0, v1) + >>> numpy.allclose(v1, numpy.dot(M, v0)) + True + >>> S = scale_matrix(random.random()) + >>> T = translation_matrix(numpy.random.random(3)-0.5) + >>> M = concatenate_matrices(T, R, S) + >>> v1 = numpy.dot(M, v0) + >>> v0[:3] += numpy.random.normal(0.0, 1e-9, 300).reshape(3, -1) + >>> M = superimposition_matrix(v0, v1, scaling=True) + >>> numpy.allclose(v1, numpy.dot(M, v0)) + True + >>> M = superimposition_matrix(v0, v1, scaling=True, usesvd=False) + >>> numpy.allclose(v1, numpy.dot(M, v0)) + True + >>> v = numpy.empty((4, 100, 3), dtype=numpy.float64) + >>> v[:, :, 0] = v0 + >>> M = superimposition_matrix(v0, v1, scaling=True, usesvd=False) + >>> numpy.allclose(v1, numpy.dot(M, v[:, :, 0])) + True + + """ + v0 = numpy.array(v0, dtype=numpy.float64, copy=False)[:3] + v1 = numpy.array(v1, dtype=numpy.float64, copy=False)[:3] + + if v0.shape != v1.shape or v0.shape[1] < 3: + raise ValueError("Vector sets are of wrong shape or type.") + + # move centroids to origin + t0 = numpy.mean(v0, axis=1) + t1 = numpy.mean(v1, axis=1) + v0 = v0 - t0.reshape(3, 1) + v1 = v1 - t1.reshape(3, 1) + + if usesvd: + # Singular Value Decomposition of covariance matrix + u, s, vh = numpy.linalg.svd(numpy.dot(v1, v0.T)) + # rotation matrix from SVD orthonormal bases + R = numpy.dot(u, vh) + if numpy.linalg.det(R) < 0.0: + # R does not constitute right handed system + R -= numpy.outer(u[:, 2], vh[2, :]*2.0) + s[-1] *= -1.0 + # homogeneous transformation matrix + M = numpy.identity(4) + M[:3, :3] = R + else: + # compute symmetric matrix N + xx, yy, zz = numpy.sum(v0 * v1, axis=1) + xy, yz, zx = numpy.sum(v0 * numpy.roll(v1, -1, axis=0), axis=1) + xz, yx, zy = numpy.sum(v0 * numpy.roll(v1, -2, axis=0), axis=1) + N = ((xx+yy+zz, yz-zy, zx-xz, xy-yx), + (yz-zy, xx-yy-zz, xy+yx, zx+xz), + (zx-xz, xy+yx, -xx+yy-zz, yz+zy), + (xy-yx, zx+xz, yz+zy, -xx-yy+zz)) + # quaternion: eigenvector corresponding to most positive eigenvalue + l, V = numpy.linalg.eig(N) + q = V[:, numpy.argmax(l)] + q /= vector_norm(q) # unit quaternion + q = numpy.roll(q, -1) # move w component to end + # homogeneous transformation matrix + M = quaternion_matrix(q) + + # scale: ratio of rms deviations from centroid + if scaling: + v0 *= v0 + v1 *= v1 + M[:3, :3] *= math.sqrt(numpy.sum(v1) / numpy.sum(v0)) + + # translation + M[:3, 3] = t1 + T = numpy.identity(4) + T[:3, 3] = -t0 + M = numpy.dot(M, T) + return M + + +def euler_matrix(ai, aj, ak, axes='sxyz'): + """Return homogeneous rotation matrix from Euler angles and axis sequence. + + ai, aj, ak : Euler's roll, pitch and yaw angles + axes : One of 24 axis sequences as string or encoded tuple + + >>> R = euler_matrix(1, 2, 3, 'syxz') + >>> numpy.allclose(numpy.sum(R[0]), -1.34786452) + True + >>> R = euler_matrix(1, 2, 3, (0, 1, 0, 1)) + >>> numpy.allclose(numpy.sum(R[0]), -0.383436184) + True + >>> ai, aj, ak = (4.0*math.pi) * (numpy.random.random(3) - 0.5) + >>> for axes in _AXES2TUPLE.keys(): + ... R = euler_matrix(ai, aj, ak, axes) + >>> for axes in _TUPLE2AXES.keys(): + ... R = euler_matrix(ai, aj, ak, axes) + + """ + try: + firstaxis, parity, repetition, frame = _AXES2TUPLE[axes] + except (AttributeError, KeyError): + _ = _TUPLE2AXES[axes] + firstaxis, parity, repetition, frame = axes + + i = firstaxis + j = _NEXT_AXIS[i+parity] + k = _NEXT_AXIS[i-parity+1] + + if frame: + ai, ak = ak, ai + if parity: + ai, aj, ak = -ai, -aj, -ak + + si, sj, sk = math.sin(ai), math.sin(aj), math.sin(ak) + ci, cj, ck = math.cos(ai), math.cos(aj), math.cos(ak) + cc, cs = ci*ck, ci*sk + sc, ss = si*ck, si*sk + + M = numpy.identity(4) + if repetition: + M[i, i] = cj + M[i, j] = sj*si + M[i, k] = sj*ci + M[j, i] = sj*sk + M[j, j] = -cj*ss+cc + M[j, k] = -cj*cs-sc + M[k, i] = -sj*ck + M[k, j] = cj*sc+cs + M[k, k] = cj*cc-ss + else: + M[i, i] = cj*ck + M[i, j] = sj*sc-cs + M[i, k] = sj*cc+ss + M[j, i] = cj*sk + M[j, j] = sj*ss+cc + M[j, k] = sj*cs-sc + M[k, i] = -sj + M[k, j] = cj*si + M[k, k] = cj*ci + return M + + +def euler_from_matrix(matrix, axes='sxyz'): + """Return Euler angles from rotation matrix for specified axis sequence. + + axes : One of 24 axis sequences as string or encoded tuple + + Note that many Euler angle triplets can describe one matrix. + + >>> R0 = euler_matrix(1, 2, 3, 'syxz') + >>> al, be, ga = euler_from_matrix(R0, 'syxz') + >>> R1 = euler_matrix(al, be, ga, 'syxz') + >>> numpy.allclose(R0, R1) + True + >>> angles = (4.0*math.pi) * (numpy.random.random(3) - 0.5) + >>> for axes in _AXES2TUPLE.keys(): + ... R0 = euler_matrix(axes=axes, *angles) + ... R1 = euler_matrix(axes=axes, *euler_from_matrix(R0, axes)) + ... if not numpy.allclose(R0, R1): print axes, "failed" + + """ + try: + firstaxis, parity, repetition, frame = _AXES2TUPLE[axes.lower()] + except (AttributeError, KeyError): + _ = _TUPLE2AXES[axes] + firstaxis, parity, repetition, frame = axes + + i = firstaxis + j = _NEXT_AXIS[i+parity] + k = _NEXT_AXIS[i-parity+1] + + M = numpy.array(matrix, dtype=numpy.float64, copy=False)[:3, :3] + if repetition: + sy = math.sqrt(M[i, j]*M[i, j] + M[i, k]*M[i, k]) + if sy > _EPS: + ax = math.atan2( M[i, j], M[i, k]) + ay = math.atan2( sy, M[i, i]) + az = math.atan2( M[j, i], -M[k, i]) + else: + ax = math.atan2(-M[j, k], M[j, j]) + ay = math.atan2( sy, M[i, i]) + az = 0.0 + else: + cy = math.sqrt(M[i, i]*M[i, i] + M[j, i]*M[j, i]) + if cy > _EPS: + ax = math.atan2( M[k, j], M[k, k]) + ay = math.atan2(-M[k, i], cy) + az = math.atan2( M[j, i], M[i, i]) + else: + ax = math.atan2(-M[j, k], M[j, j]) + ay = math.atan2(-M[k, i], cy) + az = 0.0 + + if parity: + ax, ay, az = -ax, -ay, -az + if frame: + ax, az = az, ax + return ax, ay, az + + +def euler_from_quaternion(quaternion, axes='sxyz'): + """Return Euler angles from quaternion for specified axis sequence. + + >>> angles = euler_from_quaternion([0.06146124, 0, 0, 0.99810947]) + >>> numpy.allclose(angles, [0.123, 0, 0]) + True + + """ + return euler_from_matrix(quaternion_matrix(quaternion), axes) + + +def quaternion_from_euler(ai, aj, ak, axes='sxyz'): + """Return quaternion from Euler angles and axis sequence. + + ai, aj, ak : Euler's roll, pitch and yaw angles + axes : One of 24 axis sequences as string or encoded tuple + + >>> q = quaternion_from_euler(1, 2, 3, 'ryxz') + >>> numpy.allclose(q, [0.310622, -0.718287, 0.444435, 0.435953]) + True + + """ + try: + firstaxis, parity, repetition, frame = _AXES2TUPLE[axes.lower()] + except (AttributeError, KeyError): + _ = _TUPLE2AXES[axes] + firstaxis, parity, repetition, frame = axes + + i = firstaxis + j = _NEXT_AXIS[i+parity] + k = _NEXT_AXIS[i-parity+1] + + if frame: + ai, ak = ak, ai + if parity: + aj = -aj + + ai /= 2.0 + aj /= 2.0 + ak /= 2.0 + ci = math.cos(ai) + si = math.sin(ai) + cj = math.cos(aj) + sj = math.sin(aj) + ck = math.cos(ak) + sk = math.sin(ak) + cc = ci*ck + cs = ci*sk + sc = si*ck + ss = si*sk + + quaternion = numpy.empty((4, ), dtype=numpy.float64) + if repetition: + quaternion[i] = cj*(cs + sc) + quaternion[j] = sj*(cc + ss) + quaternion[k] = sj*(cs - sc) + quaternion[3] = cj*(cc - ss) + else: + quaternion[i] = cj*sc - sj*cs + quaternion[j] = cj*ss + sj*cc + quaternion[k] = cj*cs - sj*sc + quaternion[3] = cj*cc + sj*ss + if parity: + quaternion[j] *= -1 + + return quaternion + + +def quaternion_about_axis(angle, axis): + """Return quaternion for rotation about axis. + + >>> q = quaternion_about_axis(0.123, (1, 0, 0)) + >>> numpy.allclose(q, [0.06146124, 0, 0, 0.99810947]) + True + + """ + quaternion = numpy.zeros((4, ), dtype=numpy.float64) + quaternion[:3] = axis[:3] + qlen = vector_norm(quaternion) + if qlen > _EPS: + quaternion *= math.sin(angle/2.0) / qlen + quaternion[3] = math.cos(angle/2.0) + return quaternion + + +def quaternion_matrix(quaternion): + """Return homogeneous rotation matrix from quaternion. + + >>> R = quaternion_matrix([0.06146124, 0, 0, 0.99810947]) + >>> numpy.allclose(R, rotation_matrix(0.123, (1, 0, 0))) + True + + """ + q = numpy.array(quaternion[:4], dtype=numpy.float64, copy=True) + nq = numpy.dot(q, q) + if nq < _EPS: + return numpy.identity(4) + q *= math.sqrt(2.0 / nq) + q = numpy.outer(q, q) + return numpy.array(( + (1.0-q[1, 1]-q[2, 2], q[0, 1]-q[2, 3], q[0, 2]+q[1, 3], 0.0), + ( q[0, 1]+q[2, 3], 1.0-q[0, 0]-q[2, 2], q[1, 2]-q[0, 3], 0.0), + ( q[0, 2]-q[1, 3], q[1, 2]+q[0, 3], 1.0-q[0, 0]-q[1, 1], 0.0), + ( 0.0, 0.0, 0.0, 1.0) + ), dtype=numpy.float64) + + +def quaternion_from_matrix(matrix): + """Return quaternion from rotation matrix. + + >>> R = rotation_matrix(0.123, (1, 2, 3)) + >>> q = quaternion_from_matrix(R) + >>> numpy.allclose(q, [0.0164262, 0.0328524, 0.0492786, 0.9981095]) + True + + """ + q = numpy.empty((4, ), dtype=numpy.float64) + M = numpy.array(matrix, dtype=numpy.float64, copy=False)[:4, :4] + t = numpy.trace(M) + if t > M[3, 3]: + q[3] = t + q[2] = M[1, 0] - M[0, 1] + q[1] = M[0, 2] - M[2, 0] + q[0] = M[2, 1] - M[1, 2] + else: + i, j, k = 0, 1, 2 + if M[1, 1] > M[0, 0]: + i, j, k = 1, 2, 0 + if M[2, 2] > M[i, i]: + i, j, k = 2, 0, 1 + t = M[i, i] - (M[j, j] + M[k, k]) + M[3, 3] + q[i] = t + q[j] = M[i, j] + M[j, i] + q[k] = M[k, i] + M[i, k] + q[3] = M[k, j] - M[j, k] + q *= 0.5 / math.sqrt(t * M[3, 3]) + return q + + +def quaternion_multiply(quaternion1, quaternion0): + """Return multiplication of two quaternions. + + >>> q = quaternion_multiply([1, -2, 3, 4], [-5, 6, 7, 8]) + >>> numpy.allclose(q, [-44, -14, 48, 28]) + True + + """ + x0, y0, z0, w0 = quaternion0 + x1, y1, z1, w1 = quaternion1 + return numpy.array(( + x1*w0 + y1*z0 - z1*y0 + w1*x0, + -x1*z0 + y1*w0 + z1*x0 + w1*y0, + x1*y0 - y1*x0 + z1*w0 + w1*z0, + -x1*x0 - y1*y0 - z1*z0 + w1*w0), dtype=numpy.float64) + + +def quaternion_conjugate(quaternion): + """Return conjugate of quaternion. + + >>> q0 = random_quaternion() + >>> q1 = quaternion_conjugate(q0) + >>> q1[3] == q0[3] and all(q1[:3] == -q0[:3]) + True + + """ + return numpy.array((-quaternion[0], -quaternion[1], + -quaternion[2], quaternion[3]), dtype=numpy.float64) + + +def quaternion_inverse(quaternion): + """Return inverse of quaternion. + + >>> q0 = random_quaternion() + >>> q1 = quaternion_inverse(q0) + >>> numpy.allclose(quaternion_multiply(q0, q1), [0, 0, 0, 1]) + True + + """ + return quaternion_conjugate(quaternion) / numpy.dot(quaternion, quaternion) + + +def quaternion_slerp(quat0, quat1, fraction, spin=0, shortestpath=True): + """Return spherical linear interpolation between two quaternions. + + >>> q0 = random_quaternion() + >>> q1 = random_quaternion() + >>> q = quaternion_slerp(q0, q1, 0.0) + >>> numpy.allclose(q, q0) + True + >>> q = quaternion_slerp(q0, q1, 1.0, 1) + >>> numpy.allclose(q, q1) + True + >>> q = quaternion_slerp(q0, q1, 0.5) + >>> angle = math.acos(numpy.dot(q0, q)) + >>> numpy.allclose(2.0, math.acos(numpy.dot(q0, q1)) / angle) or \ + numpy.allclose(2.0, math.acos(-numpy.dot(q0, q1)) / angle) + True + + """ + q0 = unit_vector(quat0[:4]) + q1 = unit_vector(quat1[:4]) + if fraction == 0.0: + return q0 + elif fraction == 1.0: + return q1 + d = numpy.dot(q0, q1) + if abs(abs(d) - 1.0) < _EPS: + return q0 + if shortestpath and d < 0.0: + # invert rotation + d = -d + q1 *= -1.0 + angle = math.acos(d) + spin * math.pi + if abs(angle) < _EPS: + return q0 + isin = 1.0 / math.sin(angle) + q0 *= math.sin((1.0 - fraction) * angle) * isin + q1 *= math.sin(fraction * angle) * isin + q0 += q1 + return q0 + + +def random_quaternion(rand=None): + """Return uniform random unit quaternion. + + rand: array like or None + Three independent random variables that are uniformly distributed + between 0 and 1. + + >>> q = random_quaternion() + >>> numpy.allclose(1.0, vector_norm(q)) + True + >>> q = random_quaternion(numpy.random.random(3)) + >>> q.shape + (4,) + + """ + if rand is None: + rand = numpy.random.rand(3) + else: + assert len(rand) == 3 + r1 = numpy.sqrt(1.0 - rand[0]) + r2 = numpy.sqrt(rand[0]) + pi2 = math.pi * 2.0 + t1 = pi2 * rand[1] + t2 = pi2 * rand[2] + return numpy.array((numpy.sin(t1)*r1, + numpy.cos(t1)*r1, + numpy.sin(t2)*r2, + numpy.cos(t2)*r2), dtype=numpy.float64) + + +def random_rotation_matrix(rand=None): + """Return uniform random rotation matrix. + + rnd: array like + Three independent random variables that are uniformly distributed + between 0 and 1 for each returned quaternion. + + >>> R = random_rotation_matrix() + >>> numpy.allclose(numpy.dot(R.T, R), numpy.identity(4)) + True + + """ + return quaternion_matrix(random_quaternion(rand)) + + +class Arcball(object): + """Virtual Trackball Control. + + >>> ball = Arcball() + >>> ball = Arcball(initial=numpy.identity(4)) + >>> ball.place([320, 320], 320) + >>> ball.down([500, 250]) + >>> ball.drag([475, 275]) + >>> R = ball.matrix() + >>> numpy.allclose(numpy.sum(R), 3.90583455) + True + >>> ball = Arcball(initial=[0, 0, 0, 1]) + >>> ball.place([320, 320], 320) + >>> ball.setaxes([1,1,0], [-1, 1, 0]) + >>> ball.setconstrain(True) + >>> ball.down([400, 200]) + >>> ball.drag([200, 400]) + >>> R = ball.matrix() + >>> numpy.allclose(numpy.sum(R), 0.2055924) + True + >>> ball.next() + + """ + + def __init__(self, initial=None): + """Initialize virtual trackball control. + + initial : quaternion or rotation matrix + + """ + self._axis = None + self._axes = None + self._radius = 1.0 + self._center = [0.0, 0.0] + self._vdown = numpy.array([0, 0, 1], dtype=numpy.float64) + self._constrain = False + + if initial is None: + self._qdown = numpy.array([0, 0, 0, 1], dtype=numpy.float64) + else: + initial = numpy.array(initial, dtype=numpy.float64) + if initial.shape == (4, 4): + self._qdown = quaternion_from_matrix(initial) + elif initial.shape == (4, ): + initial /= vector_norm(initial) + self._qdown = initial + else: + raise ValueError("initial not a quaternion or matrix.") + + self._qnow = self._qpre = self._qdown + + def place(self, center, radius): + """Place Arcball, e.g. when window size changes. + + center : sequence[2] + Window coordinates of trackball center. + radius : float + Radius of trackball in window coordinates. + + """ + self._radius = float(radius) + self._center[0] = center[0] + self._center[1] = center[1] + + def setaxes(self, *axes): + """Set axes to constrain rotations.""" + if axes is None: + self._axes = None + else: + self._axes = [unit_vector(axis) for axis in axes] + + def setconstrain(self, constrain): + """Set state of constrain to axis mode.""" + self._constrain = constrain == True + + def getconstrain(self): + """Return state of constrain to axis mode.""" + return self._constrain + + def down(self, point): + """Set initial cursor window coordinates and pick constrain-axis.""" + self._vdown = arcball_map_to_sphere(point, self._center, self._radius) + self._qdown = self._qpre = self._qnow + + if self._constrain and self._axes is not None: + self._axis = arcball_nearest_axis(self._vdown, self._axes) + self._vdown = arcball_constrain_to_axis(self._vdown, self._axis) + else: + self._axis = None + + def drag(self, point): + """Update current cursor window coordinates.""" + vnow = arcball_map_to_sphere(point, self._center, self._radius) + + if self._axis is not None: + vnow = arcball_constrain_to_axis(vnow, self._axis) + + self._qpre = self._qnow + + t = numpy.cross(self._vdown, vnow) + if numpy.dot(t, t) < _EPS: + self._qnow = self._qdown + else: + q = [t[0], t[1], t[2], numpy.dot(self._vdown, vnow)] + self._qnow = quaternion_multiply(q, self._qdown) + + def next(self, acceleration=0.0): + """Continue rotation in direction of last drag.""" + q = quaternion_slerp(self._qpre, self._qnow, 2.0+acceleration, False) + self._qpre, self._qnow = self._qnow, q + + def matrix(self): + """Return homogeneous rotation matrix.""" + return quaternion_matrix(self._qnow) + + +def arcball_map_to_sphere(point, center, radius): + """Return unit sphere coordinates from window coordinates.""" + v = numpy.array(((point[0] - center[0]) / radius, + (center[1] - point[1]) / radius, + 0.0), dtype=numpy.float64) + n = v[0]*v[0] + v[1]*v[1] + if n > 1.0: + v /= math.sqrt(n) # position outside of sphere + else: + v[2] = math.sqrt(1.0 - n) + return v + + +def arcball_constrain_to_axis(point, axis): + """Return sphere point perpendicular to axis.""" + v = numpy.array(point, dtype=numpy.float64, copy=True) + a = numpy.array(axis, dtype=numpy.float64, copy=True) + v -= a * numpy.dot(a, v) # on plane + n = vector_norm(v) + if n > _EPS: + if v[2] < 0.0: + v *= -1.0 + v /= n + return v + if a[2] == 1.0: + return numpy.array([1, 0, 0], dtype=numpy.float64) + return unit_vector([-a[1], a[0], 0]) + + +def arcball_nearest_axis(point, axes): + """Return axis, which arc is nearest to point.""" + point = numpy.array(point, dtype=numpy.float64, copy=False) + nearest = None + mx = -1.0 + for axis in axes: + t = numpy.dot(arcball_constrain_to_axis(point, axis), point) + if t > mx: + nearest = axis + mx = t + return nearest + + +# epsilon for testing whether a number is close to zero +_EPS = numpy.finfo(float).eps * 4.0 + +# axis sequences for Euler angles +_NEXT_AXIS = [1, 2, 0, 1] + +# map axes strings to/from tuples of inner axis, parity, repetition, frame +_AXES2TUPLE = { + 'sxyz': (0, 0, 0, 0), 'sxyx': (0, 0, 1, 0), 'sxzy': (0, 1, 0, 0), + 'sxzx': (0, 1, 1, 0), 'syzx': (1, 0, 0, 0), 'syzy': (1, 0, 1, 0), + 'syxz': (1, 1, 0, 0), 'syxy': (1, 1, 1, 0), 'szxy': (2, 0, 0, 0), + 'szxz': (2, 0, 1, 0), 'szyx': (2, 1, 0, 0), 'szyz': (2, 1, 1, 0), + 'rzyx': (0, 0, 0, 1), 'rxyx': (0, 0, 1, 1), 'ryzx': (0, 1, 0, 1), + 'rxzx': (0, 1, 1, 1), 'rxzy': (1, 0, 0, 1), 'ryzy': (1, 0, 1, 1), + 'rzxy': (1, 1, 0, 1), 'ryxy': (1, 1, 1, 1), 'ryxz': (2, 0, 0, 1), + 'rzxz': (2, 0, 1, 1), 'rxyz': (2, 1, 0, 1), 'rzyz': (2, 1, 1, 1)} + +_TUPLE2AXES = dict((v, k) for k, v in _AXES2TUPLE.items()) + +# helper functions + +def vector_norm(data, axis=None, out=None): + """Return length, i.e. eucledian norm, of ndarray along axis. + + >>> v = numpy.random.random(3) + >>> n = vector_norm(v) + >>> numpy.allclose(n, numpy.linalg.norm(v)) + True + >>> v = numpy.random.rand(6, 5, 3) + >>> n = vector_norm(v, axis=-1) + >>> numpy.allclose(n, numpy.sqrt(numpy.sum(v*v, axis=2))) + True + >>> n = vector_norm(v, axis=1) + >>> numpy.allclose(n, numpy.sqrt(numpy.sum(v*v, axis=1))) + True + >>> v = numpy.random.rand(5, 4, 3) + >>> n = numpy.empty((5, 3), dtype=numpy.float64) + >>> vector_norm(v, axis=1, out=n) + >>> numpy.allclose(n, numpy.sqrt(numpy.sum(v*v, axis=1))) + True + >>> vector_norm([]) + 0.0 + >>> vector_norm([1.0]) + 1.0 + + """ + data = numpy.array(data, dtype=numpy.float64, copy=True) + if out is None: + if data.ndim == 1: + return math.sqrt(numpy.dot(data, data)) + data *= data + out = numpy.atleast_1d(numpy.sum(data, axis=axis)) + numpy.sqrt(out, out) + return out + else: + data *= data + numpy.sum(data, axis=axis, out=out) + numpy.sqrt(out, out) + + +def unit_vector(data, axis=None, out=None): + """Return ndarray normalized by length, i.e. eucledian norm, along axis. + + >>> v0 = numpy.random.random(3) + >>> v1 = unit_vector(v0) + >>> numpy.allclose(v1, v0 / numpy.linalg.norm(v0)) + True + >>> v0 = numpy.random.rand(5, 4, 3) + >>> v1 = unit_vector(v0, axis=-1) + >>> v2 = v0 / numpy.expand_dims(numpy.sqrt(numpy.sum(v0*v0, axis=2)), 2) + >>> numpy.allclose(v1, v2) + True + >>> v1 = unit_vector(v0, axis=1) + >>> v2 = v0 / numpy.expand_dims(numpy.sqrt(numpy.sum(v0*v0, axis=1)), 1) + >>> numpy.allclose(v1, v2) + True + >>> v1 = numpy.empty((5, 4, 3), dtype=numpy.float64) + >>> unit_vector(v0, axis=1, out=v1) + >>> numpy.allclose(v1, v2) + True + >>> list(unit_vector([])) + [] + >>> list(unit_vector([1.0])) + [1.0] + + """ + if out is None: + data = numpy.array(data, dtype=numpy.float64, copy=True) + if data.ndim == 1: + data /= math.sqrt(numpy.dot(data, data)) + return data + else: + if out is not data: + out[:] = numpy.array(data, copy=False) + data = out + length = numpy.atleast_1d(numpy.sum(data*data, axis)) + numpy.sqrt(length, length) + if axis is not None: + length = numpy.expand_dims(length, axis) + data /= length + if out is None: + return data + + +def random_vector(size): + """Return array of random doubles in the half-open interval [0.0, 1.0). + + >>> v = random_vector(10000) + >>> numpy.all(v >= 0.0) and numpy.all(v < 1.0) + True + >>> v0 = random_vector(10) + >>> v1 = random_vector(10) + >>> numpy.any(v0 == v1) + False + + """ + return numpy.random.random(size) + + +def inverse_matrix(matrix): + """Return inverse of square transformation matrix. + + >>> M0 = random_rotation_matrix() + >>> M1 = inverse_matrix(M0.T) + >>> numpy.allclose(M1, numpy.linalg.inv(M0.T)) + True + >>> for size in range(1, 7): + ... M0 = numpy.random.rand(size, size) + ... M1 = inverse_matrix(M0) + ... if not numpy.allclose(M1, numpy.linalg.inv(M0)): print size + + """ + return numpy.linalg.inv(matrix) + + +def concatenate_matrices(*matrices): + """Return concatenation of series of transformation matrices. + + >>> M = numpy.random.rand(16).reshape((4, 4)) - 0.5 + >>> numpy.allclose(M, concatenate_matrices(M)) + True + >>> numpy.allclose(numpy.dot(M, M.T), concatenate_matrices(M, M.T)) + True + + """ + M = numpy.identity(4) + for i in matrices: + M = numpy.dot(M, i) + return M + + +def is_same_transform(matrix0, matrix1): + """Return True if two matrices perform same transformation. + + >>> is_same_transform(numpy.identity(4), numpy.identity(4)) + True + >>> is_same_transform(numpy.identity(4), random_rotation_matrix()) + False + + """ + matrix0 = numpy.array(matrix0, dtype=numpy.float64, copy=True) + matrix0 /= matrix0[3, 3] + matrix1 = numpy.array(matrix1, dtype=numpy.float64, copy=True) + matrix1 /= matrix1[3, 3] + return numpy.allclose(matrix0, matrix1) + + +def _import_module(module_name, warn=True, prefix='_py_', ignore='_'): + """Try import all public attributes from module into global namespace. + + Existing attributes with name clashes are renamed with prefix. + Attributes starting with underscore are ignored by default. + + Return True on successful import. + + """ + try: + module = __import__(module_name) + except ImportError: + if warn: + warnings.warn("Failed to import module " + module_name) + else: + for attr in dir(module): + if ignore and attr.startswith(ignore): + continue + if prefix: + if attr in globals(): + globals()[prefix + attr] = globals()[attr] + elif warn: + warnings.warn("No Python implementation of " + attr) + globals()[attr] = getattr(module, attr) + return True diff --git a/port/PyAssimp/setup.py b/port/PyAssimp/setup.py index 9b30aa7ba..26cf9b400 100644 --- a/port/PyAssimp/setup.py +++ b/port/PyAssimp/setup.py @@ -3,11 +3,14 @@ import os from distutils.core import setup setup(name='pyassimp', - version='0.1', + version='3.3', license='ISC', description='Python bindings for the Open Asset Import Library (ASSIMP)', url='https://github.com/assimp/assimp', packages=['pyassimp'], - data_files=[('share/pyassimp', ['README.md']), - ('share/examples/pyassimp', ['scripts/' + f for f in os.listdir('scripts/')])] + data_files=[ + ('share/pyassimp', ['README.md']), + ('share/examples/pyassimp', ['scripts/' + f for f in os.listdir('scripts/')]) + ], + requires=['numpy'] ) diff --git a/port/dAssimp/assimp/mesh.d b/port/dAssimp/assimp/mesh.d index 9f20c9a66..da6193631 100644 --- a/port/dAssimp/assimp/mesh.d +++ b/port/dAssimp/assimp/mesh.d @@ -51,7 +51,7 @@ import assimp.types; extern ( C ) { /* * These limits are required to match the settings Assimp was compiled - * against. Therfore, do not redefine them unless you build the library + * against. Therefore, do not redefine them unless you build the library * from source using the same definitions. */ diff --git a/port/iOS/IPHONEOS_ARM64_TOOLCHAIN.cmake b/port/iOS/IPHONEOS_ARM64_TOOLCHAIN.cmake index bd7199cc5..3aea8342e 100644 --- a/port/iOS/IPHONEOS_ARM64_TOOLCHAIN.cmake +++ b/port/iOS/IPHONEOS_ARM64_TOOLCHAIN.cmake @@ -7,8 +7,8 @@ SET (CMAKE_SYSTEM_PROCESSOR "arm64") SET (SDKVER "7.1") SET (DEVROOT "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain") SET (SDKROOT "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS${SDKVER}.sdk") -SET (CC "${DEVROOT}/usr/bin/llvm-gcc") -SET (CXX "${DEVROOT}/usr/bin/llvm-g++") +SET (CC "${DEVROOT}/usr/bin/clang") +SET (CXX "${DEVROOT}/usr/bin/clang++") CMAKE_FORCE_C_COMPILER (${CC} LLVM) CMAKE_FORCE_CXX_COMPILER (${CXX} LLVM) diff --git a/port/iOS/build.sh b/port/iOS/build.sh index beca60014..44683f0c7 100755 --- a/port/iOS/build.sh +++ b/port/iOS/build.sh @@ -22,7 +22,7 @@ CPP_DEV_TARGET_LIST=(miphoneos-version-min mios-simulator-version-min) CPP_DEV_TARGET= CPP_STD_LIB_LIST=(libc++ libstdc++) CPP_STD_LIB= -CPP_STD_LIST=(c++03 c++11 c++14) +CPP_STD_LIST=(c++11 c++14) CPP_STD= function join { local IFS="$1"; shift; echo "$*"; } diff --git a/port/jassimp/README b/port/jassimp/README index 1ce9acc2b..a642f750a 100644 --- a/port/jassimp/README +++ b/port/jassimp/README @@ -44,7 +44,6 @@ jassimp supports most of assimps features. Current limitations are * no support for mesh animations * no support for embedded textures * no support for importer configurations -* no support for the custom I/O API of assimp * some texture related material properties are not exposed via the API but only accessible by traversing the list of properties. However this limitation is also present in the c-API ... diff --git a/port/jassimp/jassimp-native/src/jassimp.cpp b/port/jassimp/jassimp-native/src/jassimp.cpp index 226e416aa..070dbc95d 100644 --- a/port/jassimp/jassimp-native/src/jassimp.cpp +++ b/port/jassimp/jassimp-native/src/jassimp.cpp @@ -1,7 +1,9 @@ #include "jassimp.h" -#include +#include #include +#include +#include #ifdef JNI_LOG @@ -12,9 +14,11 @@ #define lprintf(...) printf (__VA_ARGS__) #endif /* ANDROID */ #else -#define lprintf +#define lprintf #endif +static std::string gLastErrorString; + // Automatically deletes a local ref when it goes out of scope class SmartLocalRef { private: @@ -210,7 +214,7 @@ static bool getStaticField(JNIEnv *env, const char* className, const char* field return false; } - jfieldID fieldId = env->GetFieldID(clazz, fieldName, signature); + jfieldID fieldId = env->GetStaticFieldID(clazz, fieldName, signature); if (NULL == fieldId) { @@ -270,6 +274,81 @@ static bool callv(JNIEnv *env, jobject object, const char* typeName, return true; } +static jobject callo(JNIEnv *env, jobject object, const char* typeName, const char* methodName, + const char* signature,/* const*/ jvalue* params) +{ + jclass clazz = env->FindClass(typeName); + SmartLocalRef clazzRef(env, clazz); + + if (NULL == clazz) + { + lprintf("could not find class %s\n", typeName); + return NULL; + } + + jmethodID mid = env->GetMethodID(clazz, methodName, signature); + + if (NULL == mid) + { + lprintf("could not find method %s with signature %s in type %s\n", methodName, signature, typeName); + return NULL; + } + + jobject jReturnValue = env->CallObjectMethodA(object, mid, params); + + return jReturnValue; +} + +static int calli(JNIEnv *env, jobject object, const char* typeName, const char* methodName, + const char* signature) +{ + jclass clazz = env->FindClass(typeName); + SmartLocalRef clazzRef(env, clazz); + + if (NULL == clazz) + { + lprintf("could not find class %s\n", typeName); + return false; + } + + jmethodID mid = env->GetMethodID(clazz, methodName, signature); + + if (NULL == mid) + { + lprintf("could not find method %s with signature %s in type %s\n", methodName, signature, typeName); + return false; + } + + jint jReturnValue = env->CallIntMethod(object, mid); + + return (int) jReturnValue; +} + +static int callc(JNIEnv *env, jobject object, const char* typeName, const char* methodName, + const char* signature) +{ + jclass clazz = env->FindClass(typeName); + SmartLocalRef clazzRef(env, clazz); + + if (NULL == clazz) + { + lprintf("could not find class %s\n", typeName); + return false; + } + + jmethodID mid = env->GetMethodID(clazz, methodName, signature); + + if (NULL == mid) + { + lprintf("could not find method %s with signature %s in type %s\n", methodName, signature, typeName); + return false; + } + + jint jReturnValue = env->CallCharMethod(object, mid); + + return (int) jReturnValue; +} + static bool callStaticObject(JNIEnv *env, const char* typeName, const char* methodName, const char* signature,/* const*/ jvalue* params, jobject& returnValue) @@ -359,6 +438,158 @@ static bool copyBufferArray(JNIEnv *env, jobject jMesh, const char* jBufferName, return true; } +class JavaIOStream : public Assimp::IOStream +{ +private: + size_t pos; + size_t size; + char* buffer; + jobject jIOStream; + + +public: + JavaIOStream(size_t size, char* buffer, jobject jIOStream) : + pos(0), + size(size), + buffer(buffer), + jIOStream(jIOStream) + {}; + + + ~JavaIOStream(void) + { + free(buffer); + }; + + size_t Read(void* pvBuffer, size_t pSize, size_t pCount) + { + const size_t cnt = std::min(pCount,(size - pos)/pSize); + const size_t ofs = pSize*cnt; + + memcpy(pvBuffer, buffer + pos, ofs); + pos += ofs; + + return cnt; + }; + size_t Write(const void* pvBuffer, size_t pSize, size_t pCount) + { + return 0; + }; + + aiReturn Seek(size_t pOffset, aiOrigin pOrigin) + { + if (aiOrigin_SET == pOrigin) { + if (pOffset >= size) { + return AI_FAILURE; + } + pos = pOffset; + } + else if (aiOrigin_END == pOrigin) { + if (pOffset >= size) { + return AI_FAILURE; + } + pos = size-pOffset; + } + else { + if (pOffset + pos >= size) { + return AI_FAILURE; + } + pos += pOffset; + } + return AI_SUCCESS; + }; + + size_t Tell(void) const + { + return pos; + }; + + size_t FileSize() const + { + return size; + }; + + void Flush() {}; + + + jobject javaObject() + { + return jIOStream; + }; + + +}; + + +class JavaIOSystem : public Assimp::IOSystem { + private: + JNIEnv* mJniEnv; + jobject& mJavaIOSystem; + + public: + JavaIOSystem(JNIEnv* env, jobject& javaIOSystem) : + mJniEnv(env), + mJavaIOSystem(javaIOSystem) + {}; + + bool Exists( const char* pFile) const + { + jvalue params[1]; + params[0].l = mJniEnv->NewStringUTF(pFile); + return call(mJniEnv, mJavaIOSystem, "jassimp/AiIOSystem", "exists", "(Ljava/lang/String;)Z", params); + + }; + char getOsSeparator() const + { + return (char) callc(mJniEnv, mJavaIOSystem, "jassimp/AiIOSystem", "getOsSeparator", "()C"); + }; + + Assimp::IOStream* Open(const char* pFile,const char* pMode = "rb") + { + jvalue params[2]; + params[0].l = mJniEnv->NewStringUTF(pFile); + params[1].l = mJniEnv->NewStringUTF(pMode); + + + jobject jStream = callo(mJniEnv, mJavaIOSystem, "jassimp/AiIOSystem", "open", "(Ljava/lang/String;Ljava/lang/String;)Ljassimp/AiIOStream;", params); + if(NULL == jStream) + { + lprintf("NULL object from AiIOSystem.open\n"); + return NULL; + } + + size_t size = calli(mJniEnv, jStream, "jassimp/AiIOStream", "getFileSize", "()I"); + lprintf("Model file size is %d\n", size); + + char* buffer = (char*)malloc(size); + jobject javaBuffer = mJniEnv->NewDirectByteBuffer(buffer, size); + + jvalue readParams[1]; + readParams[0].l = javaBuffer; + if(call(mJniEnv, jStream, "jassimp/AiIOStream", "read", "(Ljava/nio/ByteBuffer;)Z", readParams)) + { + return new JavaIOStream(size, buffer, jStream); + } + else + { + lprintf("Read failure on AiIOStream.read"); + free(buffer); + return NULL; + } + + }; + void Close( Assimp::IOStream* pFile) + { + + jvalue params[1]; + params[0].l = ((JavaIOStream*) pFile)->javaObject(); + callv(mJniEnv, mJavaIOSystem, "jassimp/AiIOSystem", "close", "(Ljassimp/AiIOStream;)V", params); + delete pFile; + }; + + + +}; static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene) @@ -774,8 +1005,164 @@ static bool loadMeshes(JNIEnv *env, const aiScene* cScene, jobject& jScene) return true; } +static bool loadMetadata(JNIEnv *env, const aiNode* cNode, jobject& jNode) +{ + aiMetadata *cMetadata = cNode->mMetaData; -static bool loadSceneNode(JNIEnv *env, const aiNode *cNode, jobject parent, jobject* loadedNode = NULL) + for(unsigned i = 0; imNumProperties; i++) { + + aiString& metaDataKey = cMetadata->mKeys[i]; + void* cData = cMetadata->mValues[i].mData; + aiMetadataType cMetadataType = cMetadata->mValues[i].mType; + + jobject jAiMetadataEntry = NULL; + SmartLocalRef refMetadataEntry(env, jAiMetadataEntry); + + if(!createInstance(env, "jassimp/AiMetadataEntry", jAiMetadataEntry)) { + return false; + } + + jobject jAiMetadataTypeEnumValue = NULL; + SmartLocalRef refMetadataTypeEnumValue(env, jAiMetadataTypeEnumValue); + + jobject jMetadataData = NULL; + SmartLocalRef refMetadataData(env, jMetadataData); + + bool getMetadataTypeSuccess = false; + bool getMetadataDataSuccess = false; + + jvalue boxingMethodArgument[1]; + + jboolean exceptionThrown; + + switch (cMetadataType) { + + case AI_BOOL: { + getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_BOOL", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue); + boxingMethodArgument[0].z = (jboolean) *static_cast(cData); + getMetadataDataSuccess = callStaticObject(env, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", boxingMethodArgument, jMetadataData); + break; + } + case AI_INT32: { + getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_INT32", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue); + boxingMethodArgument[0].i = (jint) *static_cast(cData); + getMetadataDataSuccess = callStaticObject(env, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", boxingMethodArgument, jMetadataData); + break; + } + case AI_UINT64: { + getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_UINT64", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue); + boxingMethodArgument[0].j = (jlong) *static_cast(cData); + getMetadataDataSuccess = callStaticObject(env, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", boxingMethodArgument, jMetadataData); + break; + } + case AI_FLOAT: { + getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_FLOAT", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue); + boxingMethodArgument[0].f = (jfloat) *static_cast(cData); + getMetadataDataSuccess = callStaticObject(env, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", boxingMethodArgument, jMetadataData); + break; + } + case AI_DOUBLE: { + getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_DOUBLE", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue); + boxingMethodArgument[0].d = (jdouble) *static_cast(cData); + getMetadataDataSuccess = callStaticObject(env, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", boxingMethodArgument, jMetadataData); + break; + } + case AI_AISTRING: { + getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_AISTRING", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue); + jMetadataData = env->NewStringUTF(static_cast(cData)->C_Str()); + getMetadataDataSuccess = (jMetadataData != NULL); + break; + } + case AI_AIVECTOR3D: { + getMetadataTypeSuccess = getStaticField(env, "jassimp/AiMetadataEntry$AiMetadataType", "AI_AIVECTOR3D", + "Ljassimp/AiMetadataEntry$AiMetadataType;", + jAiMetadataTypeEnumValue); + jvalue wrapVec3Args[3]; + aiVector3D *vector3D = static_cast(cData); + wrapVec3Args[0].f = vector3D->x; + wrapVec3Args[1].f = vector3D->y; + wrapVec3Args[2].f = vector3D->z; + getMetadataDataSuccess = callStaticObject(env, "jassimp/Jassimp", "wrapVec3", "(FFF)Ljava/lang/Object;", + wrapVec3Args, jMetadataData); + break; + } + default: { + getMetadataTypeSuccess = false; + getMetadataDataSuccess = false; + break; + } + } + + exceptionThrown = env->ExceptionCheck(); + + if(!getMetadataTypeSuccess || !getMetadataDataSuccess) { + if(exceptionThrown) + { + env->ExceptionDescribe(); + } + + return false; + } + + if(!setObjectField(env, jAiMetadataEntry, "mType", "Ljassimp/AiMetadataEntry$AiMetadataType;", jAiMetadataTypeEnumValue)) { + exceptionThrown = env->ExceptionCheck(); + + if(exceptionThrown) + { + env->ExceptionDescribe(); + } + + return false; + } + + if(!setObjectField(env, jAiMetadataEntry, "mData", "Ljava/lang/Object;", jMetadataData)) { + exceptionThrown = env->ExceptionCheck(); + + if(exceptionThrown) + { + env->ExceptionDescribe(); + } + + return false; + } + + jobject jNodeMetadata = NULL; + SmartLocalRef refMetadata(env, jNodeMetadata); + + if(!getField(env, jNode, "m_metaData", "Ljava/util/Map;", jNodeMetadata)) { + exceptionThrown = env->ExceptionCheck(); + + if(exceptionThrown) + { + env->ExceptionDescribe(); + } + + return false; + } + + jclass hashMapClass = env->FindClass("java/util/HashMap"); + jmethodID jHashMapPutMethod = env->GetMethodID(hashMapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + + jstring jKey = env->NewStringUTF(metaDataKey.C_Str()); + SmartLocalRef keyRef(env, jKey); + + // Only check exception instead of result here because maps will return + // null on success if they did not overwrite an existing mapping for the given key. + env->CallObjectMethod(jNodeMetadata, jHashMapPutMethod, jKey, jAiMetadataEntry); + + exceptionThrown = env->ExceptionCheck(); + + if(exceptionThrown) { + env->ExceptionDescribe(); + return false; + } + + } + + return true; +} + +static bool loadSceneNode(JNIEnv *env, const aiNode *cNode, jobject parent, jobject* loadedNode = NULL) { lprintf(" converting node %s ...\n", cNode->mName.C_Str()); @@ -788,7 +1175,7 @@ static bool loadSceneNode(JNIEnv *env, const aiNode *cNode, jobject parent, jobj wrapMatParams[0].l = jMatrixArr; jobject jMatrix; SmartLocalRef refMatrix(env, jMatrix); - + if (!callStaticObject(env, "jassimp/Jassimp", "wrapMatrix", "([F)Ljava/lang/Object;", wrapMatParams, jMatrix)) { return false; @@ -837,12 +1224,19 @@ static bool loadSceneNode(JNIEnv *env, const aiNode *cNode, jobject parent, jobj } } - if (NULL != loadedNode) - { - *loadedNode = jNode; - } else { - env->DeleteLocalRef(jNode); - } + if (NULL != loadedNode) + { + if(cNode->mMetaData) { + if(!loadMetadata(env, cNode, jNode)) + { + return false; + } + } + + *loadedNode = jNode; + } else { + env->DeleteLocalRef(jNode); + } return true; } @@ -1474,7 +1868,7 @@ JNIEXPORT jint JNICALL Java_jassimp_Jassimp_getlongsize JNIEXPORT jstring JNICALL Java_jassimp_Jassimp_getErrorString (JNIEnv *env, jclass jClazz) { - const char *err = aiGetErrorString(); + const char *err = gLastErrorString.c_str(); if (NULL == err) { @@ -1486,18 +1880,26 @@ JNIEXPORT jstring JNICALL Java_jassimp_Jassimp_getErrorString JNIEXPORT jobject JNICALL Java_jassimp_Jassimp_aiImportFile - (JNIEnv *env, jclass jClazz, jstring jFilename, jlong postProcess) + (JNIEnv *env, jclass jClazz, jstring jFilename, jlong postProcess, jobject ioSystem) { jobject jScene = NULL; /* convert params */ const char* cFilename = env->GetStringUTFChars(jFilename, NULL); + + Assimp::Importer imp; - + + if(ioSystem != NULL) + { + imp.SetIOHandler(new JavaIOSystem(env, ioSystem)); + lprintf("Created aiFileIO\n"); + } + lprintf("opening file: %s\n", cFilename); /* do import */ - const aiScene *cScene = aiImportFile(cFilename, (unsigned int) postProcess); + const aiScene *cScene = imp.ReadFile(cFilename, (unsigned int) postProcess); if (!cScene) { @@ -1549,22 +1951,16 @@ error: if (NULL == exception) { - /* thats really a problem because we cannot throw in this case */ + /* that's really a problem because we cannot throw in this case */ env->FatalError("could not throw java.io.IOException"); } - - env->ThrowNew(exception, aiGetErrorString()); + gLastErrorString = imp.GetErrorString(); + env->ThrowNew(exception, gLastErrorString.c_str()); lprintf("problem detected\n"); } end: - /* - * NOTE: this releases all memory used in the native domain. - * Ensure all data has been passed to java before! - */ - aiReleaseImport(cScene); - /* free params */ env->ReleaseStringUTFChars(jFilename, cFilename); diff --git a/port/jassimp/jassimp-native/src/jassimp.h b/port/jassimp/jassimp-native/src/jassimp.h index 188a4e904..7d4b66e29 100644 --- a/port/jassimp/jassimp-native/src/jassimp.h +++ b/port/jassimp/jassimp-native/src/jassimp.h @@ -1,5 +1,6 @@ /* DO NOT EDIT THIS FILE - it is machine generated */ #include +#include /* Header for class jassimp_Jassimp */ #ifndef _Included_jassimp_Jassimp @@ -38,7 +39,7 @@ JNIEXPORT jstring JNICALL Java_jassimp_Jassimp_getErrorString * Signature: (Ljava/lang/String;J)Ljassimp/AiScene; */ JNIEXPORT jobject JNICALL Java_jassimp_Jassimp_aiImportFile - (JNIEnv *, jclass, jstring, jlong); + (JNIEnv *, jclass, jstring, jlong, jobject); #ifdef __cplusplus } diff --git a/port/jassimp/jassimp/src/jassimp/AiClassLoaderIOSystem.java b/port/jassimp/jassimp/src/jassimp/AiClassLoaderIOSystem.java new file mode 100644 index 000000000..e14a87f77 --- /dev/null +++ b/port/jassimp/jassimp/src/jassimp/AiClassLoaderIOSystem.java @@ -0,0 +1,155 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library - Java Binding (jassimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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. +--------------------------------------------------------------------------- +*/ +package jassimp; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +/** + * IOSystem based on the Java classloader.

+ * + * This IOSystem allows loading models directly from the + * classpath. No extraction to the file system is + * necessary. + * + * @author Jesper Smith + * + */ +public class AiClassLoaderIOSystem implements AiIOSystem +{ + private final Class clazz; + private final ClassLoader classLoader; + + /** + * Construct a new AiClassLoaderIOSystem.

+ * + * This constructor uses a ClassLoader to resolve + * resources. + * + * @param classLoader classLoader to resolve resources. + */ + public AiClassLoaderIOSystem(ClassLoader classLoader) { + this.clazz = null; + this.classLoader = classLoader; + } + + /** + * Construct a new AiClassLoaderIOSystem.

+ * + * This constructor uses a Class to resolve + * resources. + * + * @param class class to resolve resources. + */ + public AiClassLoaderIOSystem(Class clazz) { + this.clazz = clazz; + this.classLoader = null; + } + + + @Override + public AiInputStreamIOStream open(String filename, String ioMode) { + try { + + InputStream is; + + if(clazz != null) { + is = clazz.getResourceAsStream(filename); + } + else if (classLoader != null) { + is = classLoader.getResourceAsStream(filename); + } + else { + System.err.println("[" + getClass().getSimpleName() + + "] No class or classLoader provided to resolve " + filename); + return null; + } + + if(is != null) { + return new AiInputStreamIOStream(is); + } + else { + System.err.println("[" + getClass().getSimpleName() + + "] Cannot find " + filename); + return null; + } + } + catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + @Override + public void close(AiInputStreamIOStream file) { + } + + @Override + public boolean exists(String path) + { + URL url = null; + if(clazz != null) { + url = clazz.getResource(path); + } + else if (classLoader != null) { + url = classLoader.getResource(path); + } + + + if(url == null) + { + return false; + } + else + { + return true; + } + + } + + @Override + public char getOsSeparator() + { + return '/'; + } + +} diff --git a/port/jassimp/jassimp/src/jassimp/AiIOStream.java b/port/jassimp/jassimp/src/jassimp/AiIOStream.java new file mode 100644 index 000000000..6625b3740 --- /dev/null +++ b/port/jassimp/jassimp/src/jassimp/AiIOStream.java @@ -0,0 +1,80 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library - Java Binding (jassimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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. +--------------------------------------------------------------------------- +*/ +package jassimp; + +import java.nio.ByteBuffer; + + +/** + * Interface to allow custom resource loaders for jassimp.

+ * + * The design is based on passing the file wholly in memory, + * because Java inputstreams do not have to support seek.

+ * + * Writing files from Java is unsupported. + * + * + * @author Jesper Smith + * + */ +public interface AiIOStream +{ + + /** + * Read all data into buffer.

+ * + * The whole stream should be read into the buffer. + * No support is provided for partial reads. + * + * @param buffer Target buffer for the model data + * + * @return true if successful, false if an error occurred. + */ + boolean read(ByteBuffer buffer); + + /** + * The total size of this stream.

+ * + * @return total size of this stream + */ + int getFileSize(); + +} diff --git a/port/jassimp/jassimp/src/jassimp/AiIOSystem.java b/port/jassimp/jassimp/src/jassimp/AiIOSystem.java new file mode 100644 index 000000000..213f95a12 --- /dev/null +++ b/port/jassimp/jassimp/src/jassimp/AiIOSystem.java @@ -0,0 +1,79 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library - Java Binding (jassimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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. +--------------------------------------------------------------------------- +*/ +package jassimp; + +public interface AiIOSystem +{ + /** + * + * Open a new file with a given path. + * When the access to the file is finished, call close() to release all associated resources + * + * @param path Path to the file + * @param ioMode file I/O mode. Required are: "wb", "w", "wt", "rb", "r", "rt". + * + * @return AiIOStream or null if an error occurred + */ + public T open(String path, String ioMode); + + + /** + * Tests for the existence of a file at the given path. + * + * @param path path to the file + * @return true if there is a file with this path, else false. + */ + public boolean exists(String path); + + /** + * Returns the system specific directory separator.

+ * + * @return System specific directory separator + */ + public char getOsSeparator(); + + /** + * Closes the given file and releases all resources associated with it. + * + * @param file The file instance previously created by Open(). + */ + public void close(T file); +} diff --git a/port/jassimp/jassimp/src/jassimp/AiInputStreamIOStream.java b/port/jassimp/jassimp/src/jassimp/AiInputStreamIOStream.java new file mode 100644 index 000000000..0db1ea211 --- /dev/null +++ b/port/jassimp/jassimp/src/jassimp/AiInputStreamIOStream.java @@ -0,0 +1,127 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library - Java Binding (jassimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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. +--------------------------------------------------------------------------- +*/ +package jassimp; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.net.URL; +import java.nio.ByteBuffer; + + +/** + * Implementation of AiIOStream reading from a InputStream + * + * @author Jesper Smith + * + */ +public class AiInputStreamIOStream implements AiIOStream +{ + private final ByteArrayOutputStream os = new ByteArrayOutputStream(); + + + public AiInputStreamIOStream(URI uri) throws IOException { + this(uri.toURL()); + } + + public AiInputStreamIOStream(URL url) throws IOException { + this(url.openStream()); + } + + public AiInputStreamIOStream(InputStream is) throws IOException { + int read; + byte[] data = new byte[1024]; + while((read = is.read(data, 0, data.length)) != -1) { + os.write(data, 0, read); + } + os.flush(); + + is.close(); + } + + @Override + public int getFileSize() { + return os.size(); + } + + @Override + public boolean read(ByteBuffer buffer) { + ByteBufferOutputStream bos = new ByteBufferOutputStream(buffer); + try + { + os.writeTo(bos); + } + catch (IOException e) + { + e.printStackTrace(); + return false; + } + return true; + } + + /** + * Internal helper class to copy the contents of an OutputStream + * into a ByteBuffer. This avoids a copy. + * + */ + private static class ByteBufferOutputStream extends OutputStream { + + private final ByteBuffer buffer; + + public ByteBufferOutputStream(ByteBuffer buffer) { + this.buffer = buffer; + } + + @Override + public void write(int b) throws IOException + { + buffer.put((byte) b); + } + + @Override + public void write(byte b[], int off, int len) throws IOException { + buffer.put(b, off, len); + } + } +} + diff --git a/port/jassimp/jassimp/src/jassimp/AiMesh.java b/port/jassimp/jassimp/src/jassimp/AiMesh.java index c2ebcd307..b6a478d18 100644 --- a/port/jassimp/jassimp/src/jassimp/AiMesh.java +++ b/port/jassimp/jassimp/src/jassimp/AiMesh.java @@ -140,17 +140,17 @@ public final class AiMesh { /** * Number of bytes per float value. */ - private static final int SIZEOF_FLOAT = Jassimp.NATIVE_FLOAT_SIZE; + private final int SIZEOF_FLOAT = Jassimp.NATIVE_FLOAT_SIZE; /** * Number of bytes per int value. */ - private static final int SIZEOF_INT = Jassimp.NATIVE_INT_SIZE; + private final int SIZEOF_INT = Jassimp.NATIVE_INT_SIZE; /** * Size of an AiVector3D in the native world. */ - private static final int SIZEOF_V3D = Jassimp.NATIVE_AIVEKTOR3D_SIZE; + private final int SIZEOF_V3D = Jassimp.NATIVE_AIVEKTOR3D_SIZE; /** diff --git a/port/jassimp/jassimp/src/jassimp/AiMetadataEntry.java b/port/jassimp/jassimp/src/jassimp/AiMetadataEntry.java new file mode 100644 index 000000000..dbdf1aae8 --- /dev/null +++ b/port/jassimp/jassimp/src/jassimp/AiMetadataEntry.java @@ -0,0 +1,118 @@ +package jassimp; +/* +--------------------------------------------------------------------------- +Open Asset Import Library - Java Binding (jassimp) +--------------------------------------------------------------------------- + +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. +--------------------------------------------------------------------------- +*/ +public class AiMetadataEntry +{ + public enum AiMetadataType + { + AI_BOOL, AI_INT32, AI_UINT64, AI_FLOAT, AI_DOUBLE, AI_AISTRING, AI_AIVECTOR3D + } + + private AiMetadataType mType; + private Object mData; + + public AiMetadataType getMetaDataType() + { + return mType; + } + + public Object getData() + { + return mData; + } + + public static boolean getAiBoolAsBoolean(AiMetadataEntry metadataEntry) + { + checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_BOOL); + + return (boolean) metadataEntry.mData; + } + + public static int getAiInt32AsInteger(AiMetadataEntry metadataEntry) + { + checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_INT32); + + return (int) metadataEntry.mData; + } + + public static long getAiUint64AsLong(AiMetadataEntry metadataEntry) + { + checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_UINT64); + + return (long) metadataEntry.mData; + } + + public static float getAiFloatAsFloat(AiMetadataEntry metadataEntry) + { + checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_FLOAT); + + return (float) metadataEntry.mData; + } + + public static double getAiDoubleAsDouble(AiMetadataEntry metadataEntry) + { + checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_DOUBLE); + + return (double) metadataEntry.mData; + } + + public static String getAiStringAsString(AiMetadataEntry metadataEntry) + { + checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_AISTRING); + + return (String) metadataEntry.mData; + } + + public static AiVector getAiAiVector3DAsAiVector(AiMetadataEntry metadataEntry) + { + checkTypeBeforeCasting(metadataEntry, AiMetadataType.AI_AIVECTOR3D); + + return (AiVector) metadataEntry.mData; + } + + private static void checkTypeBeforeCasting(AiMetadataEntry entry, AiMetadataType expectedType) + { + if(entry.mType != expectedType) + { + throw new RuntimeException("Cannot cast entry of type " + entry.mType.name() + " to " + expectedType.name()); + } + } +} diff --git a/port/jassimp/jassimp/src/jassimp/AiNode.java b/port/jassimp/jassimp/src/jassimp/AiNode.java index 5cd26b668..9345b7af4 100644 --- a/port/jassimp/jassimp/src/jassimp/AiNode.java +++ b/port/jassimp/jassimp/src/jassimp/AiNode.java @@ -41,7 +41,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package jassimp; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** @@ -185,6 +187,18 @@ public final class AiNode { public int[] getMeshes() { return m_meshReferences; } + + /** + * Returns the metadata entries for this node.

+ * + * Consult the original Doxygen for importer_notes to + * see which formats have metadata and what to expect. + * + * @return A map of metadata names to entries. + */ + public Map getMetadata() { + return m_metaData; + } /** @@ -219,6 +233,11 @@ public final class AiNode { * List of children. */ private final List m_children = new ArrayList(); + + /** + * List of metadata entries. + */ + private final Map m_metaData = new HashMap(); /** diff --git a/port/jassimp/jassimp/src/jassimp/AiNodeAnim.java b/port/jassimp/jassimp/src/jassimp/AiNodeAnim.java index cb1c6987c..fb317a5b1 100644 --- a/port/jassimp/jassimp/src/jassimp/AiNodeAnim.java +++ b/port/jassimp/jassimp/src/jassimp/AiNodeAnim.java @@ -70,17 +70,17 @@ public final class AiNodeAnim { /** * Size of one position key entry. */ - private static final int POS_KEY_SIZE = Jassimp.NATIVE_AIVEKTORKEY_SIZE; + private final int POS_KEY_SIZE = Jassimp.NATIVE_AIVEKTORKEY_SIZE; /** * Size of one rotation key entry. */ - private static final int ROT_KEY_SIZE = Jassimp.NATIVE_AIQUATKEY_SIZE; + private final int ROT_KEY_SIZE = Jassimp.NATIVE_AIQUATKEY_SIZE; /** * Size of one scaling key entry. */ - private static final int SCALE_KEY_SIZE = Jassimp.NATIVE_AIVEKTORKEY_SIZE; + private final int SCALE_KEY_SIZE = Jassimp.NATIVE_AIVEKTORKEY_SIZE; /** diff --git a/port/jassimp/jassimp/src/jassimp/Jassimp.java b/port/jassimp/jassimp/src/jassimp/Jassimp.java index eb4665f17..d1b4aae4e 100644 --- a/port/jassimp/jassimp/src/jassimp/Jassimp.java +++ b/port/jassimp/jassimp/src/jassimp/Jassimp.java @@ -59,7 +59,7 @@ import java.util.Set; * Pointer comparison will fail. */ public final class Jassimp { - + /** * The default wrapper provider using built in types. */ @@ -79,6 +79,20 @@ public final class Jassimp { return importFile(filename, EnumSet.noneOf(AiPostProcessSteps.class)); } + /** + * Imports a file via assimp without post processing. + * + * @param filename the file to import + * @param ioSystem ioSystem to load files, or null for default + * @return the loaded scene + * @throws IOException if an error occurs + */ + public static AiScene importFile(String filename, AiIOSystem ioSystem) + throws IOException { + + return importFile(filename, EnumSet.noneOf(AiPostProcessSteps.class), ioSystem); + } + /** * Imports a file via assimp. @@ -89,10 +103,28 @@ public final class Jassimp { * @throws IOException if an error occurs */ public static AiScene importFile(String filename, - Set postProcessing) throws IOException { + Set postProcessing) + throws IOException { + return importFile(filename, postProcessing, null); + } + + /** + * Imports a file via assimp. + * + * @param filename the file to import + * @param postProcessing post processing flags + * @param ioSystem ioSystem to load files, or null for default + * @return the loaded scene, or null if an error occurred + * @throws IOException if an error occurs + */ + public static AiScene importFile(String filename, + Set postProcessing, AiIOSystem ioSystem) + throws IOException { + loadLibrary(); + return aiImportFile(filename, AiPostProcessSteps.toRawValue( - postProcessing)); + postProcessing), ioSystem); } @@ -177,6 +209,11 @@ public final class Jassimp { } + public static void setLibraryLoader(JassimpLibraryLoader libraryLoader) { + s_libraryLoader = libraryLoader; + } + + /** * Helper method for wrapping a matrix.

* @@ -264,6 +301,35 @@ public final class Jassimp { return s_wrapperProvider.wrapSceneNode(parent, matrix, meshRefs, name); } + /** + * Helper method to load the library using the provided JassimpLibraryLoader.

+ * + * Synchronized to avoid race conditions. + */ + private static void loadLibrary() + { + if(!s_libraryLoaded) + { + synchronized(s_libraryLoadingLock) + { + if(!s_libraryLoaded) + { + s_libraryLoader.loadLibrary(); + NATIVE_AIVEKTORKEY_SIZE = getVKeysize(); + NATIVE_AIQUATKEY_SIZE = getQKeysize(); + NATIVE_AIVEKTOR3D_SIZE = getV3Dsize(); + NATIVE_FLOAT_SIZE = getfloatsize(); + NATIVE_INT_SIZE = getintsize(); + NATIVE_UINT_SIZE = getuintsize(); + NATIVE_DOUBLE_SIZE = getdoublesize(); + NATIVE_LONG_SIZE = getlongsize(); + + s_libraryLoaded = true; + } + } + + } + } /** * The native interface. @@ -274,7 +340,7 @@ public final class Jassimp { * @throws IOException if an error occurs */ private static native AiScene aiImportFile(String filename, - long postProcessing) throws IOException; + long postProcessing, AiIOSystem ioSystem) throws IOException; /** @@ -284,6 +350,25 @@ public final class Jassimp { new AiBuiltInWrapperProvider(); + /** + * The library loader to load the native library. + */ + private static JassimpLibraryLoader s_libraryLoader = + new JassimpLibraryLoader(); + + /** + * Status flag if the library is loaded. + * + * Volatile to avoid problems with double checked locking. + * + */ + private static volatile boolean s_libraryLoaded = false; + + /** + * Lock for library loading. + */ + private static final Object s_libraryLoadingLock = new Object(); + /** * Pure static class, no accessible constructor. */ @@ -291,24 +376,13 @@ public final class Jassimp { /* nothing to do */ } - public static final int NATIVE_AIVEKTORKEY_SIZE; - public static final int NATIVE_AIQUATKEY_SIZE; - public static final int NATIVE_AIVEKTOR3D_SIZE; - public static final int NATIVE_FLOAT_SIZE; - public static final int NATIVE_INT_SIZE; - public static final int NATIVE_UINT_SIZE; - public static final int NATIVE_DOUBLE_SIZE; - public static final int NATIVE_LONG_SIZE; + public static int NATIVE_AIVEKTORKEY_SIZE; + public static int NATIVE_AIQUATKEY_SIZE; + public static int NATIVE_AIVEKTOR3D_SIZE; + public static int NATIVE_FLOAT_SIZE; + public static int NATIVE_INT_SIZE; + public static int NATIVE_UINT_SIZE; + public static int NATIVE_DOUBLE_SIZE; + public static int NATIVE_LONG_SIZE; - static { - System.loadLibrary("jassimp"); - NATIVE_AIVEKTORKEY_SIZE = getVKeysize(); - NATIVE_AIQUATKEY_SIZE = getQKeysize(); - NATIVE_AIVEKTOR3D_SIZE = getV3Dsize(); - NATIVE_FLOAT_SIZE = getfloatsize(); - NATIVE_INT_SIZE = getintsize(); - NATIVE_UINT_SIZE = getuintsize(); - NATIVE_DOUBLE_SIZE = getdoublesize(); - NATIVE_LONG_SIZE = getlongsize(); - } } diff --git a/port/jassimp/jassimp/src/jassimp/JassimpLibraryLoader.java b/port/jassimp/jassimp/src/jassimp/JassimpLibraryLoader.java new file mode 100644 index 000000000..c299706b7 --- /dev/null +++ b/port/jassimp/jassimp/src/jassimp/JassimpLibraryLoader.java @@ -0,0 +1,65 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library - Java Binding (jassimp) +--------------------------------------------------------------------------- + +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. +--------------------------------------------------------------------------- +*/ +package jassimp; + +/** + * Library loader for the jassimp library.

+ * + * The default implementation uses "System.loadLibrary" to + * load the jassimp native library.

+ * + * Custom implementations should override the loadLibrary() + * function. + * + */ +public class JassimpLibraryLoader +{ + /** + * Function to load the native jassimp library. + * + * Called the first time Jassimp.importFile() is + * called. + */ + public void loadLibrary() + { + System.loadLibrary("jassimp"); + } +} diff --git a/port/swig/assimp.i b/port/swig/assimp.i index d1a078d49..58e1546e7 100644 --- a/port/swig/assimp.i +++ b/port/swig/assimp.i @@ -114,7 +114,7 @@ %include "interface/IOSystem.i" -// We have to "instanciate" the templates used by the ASSSIMP_*_ARRAY macros +// We have to "instantiate" the templates used by the ASSSIMP_*_ARRAY macros // here at the end to avoid running into forward reference issues (SWIG would // spit out the helper functions before the header includes for the element // types otherwise). diff --git a/samples/SimpleAssimpViewX/MyDocument.mm b/samples/SimpleAssimpViewX/MyDocument.mm index be688a6be..cbe034842 100644 --- a/samples/SimpleAssimpViewX/MyDocument.mm +++ b/samples/SimpleAssimpViewX/MyDocument.mm @@ -641,7 +641,7 @@ static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink,const CVTimeS { for(MeshHelper* helper in modelMeshes) { - // Set up meterial state. + // Set up material state. glCallList(helper.displayList); } } diff --git a/samples/SimpleOpenGL/CMakeLists.txt b/samples/SimpleOpenGL/CMakeLists.txt index 52c994b63..455cbd8ca 100644 --- a/samples/SimpleOpenGL/CMakeLists.txt +++ b/samples/SimpleOpenGL/CMakeLists.txt @@ -16,6 +16,11 @@ IF ( NOT GLUT_FOUND ) ENDIF ( MSVC ) ENDIF ( NOT GLUT_FOUND ) +if ( MSVC ) + ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS ) + ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS ) +endif ( MSVC ) + INCLUDE_DIRECTORIES( ${Assimp_SOURCE_DIR}/include ${Assimp_SOURCE_DIR}/code diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11.sln b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11.sln new file mode 100644 index 000000000..46b37e5ee --- /dev/null +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.9 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SimpleTexturedDirectx11", "SimpleTexturedDirectx11\SimpleTexturedDirectx11.vcxproj", "{E3B160B5-E71F-4F3F-9310-B8F156F736D8}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x64.ActiveCfg = Debug|x64 + {E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x64.Build.0 = Debug|x64 + {E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x86.ActiveCfg = Debug|Win32 + {E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Debug|x86.Build.0 = Debug|Win32 + {E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x64.ActiveCfg = Release|x64 + {E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x64.Build.0 = Release|x64 + {E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x86.ActiveCfg = Release|Win32 + {E3B160B5-E71F-4F3F-9310-B8F156F736D8}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h new file mode 100644 index 000000000..87433219f --- /dev/null +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h @@ -0,0 +1,102 @@ +#ifndef MESH_H +#define MESH_H + +#include +#include +#include +#include +#include +using namespace std; + +#include +#include +#include +using namespace DirectX; + +struct VERTEX { + FLOAT X, Y, Z; + XMFLOAT2 texcoord; +}; + +struct Texture { + string type; + string path; + ID3D11ShaderResourceView *texture; +}; + +class Mesh { +public: + vector vertices; + vector indices; + vector textures; + ID3D11Device *dev; + + Mesh(ID3D11Device *dev, vector vertices, vector indices, vector textures) + { + this->vertices = vertices; + this->indices = indices; + this->textures = textures; + + this->dev = dev; + + this->setupMesh(dev); + } + + void Draw(ID3D11DeviceContext *devcon) + { + UINT stride = sizeof(VERTEX); + UINT offset = 0; + + devcon->IASetVertexBuffers(0, 1, &VertexBuffer, &stride, &offset); + devcon->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0); + + devcon->PSSetShaderResources(0, 1, &textures[0].texture); + + devcon->DrawIndexed(indices.size(), 0, 0); + } + + void Close() + { + VertexBuffer->Release(); + IndexBuffer->Release(); + } +private: + /* Render data */ + ID3D11Buffer *VertexBuffer, *IndexBuffer; + + /* Functions */ + // Initializes all the buffer objects/arrays + bool setupMesh(ID3D11Device *dev) + { + HRESULT hr; + + D3D11_BUFFER_DESC vbd; + vbd.Usage = D3D11_USAGE_IMMUTABLE; + vbd.ByteWidth = sizeof(VERTEX) * vertices.size(); + vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbd.CPUAccessFlags = 0; + vbd.MiscFlags = 0; + + D3D11_SUBRESOURCE_DATA initData; + initData.pSysMem = &vertices[0]; + + hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer); + if (FAILED(hr)) + return false; + + D3D11_BUFFER_DESC ibd; + ibd.Usage = D3D11_USAGE_IMMUTABLE; + ibd.ByteWidth = sizeof(UINT) * indices.size(); + ibd.BindFlags = D3D11_BIND_INDEX_BUFFER; + ibd.CPUAccessFlags = 0; + ibd.MiscFlags = 0; + + initData.pSysMem = &indices[0]; + + hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer); + if (FAILED(hr)) + return false; + } +}; + +#endif diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp new file mode 100644 index 000000000..a2d3faeb3 --- /dev/null +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp @@ -0,0 +1,205 @@ +#include "ModelLoader.h" + +ModelLoader::ModelLoader() +{ +} + + +ModelLoader::~ModelLoader() +{ +} + +bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devcon, std::string filename) +{ + Assimp::Importer importer; + + const aiScene* pScene = importer.ReadFile(filename, + aiProcess_Triangulate | + aiProcess_ConvertToLeftHanded); + + if (pScene == NULL) + return false; + + this->directory = filename.substr(0, filename.find_last_of('/')); + + this->dev = dev; + this->hwnd = hwnd; + + processNode(pScene->mRootNode, pScene); + + return true; +} + +void ModelLoader::Draw(ID3D11DeviceContext * devcon) +{ + for (int i = 0; i < meshes.size(); i++) + { + meshes[i].Draw(devcon); + } +} + +string textype; + +Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) +{ + // Data to fill + vector vertices; + vector indices; + vector textures; + + if (mesh->mMaterialIndex >= 0) + { + aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex]; + + if (textype.empty()) textype = determineTextureType(scene, mat); + } + + // Walk through each of the mesh's vertices + for (UINT i = 0; i < mesh->mNumVertices; i++) + { + VERTEX vertex; + + vertex.X = mesh->mVertices[i].x; + vertex.Y = mesh->mVertices[i].y; + vertex.Z = mesh->mVertices[i].z; + + if (mesh->mTextureCoords[0]) + { + vertex.texcoord.x = (float)mesh->mTextureCoords[0][i].x; + vertex.texcoord.y = (float)mesh->mTextureCoords[0][i].y; + } + + vertices.push_back(vertex); + } + + for (UINT i = 0; i < mesh->mNumFaces; i++) + { + aiFace face = mesh->mFaces[i]; + + for (UINT j = 0; j < face.mNumIndices; j++) + indices.push_back(face.mIndices[j]); + } + + if (mesh->mMaterialIndex >= 0) + { + aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; + + vector diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse", scene); + textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end()); + } + + return Mesh(dev, vertices, indices, textures); +} + +vector ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, string typeName, const aiScene * scene) +{ + vector textures; + for (UINT i = 0; i < mat->GetTextureCount(type); i++) + { + aiString str; + mat->GetTexture(type, i, &str); + // Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture + bool skip = false; + for (UINT j = 0; j < textures_loaded.size(); j++) + { + if (std::strcmp(textures_loaded[j].path.c_str(), str.C_Str()) == 0) + { + textures.push_back(textures_loaded[j]); + skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization) + break; + } + } + if (!skip) + { // If texture hasn't been loaded already, load it + HRESULT hr; + Texture texture; + if (textype == "embedded compressed texture") + { + int textureindex = getTextureIndex(&str); + texture.texture = getTextureFromModel(scene, textureindex); + } + else + { + string filename = string(str.C_Str()); + filename = directory + '/' + filename; + wstring filenamews = wstring(filename.begin(), filename.end()); + hr = CreateWICTextureFromFile(dev, devcon, filenamews.c_str(), nullptr, &texture.texture); + if (FAILED(hr)) + MessageBox(hwnd, "Texture couldn't be loaded", "Error!", MB_ICONERROR | MB_OK); + } + texture.type = typeName; + texture.path = str.C_Str(); + textures.push_back(texture); + this->textures_loaded.push_back(texture); // Store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures. + } + } + return textures; +} + +void ModelLoader::Close() +{ + for (int i = 0; i < meshes.size(); i++) + { + meshes[i].Close(); + } + + dev->Release(); +} + +void ModelLoader::processNode(aiNode * node, const aiScene * scene) +{ + for (UINT i = 0; i < node->mNumMeshes; i++) + { + aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; + meshes.push_back(this->processMesh(mesh, scene)); + } + + for (UINT i = 0; i < node->mNumChildren; i++) + { + this->processNode(node->mChildren[i], scene); + } +} + +string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat) +{ + aiString textypeStr; + mat->GetTexture(aiTextureType_DIFFUSE, 0, &textypeStr); + string textypeteststr = textypeStr.C_Str(); + if (textypeteststr == "*0" || textypeteststr == "*1" || textypeteststr == "*2" || textypeteststr == "*3" || textypeteststr == "*4" || textypeteststr == "*5") + { + if (scene->mTextures[0]->mHeight == 0) + { + return "embedded compressed texture"; + } + else + { + return "embedded non-compressed texture"; + } + } + if (textypeteststr.find('.') != string::npos) + { + return "textures are on disk"; + } +} + +int ModelLoader::getTextureIndex(aiString * str) +{ + string tistr; + tistr = str->C_Str(); + tistr = tistr.substr(1); + return stoi(tistr); +} + +ID3D11ShaderResourceView * ModelLoader::getTextureFromModel(const aiScene * scene, int textureindex) +{ + HRESULT hr; + ID3D11ShaderResourceView *texture; + + int* size = reinterpret_cast(&scene->mTextures[textureindex]->mWidth); + + hr = CreateWICTextureFromMemory(dev, devcon, reinterpret_cast(scene->mTextures[textureindex]->pcData), *size, nullptr, &texture); + if (FAILED(hr)) + MessageBox(hwnd, "Texture couldn't be created from memory!", "Error!", MB_ICONERROR | MB_OK); + + return texture; +} diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.h b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.h new file mode 100644 index 000000000..9b4a53c27 --- /dev/null +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.h @@ -0,0 +1,44 @@ +#ifndef MODEL_LOADER_H +#define MODEL_LOADER_H + +#include +#include +#include + +#include +#include +#include + +#include "Mesh.h" +#include "TextureLoader.h" + +using namespace DirectX; + +class ModelLoader +{ +public: + ModelLoader(); + ~ModelLoader(); + + bool Load(HWND hwnd, ID3D11Device* dev, ID3D11DeviceContext* devcon, std::string filename); + void Draw(ID3D11DeviceContext* devcon); + + void Close(); +private: + ID3D11Device *dev; + ID3D11DeviceContext *devcon; + std::vector meshes; + string directory; + vector textures_loaded; + HWND hwnd; + + void processNode(aiNode* node, const aiScene* scene); + Mesh processMesh(aiMesh* mesh, const aiScene* scene); + vector loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName, const aiScene* scene); + string determineTextureType(const aiScene* scene, aiMaterial* mat); + int getTextureIndex(aiString* str); + ID3D11ShaderResourceView* getTextureFromModel(const aiScene* scene, int textureindex); +}; + +#endif // !MODEL_LOADER_H + diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/PixelShader.hlsl b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/PixelShader.hlsl new file mode 100644 index 000000000..2e8b4eeda --- /dev/null +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/PixelShader.hlsl @@ -0,0 +1,9 @@ +Texture2D diffTexture; +SamplerState SampleType; + +float4 main(float4 pos : SV_POSITION, float2 texcoord : TEXCOORD) : SV_TARGET +{ + float4 textureColor = diffTexture.Sample(SampleType, texcoord); + + return textureColor; +} \ No newline at end of file diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SimpleTexturedDirectx11.vcxproj b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SimpleTexturedDirectx11.vcxproj new file mode 100644 index 000000000..fc82bc18e --- /dev/null +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SimpleTexturedDirectx11.vcxproj @@ -0,0 +1,146 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {E3B160B5-E71F-4F3F-9310-B8F156F736D8} + SimpleTexturedDirectx11 + 10.0.14393.0 + + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + $(IncludePath);E:\OpenGL VS Files\include + $(LibraryPath);E:\OpenGL VS Files\lib + + + + Level3 + Disabled + true + + + assimp-vc140-mt.lib;%(AdditionalDependencies) + + + + + Level3 + Disabled + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + + + true + true + + + + + + + + + + Pixel + Pixel + Pixel + Pixel + + + Vertex + Vertex + Vertex + Vertex + + + + + + + + + + + \ No newline at end of file diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SimpleTexturedDirectx11.vcxproj.filters b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SimpleTexturedDirectx11.vcxproj.filters new file mode 100644 index 000000000..271300ad8 --- /dev/null +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SimpleTexturedDirectx11.vcxproj.filters @@ -0,0 +1,50 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {b6a86d3e-70a5-4d1e-ba05-c20902300206} + + + + + Source Files + + + Source Files + + + Source Files + + + + + Shaders + + + Shaders + + + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.cpp b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.cpp new file mode 100644 index 000000000..c3269d290 --- /dev/null +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.cpp @@ -0,0 +1,691 @@ +//-------------------------------------------------------------------------------------- +// File: WICTextureLoader.cpp +// +// Function for loading a WIC image and creating a Direct3D 11 runtime texture for it +// (auto-generating mipmaps if possible) +// +// Note: Assumes application has already called CoInitializeEx +// +// Warning: CreateWICTexture* functions are not thread-safe if given a d3dContext instance for +// auto-gen mipmap support. +// +// Note these functions are useful for images created as simple 2D textures. For +// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader. +// For a full-featured DDS file reader, writer, and texture processing pipeline see +// the 'Texconv' sample and the 'DirectXTex' library. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +// We could load multi-frame images (TIFF/GIF) into a texture array. +// For now, we just load the first frame (note: DirectXTex supports multi-frame images) + +#include +#include + +#pragma warning(push) +#pragma warning(disable : 4005) +#include +#pragma warning(pop) + +#include + +#include "TextureLoader.h" + +#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) && !defined(DXGI_1_2_FORMATS) +#define DXGI_1_2_FORMATS +#endif + +//--------------------------------------------------------------------------------- +template class ScopedObject +{ +public: + explicit ScopedObject(T *p = 0) : _pointer(p) {} + ~ScopedObject() + { + if (_pointer) + { + _pointer->Release(); + _pointer = nullptr; + } + } + + bool IsNull() const { return (!_pointer); } + + T& operator*() { return *_pointer; } + T* operator->() { return _pointer; } + T** operator&() { return &_pointer; } + + void Reset(T *p = 0) { if (_pointer) { _pointer->Release(); } _pointer = p; } + + T* Get() const { return _pointer; } + +private: + ScopedObject(const ScopedObject&); + ScopedObject& operator=(const ScopedObject&); + + T* _pointer; +}; + +//------------------------------------------------------------------------------------- +// WIC Pixel Format Translation Data +//------------------------------------------------------------------------------------- +struct WICTranslate +{ + GUID wic; + DXGI_FORMAT format; +}; + +static WICTranslate g_WICFormats[] = +{ + { GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT }, + + { GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT }, + { GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM }, + + { GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM }, + { GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM }, // DXGI 1.1 + { GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM }, // DXGI 1.1 + + { GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM }, // DXGI 1.1 + { GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM }, + { GUID_WICPixelFormat32bppRGBE, DXGI_FORMAT_R9G9B9E5_SHAREDEXP }, + +#ifdef DXGI_1_2_FORMATS + + { GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM }, + { GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM }, + +#endif // DXGI_1_2_FORMATS + + { GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT }, + { GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT }, + { GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM }, + { GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM }, + + { GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM }, + +#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) + { GUID_WICPixelFormat96bppRGBFloat, DXGI_FORMAT_R32G32B32_FLOAT }, +#endif +}; + +//------------------------------------------------------------------------------------- +// WIC Pixel Format nearest conversion table +//------------------------------------------------------------------------------------- + +struct WICConvert +{ + GUID source; + GUID target; +}; + +static WICConvert g_WICConvert[] = +{ + // Note target GUID in this conversion table must be one of those directly supported formats (above). + + { GUID_WICPixelFormatBlackWhite, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM + + { GUID_WICPixelFormat1bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat2bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat4bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat8bppIndexed, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + + { GUID_WICPixelFormat2bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM + { GUID_WICPixelFormat4bppGray, GUID_WICPixelFormat8bppGray }, // DXGI_FORMAT_R8_UNORM + + { GUID_WICPixelFormat16bppGrayFixedPoint, GUID_WICPixelFormat16bppGrayHalf }, // DXGI_FORMAT_R16_FLOAT + { GUID_WICPixelFormat32bppGrayFixedPoint, GUID_WICPixelFormat32bppGrayFloat }, // DXGI_FORMAT_R32_FLOAT + +#ifdef DXGI_1_2_FORMATS + + { GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat16bppBGRA5551 }, // DXGI_FORMAT_B5G5R5A1_UNORM + +#else + + { GUID_WICPixelFormat16bppBGR555, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat16bppBGRA5551, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat16bppBGR565, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + +#endif // DXGI_1_2_FORMATS + + { GUID_WICPixelFormat32bppBGR101010, GUID_WICPixelFormat32bppRGBA1010102 }, // DXGI_FORMAT_R10G10B10A2_UNORM + + { GUID_WICPixelFormat24bppBGR, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat24bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat32bppPBGRA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat32bppPRGBA, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + + { GUID_WICPixelFormat48bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat48bppBGR, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppPRGBA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppPBGRA, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + + { GUID_WICPixelFormat48bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat48bppBGRFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppRGBAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppBGRAFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppRGBFixedPoint, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat64bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + { GUID_WICPixelFormat48bppRGBHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT + + { GUID_WICPixelFormat96bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppPRGBAFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppRGBFloat, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppRGBAFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + { GUID_WICPixelFormat128bppRGBFixedPoint, GUID_WICPixelFormat128bppRGBAFloat }, // DXGI_FORMAT_R32G32B32A32_FLOAT + + { GUID_WICPixelFormat32bppCMYK, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat64bppCMYK, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat40bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat80bppCMYKAlpha, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + +#if (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) + { GUID_WICPixelFormat32bppRGB, GUID_WICPixelFormat32bppRGBA }, // DXGI_FORMAT_R8G8B8A8_UNORM + { GUID_WICPixelFormat64bppRGB, GUID_WICPixelFormat64bppRGBA }, // DXGI_FORMAT_R16G16B16A16_UNORM + { GUID_WICPixelFormat64bppPRGBAHalf, GUID_WICPixelFormat64bppRGBAHalf }, // DXGI_FORMAT_R16G16B16A16_FLOAT +#endif + + // We don't support n-channel formats +}; + +//-------------------------------------------------------------------------------------- +static IWICImagingFactory* _GetWIC() +{ + static IWICImagingFactory* s_Factory = nullptr; + + if (s_Factory) + return s_Factory; + + HRESULT hr = CoCreateInstance( + CLSID_WICImagingFactory, + nullptr, + CLSCTX_INPROC_SERVER, + __uuidof(IWICImagingFactory), + (LPVOID*)&s_Factory + ); + + if (FAILED(hr)) + { + s_Factory = nullptr; + return nullptr; + } + + return s_Factory; +} + +//--------------------------------------------------------------------------------- +static DXGI_FORMAT _WICToDXGI(const GUID& guid) +{ + for (size_t i = 0; i < _countof(g_WICFormats); ++i) + { + if (memcmp(&g_WICFormats[i].wic, &guid, sizeof(GUID)) == 0) + return g_WICFormats[i].format; + } + + return DXGI_FORMAT_UNKNOWN; +} + +//--------------------------------------------------------------------------------- +static size_t _WICBitsPerPixel(REFGUID targetGuid) +{ + IWICImagingFactory* pWIC = _GetWIC(); + if (!pWIC) + return 0; + + ScopedObject cinfo; + if (FAILED(pWIC->CreateComponentInfo(targetGuid, &cinfo))) + return 0; + + WICComponentType type; + if (FAILED(cinfo->GetComponentType(&type))) + return 0; + + if (type != WICPixelFormat) + return 0; + + ScopedObject pfinfo; + if (FAILED(cinfo->QueryInterface(__uuidof(IWICPixelFormatInfo), reinterpret_cast(&pfinfo)))) + return 0; + + UINT bpp; + if (FAILED(pfinfo->GetBitsPerPixel(&bpp))) + return 0; + + return bpp; +} + +//--------------------------------------------------------------------------------- +static HRESULT CreateTextureFromWIC(_In_ ID3D11Device* d3dDevice, + _In_opt_ ID3D11DeviceContext* d3dContext, + _In_ IWICBitmapFrameDecode *frame, + _Out_opt_ ID3D11Resource** texture, + _Out_opt_ ID3D11ShaderResourceView** textureView, + _In_ size_t maxsize) +{ + UINT width, height; + HRESULT hr = frame->GetSize(&width, &height); + if (FAILED(hr)) + return hr; + + assert(width > 0 && height > 0); + + if (!maxsize) + { + // This is a bit conservative because the hardware could support larger textures than + // the Feature Level defined minimums, but doing it this way is much easier and more + // performant for WIC than the 'fail and retry' model used by DDSTextureLoader + + switch (d3dDevice->GetFeatureLevel()) + { + case D3D_FEATURE_LEVEL_9_1: + case D3D_FEATURE_LEVEL_9_2: + maxsize = 2048 /*D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; + break; + + case D3D_FEATURE_LEVEL_9_3: + maxsize = 4096 /*D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; + break; + + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_10_1: + maxsize = 8192 /*D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION*/; + break; + + default: + maxsize = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; + break; + } + } + + assert(maxsize > 0); + + UINT twidth, theight; + if (width > maxsize || height > maxsize) + { + float ar = static_cast(height) / static_cast(width); + if (width > height) + { + twidth = static_cast(maxsize); + theight = static_cast(static_cast(maxsize) * ar); + } + else + { + theight = static_cast(maxsize); + twidth = static_cast(static_cast(maxsize) / ar); + } + assert(twidth <= maxsize && theight <= maxsize); + } + else + { + twidth = width; + theight = height; + } + + // Determine format + WICPixelFormatGUID pixelFormat; + hr = frame->GetPixelFormat(&pixelFormat); + if (FAILED(hr)) + return hr; + + WICPixelFormatGUID convertGUID; + memcpy(&convertGUID, &pixelFormat, sizeof(WICPixelFormatGUID)); + + size_t bpp = 0; + + DXGI_FORMAT format = _WICToDXGI(pixelFormat); + if (format == DXGI_FORMAT_UNKNOWN) + { + for (size_t i = 0; i < _countof(g_WICConvert); ++i) + { + if (memcmp(&g_WICConvert[i].source, &pixelFormat, sizeof(WICPixelFormatGUID)) == 0) + { + memcpy(&convertGUID, &g_WICConvert[i].target, sizeof(WICPixelFormatGUID)); + + format = _WICToDXGI(g_WICConvert[i].target); + assert(format != DXGI_FORMAT_UNKNOWN); + bpp = _WICBitsPerPixel(convertGUID); + break; + } + } + + if (format == DXGI_FORMAT_UNKNOWN) + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + else + { + bpp = _WICBitsPerPixel(pixelFormat); + } + + if (!bpp) + return E_FAIL; + + // Verify our target format is supported by the current device + // (handles WDDM 1.0 or WDDM 1.1 device driver cases as well as DirectX 11.0 Runtime without 16bpp format support) + UINT support = 0; + hr = d3dDevice->CheckFormatSupport(format, &support); + if (FAILED(hr) || !(support & D3D11_FORMAT_SUPPORT_TEXTURE2D)) + { + // Fallback to RGBA 32-bit format which is supported by all devices + memcpy(&convertGUID, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID)); + format = DXGI_FORMAT_R8G8B8A8_UNORM; + bpp = 32; + } + + // Allocate temporary memory for image + size_t rowPitch = (twidth * bpp + 7) / 8; + size_t imageSize = rowPitch * theight; + + std::unique_ptr temp(new uint8_t[imageSize]); + + // Load image data + if (memcmp(&convertGUID, &pixelFormat, sizeof(GUID)) == 0 + && twidth == width + && theight == height) + { + // No format conversion or resize needed + hr = frame->CopyPixels(0, static_cast(rowPitch), static_cast(imageSize), temp.get()); + if (FAILED(hr)) + return hr; + } + else if (twidth != width || theight != height) + { + // Resize + IWICImagingFactory* pWIC = _GetWIC(); + if (!pWIC) + return E_NOINTERFACE; + + ScopedObject scaler; + hr = pWIC->CreateBitmapScaler(&scaler); + if (FAILED(hr)) + return hr; + + hr = scaler->Initialize(frame, twidth, theight, WICBitmapInterpolationModeFant); + if (FAILED(hr)) + return hr; + + WICPixelFormatGUID pfScaler; + hr = scaler->GetPixelFormat(&pfScaler); + if (FAILED(hr)) + return hr; + + if (memcmp(&convertGUID, &pfScaler, sizeof(GUID)) == 0) + { + // No format conversion needed + hr = scaler->CopyPixels(0, static_cast(rowPitch), static_cast(imageSize), temp.get()); + if (FAILED(hr)) + return hr; + } + else + { + ScopedObject FC; + hr = pWIC->CreateFormatConverter(&FC); + if (FAILED(hr)) + return hr; + + hr = FC->Initialize(scaler.Get(), convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom); + if (FAILED(hr)) + return hr; + + hr = FC->CopyPixels(0, static_cast(rowPitch), static_cast(imageSize), temp.get()); + if (FAILED(hr)) + return hr; + } + } + else + { + // Format conversion but no resize + IWICImagingFactory* pWIC = _GetWIC(); + if (!pWIC) + return E_NOINTERFACE; + + ScopedObject FC; + hr = pWIC->CreateFormatConverter(&FC); + if (FAILED(hr)) + return hr; + + hr = FC->Initialize(frame, convertGUID, WICBitmapDitherTypeErrorDiffusion, 0, 0, WICBitmapPaletteTypeCustom); + if (FAILED(hr)) + return hr; + + hr = FC->CopyPixels(0, static_cast(rowPitch), static_cast(imageSize), temp.get()); + if (FAILED(hr)) + return hr; + } + + // See if format is supported for auto-gen mipmaps (varies by feature level) + bool autogen = false; + if (d3dContext != 0 && textureView != 0) // Must have context and shader-view to auto generate mipmaps + { + UINT fmtSupport = 0; + hr = d3dDevice->CheckFormatSupport(format, &fmtSupport); + if (SUCCEEDED(hr) && (fmtSupport & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN)) + { + autogen = true; + } + } + + // Create texture + D3D11_TEXTURE2D_DESC desc; + desc.Width = twidth; + desc.Height = theight; + desc.MipLevels = (autogen) ? 0 : 1; + desc.ArraySize = 1; + desc.Format = format; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = (autogen) ? (D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET) : (D3D11_BIND_SHADER_RESOURCE); + desc.CPUAccessFlags = 0; + desc.MiscFlags = (autogen) ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0; + + D3D11_SUBRESOURCE_DATA initData; + initData.pSysMem = temp.get(); + initData.SysMemPitch = static_cast(rowPitch); + initData.SysMemSlicePitch = static_cast(imageSize); + + ID3D11Texture2D* tex = nullptr; + hr = d3dDevice->CreateTexture2D(&desc, (autogen) ? nullptr : &initData, &tex); + if (SUCCEEDED(hr) && tex != 0) + { + if (textureView != 0) + { + D3D11_SHADER_RESOURCE_VIEW_DESC SRVDesc; + memset(&SRVDesc, 0, sizeof(SRVDesc)); + SRVDesc.Format = format; + SRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + SRVDesc.Texture2D.MipLevels = (autogen) ? -1 : 1; + + hr = d3dDevice->CreateShaderResourceView(tex, &SRVDesc, textureView); + if (FAILED(hr)) + { + tex->Release(); + return hr; + } + + if (autogen) + { + assert(d3dContext != 0); + d3dContext->UpdateSubresource(tex, 0, nullptr, temp.get(), static_cast(rowPitch), static_cast(imageSize)); + d3dContext->GenerateMips(*textureView); + } + } + + if (texture != 0) + { + *texture = tex; + } + else + { +#if defined(_DEBUG) || defined(PROFILE) + tex->SetPrivateData(WKPDID_D3DDebugObjectName, + sizeof("WICTextureLoader") - 1, + "WICTextureLoader" + ); +#endif + tex->Release(); + } + } + + return hr; +} + +//-------------------------------------------------------------------------------------- +HRESULT CreateWICTextureFromMemory(_In_ ID3D11Device* d3dDevice, + _In_opt_ ID3D11DeviceContext* d3dContext, + _In_bytecount_(wicDataSize) const uint8_t* wicData, + _In_ size_t wicDataSize, + _Out_opt_ ID3D11Resource** texture, + _Out_opt_ ID3D11ShaderResourceView** textureView, + _In_ size_t maxsize +) +{ + if (!d3dDevice || !wicData || (!texture && !textureView)) + { + return E_INVALIDARG; + } + + if (!wicDataSize) + { + return E_FAIL; + } + +#ifdef _M_AMD64 + if (wicDataSize > 0xFFFFFFFF) + return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE); +#endif + + IWICImagingFactory* pWIC = _GetWIC(); + if (!pWIC) + return E_NOINTERFACE; + + // Create input stream for memory + ScopedObject stream; + HRESULT hr = pWIC->CreateStream(&stream); + if (FAILED(hr)) + return hr; + + hr = stream->InitializeFromMemory(const_cast(wicData), static_cast(wicDataSize)); + if (FAILED(hr)) + return hr; + + // Initialize WIC + ScopedObject decoder; + hr = pWIC->CreateDecoderFromStream(stream.Get(), 0, WICDecodeMetadataCacheOnDemand, &decoder); + if (FAILED(hr)) + return hr; + + ScopedObject frame; + hr = decoder->GetFrame(0, &frame); + if (FAILED(hr)) + return hr; + + hr = CreateTextureFromWIC(d3dDevice, d3dContext, frame.Get(), texture, textureView, maxsize); + if (FAILED(hr)) + return hr; + +#if defined(_DEBUG) || defined(PROFILE) + if (texture != 0 && *texture != 0) + { + (*texture)->SetPrivateData(WKPDID_D3DDebugObjectName, + sizeof("WICTextureLoader") - 1, + "WICTextureLoader" + ); + } + + if (textureView != 0 && *textureView != 0) + { + (*textureView)->SetPrivateData(WKPDID_D3DDebugObjectName, + sizeof("WICTextureLoader") - 1, + "WICTextureLoader" + ); + } +#endif + + return hr; +} + +//-------------------------------------------------------------------------------------- +HRESULT CreateWICTextureFromFile(_In_ ID3D11Device* d3dDevice, + _In_opt_ ID3D11DeviceContext* d3dContext, + _In_z_ const wchar_t* fileName, + _Out_opt_ ID3D11Resource** texture, + _Out_opt_ ID3D11ShaderResourceView** textureView, + _In_ size_t maxsize) +{ + if (!d3dDevice || !fileName || (!texture && !textureView)) + { + return E_INVALIDARG; + } + + IWICImagingFactory* pWIC = _GetWIC(); + if (!pWIC) + return E_NOINTERFACE; + + // Initialize WIC + ScopedObject decoder; + HRESULT hr = pWIC->CreateDecoderFromFilename(fileName, 0, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder); + if (FAILED(hr)) + return hr; + + ScopedObject frame; + hr = decoder->GetFrame(0, &frame); + if (FAILED(hr)) + return hr; + + hr = CreateTextureFromWIC(d3dDevice, d3dContext, frame.Get(), texture, textureView, maxsize); + if (FAILED(hr)) + return hr; + +#if defined(_DEBUG) || defined(PROFILE) + if (texture != 0 || textureView != 0) + { + CHAR strFileA[MAX_PATH]; + WideCharToMultiByte(CP_ACP, + WC_NO_BEST_FIT_CHARS, + fileName, + -1, + strFileA, + MAX_PATH, + nullptr, + FALSE + ); + const CHAR* pstrName = strrchr(strFileA, '\\'); + if (!pstrName) + { + pstrName = strFileA; + } + else + { + pstrName++; + } + + if (texture != 0 && *texture != 0) + { + (*texture)->SetPrivateData(WKPDID_D3DDebugObjectName, + static_cast(strnlen_s(pstrName, MAX_PATH)), + pstrName + ); + } + + if (textureView != 0 && *textureView != 0) + { + (*textureView)->SetPrivateData(WKPDID_D3DDebugObjectName, + static_cast(strnlen_s(pstrName, MAX_PATH)), + pstrName + ); + } + } +#endif + + return hr; +} diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.h b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.h new file mode 100644 index 000000000..c2e0b5214 --- /dev/null +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/TextureLoader.h @@ -0,0 +1,55 @@ +//-------------------------------------------------------------------------------------- +// File: WICTextureLoader.h +// +// Function for loading a WIC image and creating a Direct3D 11 runtime texture for it +// (auto-generating mipmaps if possible) +// +// Note: Assumes application has already called CoInitializeEx +// +// Warning: CreateWICTexture* functions are not thread-safe if given a d3dContext instance for +// auto-gen mipmap support. +// +// Note these functions are useful for images created as simple 2D textures. For +// more complex resources, DDSTextureLoader is an excellent light-weight runtime loader. +// For a full-featured DDS file reader, writer, and texture processing pipeline see +// the 'Texconv' sample and the 'DirectXTex' library. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +// http://go.microsoft.com/fwlink/?LinkId=248929 +//-------------------------------------------------------------------------------------- + +#ifdef _MSC_VER +#pragma once +#endif + +#include + +#pragma warning(push) +#pragma warning(disable : 4005) +#include +#pragma warning(pop) + +HRESULT CreateWICTextureFromMemory(_In_ ID3D11Device* d3dDevice, + _In_opt_ ID3D11DeviceContext* d3dContext, + _In_bytecount_(wicDataSize) const uint8_t* wicData, + _In_ size_t wicDataSize, + _Out_opt_ ID3D11Resource** texture, + _Out_opt_ ID3D11ShaderResourceView** textureView, + _In_ size_t maxsize = 0 +); + +HRESULT CreateWICTextureFromFile(_In_ ID3D11Device* d3dDevice, + _In_opt_ ID3D11DeviceContext* d3dContext, + _In_z_ const wchar_t* szFileName, + _Out_opt_ ID3D11Resource** texture, + _Out_opt_ ID3D11ShaderResourceView** textureView, + _In_ size_t maxsize = 0 +); + diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/VertexShader.hlsl b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/VertexShader.hlsl new file mode 100644 index 000000000..cf7ee16ac --- /dev/null +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/VertexShader.hlsl @@ -0,0 +1,23 @@ +cbuffer ConstantBuffer : register(b0) +{ + matrix World; + matrix View; + matrix Projection; +} + +struct VOut { + float4 pos : SV_POSITION; + float2 texcoord : TEXCOORD; +}; + +VOut main(float4 pos : POSITION, float2 texcoord : TEXCOORD) +{ + VOut output; + + output.pos = mul(pos, World); + output.pos = mul(output.pos, View); + output.pos = mul(output.pos, Projection); + output.texcoord = texcoord; + + return output; +} \ No newline at end of file diff --git a/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp new file mode 100644 index 000000000..2d847095a --- /dev/null +++ b/samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp @@ -0,0 +1,518 @@ +// --------------------------------------------------------------------------- +// Simple Assimp Directx11 Sample +// This is a very basic sample and only reads diffuse texture +// but this can load both embedded textures in fbx and non-embedded textures +// +// +// Replace ourModel->Load(hwnd, dev, devcon, "Models/myModel.fbx") this with your +// model name (line 480) +// If your model isn't a fbx with embedded textures make sure your model's +// textures are in same directory as your model +// +// +// Written by IAS. :) +// --------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include +#include "ModelLoader.h" + +#pragma comment (lib, "d3d11.lib") +#pragma comment (lib, "Dxgi.lib") +#pragma comment(lib,"d3dcompiler.lib") +#pragma comment (lib, "dxguid.lib") + +using namespace DirectX; + +// ------------------------------------------------------------ +// Structs +// ------------------------------------------------------------ +struct ConstantBuffer { + XMMATRIX mWorld; + XMMATRIX mView; + XMMATRIX mProjection; +}; + +// ------------------------------------------------------------ +// Window Variables +// ------------------------------------------------------------ +#define SCREEN_WIDTH 800 +#define SCREEN_HEIGHT 600 + +const char g_szClassName[] = "directxWindowClass"; + + +UINT width, height; +HWND hwnd; + +// ------------------------------------------------------------ +// DirectX Variables +// ------------------------------------------------------------ +D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL; +D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0; +ID3D11Device *dev; +ID3D11Device1 *dev1; +ID3D11DeviceContext *devcon; +ID3D11DeviceContext1 *devcon1; +IDXGISwapChain *swapchain; +IDXGISwapChain1 *swapchain1; +ID3D11RenderTargetView *backbuffer; +ID3D11VertexShader *pVS; +ID3D11PixelShader *pPS; +ID3D11InputLayout *pLayout; +ID3D11Buffer *pConstantBuffer; +ID3D11Texture2D *g_pDepthStencil; +ID3D11DepthStencilView *g_pDepthStencilView; +ID3D11SamplerState *TexSamplerState; + +XMMATRIX m_World; +XMMATRIX m_View; +XMMATRIX m_Projection; + +// ------------------------------------------------------------ +// Function identifiers +// ------------------------------------------------------------ + +void InitD3D(HINSTANCE hinstance, HWND hWnd); +void CleanD3D(void); +void RenderFrame(void); + +void InitPipeline(); +void InitGraphics(); + +HRESULT CompileShaderFromFile(LPCWSTR pFileName, const D3D_SHADER_MACRO* pDefines, LPCSTR pEntryPoint, LPCSTR pShaderModel, ID3DBlob** ppBytecodeBlob); +void Throwanerror(LPCSTR errormessage); + +// ------------------------------------------------------------ +// Our Model +// ------------------------------------------------------------ + +ModelLoader *ourModel; + +LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_CLOSE: + DestroyWindow(hwnd); + break; + case WM_DESTROY: + PostQuitMessage(0); + break; + default: + return DefWindowProc(hwnd, msg, wParam, lParam); + } + return 0; +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, + LPSTR lpCmdLine, int nCmdShow) +{ + WNDCLASSEX wc; + MSG msg; + + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = 0; + wc.lpfnWndProc = WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = g_szClassName; + wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); + + if (!RegisterClassEx(&wc)) + { + MessageBox(NULL, "Window Registration Failed!", "Error!", + MB_ICONEXCLAMATION | MB_OK); + return 0; + } + + RECT wr = { 0,0, SCREEN_WIDTH, SCREEN_HEIGHT }; + AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); + + hwnd = CreateWindowEx( + WS_EX_CLIENTEDGE, + g_szClassName, + " Simple Textured Directx11 Sample ", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, wr.right - wr.left, wr.bottom - wr.top, + NULL, NULL, hInstance, NULL + ); + + if (hwnd == NULL) + { + MessageBox(NULL, "Window Creation Failed!", "Error!", + MB_ICONEXCLAMATION | MB_OK); + return 0; + } + + ShowWindow(hwnd, nCmdShow); + UpdateWindow(hwnd); + + width = wr.right - wr.left; + height = wr.bottom - wr.top; + + InitD3D(hInstance, hwnd); + + while (true) + { + + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + + if (msg.message == WM_QUIT) + break; + } + + RenderFrame(); + } + + CleanD3D(); + + return msg.wParam; +} + +void InitD3D(HINSTANCE hinstance, HWND hWnd) +{ + HRESULT hr; + + UINT createDeviceFlags = 0; +#ifdef _DEBUG + createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; +#endif + + D3D_DRIVER_TYPE driverTypes[] = + { + D3D_DRIVER_TYPE_HARDWARE, + D3D_DRIVER_TYPE_WARP, + D3D_DRIVER_TYPE_REFERENCE, + }; + UINT numDriverTypes = ARRAYSIZE(driverTypes); + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + }; + UINT numFeatureLevels = ARRAYSIZE(featureLevels); + + for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++) + { + g_driverType = driverTypes[driverTypeIndex]; + hr = D3D11CreateDevice(nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels, + D3D11_SDK_VERSION, &dev, &g_featureLevel, &devcon); + + if (hr == E_INVALIDARG) + { + // DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it + hr = D3D11CreateDevice(nullptr, g_driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1, + D3D11_SDK_VERSION, &dev, &g_featureLevel, &devcon); + } + + if (SUCCEEDED(hr)) + break; + } + if (FAILED(hr)) + Throwanerror("Directx Device Creation Failed!"); + + UINT m4xMsaaQuality; + dev->CheckMultisampleQualityLevels( + DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m4xMsaaQuality); + + + // Obtain DXGI factory from device (since we used nullptr for pAdapter above) + IDXGIFactory1* dxgiFactory = nullptr; + { + IDXGIDevice* dxgiDevice = nullptr; + hr = dev->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast(&dxgiDevice)); + if (SUCCEEDED(hr)) + { + IDXGIAdapter* adapter = nullptr; + hr = dxgiDevice->GetAdapter(&adapter); + if (SUCCEEDED(hr)) + { + hr = adapter->GetParent(__uuidof(IDXGIFactory1), reinterpret_cast(&dxgiFactory)); + adapter->Release(); + } + dxgiDevice->Release(); + } + } + if (FAILED(hr)) + Throwanerror("DXGI Factory couldn't be obtained!"); + + // Create swap chain + IDXGIFactory2* dxgiFactory2 = nullptr; + hr = dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast(&dxgiFactory2)); + if (dxgiFactory2) + { + // DirectX 11.1 or later + hr = dev->QueryInterface(__uuidof(ID3D11Device1), reinterpret_cast(&dev1)); + if (SUCCEEDED(hr)) + { + (void)devcon->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast(&devcon1)); + } + + DXGI_SWAP_CHAIN_DESC1 sd; + ZeroMemory(&sd, sizeof(sd)); + sd.Width = SCREEN_WIDTH; + sd.Height = SCREEN_HEIGHT; + sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + sd.SampleDesc.Count = 4; + sd.SampleDesc.Quality = m4xMsaaQuality - 1; + sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + sd.BufferCount = 1; + + hr = dxgiFactory2->CreateSwapChainForHwnd(dev, hWnd, &sd, nullptr, nullptr, &swapchain1); + if (SUCCEEDED(hr)) + { + hr = swapchain1->QueryInterface(__uuidof(IDXGISwapChain), reinterpret_cast(&swapchain)); + } + + dxgiFactory2->Release(); + } + else + { + // DirectX 11.0 systems + DXGI_SWAP_CHAIN_DESC sd; + ZeroMemory(&sd, sizeof(sd)); + sd.BufferCount = 1; + sd.BufferDesc.Width = SCREEN_WIDTH; + sd.BufferDesc.Height = SCREEN_HEIGHT; + sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + sd.BufferDesc.RefreshRate.Numerator = 60; + sd.BufferDesc.RefreshRate.Denominator = 1; + sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + sd.OutputWindow = hWnd; + sd.SampleDesc.Count = 1; + sd.SampleDesc.Quality = m4xMsaaQuality - 1; + sd.Windowed = TRUE; + + hr = dxgiFactory->CreateSwapChain(dev, &sd, &swapchain); + } + + // Note this tutorial doesn't handle full-screen swapchains so we block the ALT+ENTER shortcut + dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER); + + dxgiFactory->Release(); + + if (FAILED(hr)) + Throwanerror("Swapchain Creation Failed!"); + + ID3D11Texture2D *pBackBuffer; + swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); + + dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer); + pBackBuffer->Release(); + + D3D11_TEXTURE2D_DESC descDepth; + ZeroMemory(&descDepth, sizeof(descDepth)); + descDepth.Width = SCREEN_WIDTH; + descDepth.Height = SCREEN_HEIGHT; + descDepth.MipLevels = 1; + descDepth.ArraySize = 1; + descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + descDepth.SampleDesc.Count = 4; + descDepth.SampleDesc.Quality = m4xMsaaQuality - 1; + descDepth.Usage = D3D11_USAGE_DEFAULT; + descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL; + descDepth.CPUAccessFlags = 0; + descDepth.MiscFlags = 0; + hr = dev->CreateTexture2D(&descDepth, nullptr, &g_pDepthStencil); + if (FAILED(hr)) + Throwanerror("Depth Stencil Texture couldn't be created!"); + + // Create the depth stencil view + D3D11_DEPTH_STENCIL_VIEW_DESC descDSV; + ZeroMemory(&descDSV, sizeof(descDSV)); + descDSV.Format = descDepth.Format; + descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + descDSV.Texture2D.MipSlice = 0; + hr = dev->CreateDepthStencilView(g_pDepthStencil, 0, &g_pDepthStencilView); + if (FAILED(hr)) + { + Throwanerror("Depth Stencil View couldn't be created!"); + } + + devcon->OMSetRenderTargets(1, &backbuffer, g_pDepthStencilView); + + D3D11_RASTERIZER_DESC rasterDesc; + ID3D11RasterizerState *rasterState; + rasterDesc.AntialiasedLineEnable = false; + rasterDesc.CullMode = D3D11_CULL_BACK; + rasterDesc.DepthBias = 0; + rasterDesc.DepthBiasClamp = 0.0f; + rasterDesc.DepthClipEnable = true; + rasterDesc.FillMode = D3D11_FILL_SOLID; + rasterDesc.FrontCounterClockwise = false; + rasterDesc.MultisampleEnable = false; + rasterDesc.ScissorEnable = false; + rasterDesc.SlopeScaledDepthBias = 0.0f; + + dev->CreateRasterizerState(&rasterDesc, &rasterState); + devcon->RSSetState(rasterState); + + D3D11_VIEWPORT viewport; + ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT)); + + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + viewport.Width = SCREEN_WIDTH; + viewport.Height = SCREEN_HEIGHT; + + devcon->RSSetViewports(1, &viewport); + + InitPipeline(); + InitGraphics(); +} + +void CleanD3D(void) +{ + swapchain->SetFullscreenState(FALSE, NULL); + + ourModel->Close(); + g_pDepthStencil->Release(); + g_pDepthStencilView->Release(); + pLayout->Release(); + pVS->Release(); + pPS->Release(); + pConstantBuffer->Release(); + swapchain->Release(); + backbuffer->Release(); + dev->Release(); + devcon->Release(); +} + +void RenderFrame(void) +{ + static float t = 0.0f; + static ULONGLONG timeStart = 0; + ULONGLONG timeCur = GetTickCount64(); + if (timeStart == 0) + timeStart = timeCur; + t = (timeCur - timeStart) / 1000.0f; + + float clearColor[4] = { 0.0f, 0.2f, 0.4f, 1.0f }; + devcon->ClearRenderTargetView(backbuffer, clearColor); + devcon->ClearDepthStencilView(g_pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + + devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + m_World = XMMatrixRotationY(-t); + + ConstantBuffer cb; + cb.mWorld = XMMatrixTranspose(m_World); + cb.mView = XMMatrixTranspose(m_View); + cb.mProjection = XMMatrixTranspose(m_Projection); + devcon->UpdateSubresource(pConstantBuffer, 0, nullptr, &cb, 0, 0); + + devcon->VSSetShader(pVS, 0, 0); + devcon->VSSetConstantBuffers(0, 1, &pConstantBuffer); + devcon->PSSetShader(pPS, 0, 0); + devcon->PSSetSamplers(0, 1, &TexSamplerState); + ourModel->Draw(devcon); + + swapchain->Present(0, 0); +} + +void InitPipeline() +{ + ID3DBlob *VS, *PS; + CompileShaderFromFile(L"VertexShader.hlsl", 0, "main", "vs_4_0", &VS); + CompileShaderFromFile(L"PixelShader.hlsl", 0, "main", "ps_4_0", &PS); + + dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS); + dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS); + + D3D11_INPUT_ELEMENT_DESC ied[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 } + }; + + dev->CreateInputLayout(ied, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &pLayout); + devcon->IASetInputLayout(pLayout); +} + +void InitGraphics() +{ + HRESULT hr; + + m_Projection = XMMatrixPerspectiveFovLH(XM_PIDIV4, SCREEN_WIDTH / (float)SCREEN_HEIGHT, 0.01f, 1000.0f); + + D3D11_BUFFER_DESC bd; + ZeroMemory(&bd, sizeof(bd)); + + bd.Usage = D3D11_USAGE_DEFAULT; + bd.ByteWidth = sizeof(ConstantBuffer); + bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bd.CPUAccessFlags = 0; + + hr = dev->CreateBuffer(&bd, nullptr, &pConstantBuffer); + if (FAILED(hr)) + Throwanerror("Constant buffer couldn't be created"); + + D3D11_SAMPLER_DESC sampDesc; + ZeroMemory(&sampDesc, sizeof(sampDesc)); + sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + sampDesc.MinLOD = 0; + sampDesc.MaxLOD = D3D11_FLOAT32_MAX; + + hr = dev->CreateSamplerState(&sampDesc, &TexSamplerState); + if (FAILED(hr)) + Throwanerror("Texture sampler state couldn't be created"); + + XMVECTOR Eye = XMVectorSet(0.0f, 5.0f, -300.0f, 0.0f); + XMVECTOR At = XMVectorSet(0.0f, 100.0f, 0.0f, 0.0f); + XMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); + m_View = XMMatrixLookAtLH(Eye, At, Up); + + ourModel = new ModelLoader; + if (!ourModel->Load(hwnd, dev, devcon, "Models/myModel.fbx")) + Throwanerror("Model couldn't be loaded"); +} + +HRESULT CompileShaderFromFile(LPCWSTR pFileName, const D3D_SHADER_MACRO* pDefines, LPCSTR pEntryPoint, LPCSTR pShaderModel, ID3DBlob** ppBytecodeBlob) +{ + UINT compileFlags = D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR; + +#ifdef _DEBUG + compileFlags |= D3DCOMPILE_DEBUG; +#endif + + ID3DBlob* pErrorBlob = NULL; + + HRESULT result = D3DCompileFromFile(pFileName, pDefines, D3D_COMPILE_STANDARD_FILE_INCLUDE, pEntryPoint, pShaderModel, compileFlags, 0, ppBytecodeBlob, &pErrorBlob); + if (FAILED(result)) + { + if (pErrorBlob != NULL) + OutputDebugStringA((LPCSTR)pErrorBlob->GetBufferPointer()); + } + + if (pErrorBlob != NULL) + pErrorBlob->Release(); + + return result; +} + +void Throwanerror(LPCSTR errormessage) +{ + MessageBox(hwnd, errormessage, "Error!", MB_ICONERROR | MB_OK); +} \ No newline at end of file diff --git a/samples/SimpleTexturedOpenGL/CMakeLists.txt b/samples/SimpleTexturedOpenGL/CMakeLists.txt index 6c34acda5..1b206af50 100644 --- a/samples/SimpleTexturedOpenGL/CMakeLists.txt +++ b/samples/SimpleTexturedOpenGL/CMakeLists.txt @@ -11,6 +11,11 @@ IF ( NOT GLUT_FOUND ) ENDIF ( MSVC ) ENDIF ( NOT GLUT_FOUND ) +if ( MSVC ) + ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS ) + ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS ) +endif ( MSVC ) + INCLUDE_DIRECTORIES( ${Assimp_SOURCE_DIR}/include ${Assimp_SOURCE_DIR}/code diff --git a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp index 083650f96..df05b56c4 100644 --- a/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp +++ b/samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp @@ -13,6 +13,7 @@ // http://nehe.gamedev.net/ // ---------------------------------------------------------------------------- #include +#include #include #include #include @@ -666,7 +667,7 @@ BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool ful PFD_SUPPORT_OPENGL | // Format Must Support OpenGL PFD_DOUBLEBUFFER, // Must Support Double Buffering PFD_TYPE_RGBA, // Request An RGBA Format - bits, // Select Our Color Depth + BYTE(bits), // Select Our Color Depth 0, 0, 0, 0, 0, 0, // Color Bits Ignored 0, // No Alpha Buffer 0, // Shift Bit Ignored diff --git a/samples/glut/GL/glut.h b/samples/glut/GL/glut.h index 0e6ddfbfe..86aa5c423 100644 --- a/samples/glut/GL/glut.h +++ b/samples/glut/GL/glut.h @@ -179,7 +179,7 @@ extern void exit(int); glutSpecialUpFunc, glutIgnoreKeyRepeat, glutSetKeyRepeat, glutJoystickFunc, glutForceJoystickFunc (NOT FINALIZED!). **/ -#ifndef GLUT_API_VERSION /* allow this to be overriden */ +#ifndef GLUT_API_VERSION /* allow this to be overridden */ #define GLUT_API_VERSION 3 #endif @@ -219,7 +219,7 @@ extern void exit(int); GLUT_XLIB_IMPLEMENTATION=15 mjk's GLUT 3.7 beta sync'ed with Mesa **/ -#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overriden. */ +#ifndef GLUT_XLIB_IMPLEMENTATION /* Allow this to be overridden. */ #define GLUT_XLIB_IMPLEMENTATION 15 #endif diff --git a/scripts/AppVeyor/cacheglobs.txt b/scripts/AppVeyor/cacheglobs.txt new file mode 100644 index 000000000..0f5f04a4a --- /dev/null +++ b/scripts/AppVeyor/cacheglobs.txt @@ -0,0 +1,4 @@ +code/*.{%{cpp}} +contrib/**/*.{%{cpp}} +include/**/*.{%{cpp}} +test/**/*.{%{cpp}} diff --git a/scripts/AppVeyor/mtime_cache b/scripts/AppVeyor/mtime_cache new file mode 100644 index 000000000..e296e3658 --- /dev/null +++ b/scripts/AppVeyor/mtime_cache @@ -0,0 +1,177 @@ +#!/usr/bin/env ruby + +# +# mtime_cache +# Copyright (c) 2016 Borislav Stanimirov +# +# 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. +# + +require 'digest/md5' +require 'json' +require 'fileutils' + +VERSION = "1.0.2" + +VERSION_TEXT = "mtime_cache v#{VERSION}" + +USAGE = <] [-g globfile] [-d] [-q|V] [-c cache] +ENDUSAGE + +HELP = < '.mtime_cache.json', :globs => [] } + +ARGV.each do |arg| + case arg + when '-g', '--globfile' then param_arg = :globfile + when '-h', '-?', '--help' then ARGS[:help] = true + when '-v', '--version' then ARGS[:ver] = true + when '-q', '--quiet' then ARGS[:quiet] = true + when '-V', '--verbose' then ARGS[:verbose] = true + when '-d', '--dryrun' then ARGS[:dry] = true + when '-c', '--cache' then param_arg = :cache + else + if param_arg + ARGS[param_arg] = arg + param_arg = nil + else + ARGS[:globs] << arg + end + end +end + +def log(text, level = 0) + return if ARGS[:quiet] + return if level > 0 && !ARGS[:verbose] + puts text +end + +if ARGS[:ver] || ARGS[:help] + log VERSION_TEXT + exit if ARGS[:ver] + log USAGE + log HELP + exit +end + +if ARGS[:globs].empty? && !ARGS[:globfile] + log 'Error: Missing globs' + log USAGE + exit 1 +end + +EXTENSION_PATTERNS = { + :cpp => "c,cc,cpp,cxx,h,hpp,hxx,inl,ipp,inc,ixx" +} + +cache_file = ARGS[:cache] + +cache = {} + +if File.file?(cache_file) + log "Found #{cache_file}" + cache = JSON.parse(File.read(cache_file)) + log "Read #{cache.length} entries" +else + log "#{cache_file} not found. A new one will be created" +end + +globs = ARGS[:globs].map { |g| g % EXTENSION_PATTERNS } + +globfile = ARGS[:globfile] +if globfile + File.open(globfile, 'r').each_line do |line| + line.strip! + next if line.empty? + globs << line % EXTENSION_PATTERNS + end +end + +if globs.empty? + log 'Error: No globs in globfile' + log USAGE + exit 1 +end + +files = {} +num_changed = 0 + +globs.each do |glob| + Dir[glob].each do |file| + next if !File.file?(file) + + mtime = File.mtime(file).to_i + hash = Digest::MD5.hexdigest(File.read(file)) + + cached = cache[file] + + if cached && cached['hash'] == hash && cached['mtime'] < mtime + mtime = cached['mtime'] + + log "mtime_cache: changing mtime of #{file} to #{mtime}", 1 + + File.utime(File.atime(file), Time.at(mtime), file) if !ARGS[:dry] + num_changed += 1 + else + log "mtime_cache: NOT changing mtime of #{file}", 1 + end + + files[file] = { 'mtime' => mtime, 'hash' => hash } + end +end + +log "Changed mtime of #{num_changed} of #{files.length} files" +log "Writing #{cache_file}" + +if !ARGS[:dry] + dirname = File.dirname(cache_file) + unless File.directory?(dirname) + FileUtils.mkdir_p(dirname) + end + File.open(cache_file, 'w').write(JSON.pretty_generate(files)) +end diff --git a/scripts/BlenderImporter/genblenddna.py b/scripts/BlenderImporter/genblenddna.py index 484f01a5d..caa58ded7 100644 --- a/scripts/BlenderImporter/genblenddna.py +++ b/scripts/BlenderImporter/genblenddna.py @@ -58,24 +58,16 @@ template_src = "BlenderScene.cpp.template" # workaround for stackoverflowing when reading the linked list of scene objects # with the usual approach. See embedded notes for details. Structure_Convert_Base_fullcode = """ -template <> void Structure :: Convert ( - Base& dest, - const FileDatabase& db - ) const -{ +template <> void Structure::Convert( Base& dest, const FileDatabase& db ) const { // note: as per https://github.com/assimp/assimp/issues/128, // reading the Object linked list recursively is prone to stack overflow. // This structure converter is therefore an hand-written exception that // does it iteratively. const int initial_pos = db.reader->GetCurrentPos(); - std::pair todo = std::make_pair(&dest, initial_pos); - Base* saved_prev = NULL; - while(true) { - Base& cur_dest = *todo.first; db.reader->SetCurrentPos(todo.second); @@ -303,8 +295,3 @@ def main(): if __name__ == "__main__": sys.exit(main()) - - - - - diff --git a/scripts/android_crosscompile/make_android.bat b/scripts/android_crosscompile/make_android.bat new file mode 100644 index 000000000..a50695e16 --- /dev/null +++ b/scripts/android_crosscompile/make_android.bat @@ -0,0 +1,28 @@ +@echo off + +set ASSIMP_PATH=D:\projects\asset-importer-lib\assimp +set CMAKE_PATH="C:\Program Files\CMake\bin\cmake.exe" +set ANDROID_NDK_PATH=C:\Users\kimkulling\AppData\Local\Android\Sdk\ndk-bundle +set ANDROID_CMAKE_PATH=contrib\android-cmake + +pushd %ASSIMP_PATH% + +rmdir /s /q build +mkdir build +cd build + +%CMAKE_PATH% .. ^ + -G"MinGW Makefiles" ^ + -DCMAKE_BUILD_TYPE=Release ^ + -DCMAKE_TOOLCHAIN_FILE=%ANDROID_CMAKE_PATH%\android.toolchain.cmake ^ + -DCMAKE_MAKE_PROGRAM=%ANDROID_NDK_PATH%\prebuilt\windows-x86_64\bin\make.exe ^ + -DANDROID_NDK=%ANDROID_NDK_PATH% ^ + -DANDROID_NATIVE_API_LEVEL=android-9 ^ + -DASSIMP_ANDROID_JNIIOSYSTEM=ON ^ + -DANDROID_ABI=arm64-v8a ^ + -DASSIMP_BUILD_ZLIB=ON ^ + -DASSIMP_BUILD_TESTS=OFF + +%CMAKE_PATH% --build . + +popd \ No newline at end of file diff --git a/scripts/appveyor/compiler_setup.bat b/scripts/appveyor/compiler_setup.bat deleted file mode 100644 index 7d4851493..000000000 --- a/scripts/appveyor/compiler_setup.bat +++ /dev/null @@ -1,36 +0,0 @@ -rem @echo off - -:: Now we declare a scope -Setlocal EnableDelayedExpansion EnableExtensions - -if not defined Configuration set Configuration=14 2015 - -if "%Configuration%"=="MinGW" ( goto :mingw ) - -set arch=x86 - -if "%platform%" EQU "x64" ( set arch=x86_amd64 ) - -if "%Configuration%"=="14 2015" ( - set SET_VS_ENV="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" -) - -if "%Configuration%"=="12 2013" ( - set SET_VS_ENV="C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" -) - -if "%Configuration%"=="11 2012" ( - set SET_VS_ENV="C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" -) - -if "%Configuration%"=="10 2010" ( - set SET_VS_ENV="C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" -) - -:: Visual Studio detected -endlocal & call %SET_VS_ENV% %arch% -goto :eof - -:: MinGW detected -:mingw -endlocal & set PATH=c:\mingw\bin;%PATH% diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d39beff4e..741da9534 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,7 +1,8 @@ # Open Asset Import Library (assimp) # ---------------------------------------------------------------------- # -# Copyright (c) 2006-2016, assimp team +# Copyright (c) 2006-2017, assimp team + # All rights reserved. # # Redistribution and use of this software in source and binary forms, @@ -37,7 +38,8 @@ #---------------------------------------------------------------------- cmake_minimum_required( VERSION 2.6 ) -#INCLUDE( AddGTest ) +include( CTest ) +enable_testing() INCLUDE_DIRECTORIES( ../contrib/gtest/include @@ -50,75 +52,123 @@ INCLUDE_DIRECTORIES( # Assimp library can be found, even if it is not installed system-wide yet. LINK_DIRECTORIES( ${Assimp_BINARY_DIR} ${AssetImporter_BINARY_DIR}/lib ) -SOURCE_GROUP( unit FILES - unit/CCompilerTest.c -) - -SET( TEST_SRCS - unit/AbstractImportExportBase.cpp - unit/TestIOSystem.h - unit/TestModelFactory.h - unit/utAnim.cpp - unit/AssimpAPITest.cpp - unit/utBatchLoader.cpp - unit/utBlenderIntermediate.cpp - unit/utBlendImportAreaLight.cpp - unit/utBlendImportMaterials.cpp - unit/utColladaExportCamera.cpp - unit/utColladaExportLight.cpp - unit/utDefaultIOStream.cpp - unit/utDXFImporterExporter.cpp - unit/utFastAtof.cpp - unit/utFBXImporterExporter.cpp - unit/utFindDegenerates.cpp - unit/utFindInvalidData.cpp - unit/utFixInfacingNormals.cpp - unit/utGenNormals.cpp - unit/utImporter.cpp - unit/utImproveCacheLocality.cpp +SET( COMMON unit/utIOSystem.cpp unit/utIOStreamBuffer.cpp unit/utIssues.cpp - unit/utJoinVertices.cpp - unit/utLimitBoneWeights.cpp - unit/utMaterialSystem.cpp - unit/utMatrix3x3.cpp - unit/utMatrix4x4.cpp + unit/utAnim.cpp + unit/AssimpAPITest.cpp + unit/utBatchLoader.cpp + unit/utDefaultIOStream.cpp + unit/utFastAtof.cpp unit/utMetadata.cpp unit/SceneDiffer.h unit/SceneDiffer.cpp - unit/utSIBImporter.cpp - unit/utObjImportExport.cpp - unit/utPretransformVertices.cpp - unit/utRemoveComments.cpp - unit/utRemoveComponent.cpp - unit/utRemoveRedundantMaterials.cpp - unit/utScenePreprocessor.cpp + unit/UTLogStream.h + unit/AbstractImportExportBase.cpp + unit/TestIOSystem.h + unit/TestModelFactory.h + unit/utTypes.cpp + unit/utVersion.cpp + unit/utProfiler.cpp unit/utSharedPPData.cpp unit/utStringUtils.cpp - unit/utSortByPType.cpp - unit/utSplitLargeMeshes.cpp - unit/utTargetAnimation.cpp - unit/utTextureTransform.cpp - unit/utTriangulate.cpp - unit/utTypes.cpp - unit/utVertexTriangleAdjacency.cpp - unit/utVersion.cpp - unit/utXImporterExporter.cpp ) -SOURCE_GROUP( tests FILES ${TEST_SRCS} ) +SET( IMPORTERS + unit/utLWSImportExport.cpp + unit/utSMDImportExport.cpp + unit/utglTFImportExport.cpp + unit/utglTF2ImportExport.cpp + unit/utHMPImportExport.cpp + unit/utIFCImportExport.cpp + unit/utFBXImporterExporter.cpp + unit/utImporter.cpp + unit/ut3DImportExport.cpp + unit/ut3DSImportExport.cpp + unit/utACImportExport.cpp + unit/utAMFImportExport.cpp + unit/utASEImportExport.cpp + unit/utD3MFImportExport.cpp + unit/utQ3DImportExport.cpp + unit/utSTLImportExport.cpp + unit/utXImporterExporter.cpp + unit/utX3DImportExport.cpp + unit/utDXFImporterExporter.cpp + unit/utPMXImporter.cpp + unit/utPLYImportExport.cpp + unit/utObjImportExport.cpp + unit/utObjTools.cpp + unit/utOpenGEXImportExport.cpp + unit/utSIBImporter.cpp + unit/utBlenderIntermediate.cpp + unit/utBlendImportAreaLight.cpp + unit/utBlenderImportExport.cpp + unit/utBlendImportMaterials.cpp + unit/utBVHImportExport.cpp + unit/utColladaExportCamera.cpp + unit/utColladaExportLight.cpp + unit/utColladaImportExport.cpp + unit/utCSMImportExport.cpp + unit/utB3DImportExport.cpp +) + +SET( MATERIAL + unit/utMaterialSystem.cpp +) + +SET( MATH + unit/utMatrix3x3.cpp + unit/utMatrix4x4.cpp + unit/utVector3.cpp +) + +SET( POST_PROCESSES + unit/utImproveCacheLocality.cpp + unit/utFixInfacingNormals.cpp + unit/utGenNormals.cpp + unit/utTriangulate.cpp + unit/utTextureTransform.cpp + unit/utRemoveRedundantMaterials.cpp + unit/utRemoveVCProcess.cpp + unit/utScaleProcess.cpp + unit/utJoinVertices.cpp + unit/utRemoveComments.cpp + unit/utRemoveComponent.cpp + unit/utVertexTriangleAdjacency.cpp + unit/utJoinVertices.cpp + unit/utSplitLargeMeshes.cpp + unit/utFindDegenerates.cpp + unit/utFindInvalidData.cpp + unit/utLimitBoneWeights.cpp + unit/utPretransformVertices.cpp + unit/utScenePreprocessor.cpp + unit/utTargetAnimation.cpp + unit/utSortByPType.cpp + unit/utSceneCombiner.cpp +) + +SOURCE_GROUP( UnitTests\\Compiler FILES unit/CCompilerTest.c ) +SOURCE_GROUP( UnitTests\\Common FILES ${COMMON} ) +SOURCE_GROUP( UnitTests\\Importers FILES ${IMPORTERS} ) +SOURCE_GROUP( UnitTests\\Material FILES ${MATERIAL} ) +SOURCE_GROUP( UnitTests\\Math FILES ${MATH} ) +SOURCE_GROUP( UnitTests\\PostProcess FILES ${POST_PROCESSES}) add_executable( unit ../contrib/gtest/src/gtest-all.cc unit/CCompilerTest.c unit/Main.cpp ../code/Version.cpp - ${TEST_SRCS} + ${COMMON} + ${IMPORTERS} + ${MATERIAL} + ${MATH} + ${POST_PROCESSES} ) add_definitions(-DASSIMP_TEST_MODELS_DIR="${CMAKE_CURRENT_LIST_DIR}/models") - + SET_PROPERTY( TARGET assimp PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX} ) IF( WIN32 ) @@ -127,6 +177,13 @@ ELSE( WIN32 ) SET( platform_libs pthread ) ENDIF( WIN32 ) +IF( WIN32 ) + ADD_CUSTOM_COMMAND(TARGET unit + PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ + MAIN_DEPENDENCY assimp) +ENDIF( WIN32 ) + IF(MSVC) add_definitions(-D_CRT_SECURE_NO_WARNINGS) ENDIF(MSVC) @@ -134,15 +191,6 @@ ENDIF(MSVC) target_link_libraries( unit assimp ${platform_libs} ) add_subdirectory(headercheck) -#if (ASSIMP_COVERALLS) -# include(Coveralls) -# -# set(COVERAGE_SRCS ${assimp_src} ${TEST_SRCS} ) -# -# # Create the coveralls target. -# coveralls_setup( -# "${COVERAGE_SRCS}" # The source files. -# ON # If we should upload. -# "${PROJECT_SOURCE_DIR}/cmake-modules/") # (Optional) Alternate project cmake module path. -#endif() + +add_test( unittests unit ) diff --git a/test/models-nonbsd/BLEND/fleurOptonl.source.txt b/test/models-nonbsd/BLEND/fleurOptonl.source.txt index 13f54a108..b9c58b5d9 100644 --- a/test/models-nonbsd/BLEND/fleurOptonl.source.txt +++ b/test/models-nonbsd/BLEND/fleurOptonl.source.txt @@ -32,7 +32,7 @@ L'utilizzo della Creative Commons non influisce su questo diritto. ************************************************ This model is released under Creative Commons Licence, Attribution 2.0 -for informations see: +for information see: http://creativecommons.org http://creativecommons.org/licenses/by/2.0/ feel free to use and improve it. diff --git a/test/models-nonbsd/MMD/Alicia_blade.pmx b/test/models-nonbsd/MMD/Alicia_blade.pmx new file mode 100644 index 000000000..cdd7709cc Binary files /dev/null and b/test/models-nonbsd/MMD/Alicia_blade.pmx differ diff --git a/test/models-nonbsd/MMD/readme.txt b/test/models-nonbsd/MMD/readme.txt new file mode 100644 index 000000000..d8c882420 --- /dev/null +++ b/test/models-nonbsd/MMD/readme.txt @@ -0,0 +1,49 @@ +———————————————————————— +ニコニ立体公式キャラクター「ニコニ立体ちゃん」 +http://3d.nicovideo.jp/alicia/ +version 4 +©dwango, inc. All rights reserved. +———————————————————————— + + +この度は、ニコニ立体公式キャラクター「ニコニ立体ちゃん」をダウンロードいただきましてありがとうございます。 + +◯ 内容物 +1. MikuMikuDance(MMD)用ファイル2種 (ニコニ立体ちゃん本体・ビーム彫刻刀) +2. MMD用モーションファイル16種 (ニコファーレのモーションキャプチャーデバイスを用いて収録) +2. FBXファイル2種 (MMD用データ、Unity用データ) + MAXファイル(オリジナルデータ) +3. Unity Package1種 +4. ニコニ立体ちゃん壁紙1種 + + +◯よくある質問 +* 「ニコニ立体ちゃん」と「アリシア・ソリッド」、正式名称はどちら? +キャラクターの本名はアリシア・ソリッドですが、クレジット等での表記はニコニ立体ちゃんが正式名称となります。 +作品発表の際には「ニコニ立体ちゃん」タグをご活用ください。 + +* ニコニ立体ちゃんを用いた、年齢制限のある二次創作物の公開は可能なのか? +利用規約にある禁止事項に抵触しない限りにおいて可能です。 + + +◯ 利用規約抜粋 +必ず利用規約( http://3d.nicovideo.jp/alicia/rule.html )をご確認ください。 +利用規約の改訂などによって下記抜粋と利用規約の内容が異なる場合は利用規約が優先されます。 + +* 非営利、営利に関わらず個人(同人サークルなど、法人を除く団体を含む)の利用が可能です。 +* 二次創作物について株式会社ドワンゴ(以下、当社)のクレジットを表記する必要はありません。 +* 改変物を配布することができます。 +* niconico内でキャラクターやモーションを利用した作品を投稿する場合は、コンテンツツリーの親作品にキャラクター( http://3d.nicovideo.jp/works/td14712 )を登録するよう努めるものとします。 + + +◯禁止事項 +* 第三者の知的財産権その他一切の権利及び名誉を侵害しないこと。 +* 当社(当社が提供するサービス等を含む)及び当社キャラクターの名誉・品位傷つける行為をしないこと。 +* 公序良俗に反する行為や目的、暴力的な表現、反社会的な行為や目的、特定の信条や宗教、政治的発言のため利用しないこと。 +* 当社の公式商品であるかのような誤解を招く利用をしないこと。 +* その他、当社が不適切と判断する行為に利用しないこと。 + + +◯ クレジット +企画: 株式会社ドワンゴ +キャラクターデザイン: 黒星紅白 +モデリング: 雨刻 \ No newline at end of file diff --git a/test/models/AMF/README b/test/models/AMF/README index a64a8508e..7de7cadb2 100644 --- a/test/models/AMF/README +++ b/test/models/AMF/README @@ -1 +1 @@ -Simple models for testing importer. No desription because models are simple and created by hands. +Simple models for testing importer. No description because models are simple and created by hand. diff --git a/test/models/BLEND/box.blend b/test/models/BLEND/box.blend new file mode 100644 index 000000000..28ebbcc1f Binary files /dev/null and b/test/models/BLEND/box.blend differ diff --git a/test/models/OBJ/cube_with_vertexcolors.obj b/test/models/OBJ/cube_with_vertexcolors.obj new file mode 100644 index 000000000..d78d3a555 --- /dev/null +++ b/test/models/OBJ/cube_with_vertexcolors.obj @@ -0,0 +1,30 @@ +g cube + +v 0.0 0.0 0.0 124 110 120 +v 0.0 0.0 1.0 24 0 121 +v 0.0 1.0 0.0 4 0 44 +v 0.0 1.0 1.0 224 0 10 +v 1.0 0.0 0.0 24 200 25 +v 1.0 0.0 1.0 124 10 56 +v 1.0 1.0 0.0 78 10 50 +v 1.0 1.0 1.0 23 0 200 + +vn 0.0 0.0 1.0 +vn 0.0 0.0 -1.0 +vn 0.0 1.0 0.0 +vn 0.0 -1.0 0.0 +vn 1.0 0.0 0.0 +vn -1.0 0.0 0.0 + +f 1//2 7//2 5//2 +f 1//2 3//2 7//2 +f 1//6 4//6 3//6 +f 1//6 2//6 4//6 +f 3//3 8//3 7//3 +f 3//3 4//3 8//3 +f 5//5 7//5 8//5 +f 5//5 8//5 6//5 +f 1//4 5//4 6//4 +f 1//4 6//4 2//4 +f 2//1 6//1 8//1 +f 2//1 8//1 4//1 \ No newline at end of file diff --git a/test/models/OBJ/spider.mtl b/test/models/OBJ/spider.mtl index 38207dcc6..d225a7c62 100644 --- a/test/models/OBJ/spider.mtl +++ b/test/models/OBJ/spider.mtl @@ -1,38 +1,38 @@ -# -# spider.mtl -# - -newmtl Skin -Ka 0.200000 0.200000 0.200000 -Kd 0.827451 0.792157 0.772549 -Ks 0.000000 0.000000 0.000000 -Ns 0.000000 -map_Kd .\wal67ar_small.jpg - -newmtl Brusttex -Ka 0.200000 0.200000 0.200000 -Kd 0.800000 0.800000 0.800000 -Ks 0.000000 0.000000 0.000000 -Ns 0.000000 -map_Kd .\wal69ar_small.jpg - -newmtl HLeibTex -Ka 0.200000 0.200000 0.200000 -Kd 0.690196 0.639216 0.615686 -Ks 0.000000 0.000000 0.000000 -Ns 0.000000 -map_Kd .\SpiderTex.jpg - -newmtl BeinTex -Ka 0.200000 0.200000 0.200000 -Kd 0.800000 0.800000 0.800000 -Ks 0.000000 0.000000 0.000000 -Ns 0.000000 -map_Kd .\drkwood2.jpg - -newmtl Augentex -Ka 0.200000 0.200000 0.200000 -Kd 0.800000 0.800000 0.800000 -Ks 0.000000 0.000000 0.000000 -Ns 0.000000 +# +# spider.mtl +# + +newmtl Skin +Ka 0.200000 0.200000 0.200000 +Kd 0.827451 0.792157 0.772549 +Ks 0.000000 0.000000 0.000000 +Ns 0.000000 +map_Kd .\wal67ar_small.jpg + +newmtl Brusttex +Ka 0.200000 0.200000 0.200000 +Kd 0.800000 0.800000 0.800000 +Ks 0.000000 0.000000 0.000000 +Ns 0.000000 +map_Kd .\wal69ar_small.jpg + +newmtl HLeibTex +Ka 0.200000 0.200000 0.200000 +Kd 0.690196 0.639216 0.615686 +Ks 0.000000 0.000000 0.000000 +Ns 0.000000 +map_Kd .\SpiderTex.jpg + +newmtl BeinTex +Ka 0.200000 0.200000 0.200000 +Kd 0.800000 0.800000 0.800000 +Ks 0.000000 0.000000 0.000000 +Ns 0.000000 +map_Kd .\drkwood2.jpg + +newmtl Augentex +Ka 0.200000 0.200000 0.200000 +Kd 0.800000 0.800000 0.800000 +Ks 0.000000 0.000000 0.000000 +Ns 0.000000 map_Kd .\engineflare1.jpg \ No newline at end of file diff --git a/test/models/OBJ/spider.obj b/test/models/OBJ/spider.obj index b4e53c4a7..3e8e70fbd 100644 --- a/test/models/OBJ/spider.obj +++ b/test/models/OBJ/spider.obj @@ -1,3436 +1,3436 @@ -# Wavefront OBJ exported by MilkShape 3D - -mtllib spider.mtl - -v 1.160379 4.512684 6.449167 -v 22.656172 10.214539 16.869690 -v 4.568314 16.857113 5.619617 -v 14.402298 32.891869 3.414829 -v 27.520809 27.080326 11.451565 -v 39.186256 16.230997 12.632702 -v -6.442715 10.777405 -0.537529 -v -8.120363 15.684460 -10.500000 -v -0.886770 23.423717 -4.342854 -v -0.886770 23.423717 -16.657145 -v 14.402298 32.891869 -26.414825 -v 12.953165 36.873337 -11.500000 -v 30.527317 37.503952 -2.733282 -v 30.527317 37.503952 -20.266716 -v 44.301250 33.964729 -11.500000 -v 45.094967 27.710945 2.684846 -v 57.936218 30.276533 -11.500000 -v 54.503593 5.934020 -11.500000 -v 51.091763 11.234900 2.684846 -v 45.094967 27.710945 -25.684845 -v 39.186256 16.230997 -35.632706 -v 51.091763 11.234900 -25.684845 -v 27.520809 27.080326 -34.451565 -v 4.568314 16.857113 -26.619617 -v 1.160379 4.512684 -27.449169 -v 22.656172 10.214539 -39.869690 -v 7.838881 -6.414188 -26.619617 -v 30.910042 -12.462786 -26.414825 -v 37.223816 0.421531 -34.451565 -v 46.227112 -5.630886 -20.266716 -v 32.359184 -16.444252 -11.500000 -v 30.910042 -12.462786 3.414829 -v 46.227112 -5.630886 -2.733282 -v 4.405119 -14.230042 -16.657145 -v -4.681486 -8.784435 -10.500000 -v 4.405119 -14.230042 -4.342854 -v -4.421391 -3.605049 -0.537529 -v 7.838881 -6.414188 5.619617 -v 37.223816 0.421531 11.451565 -v -9.876476 2.961555 -10.500000 -v -6.442715 10.777405 -20.462471 -v -4.421391 -3.605049 -20.462471 -v -41.856613 -0.754846 9.430772 -v -27.950212 1.303017 3.081421 -v -32.625862 10.860188 8.479760 -v -24.401524 12.224749 -3.122690 -v -18.826405 5.435883 0.583091 -v -11.221268 -4.132547 1.127722 -v -44.882015 11.887197 1.421121 -v -44.844704 15.228493 -10.000000 -v -35.570240 16.598591 -2.941359 -v -35.570240 16.598591 -17.058643 -v -24.401524 12.224749 -16.877310 -v -23.778482 14.142281 -10.000000 -v -8.432302 6.445052 -5.957618 -v -8.432302 6.445052 -14.042381 -v -1.337093 1.108110 -10.000000 -v -3.309273 -1.735224 -0.594703 -v -0.419668 -7.642198 -10.000000 -v -6.305182 -14.182098 -10.000000 -v -6.229439 -10.722575 -0.594703 -v -3.309273 -1.735224 -19.405296 -v -11.221268 -4.132547 -21.127720 -v -6.229439 -10.722575 -19.405296 -v -18.826405 5.435883 -20.583092 -v -32.625862 10.860188 -28.479759 -v -41.856613 -0.754846 -29.430771 -v -27.950212 1.303017 -23.081421 -v -39.194733 -9.356718 -28.479759 -v -31.498898 -9.618716 -16.877310 -v -22.998137 -7.403383 -20.583092 -v -31.498898 -9.618716 -3.122690 -v -51.647591 -5.708694 -10.000000 -v -49.713837 -2.983590 1.421121 -v -39.194733 -9.356718 8.479760 -v -22.998137 -7.403383 0.583091 -v -50.637024 8.975393 -10.000000 -v -44.882015 11.887197 -21.421116 -v -49.713837 -2.983590 -21.421116 -v -40.671478 -3.472887 -21.369167 -v -47.098404 7.389261 -39.585033 -v -55.443726 28.016960 -51.020649 -v -56.413048 27.518753 -54.602135 -v -67.985016 13.435572 -79.020355 -v -81.678322 -31.379181 -101.291557 -v -87.605835 -39.983532 -104.351723 -v -41.963333 -2.246161 -18.485233 -v -47.146698 8.704388 -37.681622 -v -55.805077 29.500343 -50.360577 -v -57.932991 29.207901 -55.039448 -v -69.893600 14.105843 -80.144135 -v -82.778503 -29.843521 -101.266586 -v -87.950195 -39.455147 -104.260185 -v -45.274612 -1.921316 -17.562561 -v -48.862389 8.964325 -36.150715 -v -56.924980 29.827461 -49.555809 -v -60.012169 29.560211 -54.086689 -v -72.068741 14.206520 -79.360901 -v -83.474747 -29.518608 -100.470779 -v -88.234985 -39.350231 -103.866043 -v -48.111877 -2.742970 -19.296001 -v -50.953510 7.973352 -36.145107 -v -57.960136 28.752014 -49.212387 -v -61.084877 28.310402 -52.461258 -v -72.872513 13.661798 -77.260391 -v -83.242752 -30.649029 -99.503448 -v -88.245728 -39.747742 -103.466080 -v -48.338589 -4.092402 -22.380154 -v -51.845413 6.477697 -37.669014 -v -58.131039 27.083824 -49.588871 -v -60.343346 26.399567 -51.387123 -v -71.699661 12.881830 -75.424393 -v -82.257225 -32.383606 -99.092934 -v -87.974380 -40.348385 -103.361534 -v -45.784027 -4.953472 -24.492657 -v -50.866463 5.603586 -39.574917 -v -57.308998 26.079071 -50.401779 -v -58.345963 25.266647 -51.673157 -v -69.433350 12.453951 -75.235397 -v -81.260262 -33.416180 -99.548431 -v -87.625252 -40.699837 -103.631096 -v -42.371857 -4.677759 -24.042709 -v -48.753845 6.009277 -40.427631 -v -56.113029 26.494377 -51.038967 -v -56.596836 25.764732 -53.103985 -v -67.780197 12.700411 -76.835770 -v -81.002632 -32.969162 -100.526863 -v -87.461220 -40.537483 -104.071754 -v -87.871048 -40.017475 -103.858307 -v -44.645119 -3.443838 -21.089790 -v -41.960121 -3.154671 1.817622 -v -49.196304 7.804556 21.293488 -v -54.254692 27.272881 30.448885 -v -55.486473 27.498093 33.976906 -v -67.468346 9.109057 43.496418 -v -85.971497 -32.074684 52.638474 -v -91.959503 -39.732742 57.540760 -v -42.838028 -1.822748 -1.173377 -v -49.368126 8.476757 19.085897 -v -54.925758 28.342400 29.366055 -v -57.455009 28.706230 33.835514 -v -69.611961 9.454971 44.296452 -v -87.014175 -30.514137 52.422035 -v -92.290428 -39.211590 57.382488 -v -45.988678 -1.450131 -2.535743 -v -50.884972 7.785149 17.480999 -v -55.983421 28.087738 28.457573 -v -59.415642 28.146988 32.740971 -v -71.615807 8.682786 43.434380 -v -87.756073 -30.296221 51.631001 -v -92.600067 -39.161705 56.996368 -v -49.039581 -2.317410 -1.243531 -v -52.604645 6.250553 17.687332 -v -56.631248 26.700691 28.407564 -v -59.891945 26.241493 31.517431 -v -71.970940 7.373976 41.559353 -v -87.638519 -31.584965 50.861065 -v -92.655235 -39.620594 56.673161 -v -49.693314 -3.771509 1.730138 -v -53.232193 5.028540 19.549484 -v -56.381416 25.225716 29.253666 -v -58.525230 24.424589 31.086275 -v -70.409966 6.514069 40.083332 -v -86.750092 -33.409981 50.691986 -v -92.414413 -40.242748 56.656296 -v -47.457619 -4.717469 4.146055 -v -52.295036 5.039291 21.665272 -v -55.422035 24.773529 30.358753 -v -56.344688 24.064466 31.772144 -v -68.108238 6.750601 40.117752 -v -85.759720 -34.396961 51.251087 -v -92.058937 -40.559631 56.958412 -v -44.016029 -4.442948 4.184989 -v -50.498901 6.274748 22.441425 -v -54.475548 25.684616 30.890648 -v -54.992317 25.432327 33.058613 -v -66.799141 7.905498 41.636730 -v -85.413208 -33.802715 52.117340 -v -91.856499 -40.332680 57.352055 -v -92.262108 -39.837402 57.079941 -v -45.856201 -3.096684 0.989461 -v -32.535782 -3.154671 -19.162537 -v -35.098988 7.804556 -38.979305 -v -37.554058 27.272881 -51.632816 -v -36.856800 27.498093 -55.304066 -v -39.321587 4.109057 -79.209648 -v -40.877087 -32.426605 -89.889732 -v -43.385780 -41.583160 -95.218742 -v -34.383732 -1.822748 -16.652164 -v -36.351589 8.476757 -37.153374 -v -38.676632 28.342400 -51.030598 -v -38.632298 28.706230 -56.165878 -v -40.777988 4.454971 -80.974312 -v -41.686413 -30.958584 -90.761086 -v -43.694237 -41.068901 -95.434502 -v -37.810333 -1.450131 -16.449551 -v -38.467670 7.785149 -36.521919 -v -40.046833 28.087738 -50.772652 -v -40.877529 28.146988 -56.198307 -v -42.944405 3.682786 -81.229652 -v -42.730568 -30.604935 -90.669960 -v -44.167656 -40.946091 -95.343666 -v -40.235279 -2.317410 -18.707310 -v -39.853783 6.250553 -37.560444 -v -40.632877 26.700691 -51.053253 -v -41.901775 26.241493 -55.376835 -v -44.189468 2.373976 -79.783394 -v -43.223267 -31.631912 -89.685066 -v -44.449516 -41.307182 -95.014656 -v -39.832531 -3.771509 -21.725227 -v -39.466175 5.028540 -39.486904 -v -39.993458 25.225716 -51.661091 -v -40.933758 24.424589 -54.320080 -v -43.575638 1.514069 -77.724648 -v -42.793549 -33.266224 -88.547981 -v -44.327614 -41.880302 -94.695259 -v -36.905369 -4.717469 -23.230795 -v -37.596676 5.039291 -40.850639 -v -38.610062 24.773529 -52.138432 -v -38.702415 24.064466 -53.823795 -v -41.565083 1.750601 -76.603584 -v -41.764935 -34.277184 -88.114983 -v -43.893715 -42.233826 -94.625923 -v -33.658024 -4.442948 -22.090290 -v -35.653107 6.274748 -40.624737 -v -37.524441 25.684616 -52.125816 -v -36.888000 25.432327 -54.261726 -v -39.671886 2.905498 -77.264503 -v -40.912052 -33.903522 -88.712090 -v -43.474564 -42.101616 -94.858925 -v -43.913261 -41.588737 -95.027351 -v -36.480152 -3.096684 -19.716850 -v -32.202831 -2.602407 -2.728741 -v -34.576370 8.107365 17.247396 -v -39.058979 27.085625 30.088219 -v -38.037266 27.494461 33.666477 -v -34.540394 17.314922 46.759007 -v -28.008705 -33.484039 66.392296 -v -28.327166 -39.131874 75.694695 -v -34.502445 -1.655421 -5.032196 -v -36.107876 8.519890 15.562401 -v -40.406155 27.934097 29.606636 -v -39.897282 28.393272 34.709156 -v -35.845226 17.436094 48.666241 -v -28.966595 -31.870440 66.611580 -v -28.696358 -38.612408 75.698051 -v -37.944061 -1.883905 -4.875526 -v -38.125301 7.461887 15.155594 -v -41.730480 27.441978 29.493328 -v -41.995846 27.455360 34.976097 -v -37.806667 16.306143 49.146633 -v -30.060040 -31.714916 66.549873 -v -29.190708 -38.598446 75.644356 -v -39.936069 -3.115807 -2.376659 -v -39.109486 5.730080 16.333321 -v -42.034714 25.979904 29.833651 -v -42.752686 25.387024 34.266190 -v -38.947704 14.775947 47.838451 -v -30.465645 -33.134476 66.253670 -v -29.437933 -39.100452 75.574059 -v -38.978443 -4.423484 0.582626 -v -38.319347 4.628540 18.208712 -v -41.089756 24.648787 30.371326 -v -41.597874 23.745718 33.114037 -v -38.409119 13.997741 45.726810 -v -29.878033 -35.060257 65.945946 -v -29.251896 -39.740452 75.540138 -v -35.792297 -4.822233 1.773979 -v -36.349819 4.986736 19.369556 -v -39.607189 24.451040 30.701448 -v -39.401020 23.767401 32.387234 -v -36.596428 14.557548 44.401737 -v -28.739618 -36.042065 65.858498 -v -28.772676 -40.036469 75.568077 -v -32.776875 -4.011777 0.300282 -v -34.684055 6.534969 18.941736 -v -38.703423 25.535545 30.575422 -v -37.816402 25.435768 32.633106 -v -34.874714 16.033844 44.861141 -v -27.907713 -35.340607 66.057121 -v -28.361128 -39.765636 75.636909 -v -28.862520 -39.283707 75.622292 -v -36.019009 -3.216418 -1.765163 -v -23.494484 -3.472887 -4.813465 -v -14.855604 7.389261 12.463476 -v -12.426659 28.016960 26.410450 -v -10.523695 27.518753 29.595638 -v -0.997257 13.435572 54.882141 -v 3.675970 -31.379181 79.706490 -v 5.211229 -39.983532 86.198250 -v -26.466400 -2.246161 -5.887527 -v -16.258350 8.704388 11.176008 -v -13.152491 29.500343 26.211857 -v -11.264965 29.207901 30.992771 -v -1.514698 14.105843 57.035713 -v 3.385566 -29.843521 80.767952 -v 5.039108 -39.455147 86.510231 -v -29.430336 -1.921316 -4.146553 -v -18.551411 8.964325 11.346706 -v -14.509346 29.827461 26.458410 -v -13.394642 29.560211 31.826565 -v -3.589094 14.206520 58.056274 -v 2.445001 -29.518608 81.251015 -v 4.587766 -39.350231 86.691200 -v -30.154327 -2.742970 -0.901443 -v -20.008060 7.973352 12.847034 -v -15.475464 28.752014 26.964478 -v -15.309046 28.310402 31.469078 -v -5.658417 13.661798 57.175323 -v 1.562493 -30.649029 80.791862 -v 4.197091 -39.747742 86.604866 -v -28.093273 -4.092402 1.404079 -v -19.531422 6.477697 14.547209 -v -15.323357 27.083824 27.348948 -v -15.566597 26.399567 30.189514 -v -6.164387 12.881830 55.056259 -v 1.402615 -32.383606 79.736290 -v 4.161307 -40.348385 86.316307 -v -24.799110 -4.953472 1.033955 -v -17.480396 5.603586 15.166962 -v -14.167568 26.079071 27.322308 -v -13.973347 25.266647 28.951418 -v -4.726027 12.453951 53.294724 -v 2.085765 -33.416180 78.879143 -v 4.507323 -40.699837 86.042763 -v -22.752468 -4.677759 -1.733124 -v -15.399448 6.009277 14.239624 -v -12.878420 26.494377 26.904627 -v -11.729046 25.764732 28.687138 -v -2.426441 12.700411 53.217262 -v 3.097473 -32.969162 78.865883 -v 4.974566 -40.537483 85.990211 -v 4.668339 -40.017475 86.336220 -v -26.455776 -3.443838 -2.149143 -v -23.494484 -3.472887 -15.186539 -v -14.855604 7.389261 -32.463478 -v -12.426659 28.016960 -46.410446 -v -10.523695 27.518753 -49.595634 -v -0.997257 13.435572 -74.882133 -v 3.675970 -31.379181 -99.706490 -v 5.211229 -39.983532 -106.198250 -v -26.466400 -2.246161 -14.112476 -v -16.258350 8.704388 -31.176010 -v -13.152491 29.500343 -46.211853 -v -11.264965 29.207901 -50.992767 -v -1.514698 14.105843 -77.035713 -v 3.385567 -29.843521 -100.767952 -v 5.039108 -39.455147 -106.510231 -v -29.430336 -1.921316 -15.853451 -v -18.551411 8.964325 -31.346710 -v -14.509346 29.827461 -46.458412 -v -13.394642 29.560211 -51.826561 -v -3.589094 14.206520 -78.056267 -v 2.445001 -29.518608 -101.251015 -v 4.587765 -39.350231 -106.691200 -v -30.154327 -2.742970 -19.098560 -v -20.008060 7.973352 -32.847034 -v -15.475464 28.752014 -46.964478 -v -15.309046 28.310402 -51.469078 -v -5.658417 13.661798 -77.175316 -v 1.562493 -30.649029 -100.791862 -v 4.197090 -39.747742 -106.604866 -v -28.093273 -4.092402 -21.404083 -v -19.531422 6.477697 -34.547211 -v -15.323357 27.083824 -47.348946 -v -15.566597 26.399567 -50.189514 -v -6.164387 12.881830 -75.056252 -v 1.402615 -32.383606 -99.736290 -v 4.161308 -40.348385 -106.316307 -v -24.799110 -4.953472 -21.033958 -v -17.480396 5.603586 -35.166962 -v -14.167568 26.079071 -47.322304 -v -13.973347 25.266647 -48.951416 -v -4.726027 12.453951 -73.294716 -v 2.085765 -33.416180 -98.879143 -v 4.507324 -40.699837 -106.042763 -v -22.752468 -4.677759 -18.266880 -v -15.399448 6.009277 -34.239624 -v -12.878420 26.494377 -46.904625 -v -11.729046 25.764732 -48.687134 -v -2.426441 12.700411 -73.217262 -v 3.097473 -32.969162 -98.865883 -v 4.974566 -40.537483 -105.990211 -v 4.668339 -40.017475 -106.336220 -v -26.455776 -3.443838 -17.850861 -v -11.205212 -7.280232 -5.841879 -v -2.877649 5.517601 11.076941 -v 1.745674 26.136940 21.007814 -v 4.282450 26.647736 23.713144 -v 14.860218 5.642468 47.618973 -v 19.200661 -29.660152 61.265373 -v 19.897118 -38.155197 68.039124 -v -14.102657 -6.075779 -7.124460 -v -4.907511 6.093641 10.126818 -v 0.474552 27.209396 20.979715 -v 3.233435 28.024002 25.249430 -v 14.560253 6.223589 49.838684 -v 18.976063 -28.078100 62.273354 -v 19.749865 -37.607536 68.329926 -v -17.115952 -5.533359 -5.528418 -v -7.036675 5.467060 10.781746 -v -0.824137 27.009163 21.510900 -v 1.346554 27.595062 26.518511 -v 12.858335 5.598270 51.276505 -v 18.042278 -27.676632 62.709824 -v 19.300247 -37.467232 68.489960 -v -17.975994 -6.061425 -2.255571 -v -7.661821 4.109711 12.548561 -v -1.172436 25.687050 22.201403 -v 0.042627 25.683922 26.564661 -v 11.036061 4.237392 50.849693 -v 17.102531 -28.757996 62.246178 -v 18.886868 -37.839897 68.398773 -v -16.035194 -7.262345 0.229479 -v -6.312249 3.043694 14.096798 -v -0.308071 24.238619 22.531248 -v 0.303562 23.729671 25.353144 -v 10.465651 3.165695 48.879730 -v 16.864386 -30.507956 61.231514 -v 18.820993 -38.444942 68.125061 -v -12.754986 -8.231801 0.055506 -v -4.004155 3.071719 14.260595 -v 1.118067 23.754597 22.252031 -v 1.932854 23.203932 23.796263 -v 11.576626 3.190188 46.849907 -v 17.507248 -31.608736 60.429893 -v 19.152214 -38.826717 67.874832 -v -10.605457 -8.239758 -2.646498 -v -2.475620 4.172726 12.916639 -v 2.032040 24.599438 21.574022 -v 3.703634 24.502615 23.066408 -v 13.532379 4.292479 46.288857 -v 18.546949 -31.231438 60.444954 -v 19.631145 -38.697784 67.836639 -v 19.348364 -38.148495 68.156281 -v -14.256489 -6.954941 -3.301691 -v -12.538544 -7.280232 -13.491455 -v -4.210981 5.517601 -30.410275 -v 0.412342 26.136940 -40.341148 -v 2.949118 26.647736 -43.046478 -v 13.526886 5.642468 -66.952316 -v 17.867329 -29.660152 -80.598724 -v 18.563786 -38.155197 -87.372467 -v -15.435989 -6.075779 -12.208874 -v -6.240843 6.093641 -29.460152 -v -0.858780 27.209396 -40.313049 -v 1.900103 28.024002 -44.582764 -v 13.226921 6.223589 -69.172028 -v 17.642731 -28.078100 -81.606705 -v 18.416533 -37.607536 -87.663269 -v -18.449284 -5.533359 -13.804916 -v -8.370007 5.467060 -30.115082 -v -2.157469 27.009163 -40.844238 -v 0.013222 27.595062 -45.851845 -v 11.525003 5.598270 -70.609848 -v 16.708946 -27.676632 -82.043167 -v 17.966915 -37.467232 -87.823303 -v -19.309326 -6.061425 -17.077763 -v -8.995153 4.109711 -31.881897 -v -2.505768 25.687050 -41.534737 -v -1.290705 25.683922 -45.897995 -v 9.702729 4.237392 -70.183029 -v 15.769199 -28.757996 -81.579529 -v 17.553535 -37.839897 -87.732117 -v -17.368526 -7.262345 -19.562813 -v -7.645581 3.043694 -33.430130 -v -1.641403 24.238619 -41.864586 -v -1.029770 23.729671 -44.686478 -v 9.132318 3.165695 -68.213074 -v 15.531054 -30.507956 -80.564865 -v 17.487661 -38.444942 -87.458405 -v -14.088318 -8.231801 -19.388840 -v -5.337487 3.071719 -33.593929 -v -0.215265 23.754597 -41.585365 -v 0.599522 23.203932 -43.129601 -v 10.243294 3.190188 -66.183243 -v 16.173916 -31.608736 -79.763245 -v 17.818882 -38.826717 -87.208176 -v -11.938789 -8.239758 -16.686836 -v -3.808952 4.172726 -32.249973 -v 0.698708 24.599438 -40.907356 -v 2.370302 24.502615 -42.399742 -v 12.199047 4.292479 -65.622192 -v 17.213617 -31.231438 -79.778305 -v 18.297813 -38.697784 -87.169983 -v 18.015032 -38.148495 -87.489624 -v -15.589821 -6.954941 -16.031643 -v -66.772987 -11.885618 -0.202999 -v -63.971184 3.661695 -3.830468 -v -61.496513 6.340155 -5.812276 -v -66.772987 -11.885618 -0.202999 -v -64.845985 4.368711 -2.075660 -v -61.447578 8.190097 -3.647036 -v -66.772987 -11.885618 -0.202999 -v -67.137108 4.622091 -1.531196 -v -62.557804 11.305613 -3.485914 -v -66.772987 -11.885618 -0.202999 -v -69.119194 4.231085 -2.607096 -v -63.991096 13.340770 -5.450253 -v -66.772987 -11.885618 -0.202999 -v -69.299873 3.490133 -4.493171 -v -64.668205 12.763025 -8.060863 -v -66.772987 -11.885618 -0.202999 -v -67.542992 2.957121 -5.769162 -v -64.079262 10.007396 -9.351896 -v -66.772987 -11.885618 -0.202999 -v -65.171471 3.033510 -5.474240 -v -62.667759 7.148978 -8.351185 -v -62.986851 9.870845 -6.308486 -v -66.772987 -11.885618 -0.202999 -v -66.724846 1.179926 10.029461 -v -59.689461 8.144950 1.861810 -v -58.212650 12.086802 -3.032124 -v -66.724846 1.179926 10.029461 -v -57.915882 6.628378 1.958869 -v -55.509857 10.279719 -2.976122 -v -66.724846 1.179926 10.029461 -v -56.296860 6.188433 3.356508 -v -52.637226 10.233272 -1.254851 -v -66.724846 1.179926 10.029461 -v -56.051727 7.156466 5.002278 -v -51.757839 11.982401 0.835560 -v -66.724846 1.179926 10.029461 -v -57.364841 8.803489 5.656901 -v -53.533970 14.210047 1.721019 -v -66.724846 1.179926 10.029461 -v -59.247578 9.889247 4.827473 -v -56.628082 15.238695 0.734676 -v -66.724846 1.179926 10.029461 -v -60.282143 9.596194 3.138459 -v -58.710255 14.293749 -1.380639 -v -55.284286 12.617801 -0.764661 -v -66.724846 1.179926 10.029461 -v -53.999989 26.333338 -9.944447 -v -53.999989 2.333334 -9.944447 -v -50.999989 3.941031 -4.748295 -v -53.999989 3.941031 -3.944447 -v -55.800003 6.941027 -4.748295 -v -57.996159 5.774363 -6.944447 -v -58.800007 5.774363 -9.944447 -v -43.607685 8.333335 -9.944447 -v -45.444431 8.333335 -0.081627 -v -48.803837 8.333335 -0.944447 -v -53.999989 10.666674 1.822437 -v -59.196140 8.333335 -0.944447 -v -62.999989 8.333335 -4.748294 -v -64.192299 7.533351 -9.944447 -v -37.199986 18.654428 -9.944447 -v -39.252125 18.654428 -0.061920 -v -43.644428 18.654428 3.756354 -v -53.999989 14.333338 2.055553 -v -61.410072 13.476199 -1.042666 -v -64.609299 13.476199 -6.367094 -v -66.399986 12.333346 -9.944447 -v -38.807682 21.886042 -9.944447 -v -40.644428 21.886042 -0.760713 -v -44.448277 21.886042 2.546009 -v -53.999989 20.333338 0.447858 -v -60.293266 19.476198 -2.199143 -v -63.063873 19.476198 -6.810235 -v -64.392296 20.333338 -9.944447 -v -43.199986 24.251795 -9.944447 -v -44.003834 24.251795 -7.336517 -v -46.644428 24.251795 -0.760711 -v -53.999989 24.725641 -3.944446 -v -56.999985 24.725641 -4.748293 -v -59.196140 24.725641 -6.944447 -v -59.999992 24.725641 -9.944447 -v -61.567451 17.809526 -2.544080 -v -61.859703 18.476198 -3.143273 -v -62.298088 18.642870 -4.042075 -v -62.736469 18.142870 -4.940860 -v -62.955631 16.976198 -5.390261 -v -63.247864 16.309526 -5.989458 -v -63.320908 15.142870 -6.139256 -v -62.955631 14.642870 -5.390261 -v -62.371128 14.476198 -4.191869 -v -61.640526 15.309526 -2.693877 -v -61.421349 16.642870 -2.244477 -v -61.724983 18.155695 -3.369263 -v -61.894066 18.041590 -3.958856 -v -62.070351 17.699663 -4.573657 -v -62.118629 16.981066 -4.741918 -v -62.201881 16.161669 -5.032282 -v -62.366032 15.399149 -5.604844 -v -62.332207 15.061815 -5.486823 -v -62.077385 15.070856 -4.598178 -v -61.738106 15.737185 -3.414914 -v -61.553413 16.745081 -2.770823 -v -61.582451 17.634455 -2.872150 -v -6.305182 -14.182098 -10.000000 -v -6.229439 -10.722575 -0.594703 -v -6.229439 -10.722575 -19.405296 -v -39.194733 -9.356718 -28.479759 -v -31.498898 -9.618716 -16.877310 -v -22.998137 -7.403383 -20.583092 -v -15.182299 -14.329319 -14.042381 -v -32.121948 -11.536249 -10.000000 -v -31.498898 -9.618716 -3.122690 -v -15.182299 -14.329319 -5.957618 -v -44.949730 -12.268521 -17.058643 -v -51.647591 -5.708694 -10.000000 -v -44.949730 -12.268521 -2.941359 -v -49.713837 -2.983590 1.421121 -v -39.194733 -9.356718 8.479760 -v -22.998137 -7.403383 0.583091 -v -49.713837 -2.983590 -21.421116 -v -53.999989 26.333338 -9.988887 -v -53.999989 2.333334 -9.988887 -v -50.999989 3.941031 -15.185039 -v -53.999989 3.941031 -15.988886 -v -55.800003 6.941027 -15.185039 -v -57.996159 5.774363 -12.988887 -v -58.800007 5.774363 -9.988887 -v -43.607685 8.333335 -9.988887 -v -45.444431 8.333335 -19.851706 -v -48.803837 8.333335 -18.988886 -v -53.999989 10.666674 -21.755770 -v -59.196140 8.333335 -18.988886 -v -62.999989 8.333335 -15.185039 -v -64.192299 7.533351 -9.988887 -v -37.199986 18.654428 -9.988887 -v -39.252125 18.654428 -19.871412 -v -43.644428 18.654428 -23.689688 -v -53.999989 14.333338 -21.988886 -v -61.410072 13.476199 -18.890669 -v -64.609299 13.476199 -13.566239 -v -66.399986 12.333346 -9.988887 -v -38.807682 21.886042 -9.988887 -v -40.644428 21.886042 -19.172621 -v -44.448277 21.886042 -22.479342 -v -53.999989 20.333338 -20.381189 -v -60.293266 19.476198 -17.734190 -v -63.063873 19.476198 -13.123098 -v -64.392296 20.333338 -9.988887 -v -43.199986 24.251795 -9.988887 -v -44.003834 24.251795 -12.596816 -v -46.644428 24.251795 -19.172621 -v -53.999989 24.725641 -15.988886 -v -56.999985 24.725641 -15.185040 -v -59.196140 24.725641 -12.988887 -v -59.999992 24.725641 -9.988887 -v -61.567451 17.809526 -17.389254 -v -61.859703 18.476198 -16.790060 -v -62.298088 18.642870 -15.891256 -v -62.736469 18.142870 -14.992473 -v -62.955631 16.976198 -14.543073 -v -63.247864 16.309526 -13.943875 -v -63.320908 15.142870 -13.794078 -v -62.955631 14.642870 -14.543073 -v -62.371128 14.476198 -15.741465 -v -61.640526 15.309526 -17.239454 -v -61.421349 16.642870 -17.688856 -v -61.724983 18.155695 -16.564070 -v -61.894066 18.041590 -15.974478 -v -62.070351 17.699663 -15.359674 -v -62.118629 16.981066 -15.191415 -v -62.201881 16.161669 -14.901052 -v -62.366032 15.399149 -14.328490 -v -62.332207 15.061815 -14.446509 -v -62.077385 15.070856 -15.335154 -v -61.738106 15.737185 -16.518419 -v -61.553413 16.745081 -17.162512 -v -61.582451 17.634455 -17.061182 -v -66.591156 -11.976528 -20.112152 -v -63.789349 3.570786 -16.484684 -v -61.314701 6.249245 -14.502876 -v -66.591156 -11.976528 -20.112152 -v -64.664154 4.277802 -18.239491 -v -61.265766 8.099188 -16.668116 -v -66.591156 -11.976528 -20.112152 -v -66.955276 4.531182 -18.783955 -v -62.375992 11.214703 -16.829237 -v -66.591156 -11.976528 -20.112152 -v -68.937363 4.140175 -17.708055 -v -63.809261 13.249859 -14.864899 -v -66.591156 -11.976528 -20.112152 -v -69.118042 3.399224 -15.821981 -v -64.486374 12.672115 -12.254288 -v -66.591156 -11.976528 -20.112152 -v -67.361160 2.866211 -14.545990 -v -63.897427 9.916485 -10.963255 -v -66.591156 -11.976528 -20.112152 -v -64.989639 2.942601 -14.840912 -v -62.485947 7.058069 -11.963966 -v -62.805038 9.779934 -14.006666 -v -66.591156 -11.976528 -20.112152 -v -66.724846 1.234471 -28.696123 -v -59.689461 8.199495 -20.528475 -v -58.212650 12.141348 -15.634542 -v -66.724846 1.234471 -28.696123 -v -57.915882 6.682923 -20.625532 -v -55.509857 10.334265 -15.690544 -v -66.724846 1.234471 -28.696123 -v -56.296860 6.242978 -22.023172 -v -52.637226 10.287817 -17.411816 -v -66.724846 1.234471 -28.696123 -v -56.051727 7.211011 -23.668943 -v -51.757839 12.036945 -19.502226 -v -66.724846 1.234471 -28.696123 -v -57.364841 8.858034 -24.323565 -v -53.533970 14.264591 -20.387682 -v -66.724846 1.234471 -28.696123 -v -59.247578 9.943792 -23.494139 -v -56.628082 15.293240 -19.401342 -v -66.724846 1.234471 -28.696123 -v -60.282143 9.650740 -21.805124 -v -58.710255 14.348293 -17.286026 -v -55.284286 12.672346 -17.902004 -v -66.724846 1.234471 -28.696123 -v -59.670547 17.670856 -1.853035 -v -58.743614 17.518467 -2.271704 -v -59.467049 18.406742 -2.538975 -v -60.637596 18.103474 -2.337921 -v -61.555885 18.154240 -3.372073 -v -60.575226 18.690861 -3.431842 -v -61.644852 18.262333 -4.609260 -v -61.384178 17.941105 -5.717274 -v -61.278061 15.979283 -6.500585 -v -61.481544 16.983921 -6.448156 -v -62.267357 17.284794 -5.621511 -v -62.614960 16.491169 -5.094203 -v -62.204987 16.131672 -6.081918 -v -62.267357 15.544271 -4.988010 -v -61.384178 14.979936 -4.639498 -v -61.481544 15.243386 -5.814656 -v -60.474304 15.084535 -3.543311 -v -59.564423 15.709020 -2.636348 -v -61.644852 15.446095 -3.584234 -v -61.555885 16.324146 -2.705970 -v -60.575226 15.874639 -2.406815 -v -60.637596 17.027775 -1.946398 -v -59.467049 16.666218 -1.905474 -v -61.745773 17.311893 -2.839265 -v -62.368286 17.410069 -4.243031 -v -62.368286 16.334370 -3.851508 -v -59.670547 17.404190 -17.880299 -v -58.743614 17.251801 -17.461630 -v -59.467049 18.140076 -17.194359 -v -60.637596 17.836807 -17.395412 -v -61.555885 17.887573 -16.361259 -v -60.575226 18.424194 -16.301491 -v -61.644852 17.995667 -15.124073 -v -61.384178 17.674438 -14.016060 -v -61.278061 15.712616 -13.232748 -v -61.481544 16.717255 -13.285177 -v -62.267357 17.018127 -14.111822 -v -62.614960 16.224503 -14.639130 -v -62.204987 15.865005 -13.651415 -v -62.267357 15.277603 -14.745323 -v -61.384178 14.713268 -15.093836 -v -61.481544 14.976719 -13.918678 -v -60.474304 14.817867 -16.190023 -v -59.564423 15.442352 -17.096985 -v -61.644852 15.179428 -16.149099 -v -61.555885 16.057480 -17.027363 -v -60.575226 15.607971 -17.326519 -v -60.637596 16.761108 -17.786934 -v -59.467049 16.399551 -17.827860 -v -61.745773 17.045227 -16.894068 -v -62.368286 17.143402 -15.490303 -v -62.368286 16.067703 -15.881825 -# 762 vertices - -vt 0.186192 0.222718 -vt 0.503180 0.039063 -vt 0.236448 0.237339 -vt 0.381464 0.276197 -vt 0.574917 0.134554 -vt 0.746941 0.113737 -vt 0.074073 0.345855 -vt 0.049334 0.521438 -vt 0.156004 0.412922 -vt 0.156004 0.629954 -vt 0.381464 0.801928 -vt 0.360095 0.539063 -vt 0.619252 0.384554 -vt 0.619252 0.693571 -vt 0.822369 0.539063 -vt 0.834074 0.289063 -vt 1.023438 0.539063 -vt 0.972818 0.539063 -vt 0.922506 0.289063 -vt 0.834074 0.789063 -vt 0.746941 0.964388 -vt 0.922506 0.789063 -vt 0.574917 0.943571 -vt 0.236448 0.805537 -vt 0.186192 0.820158 -vt 0.503180 1.039063 -vt 0.284677 0.805537 -vt 0.624896 0.801928 -vt 0.718002 0.943571 -vt 0.850769 0.693571 -vt 0.646266 0.539063 -vt 0.624896 0.276197 -vt 0.850769 0.384554 -vt 0.234041 0.629954 -vt 0.100045 0.521438 -vt 0.234041 0.412922 -vt 0.103881 0.345855 -vt 0.284677 0.237339 -vt 0.718002 0.134554 -vt 0.023438 0.521438 -vt 0.074073 0.697021 -vt 0.103881 0.697021 -vt -0.065871 -0.410016 -vt 0.403088 -0.109437 -vt 0.127441 -0.364995 -vt 0.403088 0.184267 -vt 0.678735 0.008835 -vt 1.058291 -0.016948 -vt -0.318566 -0.030837 -vt -0.355704 0.509840 -vt -0.042919 0.175683 -vt -0.042919 0.843998 -vt 0.403088 0.835414 -vt 0.403088 0.509840 -vt 1.035339 0.318473 -vt 1.035339 0.701207 -vt 1.348124 0.509840 -vt 1.310985 0.064592 -vt 1.481345 0.509840 -vt 1.310985 0.955089 -vt 1.058291 1.036629 -vt 0.678735 1.010846 -vt 0.127441 1.384675 -vt -0.065871 1.429696 -vt 0.403088 1.129117 -vt -0.488925 0.509840 -vt -0.318566 1.050518 -vt 0.000000 1.000000 -vt 0.000000 0.000000 -vt 0.000000 0.166667 -vt 0.142857 0.166667 -vt 0.142857 0.000000 -vt 0.000000 0.333333 -vt 0.142857 0.333333 -vt 0.000000 0.500000 -vt 0.142857 0.500000 -vt 0.000000 0.666667 -vt 0.142857 0.666667 -vt 0.000000 0.833333 -vt 0.142857 0.833333 -vt 0.142857 1.000000 -vt 0.285714 0.000000 -vt 0.285714 0.166667 -vt 0.285714 0.333333 -vt 0.285714 0.500000 -vt 0.285714 0.666667 -vt 0.285714 0.833333 -vt 0.285714 1.000000 -vt 0.428571 0.166667 -vt 0.428571 0.000000 -vt 0.428571 0.333333 -vt 0.428571 0.500000 -vt 0.428571 0.666667 -vt 0.428571 0.833333 -vt 0.428571 1.000000 -vt 0.571429 0.000000 -vt 0.571429 0.166667 -vt 0.571429 0.333333 -vt 0.571429 0.500000 -vt 0.571429 0.666667 -vt 0.571429 0.833333 -vt 0.571429 1.000000 -vt 0.714286 0.166667 -vt 0.714286 0.000000 -vt 0.714286 0.333333 -vt 0.714286 0.500000 -vt 0.714286 0.666667 -vt 0.714286 0.833333 -vt 0.714286 1.000000 -vt 0.857143 0.000000 -vt 0.857143 0.166667 -vt 0.857143 0.333333 -vt 0.857143 0.500000 -vt 0.857143 0.666667 -vt 0.857143 0.833333 -vt 0.857143 1.000000 -vt 1.000000 0.166667 -vt 1.000000 0.000000 -vt 1.000000 0.333333 -vt 1.000000 0.500000 -vt 1.000000 0.666667 -vt 1.000000 0.833333 -vt 1.000000 1.000000 -vt 0.332919 0.272694 -vt 0.446895 0.397773 -vt 0.456977 0.422004 -vt 0.402899 0.410469 -vt 0.406626 0.379392 -vt 0.370970 0.384244 -vt 0.399625 0.431850 -vt 0.359907 0.385983 -vt 0.439539 0.445817 -vt 0.381768 0.383299 -vt 0.492584 0.441852 -vt 0.420092 0.378214 -vt 0.518816 0.422941 -vt 0.446019 0.374556 -vt 0.498483 0.403324 -vt 0.440026 0.375080 -vt 0.344810 0.338084 -vt 0.488018 0.424091 -vt 0.463158 0.428278 -vt 0.487405 0.409841 -vt 0.434361 0.393007 -vt 0.433297 0.381048 -vt 0.468532 0.409475 -vt 0.417973 0.377579 -vt 0.445613 0.423268 -vt 0.399928 0.385213 -vt 0.435904 0.440834 -vt 0.392751 0.398200 -vt 0.446719 0.448945 -vt 0.401845 0.406762 -vt 0.469911 0.441494 -vt 0.420363 0.404451 -vt 0.190349 0.913269 -vt 0.000000 0.913269 -vt 0.670306 0.913269 -vt 0.379259 0.066987 -vt 0.437931 0.066987 -vt 0.437931 0.933013 -vt 0.379259 0.191987 -vt 0.379259 0.933013 -vt 0.218965 0.143376 -vt 0.218965 0.933013 -vt 0.000000 0.143376 -vt 0.000000 0.933013 -vt 0.719872 0.250000 -vt 0.656896 0.250000 -vt 0.858846 0.347222 -vt 0.379259 0.250000 -vt 0.000000 0.216667 -vt 0.000000 0.250000 -vt 0.000000 0.680045 -vt 0.721310 0.680045 -vt 1.000000 0.680045 -vt 0.875861 0.500000 -vt 0.649727 0.464286 -vt 0.261105 0.464286 -vt 0.000000 0.416667 -vt 0.000000 0.814696 -vt 0.670306 0.814696 -vt 0.911659 0.814696 -vt 0.758518 0.750000 -vt 0.565318 0.714286 -vt 0.228761 0.714286 -vt 0.000000 0.750000 -vt 0.277735 0.533731 -vt 0.316741 0.544409 -vt 0.325355 0.530353 -vt 0.332403 0.512897 -vt 0.419872 0.505953 -vt 0.390216 0.530730 -vt 0.476580 0.558494 -vt 0.529208 0.540675 -vt 0.523592 0.600489 -vt 0.562009 0.596231 -vt 0.516196 0.637547 -vt 0.540141 0.644841 -vt 0.479912 0.659265 -vt 0.496407 0.672619 -vt 0.430805 0.679564 -vt 0.436879 0.654511 -vt 0.365204 0.658731 -vt 0.392006 0.640264 -vt 0.379724 0.610322 -vt 0.332403 0.610119 -vt 0.358531 0.576181 -vt 0.288668 0.582341 -vt 0.445345 0.686077 -vt 0.607126 0.786343 -vt 0.816422 0.609373 -vt 0.978203 0.754476 -vt 0.445345 0.500000 -vt 0.445345 0.313923 -vt 0.816422 0.390627 -vt 0.183578 0.690983 -vt 0.183578 0.309017 -vt 0.021797 0.190983 -vt 0.283564 0.000000 -vt 0.607126 0.213657 -vt 0.978203 0.245524 -vt 0.283564 1.000000 -vt 0.021797 0.809017 -vt 1.000000 0.913269 -vt 0.809651 0.913269 -vt 0.329694 0.913269 -vt 0.562069 0.066987 -vt 0.620741 0.066987 -vt 0.562069 0.933013 -vt 0.620741 0.191987 -vt 0.620741 0.933013 -vt 0.781035 0.143376 -vt 0.781035 0.933013 -vt 1.000000 0.143376 -vt 1.000000 0.933013 -vt 0.343104 0.250000 -vt 0.280128 0.250000 -vt 0.141154 0.347222 -vt 0.620741 0.250000 -vt 1.000000 0.216667 -vt 1.000000 0.250000 -vt 0.278690 0.680045 -vt 0.124139 0.500000 -vt 0.350273 0.464286 -vt 0.738895 0.464286 -vt 1.000000 0.416667 -vt 0.329694 0.814696 -vt 1.000000 0.814696 -vt 0.088341 0.814696 -vt 0.241482 0.750000 -vt 0.434682 0.714286 -vt 0.771239 0.714286 -vt 1.000000 0.750000 -vt 0.674645 0.530353 -vt 0.683259 0.544409 -vt 0.722265 0.533731 -vt 0.667597 0.512897 -vt 0.580128 0.505953 -vt 0.609784 0.530730 -vt 0.523420 0.558494 -vt 0.470792 0.540675 -vt 0.437991 0.596231 -vt 0.476408 0.600489 -vt 0.459859 0.644841 -vt 0.483804 0.637547 -vt 0.520088 0.659265 -vt 0.503593 0.672619 -vt 0.569195 0.679564 -vt 0.563121 0.654511 -vt 0.634796 0.658731 -vt 0.607995 0.640264 -vt 0.620276 0.610322 -vt 0.667597 0.610119 -vt 0.641469 0.576181 -vt 0.711332 0.582341 -vt 1.046875 0.772010 -vt 0.956791 0.730945 -vt 0.899283 0.970312 -vt 0.942544 0.888589 -vt 0.720028 0.902269 -vt 0.707168 1.046875 -vt 0.453826 0.931398 -vt 0.215418 0.844835 -vt 0.058156 0.586898 -vt 0.236023 0.667976 -vt 0.349482 0.454114 -vt 0.136958 0.357239 -vt 0.046875 0.316174 -vt 0.372331 0.198949 -vt 0.447320 0.046875 -vt 0.194464 0.117868 -vt 0.683183 0.075062 -vt 0.674378 0.172493 -vt 0.863351 0.409106 -vt 0.927720 0.287975 -vt 0.878332 0.243345 -vt 1.026786 0.598716 -vt 1.035592 0.501285 -vt 0.834671 0.675278 -vt 0.532626 0.701734 -vt 0.616869 0.411861 -# 302 texture coordinates - -vn -0.537588 -0.071798 0.840146 -vn -0.151555 -0.017111 0.988301 -vn -0.510264 0.347193 0.786822 -vn -0.383883 0.724753 0.572160 -vn 0.006791 0.547083 0.837051 -vn 0.441964 0.160862 0.882492 -vn -0.810413 0.184718 0.555976 -vn -0.915534 0.402240 -0.000000 -vn -0.710113 0.620185 0.333331 -vn -0.721673 0.607891 -0.331145 -vn -0.413629 0.701858 -0.579920 -vn -0.409411 0.912350 0.000434 -vn 0.132323 0.938010 0.320355 -vn 0.132323 0.938010 -0.320355 -vn 0.339768 0.940509 -0.000000 -vn 0.481852 0.617859 0.621345 -vn 0.881337 0.472488 -0.000000 -vn 0.942952 -0.332930 -0.000000 -vn 0.795204 -0.092522 0.599242 -vn 0.481852 0.617859 -0.621345 -vn 0.441964 0.160862 -0.882492 -vn 0.795204 -0.092522 -0.599242 -vn -0.012521 0.539701 -0.841764 -vn -0.544858 0.327294 -0.772016 -vn -0.561303 -0.075179 -0.824189 -vn -0.195775 -0.027076 -0.980275 -vn -0.299847 -0.529265 -0.793707 -vn 0.144885 -0.802478 -0.578824 -vn 0.343163 -0.420370 -0.839957 -vn 0.704306 -0.633502 -0.320355 -vn 0.260986 -0.965343 0.000322 -vn 0.173226 -0.803252 0.569894 -vn 0.704306 -0.633502 0.320355 -vn -0.346230 -0.872998 -0.343510 -vn -0.769195 -0.639014 0.000000 -vn -0.334289 -0.877615 0.343575 -vn -0.728104 -0.400942 0.555976 -vn -0.264904 -0.527345 0.807300 -vn 0.359321 -0.413990 0.836362 -vn -0.990268 -0.139173 -0.000000 -vn -0.810413 0.184718 -0.555976 -vn -0.728104 -0.400942 -0.555976 -vn -0.236279 0.029185 0.971247 -vn 0.320907 -0.108176 0.940913 -vn 0.232851 0.492069 0.838838 -vn 0.401159 0.816009 0.416173 -vn 0.362076 0.383575 0.849571 -vn 0.126098 -0.040972 0.991171 -vn -0.604687 0.614896 0.506218 -vn -0.478910 0.877864 -0.000000 -vn 0.038576 0.969348 0.242645 -vn 0.038576 0.969348 -0.242645 -vn 0.401159 0.816009 -0.416173 -vn 0.360915 0.932599 0.000000 -vn 0.494411 0.798675 0.343038 -vn 0.494411 0.798675 -0.343038 -vn 0.861265 0.508156 -0.000000 -vn 0.647910 0.246087 0.720870 -vn 0.951057 -0.309017 -0.000000 -vn 0.743317 -0.668940 -0.000000 -vn 0.535463 -0.362827 0.762651 -vn 0.647910 0.246086 -0.720870 -vn 0.126098 -0.040972 -0.991171 -vn 0.535463 -0.362827 -0.762651 -vn 0.362076 0.383575 -0.849571 -vn 0.232851 0.492069 -0.838838 -vn -0.236279 0.029185 -0.971247 -vn 0.320907 -0.108176 -0.940913 -vn 0.132934 -0.415219 -0.899956 -vn 0.188857 -0.970911 -0.147192 -vn 0.199321 -0.435181 -0.878003 -vn -0.862018 0.083023 0.500032 -vn 0.132934 -0.415219 0.899956 -vn 0.199321 -0.435181 0.878002 -vn 0.188857 -0.970911 0.147192 -vn -0.930205 0.367040 -0.000000 -vn -0.997640 0.068658 -0.000000 -vn -0.604687 0.614896 -0.506218 -vn -0.862018 0.083023 -0.500032 -vn 0.021383 -0.916512 0.399436 -vn -0.781862 -0.431561 -0.449942 -vn 0.956336 0.228461 -0.182283 -vn 0.833901 -0.104561 -0.541919 -vn 0.767800 0.601842 0.219702 -vn 0.546124 0.782549 0.298940 -vn 0.910925 0.174919 -0.373656 -vn 0.748758 0.661676 -0.039313 -vn 0.949258 -0.047485 -0.310893 -vn 0.406836 0.802260 -0.436879 -vn 0.769156 0.182669 -0.612398 -vn 0.199512 0.609083 -0.767602 -vn 0.667603 0.001959 -0.744515 -vn -0.099388 0.414937 -0.904405 -vn 0.352774 0.079499 -0.932325 -vn -0.283318 0.420843 -0.861755 -vn -0.057479 0.857527 0.511218 -vn 0.131724 0.743022 0.656177 -vn -0.005809 0.859552 0.511016 -vn -0.350571 0.931431 -0.097655 -vn -0.647693 0.664816 -0.372173 -vn -0.898309 0.404808 -0.170794 -vn -0.866249 0.480043 -0.138459 -vn -0.715121 0.360250 0.599018 -vn -0.866625 0.341770 0.363530 -vn -0.662377 0.297013 0.687780 -vn -0.811725 0.388839 0.435782 -vn -0.950899 0.243388 0.191190 -vn -0.846773 0.078043 0.526199 -vn -0.759416 0.140950 0.635154 -vn -0.940011 -0.340515 -0.020693 -vn -0.972400 -0.204991 0.111430 -vn -0.817030 -0.331766 0.471585 -vn -0.616700 -0.385898 0.686122 -vn -0.565415 -0.413211 0.713837 -vn -0.342437 -0.316577 0.884599 -vn -0.263317 -0.310224 0.913469 -vn -0.492073 -0.677280 -0.546952 -vn -0.216535 -0.832588 -0.509814 -vn -0.336313 -0.936688 -0.097510 -vn 0.085084 -0.882948 0.461697 -vn 0.196057 -0.733951 0.650291 -vn 0.454815 -0.615703 0.643470 -vn 0.489338 -0.710824 0.505250 -vn 0.458185 -0.654603 -0.601300 -vn 0.273617 -0.575276 -0.770838 -vn 0.557258 -0.641859 -0.526765 -vn 0.770791 -0.636825 0.018306 -vn 0.873238 -0.487283 0.003170 -vn 0.878760 -0.285726 -0.382285 -vn 0.775252 -0.453136 -0.440060 -vn 0.076768 -0.902254 -0.424317 -vn -0.760858 -0.310029 0.570067 -vn 0.698983 0.632728 -0.333285 -vn 0.918945 -0.018611 0.393945 -vn 0.946923 0.242706 0.210787 -vn 0.597706 0.775902 -0.201801 -vn 0.898457 0.395975 0.189682 -vn 0.584977 0.777578 -0.230597 -vn 0.061121 0.865503 0.497161 -vn 0.814891 0.173456 0.553052 -vn 0.488324 0.052196 0.871100 -vn -0.073338 0.372458 0.925147 -vn -0.168557 0.420636 0.891433 -vn 0.562606 0.011650 0.826643 -vn 0.424549 0.220069 0.878253 -vn -0.202274 0.574889 0.792835 -vn -0.201495 0.870711 -0.448622 -vn -0.147519 0.700066 -0.698674 -vn -0.247406 0.680029 -0.690182 -vn -0.659229 0.742690 -0.117596 -vn -0.823828 0.514402 0.238115 -vn -0.880755 0.462224 0.103053 -vn -0.835446 0.538148 0.111476 -vn -0.835433 0.291149 -0.466138 -vn -0.799017 0.476863 -0.366296 -vn -0.796565 -0.008375 -0.604495 -vn -0.746076 0.124458 -0.654126 -vn -0.847027 0.257512 -0.465008 -vn -0.774335 0.094113 -0.625738 -vn -0.799434 0.067311 -0.596971 -vn -0.914826 -0.403289 0.021240 -vn -0.960708 -0.276547 0.023720 -vn -0.776094 -0.562737 -0.284613 -vn -0.248105 -0.514857 -0.820589 -vn -0.231599 -0.234207 -0.944198 -vn -0.235950 -0.324119 -0.916119 -vn -0.342337 -0.448272 -0.825747 -vn -0.389047 -0.677991 0.623675 -vn -0.286549 -0.868467 0.404542 -vn -0.058292 -0.911347 0.407491 -vn 0.455951 -0.795072 -0.399962 -vn 0.489715 -0.524665 -0.696352 -vn 0.515843 -0.636580 -0.573300 -vn 0.423912 -0.809501 -0.406210 -vn 0.535603 -0.635581 0.556027 -vn 0.490862 -0.467516 0.735176 -vn 0.731377 -0.368576 0.573793 -vn 0.890119 -0.387697 0.239538 -vn 0.883630 -0.404120 0.236399 -vn 0.822699 -0.324540 0.466733 -vn 0.789247 -0.408589 0.458414 -vn -0.072988 -0.902254 0.424984 -vn -0.288148 -0.512224 -0.809072 -vn 0.918806 0.383987 0.091372 -vn 0.993163 0.114096 -0.024688 -vn 0.434383 0.709098 0.555420 -vn 0.471863 0.805177 0.359216 -vn 0.868051 0.441893 0.226313 -vn 0.386966 0.811178 0.438461 -vn 0.971729 0.236044 0.005163 -vn 0.277939 0.903859 -0.325252 -vn 0.907561 0.183989 -0.377467 -vn 0.389798 0.457680 -0.799116 -vn 0.974181 -0.045977 -0.221037 -vn 0.441749 0.266583 -0.856616 -vn 0.886674 0.017475 -0.462065 -vn 0.372092 0.327554 -0.868479 -vn -0.385080 0.834046 0.395071 -vn -0.476106 0.659961 0.581185 -vn -0.556161 0.685573 0.469761 -vn -0.626859 0.745436 -0.226656 -vn -0.554271 0.436146 -0.708915 -vn -0.561559 0.310302 -0.767049 -vn -0.543810 0.416915 -0.728322 -vn -0.974714 0.176358 0.137223 -vn -0.917252 0.369282 0.149263 -vn -0.982764 -0.036304 0.181267 -vn -0.987205 0.070377 0.143084 -vn -0.988708 0.090661 -0.119319 -vn -0.995465 0.069805 -0.064628 -vn -0.986899 0.153108 -0.050882 -vn -0.785702 -0.546219 -0.290374 -vn -0.802167 -0.447423 -0.395400 -vn -0.788300 -0.609188 -0.086443 -vn -0.635308 -0.586832 0.502008 -vn -0.748920 -0.342648 0.567196 -vn -0.829075 -0.199820 0.522213 -vn -0.811409 -0.243593 0.531299 -vn -0.029726 -0.712976 -0.700558 -vn -0.121255 -0.870385 -0.477207 -vn 0.151176 -0.929851 -0.335445 -vn 0.202841 -0.825731 0.526331 -vn 0.080914 -0.528183 0.845266 -vn 0.010675 -0.474241 0.880330 -vn 0.014489 -0.635546 0.771927 -vn 0.742724 -0.545146 -0.388814 -vn 0.786510 -0.383302 -0.484233 -vn 0.920594 -0.358142 -0.155695 -vn 0.889767 -0.359426 0.281297 -vn 0.873005 -0.294226 0.388965 -vn 0.907656 -0.291730 0.301752 -vn 0.863097 -0.445709 0.237502 -vn 0.041443 -0.908865 -0.415027 -vn -0.109957 -0.084548 0.990334 -vn 0.245131 0.763260 -0.597783 -vn 0.955445 0.284327 -0.079261 -vn 0.823805 0.535171 -0.186913 -vn 0.285353 0.867913 -0.406571 -vn 0.750150 0.580981 -0.315809 -vn 0.193001 0.857724 -0.476509 -vn 0.122062 0.961258 0.247151 -vn 0.890764 0.429947 -0.147257 -vn 0.869360 0.404802 0.283458 -vn 0.342558 0.602318 0.721018 -vn 0.449593 0.557051 0.698255 -vn 0.979971 0.160598 0.117751 -vn 0.912952 0.330027 0.240004 -vn 0.396960 0.742707 0.539267 -vn -0.562652 0.747701 -0.352655 -vn -0.640733 0.557163 -0.528234 -vn -0.712118 0.570582 -0.409053 -vn -0.719414 0.632988 0.285953 -vn -0.541635 0.392908 0.743139 -vn -0.506872 0.445328 0.738081 -vn -0.530036 0.658014 0.534864 -vn -0.999398 0.002857 -0.034586 -vn -0.977859 0.202556 -0.052566 -vn -0.974887 -0.208763 -0.077548 -vn -0.990809 -0.134971 -0.008911 -vn -0.971468 -0.084083 0.221765 -vn -0.983987 -0.035832 0.174602 -vn -0.987930 0.055655 0.144559 -vn -0.644785 -0.668339 0.370912 -vn -0.667256 -0.571980 0.477084 -vn -0.657389 -0.734501 0.168369 -vn -0.560535 -0.736307 -0.379015 -vn -0.692904 -0.540327 -0.477421 -vn -0.805447 -0.450708 -0.384860 -vn -0.807097 -0.552297 -0.208715 -vn 0.166809 -0.694562 0.699828 -vn 0.081505 -0.869441 0.487268 -vn 0.344060 -0.883528 0.317807 -vn 0.303265 -0.806548 -0.507455 -vn 0.132506 -0.587487 -0.798312 -vn 0.022610 -0.693630 -0.719976 -vn 0.045100 -0.923914 -0.379933 -vn 0.862122 -0.401541 0.309048 -vn 0.886724 -0.232862 0.399368 -vn 0.979859 -0.190892 0.058615 -vn 0.901262 -0.198277 -0.385245 -vn 0.854374 -0.181939 -0.486768 -vn 0.901238 -0.252507 -0.352151 -vn 0.898278 -0.412999 -0.150093 -vn -0.272473 -0.916512 -0.292854 -vn 0.247462 -0.431597 0.867460 -vn 0.375319 0.601842 -0.704927 -vn 0.969100 -0.104559 -0.223412 -vn 0.795449 0.228463 -0.561307 -vn 0.164332 0.782548 -0.600511 -vn 0.901567 0.174919 -0.395701 -vn 0.548411 0.661676 -0.511303 -vn 0.596875 0.802261 0.010829 -vn 0.883048 -0.047484 -0.466875 -vn 0.975847 0.140489 -0.167289 -vn 0.695006 0.600563 0.395335 -vn 0.804391 0.375485 0.460397 -vn 0.950455 -0.062330 -0.304551 -vn 0.989975 0.079498 -0.116747 -vn 0.767612 0.420846 0.483385 -vn -0.407667 0.857527 -0.313775 -vn -0.380509 0.743022 -0.550574 -vn -0.371629 0.859552 -0.350803 -vn -0.173281 0.931431 0.320017 -vn -0.088344 0.681833 0.726154 -vn -0.097862 0.460784 0.882100 -vn -0.075217 0.480042 0.874015 -vn -0.927662 0.360250 0.098302 -vn -0.863510 0.341772 0.370868 -vn -0.954873 0.297012 -0.001297 -vn -0.877348 0.388838 0.281187 -vn -0.798205 0.258643 0.544033 -vn -0.830945 0.129933 0.540970 -vn -0.800009 0.140946 0.583197 -vn -0.638103 -0.340513 0.690562 -vn -0.755642 -0.204991 0.622080 -vn -0.906786 -0.331767 0.260133 -vn -0.921950 -0.385899 -0.033004 -vn -0.932303 -0.360848 -0.024508 -vn -0.971643 -0.236380 0.005919 -vn -0.950036 -0.310227 0.034503 -vn 0.051621 -0.677280 0.733912 -vn 0.216310 -0.832587 0.509910 -vn -0.163481 -0.936688 0.309662 -vn -0.273013 -0.882948 -0.381925 -vn -0.334489 -0.728676 -0.597619 -vn -0.408235 -0.602580 -0.685741 -vn -0.371857 -0.710825 -0.597035 -vn 0.750822 -0.654602 0.088107 -vn 0.744565 -0.575276 0.338646 -vn 0.766027 -0.641859 -0.034936 -vn 0.522268 -0.636825 -0.567176 -vn 0.527667 -0.527467 -0.665842 -vn 0.641037 -0.375221 -0.669538 -vn 0.614542 -0.453134 -0.645761 -vn -0.272476 -0.916512 0.292854 -vn 0.247445 -0.431549 -0.867488 -vn 0.795449 0.228463 0.561307 -vn 0.969100 -0.104559 0.223412 -vn 0.375318 0.601842 0.704927 -vn 0.164332 0.782548 0.600511 -vn 0.901567 0.174919 0.395701 -vn 0.548410 0.661676 0.511303 -vn 0.883047 -0.047485 0.466875 -vn 0.596875 0.802261 -0.010829 -vn 0.975847 0.140489 0.167289 -vn 0.695006 0.600564 -0.395336 -vn 0.950454 -0.062330 0.304551 -vn 0.804391 0.375485 -0.460397 -vn 0.989975 0.079498 0.116747 -vn 0.767611 0.420846 -0.483385 -vn -0.407667 0.857527 0.313775 -vn -0.380509 0.743022 0.550574 -vn -0.371629 0.859552 0.350803 -vn -0.173281 0.931431 -0.320017 -vn -0.088345 0.681833 -0.726154 -vn -0.097862 0.460784 -0.882100 -vn -0.075217 0.480042 -0.874015 -vn -0.927662 0.360250 -0.098302 -vn -0.863510 0.341772 -0.370868 -vn -0.954873 0.297012 0.001297 -vn -0.877348 0.388838 -0.281187 -vn -0.798205 0.258643 -0.544033 -vn -0.830945 0.129933 -0.540970 -vn -0.800010 0.140945 -0.583196 -vn -0.638103 -0.340513 -0.690562 -vn -0.755642 -0.204991 -0.622081 -vn -0.906786 -0.331767 -0.260133 -vn -0.921950 -0.385899 0.033004 -vn -0.932303 -0.360848 0.024508 -vn -0.971643 -0.236380 -0.005919 -vn -0.950036 -0.310227 -0.034503 -vn 0.051621 -0.677280 -0.733912 -vn 0.216310 -0.832587 -0.509910 -vn -0.163481 -0.936687 -0.309662 -vn -0.273013 -0.882948 0.381925 -vn -0.334488 -0.728676 0.597620 -vn -0.408235 -0.602580 0.685741 -vn -0.371857 -0.710825 0.597035 -vn 0.750822 -0.654602 -0.088107 -vn 0.744565 -0.575276 -0.338646 -vn 0.766027 -0.641859 0.034936 -vn 0.522268 -0.636825 0.567177 -vn 0.527667 -0.527467 0.665842 -vn 0.641037 -0.375221 0.669538 -vn 0.614542 -0.453134 0.645761 -vn -0.287103 -0.930941 -0.225656 -vn 0.184368 -0.421801 0.887746 -vn 0.074051 0.631917 -0.771490 -vn 0.855333 0.060647 -0.514517 -vn 0.730773 0.322890 -0.601426 -vn 0.209807 0.742786 -0.635807 -vn 0.616222 0.371327 -0.694540 -vn 0.095819 0.746431 -0.658528 -vn 0.408064 0.912344 0.033360 -vn 0.821336 0.180467 -0.541146 -vn 0.969682 0.166170 -0.179176 -vn 0.754037 0.504418 0.420704 -vn 0.828561 0.316590 0.461798 -vn 0.943283 -0.080094 -0.322182 -vn 0.996799 0.009221 -0.079417 -vn 0.775768 0.382141 0.502148 -vn -0.535922 0.815786 -0.217442 -vn -0.711742 0.631198 -0.308241 -vn -0.720586 0.670982 -0.174754 -vn -0.411496 0.796168 0.443607 -vn -0.094379 0.527301 0.844421 -vn -0.069752 0.407704 0.910446 -vn -0.075227 0.509317 0.857284 -vn -0.899322 0.217218 0.379522 -vn -0.856971 0.404836 0.318918 -vn -0.929488 0.002263 0.368846 -vn -0.913020 0.111991 0.392239 -vn -0.775244 0.155507 0.612221 -vn -0.809953 0.130294 0.571839 -vn -0.809970 0.211451 0.547026 -vn -0.512438 -0.473965 0.716075 -vn -0.470746 -0.365488 0.803005 -vn -0.622708 -0.554524 0.552030 -vn -0.804795 -0.592927 -0.027236 -vn -0.935688 -0.349566 -0.047865 -vn -0.979826 -0.199093 0.017388 -vn -0.969660 -0.244405 0.004995 -vn 0.346030 -0.645322 0.681045 -vn 0.150051 -0.816598 0.557361 -vn 0.305963 -0.903395 0.300439 -vn -0.106894 -0.879100 -0.464497 -vn -0.379304 -0.604701 -0.700332 -vn -0.457451 -0.550271 -0.698527 -vn -0.396771 -0.701295 -0.592249 -vn 0.835906 -0.548834 -0.006518 -vn 0.923602 -0.381844 0.033966 -vn 0.863214 -0.393372 -0.316418 -vn 0.605500 -0.431678 -0.668598 -vn 0.534229 -0.375452 -0.757387 -vn 0.609831 -0.367158 -0.702354 -vn 0.606094 -0.512127 -0.608586 -vn -0.287104 -0.930941 0.225655 -vn 0.184384 -0.421751 -0.887766 -vn 0.730773 0.322890 0.601426 -vn 0.855333 0.060647 0.514517 -vn 0.074051 0.631917 0.771490 -vn 0.209807 0.742786 0.635807 -vn 0.616222 0.371327 0.694540 -vn 0.095818 0.746431 0.658528 -vn 0.821336 0.180467 0.541145 -vn 0.408064 0.912344 -0.033360 -vn 0.969682 0.166170 0.179175 -vn 0.754037 0.504418 -0.420704 -vn 0.943283 -0.080094 0.322182 -vn 0.828560 0.316590 -0.461799 -vn 0.996799 0.009221 0.079417 -vn 0.775768 0.382141 -0.502148 -vn -0.535922 0.815786 0.217442 -vn -0.711742 0.631198 0.308241 -vn -0.720586 0.670982 0.174754 -vn -0.411496 0.796168 -0.443607 -vn -0.094380 0.527301 -0.844421 -vn -0.069752 0.407704 -0.910446 -vn -0.075227 0.509317 -0.857285 -vn -0.899322 0.217218 -0.379522 -vn -0.856971 0.404836 -0.318918 -vn -0.929488 0.002263 -0.368845 -vn -0.913020 0.111991 -0.392239 -vn -0.775244 0.155506 -0.612221 -vn -0.809952 0.130294 -0.571839 -vn -0.809969 0.211450 -0.547027 -vn -0.512438 -0.473965 -0.716075 -vn -0.470746 -0.365488 -0.803005 -vn -0.622708 -0.554524 -0.552030 -vn -0.804795 -0.592928 0.027236 -vn -0.935688 -0.349566 0.047865 -vn -0.979826 -0.199093 -0.017388 -vn -0.969660 -0.244405 -0.004995 -vn 0.346030 -0.645322 -0.681045 -vn 0.150051 -0.816598 -0.557361 -vn 0.305964 -0.903395 -0.300439 -vn -0.106895 -0.879100 0.464496 -vn -0.379305 -0.604701 0.700332 -vn -0.457451 -0.550271 0.698527 -vn -0.396771 -0.701294 0.592249 -vn 0.835906 -0.548834 0.006518 -vn 0.923602 -0.381844 -0.033966 -vn 0.863214 -0.393373 0.316418 -vn 0.605500 -0.431679 0.668598 -vn 0.534230 -0.375452 0.757387 -vn 0.609831 -0.367158 0.702354 -vn 0.606094 -0.512126 0.608586 -vn 0.000000 0.000000 0.000000 -vn 0.891945 0.333606 -0.305190 -vn 0.885286 -0.051708 0.462163 -vn 0.871701 -0.486404 -0.059574 -vn 0.602535 -0.114023 0.789906 -vn 0.767332 -0.613878 0.185353 -vn 0.615704 -0.238766 0.750932 -vn -0.132228 0.076598 0.988255 -vn -0.134483 0.218923 0.966430 -vn -0.082654 0.333036 0.939285 -vn -0.794263 0.362851 0.487325 -vn -0.686973 0.538875 0.487527 -vn -0.911656 -0.242414 -0.331840 -vn -0.903470 -0.005854 -0.428611 -vn -0.880207 0.284493 -0.379868 -vn -0.359072 -0.293407 -0.885991 -vn -0.531215 -0.161650 -0.831673 -vn 0.521710 -0.333452 -0.785257 -vn 0.498223 -0.518213 -0.695147 -vn 0.319252 -0.666930 -0.673263 -vn 0.417209 0.602930 -0.680009 -vn -0.390952 -0.506393 -0.768585 -vn -0.785847 -0.219916 -0.577999 -vn -0.112803 -0.767065 -0.631575 -vn -0.676852 -0.452073 -0.580948 -vn -0.070613 -0.785109 -0.615320 -vn 0.404464 -0.913005 -0.053206 -vn 0.510041 -0.851111 -0.124372 -vn 0.600863 -0.776753 -0.188727 -vn 0.734160 -0.298249 0.609964 -vn 0.802855 -0.245127 0.543449 -vn 0.203920 0.286548 0.936113 -vn 0.259058 0.346923 0.901407 -vn 0.305077 0.413607 0.857821 -vn -0.395140 0.672313 0.625987 -vn -0.388204 0.672327 0.630297 -vn -0.844407 0.508563 -0.168344 -vn -0.907377 0.410201 -0.091666 -vn -0.943128 0.331776 0.020840 -vn -0.032685 0.987521 0.154060 -vn 0.285617 0.953018 0.100890 -vn 0.356408 0.929723 0.092678 -vn 0.058045 0.915295 0.398579 -vn -0.438098 -0.839825 0.320570 -vn 0.039808 -0.749385 0.660937 -vn -0.436422 -0.758689 0.483660 -vn -0.144622 0.858467 0.492057 -vn -0.390508 -0.802547 0.451023 -vn -0.378955 0.768626 0.515371 -vn -0.351840 -0.855427 0.380071 -vn -0.503913 0.811284 0.296463 -vn -0.434503 -0.886238 0.160593 -vn -0.589554 0.766850 0.253707 -vn 0.461124 -0.566742 0.682765 -vn -0.033279 -0.530249 0.847189 -vn -0.155076 -0.479386 0.863794 -vn -0.332554 -0.675497 0.658112 -vn -0.624353 -0.649034 0.434671 -vn -0.640430 -0.723275 0.258307 -vn 0.839146 -0.520972 0.156274 -vn 0.979386 -0.047392 0.196359 -vn 0.859197 -0.013066 0.511478 -vn 0.169781 0.017978 0.985318 -vn -0.298124 0.093164 0.949970 -vn -0.602581 0.140795 0.785540 -vn -0.760623 0.356880 0.542300 -vn -0.916442 -0.012784 0.399964 -vn 0.709959 0.689780 0.141992 -vn 0.616328 0.711155 0.338227 -vn 0.121528 0.638102 0.760300 -vn -0.308158 0.474484 0.824563 -vn -0.584949 0.497866 0.640284 -vn -0.831395 0.369875 0.414699 -vn -0.777389 0.439755 0.449757 -vn -0.712098 0.074375 0.698130 -vn -0.522162 -0.582125 0.623279 -vn -0.536293 0.842625 0.048710 -vn -0.627855 0.740316 0.240274 -vn -0.817995 0.476796 0.321792 -vn -0.729171 0.655795 0.195555 -vn -0.958544 0.215108 0.186875 -vn -0.950592 0.163928 0.263634 -vn -0.983392 -0.022830 0.180052 -vn -0.891745 0.110754 0.438776 -vn -0.991858 -0.087830 0.092218 -vn -0.859104 0.044821 0.509835 -vn -0.894952 -0.402899 0.191658 -vn -0.903611 0.009093 0.428257 -vn -0.889320 0.017457 0.456952 -vn -0.731541 -0.492421 0.471561 -vn -0.794103 -0.178378 0.581017 -vn -0.625933 -0.373553 0.684592 -vn -0.584508 -0.184831 0.790056 -vn -0.801518 -0.104269 0.588809 -vn -0.642031 -0.296727 0.706929 -vn -0.820281 -0.123456 0.558478 -vn 0.016905 -0.936472 -0.350333 -vn -0.098795 -0.739900 -0.665423 -vn -0.069462 -0.936749 -0.343039 -vn 0.123931 -0.992291 -0.000000 -vn 0.035891 -0.855981 -0.515760 -vn -0.028951 -0.999581 0.000000 -vn 0.016905 -0.936472 0.350333 -vn -0.069462 -0.936749 0.343039 -vn -0.334402 -0.916161 -0.220964 -vn -0.790477 -0.612492 -0.000000 -vn -0.334402 -0.916161 0.220964 -vn -0.741010 -0.556660 0.375544 -vn -0.274313 -0.889661 0.365042 -vn -0.098795 -0.739900 0.665423 -vn 0.035891 -0.855981 0.515760 -vn -0.274313 -0.889661 -0.365042 -vn -0.741010 -0.556660 -0.375544 -vn 0.356408 0.929723 -0.092678 -vn 0.285617 0.953018 -0.100890 -vn -0.032685 0.987521 -0.154060 -vn 0.058045 0.915295 -0.398579 -vn -0.436422 -0.758689 -0.483660 -vn 0.039808 -0.749385 -0.660937 -vn -0.438098 -0.839825 -0.320570 -vn -0.144622 0.858467 -0.492057 -vn -0.390508 -0.802547 -0.451023 -vn -0.378955 0.768626 -0.515371 -vn -0.351840 -0.855427 -0.380071 -vn -0.503913 0.811284 -0.296463 -vn -0.434503 -0.886238 -0.160593 -vn -0.589554 0.766850 -0.253707 -vn -0.033279 -0.530249 -0.847189 -vn 0.461124 -0.566742 -0.682765 -vn -0.155076 -0.479386 -0.863794 -vn -0.332554 -0.675497 -0.658112 -vn -0.624352 -0.649034 -0.434671 -vn -0.640430 -0.723275 -0.258307 -vn 0.979386 -0.047392 -0.196359 -vn 0.839147 -0.520972 -0.156274 -vn 0.859197 -0.013067 -0.511478 -vn 0.169781 0.017978 -0.985318 -vn -0.298124 0.093164 -0.949970 -vn -0.602580 0.140795 -0.785540 -vn -0.760623 0.356880 -0.542300 -vn -0.916442 -0.012784 -0.399964 -vn 0.616328 0.711155 -0.338227 -vn 0.709959 0.689780 -0.141992 -vn 0.121527 0.638102 -0.760300 -vn -0.308158 0.474484 -0.824563 -vn -0.584949 0.497867 -0.640284 -vn -0.831395 0.369875 -0.414699 -vn -0.777389 0.439755 -0.449757 -vn -0.536292 0.842626 -0.048710 -vn -0.522164 -0.582123 -0.623280 -vn -0.712098 0.074377 -0.698129 -vn -0.627854 0.740316 -0.240274 -vn -0.817995 0.476797 -0.321792 -vn -0.729171 0.655796 -0.195555 -vn -0.958544 0.215108 -0.186875 -vn -0.950592 0.163928 -0.263634 -vn -0.891745 0.110753 -0.438776 -vn -0.983392 -0.022830 -0.180053 -vn -0.859104 0.044821 -0.509834 -vn -0.991858 -0.087831 -0.092217 -vn -0.894953 -0.402899 -0.191657 -vn -0.903611 0.009093 -0.428257 -vn -0.889320 0.017458 -0.456952 -vn -0.731541 -0.492420 -0.471561 -vn -0.794103 -0.178378 -0.581018 -vn -0.625932 -0.373553 -0.684593 -vn -0.584507 -0.184830 -0.790056 -vn -0.801518 -0.104269 -0.588809 -vn -0.642031 -0.296727 -0.706930 -vn -0.820281 -0.123456 -0.558478 -vn 0.891944 0.333618 0.305179 -vn 0.602535 -0.114021 -0.789905 -vn 0.871702 -0.486402 0.059575 -vn 0.885285 -0.051707 -0.462165 -vn 0.767335 -0.613875 -0.185352 -vn 0.615706 -0.238765 -0.750931 -vn -0.132228 0.076598 -0.988255 -vn -0.134482 0.218923 -0.966430 -vn -0.082654 0.333036 -0.939284 -vn -0.794263 0.362851 -0.487325 -vn -0.686973 0.538875 -0.487526 -vn -0.911656 -0.242414 0.331840 -vn -0.903470 -0.005854 0.428611 -vn -0.880207 0.284493 0.379868 -vn -0.359072 -0.293407 0.885991 -vn -0.531215 -0.161650 0.831673 -vn 0.521709 -0.333452 0.785258 -vn 0.498223 -0.518212 0.695148 -vn 0.319253 -0.666929 0.673264 -vn 0.417208 0.602931 0.680009 -vn -0.112803 -0.767065 0.631575 -vn -0.785847 -0.219916 0.577998 -vn -0.390952 -0.506392 0.768585 -vn -0.676852 -0.452073 0.580948 -vn -0.070613 -0.785108 0.615320 -vn 0.404464 -0.913005 0.053206 -vn 0.510042 -0.851111 0.124372 -vn 0.600863 -0.776753 0.188727 -vn 0.734160 -0.298249 -0.609964 -vn 0.802854 -0.245127 -0.543450 -vn 0.203920 0.286548 -0.936113 -vn 0.259058 0.346923 -0.901407 -vn 0.305077 0.413607 -0.857821 -vn -0.395140 0.672312 -0.625988 -vn -0.388204 0.672327 -0.630297 -vn -0.844407 0.508563 0.168344 -vn -0.907377 0.410201 0.091666 -vn -0.943128 0.331776 -0.020840 -vn 0.092832 0.340544 0.935634 -vn 0.433215 0.308260 0.846936 -vn 0.075136 0.741809 0.666389 -vn -0.375593 0.622444 0.686654 -vn -0.641388 0.689588 0.336288 -vn -0.353918 0.873123 0.335258 -vn -0.662764 0.746241 -0.062188 -vn -0.545563 0.658509 -0.518389 -vn -0.542286 0.268594 -0.796105 -vn -0.776382 0.468027 -0.422116 -vn -0.995559 -0.032197 -0.088459 -vn -0.738154 -0.230737 -0.633948 -vn -0.433216 -0.308258 -0.846936 -vn -0.776385 -0.629857 -0.022517 -vn -0.467564 -0.874397 0.129668 -vn -0.542292 -0.717476 -0.437204 -vn -0.189834 -0.854102 0.484223 -vn -0.545805 -0.711395 0.442735 -vn -0.641391 -0.312091 0.700868 -vn -0.215356 -0.623780 0.751346 -vn 0.037501 -0.724698 0.688046 -vn -0.375594 -0.035443 0.926107 -vn 0.078137 -0.268605 0.960076 -vn -0.757385 0.223328 0.613590 -vn -0.902417 0.400663 0.158468 -vn -0.902417 -0.205066 0.378934 -vn 0.075136 0.741809 -0.666389 -vn 0.433215 0.308260 -0.846936 -vn 0.092832 0.340544 -0.935635 -vn -0.375593 0.622444 -0.686654 -vn -0.353918 0.873123 -0.335257 -vn -0.641388 0.689588 -0.336288 -vn -0.662764 0.746241 0.062188 -vn -0.776382 0.468027 0.422116 -vn -0.542286 0.268594 0.796105 -vn -0.545562 0.658510 0.518389 -vn -0.738154 -0.230737 0.633948 -vn -0.995559 -0.032196 0.088459 -vn -0.433216 -0.308258 0.846936 -vn -0.776385 -0.629856 0.022517 -vn -0.542292 -0.717477 0.437204 -vn -0.467565 -0.874397 -0.129668 -vn -0.545805 -0.711394 -0.442736 -vn -0.189834 -0.854102 -0.484223 -vn -0.215356 -0.623779 -0.751346 -vn -0.641391 -0.312091 -0.700869 -vn 0.037501 -0.724698 -0.688046 -vn -0.375594 -0.035443 -0.926106 -vn 0.078136 -0.268605 -0.960076 -vn -0.757384 0.223328 -0.613590 -vn -0.902417 0.400663 -0.158468 -vn -0.902417 -0.205066 -0.378934 -# 747 normals - -g HLeib01 -usemtl HLeibTex -s 1 -f 1/1/1 2/2/2 3/3/3 -f 4/4/4 3/3/3 5/5/5 -f 6/6/6 5/5/5 2/2/2 -f 3/3/3 2/2/2 5/5/5 -f 1/1/1 3/3/3 7/7/7 -f 8/8/8 7/7/7 9/9/9 -f 4/4/4 9/9/9 3/3/3 -f 7/7/7 3/3/3 9/9/9 -f 8/8/8 9/9/9 10/10/10 -f 11/11/11 10/10/10 12/12/12 -f 4/4/4 12/12/12 9/9/9 -f 10/10/10 9/9/9 12/12/12 -f 4/4/4 13/13/13 12/12/12 -f 11/11/11 12/12/12 14/14/14 -f 15/15/15 14/14/14 13/13/13 -f 12/12/12 13/13/13 14/14/14 -f 4/4/4 5/5/5 13/13/13 -f 15/15/15 13/13/13 16/16/16 -f 6/6/6 16/16/16 5/5/5 -f 13/13/13 5/5/5 16/16/16 -f 15/15/15 16/16/16 17/17/17 -f 18/18/18 17/17/17 19/19/19 -f 6/6/6 19/19/19 16/16/16 -f 17/17/17 16/16/16 19/19/19 -f 15/15/15 17/17/17 20/20/20 -f 21/21/21 20/20/20 22/22/22 -f 18/18/18 22/22/22 17/17/17 -f 20/20/20 17/17/17 22/22/22 -f 11/11/11 14/14/14 23/23/23 -f 21/21/21 23/23/23 20/20/20 -f 15/15/15 20/20/20 14/14/14 -f 23/23/23 14/14/14 20/20/20 -f 11/11/11 23/23/23 24/24/24 -f 25/25/25 24/24/24 26/26/26 -f 21/21/21 26/26/26 23/23/23 -f 24/24/24 23/23/23 26/26/26 -f 25/25/25 26/26/26 27/27/27 -f 28/28/28 27/27/27 29/29/29 -f 21/21/21 29/29/29 26/26/26 -f 27/27/27 26/26/26 29/29/29 -f 28/28/28 29/29/29 30/30/30 -f 18/18/18 30/30/30 22/22/22 -f 21/21/21 22/22/22 29/29/29 -f 30/30/30 29/29/29 22/22/22 -f 28/28/28 30/30/30 31/31/31 -f 32/32/32 31/31/31 33/33/33 -f 18/18/18 33/33/33 30/30/30 -f 31/31/31 30/30/30 33/33/33 -f 28/28/28 31/31/31 34/34/34 -f 35/35/35 34/34/34 36/36/36 -f 32/32/32 36/36/36 31/31/31 -f 34/34/34 31/31/31 36/36/36 -f 35/35/35 36/36/36 37/37/37 -f 1/1/1 37/37/37 38/38/38 -f 32/32/32 38/38/38 36/36/36 -f 37/37/37 36/36/36 38/38/38 -f 1/1/1 38/38/38 2/2/2 -f 6/6/6 2/2/2 39/39/39 -f 32/32/32 39/39/39 38/38/38 -f 2/2/2 38/38/38 39/39/39 -f 32/32/32 33/33/33 39/39/39 -f 6/6/6 39/39/39 19/19/19 -f 18/18/18 19/19/19 33/33/33 -f 39/39/39 33/33/33 19/19/19 -f 8/8/8 40/40/40 7/7/7 -f 1/1/1 7/7/7 37/37/37 -f 35/35/35 37/37/37 40/40/40 -f 7/7/7 40/40/40 37/37/37 -f 8/8/8 41/41/41 40/40/40 -f 35/35/35 40/40/40 42/42/42 -f 25/25/25 42/42/42 41/41/41 -f 40/40/40 41/41/41 42/42/42 -f 8/8/8 10/10/10 41/41/41 -f 25/25/25 41/41/41 24/24/24 -f 11/11/11 24/24/24 10/10/10 -f 41/41/41 10/10/10 24/24/24 -f 28/28/28 34/34/34 27/27/27 -f 25/25/25 27/27/27 42/42/42 -f 35/35/35 42/42/42 34/34/34 -f 27/27/27 34/34/34 42/42/42 -# 80 triangles in group - -g OK -usemtl Skin -f 43/43/43 44/44/44 45/45/45 -f 46/46/46 45/45/45 47/47/47 -f 48/48/48 47/47/47 44/44/44 -f 45/45/45 44/44/44 47/47/47 -f 43/43/43 45/45/45 49/49/49 -f 50/50/50 49/49/49 51/51/51 -f 46/46/46 51/51/51 45/45/45 -f 49/49/49 45/45/45 51/51/51 -f 50/50/50 51/51/51 52/52/52 -f 53/53/53 52/52/52 54/54/54 -f 46/46/46 54/54/54 51/51/51 -f 52/52/52 51/51/51 54/54/54 -f 46/46/46 55/55/55 54/54/54 -f 53/53/53 54/54/54 56/56/56 -f 57/57/57 56/56/56 55/55/55 -f 54/54/54 55/55/55 56/56/56 -f 46/46/46 47/47/47 55/55/55 -f 57/57/57 55/55/55 58/58/58 -f 48/48/48 58/58/58 47/47/47 -f 55/55/55 47/47/47 58/58/58 -f 57/57/57 58/58/58 59/59/59 -f 60/57/60 59/59/59 61/58/61 -f 48/48/48 61/58/61 58/58/58 -f 59/59/59 58/58/58 61/58/61 -f 57/57/57 59/59/59 62/60/62 -f 63/61/63 62/60/62 64/60/64 -f 60/57/60 64/60/64 59/59/59 -f 62/60/62 59/59/59 64/60/64 -f 53/53/53 56/56/56 65/62/65 -f 63/61/63 65/62/65 62/60/62 -f 57/57/57 62/60/62 56/56/56 -f 65/62/65 56/56/56 62/60/62 -f 53/53/53 65/62/65 66/63/66 -f 67/64/67 66/63/66 68/65/68 -f 63/61/63 68/65/68 65/62/65 -f 66/63/66 65/62/65 68/65/68 -f 67/64/67 68/65/68 69/63/69 -f 70/53/70 69/63/69 71/62/71 -f 63/61/63 71/62/71 68/65/68 -f 69/63/69 68/65/68 71/62/71 -f 63/61/63 64/60/64 71/62/71 -f 43/43/43 74/49/72 75/45/73 -f 43/43/43 75/45/73 44/44/44 -f 48/48/48 44/44/44 76/47/74 -f 72/46/75 76/47/74 75/45/73 -f 44/44/44 75/45/73 76/47/74 -f 48/48/48 76/47/74 61/58/61 -f 50/50/50 77/66/76 49/49/49 -f 43/43/43 49/49/49 74/49/72 -f 73/50/77 74/49/72 77/66/76 -f 49/49/49 77/66/76 74/49/72 -f 50/50/50 78/67/78 77/66/76 -f 73/50/77 77/66/76 79/67/79 -f 67/64/67 79/67/79 78/67/78 -f 77/66/76 78/67/78 79/67/79 -f 50/50/50 52/52/52 78/67/78 -f 67/64/67 78/67/78 66/63/66 -f 53/53/53 66/63/66 52/52/52 -f 78/67/78 52/52/52 66/63/66 -f 67/64/67 69/63/69 79/67/79 -# 60 triangles in group - -g Bein1Li -usemtl BeinTex -s 2 -f 80/68/80 87/68/80 130/68/80 -f 86/68/81 129/68/81 93/68/81 -s 1 -f 80/69/82 81/70/83 88/71/84 -f 80/69/82 88/71/84 87/72/85 -f 81/70/83 82/73/86 88/71/84 -f 82/73/86 89/74/87 88/71/84 -f 82/73/86 83/75/88 90/76/89 -f 82/73/86 90/76/89 89/74/87 -f 83/75/88 84/77/90 90/76/89 -f 84/77/90 91/78/91 90/76/89 -f 84/77/90 85/79/92 92/80/93 -f 84/77/90 92/80/93 91/78/91 -f 85/79/92 86/68/94 92/80/93 -f 86/68/94 93/81/95 92/80/93 -s 2 -f 87/68/80 94/68/80 130/68/80 -f 93/68/81 129/68/81 100/68/81 -s 1 -f 87/72/85 88/71/84 94/82/96 -f 88/71/84 95/83/97 94/82/96 -f 88/71/84 89/74/87 96/84/98 -f 88/71/84 96/84/98 95/83/97 -f 89/74/87 90/76/89 96/84/98 -f 90/76/89 97/85/99 96/84/98 -f 90/76/89 91/78/91 98/86/100 -f 90/76/89 98/86/100 97/85/99 -f 91/78/91 92/80/93 98/86/100 -f 92/80/93 99/87/101 98/86/100 -f 92/80/93 93/81/95 100/88/102 -f 92/80/93 100/88/102 99/87/101 -s 2 -f 94/68/80 101/68/80 130/68/80 -f 100/68/81 129/68/81 107/68/81 -s 1 -f 94/82/96 95/83/97 102/89/103 -f 94/82/96 102/89/103 101/90/104 -f 95/83/97 96/84/98 102/89/103 -f 96/84/98 103/91/105 102/89/103 -f 96/84/98 97/85/99 104/92/106 -f 96/84/98 104/92/106 103/91/105 -f 97/85/99 98/86/100 104/92/106 -f 98/86/100 105/93/107 104/92/106 -f 98/86/100 99/87/101 106/94/108 -f 98/86/100 106/94/108 105/93/107 -f 99/87/101 100/88/102 106/94/108 -f 100/88/102 107/95/109 106/94/108 -s 2 -f 101/68/80 108/68/80 130/68/80 -f 107/68/81 129/68/81 114/68/81 -s 1 -f 101/90/104 102/89/103 108/96/110 -f 102/89/103 109/97/111 108/96/110 -f 102/89/103 103/91/105 110/98/112 -f 102/89/103 110/98/112 109/97/111 -f 103/91/105 104/92/106 110/98/112 -f 104/92/106 111/99/113 110/98/112 -f 104/92/106 105/93/107 112/100/114 -f 104/92/106 112/100/114 111/99/113 -f 105/93/107 106/94/108 112/100/114 -f 106/94/108 113/101/115 112/100/114 -f 106/94/108 107/95/109 114/102/116 -f 106/94/108 114/102/116 113/101/115 -s 2 -f 108/68/80 115/68/80 130/68/80 -f 114/68/81 129/68/81 121/68/81 -s 1 -f 108/96/110 109/97/111 116/103/117 -f 108/96/110 116/103/117 115/104/118 -f 109/97/111 110/98/112 116/103/117 -f 110/98/112 117/105/119 116/103/117 -f 110/98/112 111/99/113 118/106/120 -f 110/98/112 118/106/120 117/105/119 -f 111/99/113 112/100/114 118/106/120 -f 112/100/114 119/107/121 118/106/120 -f 112/100/114 113/101/115 120/108/122 -f 112/100/114 120/108/122 119/107/121 -f 113/101/115 114/102/116 120/108/122 -f 114/102/116 121/109/123 120/108/122 -s 2 -f 115/68/80 122/68/80 130/68/80 -f 121/68/81 129/68/81 128/68/81 -s 1 -f 115/104/118 116/103/117 122/110/124 -f 116/103/117 123/111/125 122/110/124 -f 116/103/117 117/105/119 124/112/126 -f 116/103/117 124/112/126 123/111/125 -f 117/105/119 118/106/120 124/112/126 -f 118/106/120 125/113/127 124/112/126 -f 118/106/120 119/107/121 126/114/128 -f 118/106/120 126/114/128 125/113/127 -f 119/107/121 120/108/122 126/114/128 -f 120/108/122 127/115/129 126/114/128 -f 120/108/122 121/109/123 128/116/130 -f 120/108/122 128/116/130 127/115/129 -s 2 -f 122/68/80 80/68/80 130/68/80 -f 128/68/81 129/68/81 86/68/81 -s 1 -f 122/110/124 123/111/125 81/117/83 -f 122/110/124 81/117/83 80/118/82 -f 123/111/125 124/112/126 81/117/83 -f 124/112/126 82/119/86 81/117/83 -f 124/112/126 125/113/127 83/120/88 -f 124/112/126 83/120/88 82/119/86 -f 125/113/127 126/114/128 83/120/88 -f 126/114/128 84/121/90 83/120/88 -f 126/114/128 127/115/129 85/122/92 -f 126/114/128 85/122/92 84/121/90 -f 127/115/129 128/116/130 85/122/92 -f 128/116/130 86/123/94 85/122/92 -# 98 triangles in group - -g Bein1Re -usemtl BeinTex -s 2 -f 181/68/131 138/68/131 131/68/131 -f 144/68/132 180/68/132 137/68/132 -s 1 -f 139/71/133 132/70/134 131/69/135 -f 138/72/136 139/71/133 131/69/135 -f 139/71/133 133/73/137 132/70/134 -f 139/71/133 140/74/138 133/73/137 -f 141/76/139 134/75/140 133/73/137 -f 140/74/138 141/76/139 133/73/137 -f 141/76/139 135/77/141 134/75/140 -f 141/76/139 142/78/142 135/77/141 -f 143/80/143 136/79/144 135/77/141 -f 142/78/142 143/80/143 135/77/141 -f 143/80/143 137/68/145 136/79/144 -f 143/80/143 144/81/146 137/68/145 -s 2 -f 181/68/131 145/68/131 138/68/131 -f 151/68/132 180/68/132 144/68/132 -s 1 -f 145/82/147 139/71/133 138/72/136 -f 145/82/147 146/83/148 139/71/133 -f 147/84/149 140/74/138 139/71/133 -f 146/83/148 147/84/149 139/71/133 -f 147/84/149 141/76/139 140/74/138 -f 147/84/149 148/85/150 141/76/139 -f 149/86/151 142/78/142 141/76/139 -f 148/85/150 149/86/151 141/76/139 -f 149/86/151 143/80/143 142/78/142 -f 149/86/151 150/87/152 143/80/143 -f 151/88/153 144/81/146 143/80/143 -f 150/87/152 151/88/153 143/80/143 -s 2 -f 181/68/131 152/68/131 145/68/131 -f 158/68/132 180/68/132 151/68/132 -s 1 -f 153/89/154 146/83/148 145/82/147 -f 152/90/155 153/89/154 145/82/147 -f 153/89/154 147/84/149 146/83/148 -f 153/89/154 154/91/156 147/84/149 -f 155/92/157 148/85/150 147/84/149 -f 154/91/156 155/92/157 147/84/149 -f 155/92/157 149/86/151 148/85/150 -f 155/92/157 156/93/158 149/86/151 -f 157/94/159 150/87/152 149/86/151 -f 156/93/158 157/94/159 149/86/151 -f 157/94/159 151/88/153 150/87/152 -f 157/94/159 158/95/160 151/88/153 -s 2 -f 181/68/131 159/68/131 152/68/131 -f 165/68/132 180/68/132 158/68/132 -s 1 -f 159/96/161 153/89/154 152/90/155 -f 159/96/161 160/97/162 153/89/154 -f 161/98/163 154/91/156 153/89/154 -f 160/97/162 161/98/163 153/89/154 -f 161/98/163 155/92/157 154/91/156 -f 161/98/163 162/99/164 155/92/157 -f 163/100/165 156/93/158 155/92/157 -f 162/99/164 163/100/165 155/92/157 -f 163/100/165 157/94/159 156/93/158 -f 163/100/165 164/101/166 157/94/159 -f 165/102/167 158/95/160 157/94/159 -f 164/101/166 165/102/167 157/94/159 -s 2 -f 181/68/131 166/68/131 159/68/131 -f 172/68/132 180/68/132 165/68/132 -s 1 -f 167/103/168 160/97/162 159/96/161 -f 166/104/169 167/103/168 159/96/161 -f 167/103/168 161/98/163 160/97/162 -f 167/103/168 168/105/170 161/98/163 -f 169/106/171 162/99/164 161/98/163 -f 168/105/170 169/106/171 161/98/163 -f 169/106/171 163/100/165 162/99/164 -f 169/106/171 170/107/172 163/100/165 -f 171/108/173 164/101/166 163/100/165 -f 170/107/172 171/108/173 163/100/165 -f 171/108/173 165/102/167 164/101/166 -f 171/108/173 172/109/174 165/102/167 -s 2 -f 181/68/131 173/68/131 166/68/131 -f 179/68/132 180/68/132 172/68/132 -s 1 -f 173/110/175 167/103/168 166/104/169 -f 173/110/175 174/111/176 167/103/168 -f 175/112/177 168/105/170 167/103/168 -f 174/111/176 175/112/177 167/103/168 -f 175/112/177 169/106/171 168/105/170 -f 175/112/177 176/113/178 169/106/171 -f 177/114/179 170/107/172 169/106/171 -f 176/113/178 177/114/179 169/106/171 -f 177/114/179 171/108/173 170/107/172 -f 177/114/179 178/115/180 171/108/173 -f 179/116/181 172/109/174 171/108/173 -f 178/115/180 179/116/181 171/108/173 -s 2 -f 181/68/131 131/68/131 173/68/131 -f 137/68/132 180/68/132 179/68/132 -s 1 -f 132/117/134 174/111/176 173/110/175 -f 131/118/135 132/117/134 173/110/175 -f 132/117/134 175/112/177 174/111/176 -f 132/117/134 133/119/137 175/112/177 -f 134/120/140 176/113/178 175/112/177 -f 133/119/137 134/120/140 175/112/177 -f 134/120/140 177/114/179 176/113/178 -f 134/120/140 135/121/141 177/114/179 -f 136/122/144 178/115/180 177/114/179 -f 135/121/141 136/122/144 177/114/179 -f 136/122/144 179/116/181 178/115/180 -f 136/122/144 137/123/145 179/116/181 -# 98 triangles in group - -g Bein2Li -usemtl BeinTex -s 2 -f 182/68/182 189/68/182 232/68/182 -f 188/68/183 231/68/183 195/68/183 -s 1 -f 182/69/184 183/70/185 190/71/186 -f 182/69/184 190/71/186 189/72/187 -f 183/70/185 184/73/188 190/71/186 -f 184/73/188 191/74/189 190/71/186 -f 184/73/188 185/75/190 192/76/191 -f 184/73/188 192/76/191 191/74/189 -f 185/75/190 186/77/192 192/76/191 -f 186/77/192 193/78/193 192/76/191 -f 186/77/192 187/79/194 194/80/195 -f 186/77/192 194/80/195 193/78/193 -f 187/79/194 188/68/196 194/80/195 -f 188/68/196 195/81/197 194/80/195 -s 2 -f 189/68/182 196/68/182 232/68/182 -f 195/68/183 231/68/183 202/68/183 -s 1 -f 189/72/187 190/71/186 196/82/198 -f 190/71/186 197/83/199 196/82/198 -f 190/71/186 191/74/189 198/84/200 -f 190/71/186 198/84/200 197/83/199 -f 191/74/189 192/76/191 198/84/200 -f 192/76/191 199/85/201 198/84/200 -f 192/76/191 193/78/193 200/86/202 -f 192/76/191 200/86/202 199/85/201 -f 193/78/193 194/80/195 200/86/202 -f 194/80/195 201/87/203 200/86/202 -f 194/80/195 195/81/197 202/88/204 -f 194/80/195 202/88/204 201/87/203 -s 2 -f 196/68/182 203/68/182 232/68/182 -f 202/68/183 231/68/183 209/68/183 -s 1 -f 196/82/198 197/83/199 204/89/205 -f 196/82/198 204/89/205 203/90/206 -f 197/83/199 198/84/200 204/89/205 -f 198/84/200 205/91/207 204/89/205 -f 198/84/200 199/85/201 206/92/208 -f 198/84/200 206/92/208 205/91/207 -f 199/85/201 200/86/202 206/92/208 -f 200/86/202 207/93/209 206/92/208 -f 200/86/202 201/87/203 208/94/210 -f 200/86/202 208/94/210 207/93/209 -f 201/87/203 202/88/204 208/94/210 -f 202/88/204 209/95/211 208/94/210 -s 2 -f 203/68/182 210/68/182 232/68/182 -f 209/68/183 231/68/183 216/68/183 -s 1 -f 203/90/206 204/89/205 210/96/212 -f 204/89/205 211/97/213 210/96/212 -f 204/89/205 205/91/207 212/98/214 -f 204/89/205 212/98/214 211/97/213 -f 205/91/207 206/92/208 212/98/214 -f 206/92/208 213/99/215 212/98/214 -f 206/92/208 207/93/209 214/100/216 -f 206/92/208 214/100/216 213/99/215 -f 207/93/209 208/94/210 214/100/216 -f 208/94/210 215/101/217 214/100/216 -f 208/94/210 209/95/211 216/102/218 -f 208/94/210 216/102/218 215/101/217 -s 2 -f 210/68/182 217/68/182 232/68/182 -f 216/68/183 231/68/183 223/68/183 -s 1 -f 210/96/212 211/97/213 218/103/219 -f 210/96/212 218/103/219 217/104/220 -f 211/97/213 212/98/214 218/103/219 -f 212/98/214 219/105/221 218/103/219 -f 212/98/214 213/99/215 220/106/222 -f 212/98/214 220/106/222 219/105/221 -f 213/99/215 214/100/216 220/106/222 -f 214/100/216 221/107/223 220/106/222 -f 214/100/216 215/101/217 222/108/224 -f 214/100/216 222/108/224 221/107/223 -f 215/101/217 216/102/218 222/108/224 -f 216/102/218 223/109/225 222/108/224 -s 2 -f 217/68/182 224/68/182 232/68/182 -f 223/68/183 231/68/183 230/68/183 -s 1 -f 217/104/220 218/103/219 224/110/226 -f 218/103/219 225/111/227 224/110/226 -f 218/103/219 219/105/221 226/112/228 -f 218/103/219 226/112/228 225/111/227 -f 219/105/221 220/106/222 226/112/228 -f 220/106/222 227/113/229 226/112/228 -f 220/106/222 221/107/223 228/114/230 -f 220/106/222 228/114/230 227/113/229 -f 221/107/223 222/108/224 228/114/230 -f 222/108/224 229/115/231 228/114/230 -f 222/108/224 223/109/225 230/116/232 -f 222/108/224 230/116/232 229/115/231 -s 2 -f 224/68/182 182/68/182 232/68/182 -f 230/68/183 231/68/183 188/68/183 -s 1 -f 224/110/226 225/111/227 183/117/185 -f 224/110/226 183/117/185 182/118/184 -f 225/111/227 226/112/228 183/117/185 -f 226/112/228 184/119/188 183/117/185 -f 226/112/228 227/113/229 185/120/190 -f 226/112/228 185/120/190 184/119/188 -f 227/113/229 228/114/230 185/120/190 -f 228/114/230 186/121/192 185/120/190 -f 228/114/230 229/115/231 187/122/194 -f 228/114/230 187/122/194 186/121/192 -f 229/115/231 230/116/232 187/122/194 -f 230/116/232 188/123/196 187/122/194 -# 98 triangles in group - -g Bein2Re -usemtl BeinTex -s 2 -f 283/68/233 240/68/233 233/68/233 -f 246/68/234 282/68/234 239/68/234 -s 1 -f 241/71/235 234/70/236 233/69/237 -f 240/72/238 241/71/235 233/69/237 -f 241/71/235 235/73/239 234/70/236 -f 241/71/235 242/74/240 235/73/239 -f 243/76/241 236/75/242 235/73/239 -f 242/74/240 243/76/241 235/73/239 -f 243/76/241 237/77/243 236/75/242 -f 243/76/241 244/78/244 237/77/243 -f 245/80/245 238/79/246 237/77/243 -f 244/78/244 245/80/245 237/77/243 -f 245/80/245 239/68/247 238/79/246 -f 245/80/245 246/81/248 239/68/247 -s 2 -f 283/68/233 247/68/233 240/68/233 -f 253/68/234 282/68/234 246/68/234 -s 1 -f 247/82/249 241/71/235 240/72/238 -f 247/82/249 248/83/250 241/71/235 -f 249/84/251 242/74/240 241/71/235 -f 248/83/250 249/84/251 241/71/235 -f 249/84/251 243/76/241 242/74/240 -f 249/84/251 250/85/252 243/76/241 -f 251/86/253 244/78/244 243/76/241 -f 250/85/252 251/86/253 243/76/241 -f 251/86/253 245/80/245 244/78/244 -f 251/86/253 252/87/254 245/80/245 -f 253/88/255 246/81/248 245/80/245 -f 252/87/254 253/88/255 245/80/245 -s 2 -f 283/68/233 254/68/233 247/68/233 -f 260/68/234 282/68/234 253/68/234 -s 1 -f 255/89/256 248/83/250 247/82/249 -f 254/90/257 255/89/256 247/82/249 -f 255/89/256 249/84/251 248/83/250 -f 255/89/256 256/91/258 249/84/251 -f 257/92/259 250/85/252 249/84/251 -f 256/91/258 257/92/259 249/84/251 -f 257/92/259 251/86/253 250/85/252 -f 257/92/259 258/93/260 251/86/253 -f 259/94/261 252/87/254 251/86/253 -f 258/93/260 259/94/261 251/86/253 -f 259/94/261 253/88/255 252/87/254 -f 259/94/261 260/95/262 253/88/255 -s 2 -f 283/68/233 261/68/233 254/68/233 -f 267/68/234 282/68/234 260/68/234 -s 1 -f 261/96/263 255/89/256 254/90/257 -f 261/96/263 262/97/264 255/89/256 -f 263/98/265 256/91/258 255/89/256 -f 262/97/264 263/98/265 255/89/256 -f 263/98/265 257/92/259 256/91/258 -f 263/98/265 264/99/266 257/92/259 -f 265/100/267 258/93/260 257/92/259 -f 264/99/266 265/100/267 257/92/259 -f 265/100/267 259/94/261 258/93/260 -f 265/100/267 266/101/268 259/94/261 -f 267/102/269 260/95/262 259/94/261 -f 266/101/268 267/102/269 259/94/261 -s 2 -f 283/68/233 268/68/233 261/68/233 -f 274/68/234 282/68/234 267/68/234 -s 1 -f 269/103/270 262/97/264 261/96/263 -f 268/104/271 269/103/270 261/96/263 -f 269/103/270 263/98/265 262/97/264 -f 269/103/270 270/105/272 263/98/265 -f 271/106/273 264/99/266 263/98/265 -f 270/105/272 271/106/273 263/98/265 -f 271/106/273 265/100/267 264/99/266 -f 271/106/273 272/107/274 265/100/267 -f 273/108/275 266/101/268 265/100/267 -f 272/107/274 273/108/275 265/100/267 -f 273/108/275 267/102/269 266/101/268 -f 273/108/275 274/109/276 267/102/269 -s 2 -f 283/68/233 275/68/233 268/68/233 -f 281/68/234 282/68/234 274/68/234 -s 1 -f 275/110/277 269/103/270 268/104/271 -f 275/110/277 276/111/278 269/103/270 -f 277/112/279 270/105/272 269/103/270 -f 276/111/278 277/112/279 269/103/270 -f 277/112/279 271/106/273 270/105/272 -f 277/112/279 278/113/280 271/106/273 -f 279/114/281 272/107/274 271/106/273 -f 278/113/280 279/114/281 271/106/273 -f 279/114/281 273/108/275 272/107/274 -f 279/114/281 280/115/282 273/108/275 -f 281/116/283 274/109/276 273/108/275 -f 280/115/282 281/116/283 273/108/275 -s 2 -f 283/68/233 233/68/233 275/68/233 -f 239/68/234 282/68/234 281/68/234 -s 1 -f 234/117/236 276/111/278 275/110/277 -f 233/118/237 234/117/236 275/110/277 -f 234/117/236 277/112/279 276/111/278 -f 234/117/236 235/119/239 277/112/279 -f 236/120/242 278/113/280 277/112/279 -f 235/119/239 236/120/242 277/112/279 -f 236/120/242 279/114/281 278/113/280 -f 236/120/242 237/121/243 279/114/281 -f 238/122/246 280/115/282 279/114/281 -f 237/121/243 238/122/246 279/114/281 -f 238/122/246 281/116/283 280/115/282 -f 238/122/246 239/123/247 281/116/283 -# 98 triangles in group - -g Bein3Re -usemtl BeinTex -s 2 -f 334/68/284 291/68/284 284/68/284 -f 297/68/285 333/68/285 290/68/285 -s 1 -f 292/71/286 285/70/287 284/69/288 -f 291/72/289 292/71/286 284/69/288 -f 292/71/286 286/73/290 285/70/287 -f 292/71/286 293/74/291 286/73/290 -f 294/76/292 287/75/293 286/73/290 -f 293/74/291 294/76/292 286/73/290 -f 294/76/292 288/77/294 287/75/293 -f 294/76/292 295/78/295 288/77/294 -f 296/80/296 289/79/297 288/77/294 -f 295/78/295 296/80/296 288/77/294 -f 296/80/296 290/68/298 289/79/297 -f 296/80/296 297/81/299 290/68/298 -s 2 -f 334/68/284 298/68/284 291/68/284 -f 304/68/285 333/68/285 297/68/285 -s 1 -f 298/82/300 292/71/286 291/72/289 -f 298/82/300 299/83/301 292/71/286 -f 300/84/302 293/74/291 292/71/286 -f 299/83/301 300/84/302 292/71/286 -f 300/84/302 294/76/292 293/74/291 -f 300/84/302 301/85/303 294/76/292 -f 302/86/304 295/78/295 294/76/292 -f 301/85/303 302/86/304 294/76/292 -f 302/86/304 296/80/296 295/78/295 -f 302/86/304 303/87/305 296/80/296 -f 304/88/306 297/81/299 296/80/296 -f 303/87/305 304/88/306 296/80/296 -s 2 -f 334/68/284 305/68/284 298/68/284 -f 311/68/285 333/68/285 304/68/285 -s 1 -f 306/89/307 299/83/301 298/82/300 -f 305/90/308 306/89/307 298/82/300 -f 306/89/307 300/84/302 299/83/301 -f 306/89/307 307/91/309 300/84/302 -f 308/92/310 301/85/303 300/84/302 -f 307/91/309 308/92/310 300/84/302 -f 308/92/310 302/86/304 301/85/303 -f 308/92/310 309/93/311 302/86/304 -f 310/94/312 303/87/305 302/86/304 -f 309/93/311 310/94/312 302/86/304 -f 310/94/312 304/88/306 303/87/305 -f 310/94/312 311/95/313 304/88/306 -s 2 -f 334/68/284 312/68/284 305/68/284 -f 318/68/285 333/68/285 311/68/285 -s 1 -f 312/96/314 306/89/307 305/90/308 -f 312/96/314 313/97/315 306/89/307 -f 314/98/316 307/91/309 306/89/307 -f 313/97/315 314/98/316 306/89/307 -f 314/98/316 308/92/310 307/91/309 -f 314/98/316 315/99/317 308/92/310 -f 316/100/318 309/93/311 308/92/310 -f 315/99/317 316/100/318 308/92/310 -f 316/100/318 310/94/312 309/93/311 -f 316/100/318 317/101/319 310/94/312 -f 318/102/320 311/95/313 310/94/312 -f 317/101/319 318/102/320 310/94/312 -s 2 -f 334/68/284 319/68/284 312/68/284 -f 325/68/285 333/68/285 318/68/285 -s 1 -f 320/103/321 313/97/315 312/96/314 -f 319/104/322 320/103/321 312/96/314 -f 320/103/321 314/98/316 313/97/315 -f 320/103/321 321/105/323 314/98/316 -f 322/106/324 315/99/317 314/98/316 -f 321/105/323 322/106/324 314/98/316 -f 322/106/324 316/100/318 315/99/317 -f 322/106/324 323/107/325 316/100/318 -f 324/108/326 317/101/319 316/100/318 -f 323/107/325 324/108/326 316/100/318 -f 324/108/326 318/102/320 317/101/319 -f 324/108/326 325/109/327 318/102/320 -s 2 -f 334/68/284 326/68/284 319/68/284 -f 332/68/285 333/68/285 325/68/285 -s 1 -f 326/110/328 320/103/321 319/104/322 -f 326/110/328 327/111/329 320/103/321 -f 328/112/330 321/105/323 320/103/321 -f 327/111/329 328/112/330 320/103/321 -f 328/112/330 322/106/324 321/105/323 -f 328/112/330 329/113/331 322/106/324 -f 330/114/332 323/107/325 322/106/324 -f 329/113/331 330/114/332 322/106/324 -f 330/114/332 324/108/326 323/107/325 -f 330/114/332 331/115/333 324/108/326 -f 332/116/334 325/109/327 324/108/326 -f 331/115/333 332/116/334 324/108/326 -s 2 -f 334/68/284 284/68/284 326/68/284 -f 290/68/285 333/68/285 332/68/285 -s 1 -f 285/117/287 327/111/329 326/110/328 -f 284/118/288 285/117/287 326/110/328 -f 285/117/287 328/112/330 327/111/329 -f 285/117/287 286/119/290 328/112/330 -f 287/120/293 329/113/331 328/112/330 -f 286/119/290 287/120/293 328/112/330 -f 287/120/293 330/114/332 329/113/331 -f 287/120/293 288/121/294 330/114/332 -f 289/122/297 331/115/333 330/114/332 -f 288/121/294 289/122/297 330/114/332 -f 289/122/297 332/116/334 331/115/333 -f 289/122/297 290/123/298 332/116/334 -# 98 triangles in group - -g Bein3Li -usemtl BeinTex -s 2 -f 335/68/335 342/68/335 385/68/335 -f 341/68/336 384/68/336 348/68/336 -s 1 -f 335/69/337 336/70/338 343/71/339 -f 335/69/337 343/71/339 342/72/340 -f 336/70/338 337/73/341 343/71/339 -f 337/73/341 344/74/342 343/71/339 -f 337/73/341 338/75/343 345/76/344 -f 337/73/341 345/76/344 344/74/342 -f 338/75/343 339/77/345 345/76/344 -f 339/77/345 346/78/346 345/76/344 -f 339/77/345 340/79/347 347/80/348 -f 339/77/345 347/80/348 346/78/346 -f 340/79/347 341/68/349 347/80/348 -f 341/68/349 348/81/350 347/80/348 -s 2 -f 342/68/335 349/68/335 385/68/335 -f 348/68/336 384/68/336 355/68/336 -s 1 -f 342/72/340 343/71/339 349/82/351 -f 343/71/339 350/83/352 349/82/351 -f 343/71/339 344/74/342 351/84/353 -f 343/71/339 351/84/353 350/83/352 -f 344/74/342 345/76/344 351/84/353 -f 345/76/344 352/85/354 351/84/353 -f 345/76/344 346/78/346 353/86/355 -f 345/76/344 353/86/355 352/85/354 -f 346/78/346 347/80/348 353/86/355 -f 347/80/348 354/87/356 353/86/355 -f 347/80/348 348/81/350 355/88/357 -f 347/80/348 355/88/357 354/87/356 -s 2 -f 349/68/335 356/68/335 385/68/335 -f 355/68/336 384/68/336 362/68/336 -s 1 -f 349/82/351 350/83/352 357/89/358 -f 349/82/351 357/89/358 356/90/359 -f 350/83/352 351/84/353 357/89/358 -f 351/84/353 358/91/360 357/89/358 -f 351/84/353 352/85/354 359/92/361 -f 351/84/353 359/92/361 358/91/360 -f 352/85/354 353/86/355 359/92/361 -f 353/86/355 360/93/362 359/92/361 -f 353/86/355 354/87/356 361/94/363 -f 353/86/355 361/94/363 360/93/362 -f 354/87/356 355/88/357 361/94/363 -f 355/88/357 362/95/364 361/94/363 -s 2 -f 356/68/335 363/68/335 385/68/335 -f 362/68/336 384/68/336 369/68/336 -s 1 -f 356/90/359 357/89/358 363/96/365 -f 357/89/358 364/97/366 363/96/365 -f 357/89/358 358/91/360 365/98/367 -f 357/89/358 365/98/367 364/97/366 -f 358/91/360 359/92/361 365/98/367 -f 359/92/361 366/99/368 365/98/367 -f 359/92/361 360/93/362 367/100/369 -f 359/92/361 367/100/369 366/99/368 -f 360/93/362 361/94/363 367/100/369 -f 361/94/363 368/101/370 367/100/369 -f 361/94/363 362/95/364 369/102/371 -f 361/94/363 369/102/371 368/101/370 -s 2 -f 363/68/335 370/68/335 385/68/335 -f 369/68/336 384/68/336 376/68/336 -s 1 -f 363/96/365 364/97/366 371/103/372 -f 363/96/365 371/103/372 370/104/373 -f 364/97/366 365/98/367 371/103/372 -f 365/98/367 372/105/374 371/103/372 -f 365/98/367 366/99/368 373/106/375 -f 365/98/367 373/106/375 372/105/374 -f 366/99/368 367/100/369 373/106/375 -f 367/100/369 374/107/376 373/106/375 -f 367/100/369 368/101/370 375/108/377 -f 367/100/369 375/108/377 374/107/376 -f 368/101/370 369/102/371 375/108/377 -f 369/102/371 376/109/378 375/108/377 -s 2 -f 370/68/335 377/68/335 385/68/335 -f 376/68/336 384/68/336 383/68/336 -s 1 -f 370/104/373 371/103/372 377/110/379 -f 371/103/372 378/111/380 377/110/379 -f 371/103/372 372/105/374 379/112/381 -f 371/103/372 379/112/381 378/111/380 -f 372/105/374 373/106/375 379/112/381 -f 373/106/375 380/113/382 379/112/381 -f 373/106/375 374/107/376 381/114/383 -f 373/106/375 381/114/383 380/113/382 -f 374/107/376 375/108/377 381/114/383 -f 375/108/377 382/115/384 381/114/383 -f 375/108/377 376/109/378 383/116/385 -f 375/108/377 383/116/385 382/115/384 -s 2 -f 377/68/335 335/68/335 385/68/335 -f 383/68/336 384/68/336 341/68/336 -s 1 -f 377/110/379 378/111/380 336/117/338 -f 377/110/379 336/117/338 335/118/337 -f 378/111/380 379/112/381 336/117/338 -f 379/112/381 337/119/341 336/117/338 -f 379/112/381 380/113/382 338/120/343 -f 379/112/381 338/120/343 337/119/341 -f 380/113/382 381/114/383 338/120/343 -f 381/114/383 339/121/345 338/120/343 -f 381/114/383 382/115/384 340/122/347 -f 381/114/383 340/122/347 339/121/345 -f 382/115/384 383/116/385 340/122/347 -f 383/116/385 341/123/349 340/122/347 -# 98 triangles in group - -g Bein4Re -usemtl BeinTex -s 2 -f 436/68/386 393/68/386 386/68/386 -f 399/68/387 435/68/387 392/68/387 -s 1 -f 394/71/388 387/70/389 386/69/390 -f 393/72/391 394/71/388 386/69/390 -f 394/71/388 388/73/392 387/70/389 -f 394/71/388 395/74/393 388/73/392 -f 396/76/394 389/75/395 388/73/392 -f 395/74/393 396/76/394 388/73/392 -f 396/76/394 390/77/396 389/75/395 -f 396/76/394 397/78/397 390/77/396 -f 398/80/398 391/79/399 390/77/396 -f 397/78/397 398/80/398 390/77/396 -f 398/80/398 392/68/400 391/79/399 -f 398/80/398 399/81/401 392/68/400 -s 2 -f 436/68/386 400/68/386 393/68/386 -f 406/68/387 435/68/387 399/68/387 -s 1 -f 400/82/402 394/71/388 393/72/391 -f 400/82/402 401/83/403 394/71/388 -f 402/84/404 395/74/393 394/71/388 -f 401/83/403 402/84/404 394/71/388 -f 402/84/404 396/76/394 395/74/393 -f 402/84/404 403/85/405 396/76/394 -f 404/86/406 397/78/397 396/76/394 -f 403/85/405 404/86/406 396/76/394 -f 404/86/406 398/80/398 397/78/397 -f 404/86/406 405/87/407 398/80/398 -f 406/88/408 399/81/401 398/80/398 -f 405/87/407 406/88/408 398/80/398 -s 2 -f 436/68/386 407/68/386 400/68/386 -f 413/68/387 435/68/387 406/68/387 -s 1 -f 408/89/409 401/83/403 400/82/402 -f 407/90/410 408/89/409 400/82/402 -f 408/89/409 402/84/404 401/83/403 -f 408/89/409 409/91/411 402/84/404 -f 410/92/412 403/85/405 402/84/404 -f 409/91/411 410/92/412 402/84/404 -f 410/92/412 404/86/406 403/85/405 -f 410/92/412 411/93/413 404/86/406 -f 412/94/414 405/87/407 404/86/406 -f 411/93/413 412/94/414 404/86/406 -f 412/94/414 406/88/408 405/87/407 -f 412/94/414 413/95/415 406/88/408 -s 2 -f 436/68/386 414/68/386 407/68/386 -f 420/68/387 435/68/387 413/68/387 -s 1 -f 414/96/416 408/89/409 407/90/410 -f 414/96/416 415/97/417 408/89/409 -f 416/98/418 409/91/411 408/89/409 -f 415/97/417 416/98/418 408/89/409 -f 416/98/418 410/92/412 409/91/411 -f 416/98/418 417/99/419 410/92/412 -f 418/100/420 411/93/413 410/92/412 -f 417/99/419 418/100/420 410/92/412 -f 418/100/420 412/94/414 411/93/413 -f 418/100/420 419/101/421 412/94/414 -f 420/102/422 413/95/415 412/94/414 -f 419/101/421 420/102/422 412/94/414 -s 2 -f 436/68/386 421/68/386 414/68/386 -f 427/68/387 435/68/387 420/68/387 -s 1 -f 422/103/423 415/97/417 414/96/416 -f 421/104/424 422/103/423 414/96/416 -f 422/103/423 416/98/418 415/97/417 -f 422/103/423 423/105/425 416/98/418 -f 424/106/426 417/99/419 416/98/418 -f 423/105/425 424/106/426 416/98/418 -f 424/106/426 418/100/420 417/99/419 -f 424/106/426 425/107/427 418/100/420 -f 426/108/428 419/101/421 418/100/420 -f 425/107/427 426/108/428 418/100/420 -f 426/108/428 420/102/422 419/101/421 -f 426/108/428 427/109/429 420/102/422 -s 2 -f 436/68/386 428/68/386 421/68/386 -f 434/68/387 435/68/387 427/68/387 -s 1 -f 428/110/430 422/103/423 421/104/424 -f 428/110/430 429/111/431 422/103/423 -f 430/112/432 423/105/425 422/103/423 -f 429/111/431 430/112/432 422/103/423 -f 430/112/432 424/106/426 423/105/425 -f 430/112/432 431/113/433 424/106/426 -f 432/114/434 425/107/427 424/106/426 -f 431/113/433 432/114/434 424/106/426 -f 432/114/434 426/108/428 425/107/427 -f 432/114/434 433/115/435 426/108/428 -f 434/116/436 427/109/429 426/108/428 -f 433/115/435 434/116/436 426/108/428 -s 2 -f 436/68/386 386/68/386 428/68/386 -f 392/68/387 435/68/387 434/68/387 -s 1 -f 387/117/389 429/111/431 428/110/430 -f 386/118/390 387/117/389 428/110/430 -f 387/117/389 430/112/432 429/111/431 -f 387/117/389 388/119/392 430/112/432 -f 389/120/395 431/113/433 430/112/432 -f 388/119/392 389/120/395 430/112/432 -f 389/120/395 432/114/434 431/113/433 -f 389/120/395 390/121/396 432/114/434 -f 391/122/399 433/115/435 432/114/434 -f 390/121/396 391/122/399 432/114/434 -f 391/122/399 434/116/436 433/115/435 -f 391/122/399 392/123/400 434/116/436 -# 98 triangles in group - -g Bein4Li -usemtl BeinTex -s 2 -f 437/68/437 444/68/437 487/68/437 -f 443/68/438 486/68/438 450/68/438 -s 1 -f 437/69/439 438/70/440 445/71/441 -f 437/69/439 445/71/441 444/72/442 -f 438/70/440 439/73/443 445/71/441 -f 439/73/443 446/74/444 445/71/441 -f 439/73/443 440/75/445 447/76/446 -f 439/73/443 447/76/446 446/74/444 -f 440/75/445 441/77/447 447/76/446 -f 441/77/447 448/78/448 447/76/446 -f 441/77/447 442/79/449 449/80/450 -f 441/77/447 449/80/450 448/78/448 -f 442/79/449 443/68/451 449/80/450 -f 443/68/451 450/81/452 449/80/450 -s 2 -f 444/68/437 451/68/437 487/68/437 -f 450/68/438 486/68/438 457/68/438 -s 1 -f 444/72/442 445/71/441 451/82/453 -f 445/71/441 452/83/454 451/82/453 -f 445/71/441 446/74/444 453/84/455 -f 445/71/441 453/84/455 452/83/454 -f 446/74/444 447/76/446 453/84/455 -f 447/76/446 454/85/456 453/84/455 -f 447/76/446 448/78/448 455/86/457 -f 447/76/446 455/86/457 454/85/456 -f 448/78/448 449/80/450 455/86/457 -f 449/80/450 456/87/458 455/86/457 -f 449/80/450 450/81/452 457/88/459 -f 449/80/450 457/88/459 456/87/458 -s 2 -f 451/68/437 458/68/437 487/68/437 -f 457/68/438 486/68/438 464/68/438 -s 1 -f 451/82/453 452/83/454 459/89/460 -f 451/82/453 459/89/460 458/90/461 -f 452/83/454 453/84/455 459/89/460 -f 453/84/455 460/91/462 459/89/460 -f 453/84/455 454/85/456 461/92/463 -f 453/84/455 461/92/463 460/91/462 -f 454/85/456 455/86/457 461/92/463 -f 455/86/457 462/93/464 461/92/463 -f 455/86/457 456/87/458 463/94/465 -f 455/86/457 463/94/465 462/93/464 -f 456/87/458 457/88/459 463/94/465 -f 457/88/459 464/95/466 463/94/465 -s 2 -f 458/68/437 465/68/437 487/68/437 -f 464/68/438 486/68/438 471/68/438 -s 1 -f 458/90/461 459/89/460 465/96/467 -f 459/89/460 466/97/468 465/96/467 -f 459/89/460 460/91/462 467/98/469 -f 459/89/460 467/98/469 466/97/468 -f 460/91/462 461/92/463 467/98/469 -f 461/92/463 468/99/470 467/98/469 -f 461/92/463 462/93/464 469/100/471 -f 461/92/463 469/100/471 468/99/470 -f 462/93/464 463/94/465 469/100/471 -f 463/94/465 470/101/472 469/100/471 -f 463/94/465 464/95/466 471/102/473 -f 463/94/465 471/102/473 470/101/472 -s 2 -f 465/68/437 472/68/437 487/68/437 -f 471/68/438 486/68/438 478/68/438 -s 1 -f 465/96/467 466/97/468 473/103/474 -f 465/96/467 473/103/474 472/104/475 -f 466/97/468 467/98/469 473/103/474 -f 467/98/469 474/105/476 473/103/474 -f 467/98/469 468/99/470 475/106/477 -f 467/98/469 475/106/477 474/105/476 -f 468/99/470 469/100/471 475/106/477 -f 469/100/471 476/107/478 475/106/477 -f 469/100/471 470/101/472 477/108/479 -f 469/100/471 477/108/479 476/107/478 -f 470/101/472 471/102/473 477/108/479 -f 471/102/473 478/109/480 477/108/479 -s 2 -f 472/68/437 479/68/437 487/68/437 -f 478/68/438 486/68/438 485/68/438 -s 1 -f 472/104/475 473/103/474 479/110/481 -f 473/103/474 480/111/482 479/110/481 -f 473/103/474 474/105/476 481/112/483 -f 473/103/474 481/112/483 480/111/482 -f 474/105/476 475/106/477 481/112/483 -f 475/106/477 482/113/484 481/112/483 -f 475/106/477 476/107/478 483/114/485 -f 475/106/477 483/114/485 482/113/484 -f 476/107/478 477/108/479 483/114/485 -f 477/108/479 484/115/486 483/114/485 -f 477/108/479 478/109/480 485/116/487 -f 477/108/479 485/116/487 484/115/486 -s 2 -f 479/68/437 437/68/437 487/68/437 -f 485/68/438 486/68/438 443/68/438 -s 1 -f 479/110/481 480/111/482 438/117/440 -f 479/110/481 438/117/440 437/118/439 -f 480/111/482 481/112/483 438/117/440 -f 481/112/483 439/119/443 438/117/440 -f 481/112/483 482/113/484 440/120/445 -f 481/112/483 440/120/445 439/119/443 -f 482/113/484 483/114/485 440/120/445 -f 483/114/485 441/121/447 440/120/445 -f 483/114/485 484/115/486 442/122/449 -f 483/114/485 442/122/449 441/121/447 -f 484/115/486 485/116/487 442/122/449 -f 485/116/487 443/123/451 442/122/449 -# 98 triangles in group - -g Zahn -usemtl BeinTex -s 2 -f 488/124/488 491/124/488 510/124/488 -f 490/125/489 509/126/489 493/127/489 -s 1 -f 488/124/490 489/128/491 492/129/492 -f 488/124/490 492/129/492 491/124/488 -f 489/128/491 490/125/493 492/129/492 -f 490/125/493 493/127/494 492/129/492 -s 2 -f 491/124/488 494/124/488 510/124/488 -f 493/127/489 509/126/489 496/130/489 -s 1 -f 491/124/488 492/129/492 494/124/495 -f 492/129/492 495/131/496 494/124/495 -f 492/129/492 493/127/494 496/130/497 -f 492/129/492 496/130/497 495/131/496 -s 2 -f 494/124/488 497/124/488 510/124/488 -f 496/130/489 509/126/489 499/132/489 -s 1 -f 494/124/495 495/131/496 498/133/498 -f 494/124/495 498/133/498 497/124/488 -f 495/131/496 496/130/497 498/133/498 -f 496/130/497 499/132/499 498/133/498 -s 2 -f 497/124/488 500/124/488 510/124/488 -f 499/132/489 509/126/489 502/134/489 -s 1 -f 497/124/488 498/133/498 500/124/500 -f 498/133/498 501/135/501 500/124/500 -f 498/133/498 499/132/499 502/134/502 -f 498/133/498 502/134/502 501/135/501 -s 2 -f 500/124/488 503/124/488 510/124/488 -f 502/134/489 509/126/489 505/136/489 -s 1 -f 500/124/500 501/135/501 504/137/503 -f 500/124/500 504/137/503 503/124/488 -f 501/135/501 502/134/502 504/137/503 -f 502/134/502 505/136/504 504/137/503 -s 2 -f 503/124/488 506/124/488 510/124/488 -f 505/136/489 509/126/489 508/138/489 -s 1 -f 503/124/488 504/137/503 506/124/505 -f 504/137/503 507/139/506 506/124/505 -f 504/137/503 505/136/504 508/138/507 -f 504/137/503 508/138/507 507/139/506 -s 2 -f 506/124/488 488/124/488 510/124/488 -f 508/138/489 509/126/489 490/125/489 -s 1 -f 506/124/505 507/139/506 489/128/491 -f 506/124/505 489/128/491 488/124/490 -f 507/139/506 508/138/507 489/128/491 -f 508/138/507 490/125/493 489/128/491 -# 42 triangles in group - -g klZahn -usemtl BeinTex -s 2 -f 511/140/488 514/140/488 533/140/488 -f 513/141/508 532/142/508 516/143/508 -s 1 -f 511/140/509 512/144/510 515/145/511 -f 511/140/509 515/145/511 514/140/488 -f 512/144/510 513/141/512 515/145/511 -f 513/141/512 516/143/513 515/145/511 -s 2 -f 514/140/488 517/140/488 533/140/488 -f 516/143/508 532/142/508 519/146/508 -s 1 -f 514/140/488 515/145/511 517/140/514 -f 515/145/511 518/147/515 517/140/514 -f 515/145/511 516/143/513 519/146/516 -f 515/145/511 519/146/516 518/147/515 -s 2 -f 517/140/488 520/140/488 533/140/488 -f 519/146/508 532/142/508 522/148/508 -s 1 -f 517/140/514 518/147/515 521/149/517 -f 517/140/514 521/149/517 520/140/488 -f 518/147/515 519/146/516 521/149/517 -f 519/146/516 522/148/518 521/149/517 -s 2 -f 520/140/488 523/140/488 533/140/488 -f 522/148/508 532/142/508 525/150/508 -s 1 -f 520/140/488 521/149/517 523/140/519 -f 521/149/517 524/151/520 523/140/519 -f 521/149/517 522/148/518 525/150/521 -f 521/149/517 525/150/521 524/151/520 -s 2 -f 523/140/488 526/140/488 533/140/488 -f 525/150/508 532/142/508 528/152/508 -s 1 -f 523/140/519 524/151/520 527/153/522 -f 523/140/519 527/153/522 526/140/488 -f 524/151/520 525/150/521 527/153/522 -f 525/150/521 528/152/523 527/153/522 -s 2 -f 526/140/488 529/140/488 533/140/488 -f 528/152/508 532/142/508 531/154/508 -s 1 -f 526/140/488 527/153/522 529/140/524 -f 527/153/522 530/155/525 529/140/524 -f 527/153/522 528/152/523 531/154/526 -f 527/153/522 531/154/526 530/155/525 -s 2 -f 529/140/488 511/140/488 533/140/488 -f 531/154/508 532/142/508 513/141/508 -s 1 -f 529/140/524 530/155/525 512/144/510 -f 529/140/524 512/144/510 511/140/509 -f 530/155/525 531/154/526 512/144/510 -f 531/154/526 513/141/512 512/144/510 -# 42 triangles in group - -g Kopf -usemtl Skin -f 534/68/527 563/156/528 562/157/529 -f 534/68/527 564/158/530 563/156/528 -f 535/69/531 536/159/532 537/160/533 -f 534/68/527 565/161/534 564/158/530 -f 535/69/531 537/160/533 538/162/535 -f 534/68/527 566/163/536 565/161/534 -f 535/69/531 538/162/535 539/164/537 -f 534/68/527 567/165/538 566/163/536 -f 535/69/531 539/164/537 540/166/539 -f 534/68/527 568/167/540 567/165/538 -f 542/168/541 543/169/542 536/159/532 -f 536/159/532 543/169/542 544/170/543 -f 536/159/532 544/170/543 537/160/533 -f 537/160/533 544/170/543 538/162/535 -f 544/170/543 545/169/544 538/162/535 -f 538/162/535 545/169/544 546/171/545 -f 538/162/535 546/171/545 539/164/537 -f 539/164/537 546/171/545 540/166/539 -f 546/171/545 547/172/546 540/166/539 -f 541/173/547 548/174/548 542/168/541 -f 548/174/548 549/175/549 542/168/541 -f 542/168/541 549/175/549 550/176/550 -f 542/168/541 550/176/550 543/169/542 -f 543/169/542 550/176/550 544/170/543 -f 550/176/550 551/177/551 544/170/543 -f 544/170/543 551/177/551 552/178/552 -f 544/170/543 552/178/552 545/169/544 -f 545/169/544 552/178/552 546/171/545 -f 552/178/552 553/179/553 546/171/545 -f 546/171/545 553/179/553 554/180/554 -f 546/171/545 554/180/554 547/172/546 -f 548/174/548 555/181/555 556/182/556 -f 548/174/548 556/182/556 549/175/549 -f 549/175/549 556/182/556 550/176/550 -f 556/182/556 557/183/557 550/176/550 -f 550/176/550 557/183/557 558/184/558 -f 550/176/550 558/184/558 551/177/551 -f 551/177/551 558/184/558 552/178/552 -f 558/184/558 559/185/559 552/178/552 -f 553/179/553 560/186/560 554/180/554 -f 560/186/560 561/187/561 554/180/554 -f 555/181/555 562/157/529 556/182/556 -f 562/157/529 563/156/528 556/182/556 -f 556/182/556 563/156/528 564/158/530 -f 556/182/556 564/158/530 557/183/557 -f 557/183/557 564/158/530 558/184/558 -f 564/158/530 565/161/534 558/184/558 -f 558/184/558 565/161/534 566/163/536 -f 558/184/558 566/163/536 559/185/559 -f 559/185/559 566/163/536 560/186/560 -f 566/163/536 567/165/538 560/186/560 -f 560/186/560 567/165/538 568/167/540 -f 560/186/560 568/167/540 561/187/561 -f 575/188/562 585/189/563 586/190/564 -f 553/179/553 576/191/565 586/190/564 -f 586/190/564 575/188/562 553/179/553 -f 577/192/566 576/191/565 553/179/553 -f 576/191/565 577/192/566 587/193/567 -f 587/193/567 586/190/564 576/191/565 -f 588/194/568 587/193/567 577/192/566 -f 577/192/566 578/195/569 588/194/568 -f 589/196/570 588/194/568 579/197/571 -f 578/195/569 579/197/571 588/194/568 -f 590/198/572 589/196/570 569/199/573 -f 589/196/570 579/197/571 569/199/573 -f 569/199/573 580/200/574 590/198/572 -f 569/199/573 570/201/575 580/200/574 -f 570/201/575 571/202/576 580/200/574 -f 581/203/577 580/200/574 571/202/576 -f 571/202/576 572/204/578 581/203/577 -f 582/205/579 581/203/577 572/204/578 -f 583/206/580 582/205/579 572/204/578 -f 572/204/578 573/207/581 583/206/580 -f 584/208/582 583/206/580 573/207/581 -f 573/207/581 574/209/583 584/208/582 -f 585/189/563 584/208/582 574/209/583 -f 574/209/583 575/188/562 585/189/563 -f 575/188/562 560/186/560 553/179/553 -f 575/188/562 574/209/583 560/186/560 -f 574/209/583 573/207/581 560/186/560 -f 573/207/581 572/204/578 560/186/560 -f 572/204/578 571/202/576 560/186/560 -f 559/185/559 560/186/560 571/202/576 -f 571/202/576 570/201/575 559/185/559 -f 570/201/575 569/199/573 559/185/559 -f 577/192/566 553/179/553 552/178/552 -f 578/195/569 577/192/566 552/178/552 -f 579/197/571 578/195/569 552/178/552 -f 552/178/552 559/185/559 569/199/573 -f 579/197/571 569/199/573 552/178/552 -# 90 triangles in group - -g Brust -usemtl Skin -f 595/210/584 596/211/585 597/212/586 -f 591/120/587 597/212/586 593/213/588 -f 597/212/586 596/211/585 593/213/588 -f 595/210/584 597/212/586 598/214/589 -f 599/215/590 598/214/589 600/216/591 -f 591/120/587 600/216/591 597/212/586 -f 598/214/589 597/212/586 600/216/591 -f 595/210/584 598/214/589 601/217/592 -f 602/75/593 601/217/592 603/218/594 -f 599/215/590 603/218/594 598/214/589 -f 601/217/592 598/214/589 603/218/594 -f 602/75/593 603/218/594 604/219/595 -f 599/215/590 605/220/596 603/218/594 -f 604/219/595 603/218/594 605/220/596 -f 599/215/590 600/216/591 606/221/597 -f 591/120/587 592/222/598 600/216/591 -f 606/221/597 600/216/591 592/222/598 -f 595/210/584 601/217/592 594/223/599 -f 602/75/593 607/224/600 601/217/592 -f 594/223/599 601/217/592 607/224/600 -# 20 triangles in group - -g Kopf2 -usemtl Skin -f 636/225/601 637/226/602 608/123/603 -f 637/226/602 638/227/604 608/123/603 -f 611/228/605 610/229/606 609/118/607 -f 638/227/604 639/230/608 608/123/603 -f 612/231/609 611/228/605 609/118/607 -f 639/230/608 640/232/610 608/123/603 -f 613/233/611 612/231/609 609/118/607 -f 640/232/610 641/234/612 608/123/603 -f 614/235/613 613/233/611 609/118/607 -f 641/234/612 642/236/614 608/123/603 -f 610/229/606 617/237/615 616/238/616 -f 618/239/617 617/237/615 610/229/606 -f 611/228/605 618/239/617 610/229/606 -f 612/231/609 618/239/617 611/228/605 -f 612/231/609 619/237/618 618/239/617 -f 620/240/619 619/237/618 612/231/609 -f 613/233/611 620/240/619 612/231/609 -f 614/235/613 620/240/619 613/233/611 -f 614/235/613 621/241/620 620/240/619 -f 616/238/616 622/176/621 615/242/622 -f 616/238/616 623/243/623 622/176/621 -f 624/174/624 623/243/623 616/238/616 -f 617/237/615 624/174/624 616/238/616 -f 618/239/617 624/174/624 617/237/615 -f 618/239/617 625/244/625 624/174/624 -f 626/245/626 625/244/625 618/239/617 -f 619/237/618 626/245/626 618/239/617 -f 620/240/619 626/245/626 619/237/618 -f 620/240/619 627/246/627 626/245/626 -f 628/247/628 627/246/627 620/240/619 -f 621/241/620 628/247/628 620/240/619 -f 630/248/629 629/249/630 622/176/621 -f 623/243/623 630/248/629 622/176/621 -f 624/174/624 630/248/629 623/243/623 -f 624/174/624 631/250/631 630/248/629 -f 632/251/632 631/250/631 624/174/624 -f 625/244/625 632/251/632 624/174/624 -f 626/245/626 632/251/632 625/244/625 -f 626/245/626 633/252/633 632/251/632 -f 628/247/628 634/253/634 627/246/627 -f 628/247/628 635/254/635 634/253/634 -f 630/248/629 636/225/601 629/249/630 -f 630/248/629 637/226/602 636/225/601 -f 638/227/604 637/226/602 630/248/629 -f 631/250/631 638/227/604 630/248/629 -f 632/251/632 638/227/604 631/250/631 -f 632/251/632 639/230/608 638/227/604 -f 640/232/610 639/230/608 632/251/632 -f 633/252/633 640/232/610 632/251/632 -f 634/253/634 640/232/610 633/252/633 -f 634/253/634 641/234/612 640/232/610 -f 642/236/614 641/234/612 634/253/634 -f 635/254/635 642/236/614 634/253/634 -f 660/255/636 659/256/637 649/257/638 -f 660/255/636 650/258/639 627/246/627 -f 627/246/627 649/257/638 660/255/636 -f 627/246/627 650/258/639 651/259/640 -f 661/260/641 651/259/640 650/258/639 -f 650/258/639 660/255/636 661/260/641 -f 651/259/640 661/260/641 662/261/642 -f 662/261/642 652/262/643 651/259/640 -f 653/263/644 662/261/642 663/264/645 -f 662/261/642 653/263/644 652/262/643 -f 643/265/646 663/264/645 664/266/647 -f 643/265/646 653/263/644 663/264/645 -f 664/266/647 654/267/648 643/265/646 -f 654/267/648 644/268/649 643/265/646 -f 654/267/648 645/269/650 644/268/649 -f 645/269/650 654/267/648 655/270/651 -f 655/270/651 646/271/652 645/269/650 -f 646/271/652 655/270/651 656/272/653 -f 646/271/652 656/272/653 657/273/654 -f 657/273/654 647/274/655 646/271/652 -f 647/274/655 657/273/654 658/275/656 -f 658/275/656 648/276/657 647/274/655 -f 648/276/657 658/275/656 659/256/637 -f 659/256/637 649/257/638 648/276/657 -f 627/246/627 634/253/634 649/257/638 -f 634/253/634 648/276/657 649/257/638 -f 634/253/634 647/274/655 648/276/657 -f 634/253/634 646/271/652 647/274/655 -f 634/253/634 645/269/650 646/271/652 -f 645/269/650 634/253/634 633/252/633 -f 633/252/633 644/268/649 645/269/650 -f 633/252/633 643/265/646 644/268/649 -f 626/245/626 627/246/627 651/259/640 -f 626/245/626 651/259/640 652/262/643 -f 626/245/626 652/262/643 653/263/644 -f 643/265/646 633/252/633 626/245/626 -f 626/245/626 643/265/646 653/263/644 -# 90 triangles in group - -g Zahn2 -usemtl BeinTex -s 2 -f 687/124/488 668/124/488 665/124/488 -f 670/127/658 686/126/658 667/125/658 -s 1 -f 669/129/659 666/128/660 665/124/661 -f 668/124/488 669/129/659 665/124/661 -f 669/129/659 667/125/662 666/128/660 -f 669/129/659 670/127/663 667/125/662 -s 2 -f 687/124/488 671/124/488 668/124/488 -f 673/130/658 686/126/658 670/127/658 -s 1 -f 671/124/664 669/129/659 668/124/488 -f 671/124/664 672/131/665 669/129/659 -f 673/130/666 670/127/663 669/129/659 -f 672/131/665 673/130/666 669/129/659 -s 2 -f 687/124/488 674/124/488 671/124/488 -f 676/132/658 686/126/658 673/130/658 -s 1 -f 675/133/667 672/131/665 671/124/664 -f 674/124/488 675/133/667 671/124/664 -f 675/133/667 673/130/666 672/131/665 -f 675/133/667 676/132/668 673/130/666 -s 2 -f 687/124/488 677/124/488 674/124/488 -f 679/134/658 686/126/658 676/132/658 -s 1 -f 677/124/669 675/133/667 674/124/488 -f 677/124/669 678/135/670 675/133/667 -f 679/134/671 676/132/668 675/133/667 -f 678/135/670 679/134/671 675/133/667 -s 2 -f 687/124/488 680/124/488 677/124/488 -f 682/136/658 686/126/658 679/134/658 -s 1 -f 681/137/672 678/135/670 677/124/669 -f 680/124/488 681/137/672 677/124/669 -f 681/137/672 679/134/671 678/135/670 -f 681/137/672 682/136/673 679/134/671 -s 2 -f 687/124/488 683/124/488 680/124/488 -f 685/138/658 686/126/658 682/136/658 -s 1 -f 683/124/674 681/137/672 680/124/488 -f 683/124/674 684/139/675 681/137/672 -f 685/138/676 682/136/673 681/137/672 -f 684/139/675 685/138/676 681/137/672 -s 2 -f 687/124/488 665/124/488 683/124/488 -f 667/125/658 686/126/658 685/138/658 -s 1 -f 666/128/660 684/139/675 683/124/674 -f 665/124/661 666/128/660 683/124/674 -f 666/128/660 685/138/676 684/139/675 -f 666/128/660 667/125/662 685/138/676 -# 42 triangles in group - -g klZahn2 -usemtl BeinTex -s 2 -f 710/140/488 691/140/488 688/140/488 -f 693/143/677 709/142/677 690/141/677 -s 1 -f 692/145/678 689/144/679 688/140/680 -f 691/140/488 692/145/678 688/140/680 -f 692/145/678 690/141/681 689/144/679 -f 692/145/678 693/143/682 690/141/681 -s 2 -f 710/140/488 694/140/488 691/140/488 -f 696/146/677 709/142/677 693/143/677 -s 1 -f 694/140/683 692/145/678 691/140/488 -f 694/140/683 695/147/684 692/145/678 -f 696/146/685 693/143/682 692/145/678 -f 695/147/684 696/146/685 692/145/678 -s 2 -f 710/140/488 697/140/488 694/140/488 -f 699/148/677 709/142/677 696/146/677 -s 1 -f 698/149/686 695/147/684 694/140/683 -f 697/140/488 698/149/686 694/140/683 -f 698/149/686 696/146/685 695/147/684 -f 698/149/686 699/148/687 696/146/685 -s 2 -f 710/140/488 700/140/488 697/140/488 -f 702/150/677 709/142/677 699/148/677 -s 1 -f 700/140/688 698/149/686 697/140/488 -f 700/140/688 701/151/689 698/149/686 -f 702/150/690 699/148/687 698/149/686 -f 701/151/689 702/150/690 698/149/686 -s 2 -f 710/140/488 703/140/488 700/140/488 -f 705/152/677 709/142/677 702/150/677 -s 1 -f 704/153/691 701/151/689 700/140/688 -f 703/140/488 704/153/691 700/140/688 -f 704/153/691 702/150/690 701/151/689 -f 704/153/691 705/152/692 702/150/690 -s 2 -f 710/140/488 706/140/488 703/140/488 -f 708/154/677 709/142/677 705/152/677 -s 1 -f 706/140/693 704/153/691 703/140/488 -f 706/140/693 707/155/694 704/153/691 -f 708/154/695 705/152/692 704/153/691 -f 707/155/694 708/154/695 704/153/691 -s 2 -f 710/140/488 688/140/488 706/140/488 -f 690/141/677 709/142/677 708/154/677 -s 1 -f 689/144/679 707/155/694 706/140/693 -f 688/140/680 689/144/679 706/140/693 -f 689/144/679 708/154/695 707/155/694 -f 689/144/679 690/141/681 708/154/695 -# 42 triangles in group - -g Auge -usemtl Augentex -f 711/277/696 712/278/697 713/279/698 -f 711/277/696 713/279/698 714/280/699 -f 715/281/700 714/280/699 716/282/701 -f 714/280/699 713/279/698 716/282/701 -f 715/281/700 716/282/701 717/283/702 -f 718/284/703 720/285/704 721/286/705 -f 722/287/706 721/286/705 723/288/707 -f 719/289/708 723/288/707 720/285/704 -f 721/286/705 720/285/704 723/288/707 -f 722/287/706 723/288/707 724/290/709 -f 725/291/710 724/290/709 726/292/711 -f 719/289/708 726/292/711 723/288/707 -f 724/290/709 723/288/707 726/292/711 -f 725/291/710 727/293/712 729/294/713 -f 730/295/714 729/294/713 731/296/715 -f 728/297/716 731/296/715 727/293/712 -f 729/294/713 727/293/712 731/296/715 -f 730/295/714 731/296/715 732/298/717 -f 711/277/696 732/298/717 733/299/718 -f 728/297/716 733/299/718 731/296/715 -f 732/298/717 731/296/715 733/299/718 -f 711/277/696 733/299/718 712/278/697 -f 715/281/700 734/300/719 714/280/699 -f 711/277/696 714/280/699 732/298/717 -f 730/295/714 732/298/717 734/300/719 -f 714/280/699 734/300/719 732/298/717 -f 715/281/700 735/301/720 734/300/719 -f 730/295/714 734/300/719 736/302/721 -f 722/287/706 736/302/721 735/301/720 -f 734/300/719 735/301/720 736/302/721 -f 715/281/700 717/283/702 735/301/720 -f 722/287/706 735/301/720 721/286/705 -f 718/284/703 721/286/705 717/283/702 -f 735/301/720 717/283/702 721/286/705 -f 725/291/710 729/294/713 724/290/709 -f 722/287/706 724/290/709 736/302/721 -f 730/295/714 736/302/721 729/294/713 -f 724/290/709 729/294/713 736/302/721 -# 38 triangles in group - -g Duplicate05 -usemtl Augentex -f 739/279/722 738/278/723 737/277/724 -f 740/280/725 739/279/722 737/277/724 -f 742/282/726 740/280/725 741/281/727 -f 742/282/726 739/279/722 740/280/725 -f 743/283/728 742/282/726 741/281/727 -f 747/286/729 746/285/730 744/284/731 -f 749/288/732 747/286/729 748/287/733 -f 746/285/730 749/288/732 745/289/734 -f 749/288/732 746/285/730 747/286/729 -f 750/290/735 749/288/732 748/287/733 -f 752/292/736 750/290/735 751/291/737 -f 749/288/732 752/292/736 745/289/734 -f 752/292/736 749/288/732 750/290/735 -f 755/294/738 753/293/739 751/291/737 -f 757/296/740 755/294/738 756/295/741 -f 753/293/739 757/296/740 754/297/742 -f 757/296/740 753/293/739 755/294/738 -f 758/298/743 757/296/740 756/295/741 -f 759/299/744 758/298/743 737/277/724 -f 757/296/740 759/299/744 754/297/742 -f 759/299/744 757/296/740 758/298/743 -f 738/278/723 759/299/744 737/277/724 -f 740/280/725 760/300/745 741/281/727 -f 758/298/743 740/280/725 737/277/724 -f 760/300/745 758/298/743 756/295/741 -f 758/298/743 760/300/745 740/280/725 -f 760/300/745 761/301/746 741/281/727 -f 762/302/747 760/300/745 756/295/741 -f 761/301/746 762/302/747 748/287/733 -f 762/302/747 761/301/746 760/300/745 -f 761/301/746 743/283/728 741/281/727 -f 747/286/729 761/301/746 748/287/733 -f 743/283/728 747/286/729 744/284/731 -f 747/286/729 743/283/728 761/301/746 -f 750/290/735 755/294/738 751/291/737 -f 762/302/747 750/290/735 748/287/733 -f 755/294/738 762/302/747 756/295/741 -f 762/302/747 755/294/738 750/290/735 -# 38 triangles in group - -# 1368 triangles total - +# Wavefront OBJ exported by MilkShape 3D + +mtllib spider.mtl + +v 1.160379 4.512684 6.449167 +v 22.656172 10.214539 16.869690 +v 4.568314 16.857113 5.619617 +v 14.402298 32.891869 3.414829 +v 27.520809 27.080326 11.451565 +v 39.186256 16.230997 12.632702 +v -6.442715 10.777405 -0.537529 +v -8.120363 15.684460 -10.500000 +v -0.886770 23.423717 -4.342854 +v -0.886770 23.423717 -16.657145 +v 14.402298 32.891869 -26.414825 +v 12.953165 36.873337 -11.500000 +v 30.527317 37.503952 -2.733282 +v 30.527317 37.503952 -20.266716 +v 44.301250 33.964729 -11.500000 +v 45.094967 27.710945 2.684846 +v 57.936218 30.276533 -11.500000 +v 54.503593 5.934020 -11.500000 +v 51.091763 11.234900 2.684846 +v 45.094967 27.710945 -25.684845 +v 39.186256 16.230997 -35.632706 +v 51.091763 11.234900 -25.684845 +v 27.520809 27.080326 -34.451565 +v 4.568314 16.857113 -26.619617 +v 1.160379 4.512684 -27.449169 +v 22.656172 10.214539 -39.869690 +v 7.838881 -6.414188 -26.619617 +v 30.910042 -12.462786 -26.414825 +v 37.223816 0.421531 -34.451565 +v 46.227112 -5.630886 -20.266716 +v 32.359184 -16.444252 -11.500000 +v 30.910042 -12.462786 3.414829 +v 46.227112 -5.630886 -2.733282 +v 4.405119 -14.230042 -16.657145 +v -4.681486 -8.784435 -10.500000 +v 4.405119 -14.230042 -4.342854 +v -4.421391 -3.605049 -0.537529 +v 7.838881 -6.414188 5.619617 +v 37.223816 0.421531 11.451565 +v -9.876476 2.961555 -10.500000 +v -6.442715 10.777405 -20.462471 +v -4.421391 -3.605049 -20.462471 +v -41.856613 -0.754846 9.430772 +v -27.950212 1.303017 3.081421 +v -32.625862 10.860188 8.479760 +v -24.401524 12.224749 -3.122690 +v -18.826405 5.435883 0.583091 +v -11.221268 -4.132547 1.127722 +v -44.882015 11.887197 1.421121 +v -44.844704 15.228493 -10.000000 +v -35.570240 16.598591 -2.941359 +v -35.570240 16.598591 -17.058643 +v -24.401524 12.224749 -16.877310 +v -23.778482 14.142281 -10.000000 +v -8.432302 6.445052 -5.957618 +v -8.432302 6.445052 -14.042381 +v -1.337093 1.108110 -10.000000 +v -3.309273 -1.735224 -0.594703 +v -0.419668 -7.642198 -10.000000 +v -6.305182 -14.182098 -10.000000 +v -6.229439 -10.722575 -0.594703 +v -3.309273 -1.735224 -19.405296 +v -11.221268 -4.132547 -21.127720 +v -6.229439 -10.722575 -19.405296 +v -18.826405 5.435883 -20.583092 +v -32.625862 10.860188 -28.479759 +v -41.856613 -0.754846 -29.430771 +v -27.950212 1.303017 -23.081421 +v -39.194733 -9.356718 -28.479759 +v -31.498898 -9.618716 -16.877310 +v -22.998137 -7.403383 -20.583092 +v -31.498898 -9.618716 -3.122690 +v -51.647591 -5.708694 -10.000000 +v -49.713837 -2.983590 1.421121 +v -39.194733 -9.356718 8.479760 +v -22.998137 -7.403383 0.583091 +v -50.637024 8.975393 -10.000000 +v -44.882015 11.887197 -21.421116 +v -49.713837 -2.983590 -21.421116 +v -40.671478 -3.472887 -21.369167 +v -47.098404 7.389261 -39.585033 +v -55.443726 28.016960 -51.020649 +v -56.413048 27.518753 -54.602135 +v -67.985016 13.435572 -79.020355 +v -81.678322 -31.379181 -101.291557 +v -87.605835 -39.983532 -104.351723 +v -41.963333 -2.246161 -18.485233 +v -47.146698 8.704388 -37.681622 +v -55.805077 29.500343 -50.360577 +v -57.932991 29.207901 -55.039448 +v -69.893600 14.105843 -80.144135 +v -82.778503 -29.843521 -101.266586 +v -87.950195 -39.455147 -104.260185 +v -45.274612 -1.921316 -17.562561 +v -48.862389 8.964325 -36.150715 +v -56.924980 29.827461 -49.555809 +v -60.012169 29.560211 -54.086689 +v -72.068741 14.206520 -79.360901 +v -83.474747 -29.518608 -100.470779 +v -88.234985 -39.350231 -103.866043 +v -48.111877 -2.742970 -19.296001 +v -50.953510 7.973352 -36.145107 +v -57.960136 28.752014 -49.212387 +v -61.084877 28.310402 -52.461258 +v -72.872513 13.661798 -77.260391 +v -83.242752 -30.649029 -99.503448 +v -88.245728 -39.747742 -103.466080 +v -48.338589 -4.092402 -22.380154 +v -51.845413 6.477697 -37.669014 +v -58.131039 27.083824 -49.588871 +v -60.343346 26.399567 -51.387123 +v -71.699661 12.881830 -75.424393 +v -82.257225 -32.383606 -99.092934 +v -87.974380 -40.348385 -103.361534 +v -45.784027 -4.953472 -24.492657 +v -50.866463 5.603586 -39.574917 +v -57.308998 26.079071 -50.401779 +v -58.345963 25.266647 -51.673157 +v -69.433350 12.453951 -75.235397 +v -81.260262 -33.416180 -99.548431 +v -87.625252 -40.699837 -103.631096 +v -42.371857 -4.677759 -24.042709 +v -48.753845 6.009277 -40.427631 +v -56.113029 26.494377 -51.038967 +v -56.596836 25.764732 -53.103985 +v -67.780197 12.700411 -76.835770 +v -81.002632 -32.969162 -100.526863 +v -87.461220 -40.537483 -104.071754 +v -87.871048 -40.017475 -103.858307 +v -44.645119 -3.443838 -21.089790 +v -41.960121 -3.154671 1.817622 +v -49.196304 7.804556 21.293488 +v -54.254692 27.272881 30.448885 +v -55.486473 27.498093 33.976906 +v -67.468346 9.109057 43.496418 +v -85.971497 -32.074684 52.638474 +v -91.959503 -39.732742 57.540760 +v -42.838028 -1.822748 -1.173377 +v -49.368126 8.476757 19.085897 +v -54.925758 28.342400 29.366055 +v -57.455009 28.706230 33.835514 +v -69.611961 9.454971 44.296452 +v -87.014175 -30.514137 52.422035 +v -92.290428 -39.211590 57.382488 +v -45.988678 -1.450131 -2.535743 +v -50.884972 7.785149 17.480999 +v -55.983421 28.087738 28.457573 +v -59.415642 28.146988 32.740971 +v -71.615807 8.682786 43.434380 +v -87.756073 -30.296221 51.631001 +v -92.600067 -39.161705 56.996368 +v -49.039581 -2.317410 -1.243531 +v -52.604645 6.250553 17.687332 +v -56.631248 26.700691 28.407564 +v -59.891945 26.241493 31.517431 +v -71.970940 7.373976 41.559353 +v -87.638519 -31.584965 50.861065 +v -92.655235 -39.620594 56.673161 +v -49.693314 -3.771509 1.730138 +v -53.232193 5.028540 19.549484 +v -56.381416 25.225716 29.253666 +v -58.525230 24.424589 31.086275 +v -70.409966 6.514069 40.083332 +v -86.750092 -33.409981 50.691986 +v -92.414413 -40.242748 56.656296 +v -47.457619 -4.717469 4.146055 +v -52.295036 5.039291 21.665272 +v -55.422035 24.773529 30.358753 +v -56.344688 24.064466 31.772144 +v -68.108238 6.750601 40.117752 +v -85.759720 -34.396961 51.251087 +v -92.058937 -40.559631 56.958412 +v -44.016029 -4.442948 4.184989 +v -50.498901 6.274748 22.441425 +v -54.475548 25.684616 30.890648 +v -54.992317 25.432327 33.058613 +v -66.799141 7.905498 41.636730 +v -85.413208 -33.802715 52.117340 +v -91.856499 -40.332680 57.352055 +v -92.262108 -39.837402 57.079941 +v -45.856201 -3.096684 0.989461 +v -32.535782 -3.154671 -19.162537 +v -35.098988 7.804556 -38.979305 +v -37.554058 27.272881 -51.632816 +v -36.856800 27.498093 -55.304066 +v -39.321587 4.109057 -79.209648 +v -40.877087 -32.426605 -89.889732 +v -43.385780 -41.583160 -95.218742 +v -34.383732 -1.822748 -16.652164 +v -36.351589 8.476757 -37.153374 +v -38.676632 28.342400 -51.030598 +v -38.632298 28.706230 -56.165878 +v -40.777988 4.454971 -80.974312 +v -41.686413 -30.958584 -90.761086 +v -43.694237 -41.068901 -95.434502 +v -37.810333 -1.450131 -16.449551 +v -38.467670 7.785149 -36.521919 +v -40.046833 28.087738 -50.772652 +v -40.877529 28.146988 -56.198307 +v -42.944405 3.682786 -81.229652 +v -42.730568 -30.604935 -90.669960 +v -44.167656 -40.946091 -95.343666 +v -40.235279 -2.317410 -18.707310 +v -39.853783 6.250553 -37.560444 +v -40.632877 26.700691 -51.053253 +v -41.901775 26.241493 -55.376835 +v -44.189468 2.373976 -79.783394 +v -43.223267 -31.631912 -89.685066 +v -44.449516 -41.307182 -95.014656 +v -39.832531 -3.771509 -21.725227 +v -39.466175 5.028540 -39.486904 +v -39.993458 25.225716 -51.661091 +v -40.933758 24.424589 -54.320080 +v -43.575638 1.514069 -77.724648 +v -42.793549 -33.266224 -88.547981 +v -44.327614 -41.880302 -94.695259 +v -36.905369 -4.717469 -23.230795 +v -37.596676 5.039291 -40.850639 +v -38.610062 24.773529 -52.138432 +v -38.702415 24.064466 -53.823795 +v -41.565083 1.750601 -76.603584 +v -41.764935 -34.277184 -88.114983 +v -43.893715 -42.233826 -94.625923 +v -33.658024 -4.442948 -22.090290 +v -35.653107 6.274748 -40.624737 +v -37.524441 25.684616 -52.125816 +v -36.888000 25.432327 -54.261726 +v -39.671886 2.905498 -77.264503 +v -40.912052 -33.903522 -88.712090 +v -43.474564 -42.101616 -94.858925 +v -43.913261 -41.588737 -95.027351 +v -36.480152 -3.096684 -19.716850 +v -32.202831 -2.602407 -2.728741 +v -34.576370 8.107365 17.247396 +v -39.058979 27.085625 30.088219 +v -38.037266 27.494461 33.666477 +v -34.540394 17.314922 46.759007 +v -28.008705 -33.484039 66.392296 +v -28.327166 -39.131874 75.694695 +v -34.502445 -1.655421 -5.032196 +v -36.107876 8.519890 15.562401 +v -40.406155 27.934097 29.606636 +v -39.897282 28.393272 34.709156 +v -35.845226 17.436094 48.666241 +v -28.966595 -31.870440 66.611580 +v -28.696358 -38.612408 75.698051 +v -37.944061 -1.883905 -4.875526 +v -38.125301 7.461887 15.155594 +v -41.730480 27.441978 29.493328 +v -41.995846 27.455360 34.976097 +v -37.806667 16.306143 49.146633 +v -30.060040 -31.714916 66.549873 +v -29.190708 -38.598446 75.644356 +v -39.936069 -3.115807 -2.376659 +v -39.109486 5.730080 16.333321 +v -42.034714 25.979904 29.833651 +v -42.752686 25.387024 34.266190 +v -38.947704 14.775947 47.838451 +v -30.465645 -33.134476 66.253670 +v -29.437933 -39.100452 75.574059 +v -38.978443 -4.423484 0.582626 +v -38.319347 4.628540 18.208712 +v -41.089756 24.648787 30.371326 +v -41.597874 23.745718 33.114037 +v -38.409119 13.997741 45.726810 +v -29.878033 -35.060257 65.945946 +v -29.251896 -39.740452 75.540138 +v -35.792297 -4.822233 1.773979 +v -36.349819 4.986736 19.369556 +v -39.607189 24.451040 30.701448 +v -39.401020 23.767401 32.387234 +v -36.596428 14.557548 44.401737 +v -28.739618 -36.042065 65.858498 +v -28.772676 -40.036469 75.568077 +v -32.776875 -4.011777 0.300282 +v -34.684055 6.534969 18.941736 +v -38.703423 25.535545 30.575422 +v -37.816402 25.435768 32.633106 +v -34.874714 16.033844 44.861141 +v -27.907713 -35.340607 66.057121 +v -28.361128 -39.765636 75.636909 +v -28.862520 -39.283707 75.622292 +v -36.019009 -3.216418 -1.765163 +v -23.494484 -3.472887 -4.813465 +v -14.855604 7.389261 12.463476 +v -12.426659 28.016960 26.410450 +v -10.523695 27.518753 29.595638 +v -0.997257 13.435572 54.882141 +v 3.675970 -31.379181 79.706490 +v 5.211229 -39.983532 86.198250 +v -26.466400 -2.246161 -5.887527 +v -16.258350 8.704388 11.176008 +v -13.152491 29.500343 26.211857 +v -11.264965 29.207901 30.992771 +v -1.514698 14.105843 57.035713 +v 3.385566 -29.843521 80.767952 +v 5.039108 -39.455147 86.510231 +v -29.430336 -1.921316 -4.146553 +v -18.551411 8.964325 11.346706 +v -14.509346 29.827461 26.458410 +v -13.394642 29.560211 31.826565 +v -3.589094 14.206520 58.056274 +v 2.445001 -29.518608 81.251015 +v 4.587766 -39.350231 86.691200 +v -30.154327 -2.742970 -0.901443 +v -20.008060 7.973352 12.847034 +v -15.475464 28.752014 26.964478 +v -15.309046 28.310402 31.469078 +v -5.658417 13.661798 57.175323 +v 1.562493 -30.649029 80.791862 +v 4.197091 -39.747742 86.604866 +v -28.093273 -4.092402 1.404079 +v -19.531422 6.477697 14.547209 +v -15.323357 27.083824 27.348948 +v -15.566597 26.399567 30.189514 +v -6.164387 12.881830 55.056259 +v 1.402615 -32.383606 79.736290 +v 4.161307 -40.348385 86.316307 +v -24.799110 -4.953472 1.033955 +v -17.480396 5.603586 15.166962 +v -14.167568 26.079071 27.322308 +v -13.973347 25.266647 28.951418 +v -4.726027 12.453951 53.294724 +v 2.085765 -33.416180 78.879143 +v 4.507323 -40.699837 86.042763 +v -22.752468 -4.677759 -1.733124 +v -15.399448 6.009277 14.239624 +v -12.878420 26.494377 26.904627 +v -11.729046 25.764732 28.687138 +v -2.426441 12.700411 53.217262 +v 3.097473 -32.969162 78.865883 +v 4.974566 -40.537483 85.990211 +v 4.668339 -40.017475 86.336220 +v -26.455776 -3.443838 -2.149143 +v -23.494484 -3.472887 -15.186539 +v -14.855604 7.389261 -32.463478 +v -12.426659 28.016960 -46.410446 +v -10.523695 27.518753 -49.595634 +v -0.997257 13.435572 -74.882133 +v 3.675970 -31.379181 -99.706490 +v 5.211229 -39.983532 -106.198250 +v -26.466400 -2.246161 -14.112476 +v -16.258350 8.704388 -31.176010 +v -13.152491 29.500343 -46.211853 +v -11.264965 29.207901 -50.992767 +v -1.514698 14.105843 -77.035713 +v 3.385567 -29.843521 -100.767952 +v 5.039108 -39.455147 -106.510231 +v -29.430336 -1.921316 -15.853451 +v -18.551411 8.964325 -31.346710 +v -14.509346 29.827461 -46.458412 +v -13.394642 29.560211 -51.826561 +v -3.589094 14.206520 -78.056267 +v 2.445001 -29.518608 -101.251015 +v 4.587765 -39.350231 -106.691200 +v -30.154327 -2.742970 -19.098560 +v -20.008060 7.973352 -32.847034 +v -15.475464 28.752014 -46.964478 +v -15.309046 28.310402 -51.469078 +v -5.658417 13.661798 -77.175316 +v 1.562493 -30.649029 -100.791862 +v 4.197090 -39.747742 -106.604866 +v -28.093273 -4.092402 -21.404083 +v -19.531422 6.477697 -34.547211 +v -15.323357 27.083824 -47.348946 +v -15.566597 26.399567 -50.189514 +v -6.164387 12.881830 -75.056252 +v 1.402615 -32.383606 -99.736290 +v 4.161308 -40.348385 -106.316307 +v -24.799110 -4.953472 -21.033958 +v -17.480396 5.603586 -35.166962 +v -14.167568 26.079071 -47.322304 +v -13.973347 25.266647 -48.951416 +v -4.726027 12.453951 -73.294716 +v 2.085765 -33.416180 -98.879143 +v 4.507324 -40.699837 -106.042763 +v -22.752468 -4.677759 -18.266880 +v -15.399448 6.009277 -34.239624 +v -12.878420 26.494377 -46.904625 +v -11.729046 25.764732 -48.687134 +v -2.426441 12.700411 -73.217262 +v 3.097473 -32.969162 -98.865883 +v 4.974566 -40.537483 -105.990211 +v 4.668339 -40.017475 -106.336220 +v -26.455776 -3.443838 -17.850861 +v -11.205212 -7.280232 -5.841879 +v -2.877649 5.517601 11.076941 +v 1.745674 26.136940 21.007814 +v 4.282450 26.647736 23.713144 +v 14.860218 5.642468 47.618973 +v 19.200661 -29.660152 61.265373 +v 19.897118 -38.155197 68.039124 +v -14.102657 -6.075779 -7.124460 +v -4.907511 6.093641 10.126818 +v 0.474552 27.209396 20.979715 +v 3.233435 28.024002 25.249430 +v 14.560253 6.223589 49.838684 +v 18.976063 -28.078100 62.273354 +v 19.749865 -37.607536 68.329926 +v -17.115952 -5.533359 -5.528418 +v -7.036675 5.467060 10.781746 +v -0.824137 27.009163 21.510900 +v 1.346554 27.595062 26.518511 +v 12.858335 5.598270 51.276505 +v 18.042278 -27.676632 62.709824 +v 19.300247 -37.467232 68.489960 +v -17.975994 -6.061425 -2.255571 +v -7.661821 4.109711 12.548561 +v -1.172436 25.687050 22.201403 +v 0.042627 25.683922 26.564661 +v 11.036061 4.237392 50.849693 +v 17.102531 -28.757996 62.246178 +v 18.886868 -37.839897 68.398773 +v -16.035194 -7.262345 0.229479 +v -6.312249 3.043694 14.096798 +v -0.308071 24.238619 22.531248 +v 0.303562 23.729671 25.353144 +v 10.465651 3.165695 48.879730 +v 16.864386 -30.507956 61.231514 +v 18.820993 -38.444942 68.125061 +v -12.754986 -8.231801 0.055506 +v -4.004155 3.071719 14.260595 +v 1.118067 23.754597 22.252031 +v 1.932854 23.203932 23.796263 +v 11.576626 3.190188 46.849907 +v 17.507248 -31.608736 60.429893 +v 19.152214 -38.826717 67.874832 +v -10.605457 -8.239758 -2.646498 +v -2.475620 4.172726 12.916639 +v 2.032040 24.599438 21.574022 +v 3.703634 24.502615 23.066408 +v 13.532379 4.292479 46.288857 +v 18.546949 -31.231438 60.444954 +v 19.631145 -38.697784 67.836639 +v 19.348364 -38.148495 68.156281 +v -14.256489 -6.954941 -3.301691 +v -12.538544 -7.280232 -13.491455 +v -4.210981 5.517601 -30.410275 +v 0.412342 26.136940 -40.341148 +v 2.949118 26.647736 -43.046478 +v 13.526886 5.642468 -66.952316 +v 17.867329 -29.660152 -80.598724 +v 18.563786 -38.155197 -87.372467 +v -15.435989 -6.075779 -12.208874 +v -6.240843 6.093641 -29.460152 +v -0.858780 27.209396 -40.313049 +v 1.900103 28.024002 -44.582764 +v 13.226921 6.223589 -69.172028 +v 17.642731 -28.078100 -81.606705 +v 18.416533 -37.607536 -87.663269 +v -18.449284 -5.533359 -13.804916 +v -8.370007 5.467060 -30.115082 +v -2.157469 27.009163 -40.844238 +v 0.013222 27.595062 -45.851845 +v 11.525003 5.598270 -70.609848 +v 16.708946 -27.676632 -82.043167 +v 17.966915 -37.467232 -87.823303 +v -19.309326 -6.061425 -17.077763 +v -8.995153 4.109711 -31.881897 +v -2.505768 25.687050 -41.534737 +v -1.290705 25.683922 -45.897995 +v 9.702729 4.237392 -70.183029 +v 15.769199 -28.757996 -81.579529 +v 17.553535 -37.839897 -87.732117 +v -17.368526 -7.262345 -19.562813 +v -7.645581 3.043694 -33.430130 +v -1.641403 24.238619 -41.864586 +v -1.029770 23.729671 -44.686478 +v 9.132318 3.165695 -68.213074 +v 15.531054 -30.507956 -80.564865 +v 17.487661 -38.444942 -87.458405 +v -14.088318 -8.231801 -19.388840 +v -5.337487 3.071719 -33.593929 +v -0.215265 23.754597 -41.585365 +v 0.599522 23.203932 -43.129601 +v 10.243294 3.190188 -66.183243 +v 16.173916 -31.608736 -79.763245 +v 17.818882 -38.826717 -87.208176 +v -11.938789 -8.239758 -16.686836 +v -3.808952 4.172726 -32.249973 +v 0.698708 24.599438 -40.907356 +v 2.370302 24.502615 -42.399742 +v 12.199047 4.292479 -65.622192 +v 17.213617 -31.231438 -79.778305 +v 18.297813 -38.697784 -87.169983 +v 18.015032 -38.148495 -87.489624 +v -15.589821 -6.954941 -16.031643 +v -66.772987 -11.885618 -0.202999 +v -63.971184 3.661695 -3.830468 +v -61.496513 6.340155 -5.812276 +v -66.772987 -11.885618 -0.202999 +v -64.845985 4.368711 -2.075660 +v -61.447578 8.190097 -3.647036 +v -66.772987 -11.885618 -0.202999 +v -67.137108 4.622091 -1.531196 +v -62.557804 11.305613 -3.485914 +v -66.772987 -11.885618 -0.202999 +v -69.119194 4.231085 -2.607096 +v -63.991096 13.340770 -5.450253 +v -66.772987 -11.885618 -0.202999 +v -69.299873 3.490133 -4.493171 +v -64.668205 12.763025 -8.060863 +v -66.772987 -11.885618 -0.202999 +v -67.542992 2.957121 -5.769162 +v -64.079262 10.007396 -9.351896 +v -66.772987 -11.885618 -0.202999 +v -65.171471 3.033510 -5.474240 +v -62.667759 7.148978 -8.351185 +v -62.986851 9.870845 -6.308486 +v -66.772987 -11.885618 -0.202999 +v -66.724846 1.179926 10.029461 +v -59.689461 8.144950 1.861810 +v -58.212650 12.086802 -3.032124 +v -66.724846 1.179926 10.029461 +v -57.915882 6.628378 1.958869 +v -55.509857 10.279719 -2.976122 +v -66.724846 1.179926 10.029461 +v -56.296860 6.188433 3.356508 +v -52.637226 10.233272 -1.254851 +v -66.724846 1.179926 10.029461 +v -56.051727 7.156466 5.002278 +v -51.757839 11.982401 0.835560 +v -66.724846 1.179926 10.029461 +v -57.364841 8.803489 5.656901 +v -53.533970 14.210047 1.721019 +v -66.724846 1.179926 10.029461 +v -59.247578 9.889247 4.827473 +v -56.628082 15.238695 0.734676 +v -66.724846 1.179926 10.029461 +v -60.282143 9.596194 3.138459 +v -58.710255 14.293749 -1.380639 +v -55.284286 12.617801 -0.764661 +v -66.724846 1.179926 10.029461 +v -53.999989 26.333338 -9.944447 +v -53.999989 2.333334 -9.944447 +v -50.999989 3.941031 -4.748295 +v -53.999989 3.941031 -3.944447 +v -55.800003 6.941027 -4.748295 +v -57.996159 5.774363 -6.944447 +v -58.800007 5.774363 -9.944447 +v -43.607685 8.333335 -9.944447 +v -45.444431 8.333335 -0.081627 +v -48.803837 8.333335 -0.944447 +v -53.999989 10.666674 1.822437 +v -59.196140 8.333335 -0.944447 +v -62.999989 8.333335 -4.748294 +v -64.192299 7.533351 -9.944447 +v -37.199986 18.654428 -9.944447 +v -39.252125 18.654428 -0.061920 +v -43.644428 18.654428 3.756354 +v -53.999989 14.333338 2.055553 +v -61.410072 13.476199 -1.042666 +v -64.609299 13.476199 -6.367094 +v -66.399986 12.333346 -9.944447 +v -38.807682 21.886042 -9.944447 +v -40.644428 21.886042 -0.760713 +v -44.448277 21.886042 2.546009 +v -53.999989 20.333338 0.447858 +v -60.293266 19.476198 -2.199143 +v -63.063873 19.476198 -6.810235 +v -64.392296 20.333338 -9.944447 +v -43.199986 24.251795 -9.944447 +v -44.003834 24.251795 -7.336517 +v -46.644428 24.251795 -0.760711 +v -53.999989 24.725641 -3.944446 +v -56.999985 24.725641 -4.748293 +v -59.196140 24.725641 -6.944447 +v -59.999992 24.725641 -9.944447 +v -61.567451 17.809526 -2.544080 +v -61.859703 18.476198 -3.143273 +v -62.298088 18.642870 -4.042075 +v -62.736469 18.142870 -4.940860 +v -62.955631 16.976198 -5.390261 +v -63.247864 16.309526 -5.989458 +v -63.320908 15.142870 -6.139256 +v -62.955631 14.642870 -5.390261 +v -62.371128 14.476198 -4.191869 +v -61.640526 15.309526 -2.693877 +v -61.421349 16.642870 -2.244477 +v -61.724983 18.155695 -3.369263 +v -61.894066 18.041590 -3.958856 +v -62.070351 17.699663 -4.573657 +v -62.118629 16.981066 -4.741918 +v -62.201881 16.161669 -5.032282 +v -62.366032 15.399149 -5.604844 +v -62.332207 15.061815 -5.486823 +v -62.077385 15.070856 -4.598178 +v -61.738106 15.737185 -3.414914 +v -61.553413 16.745081 -2.770823 +v -61.582451 17.634455 -2.872150 +v -6.305182 -14.182098 -10.000000 +v -6.229439 -10.722575 -0.594703 +v -6.229439 -10.722575 -19.405296 +v -39.194733 -9.356718 -28.479759 +v -31.498898 -9.618716 -16.877310 +v -22.998137 -7.403383 -20.583092 +v -15.182299 -14.329319 -14.042381 +v -32.121948 -11.536249 -10.000000 +v -31.498898 -9.618716 -3.122690 +v -15.182299 -14.329319 -5.957618 +v -44.949730 -12.268521 -17.058643 +v -51.647591 -5.708694 -10.000000 +v -44.949730 -12.268521 -2.941359 +v -49.713837 -2.983590 1.421121 +v -39.194733 -9.356718 8.479760 +v -22.998137 -7.403383 0.583091 +v -49.713837 -2.983590 -21.421116 +v -53.999989 26.333338 -9.988887 +v -53.999989 2.333334 -9.988887 +v -50.999989 3.941031 -15.185039 +v -53.999989 3.941031 -15.988886 +v -55.800003 6.941027 -15.185039 +v -57.996159 5.774363 -12.988887 +v -58.800007 5.774363 -9.988887 +v -43.607685 8.333335 -9.988887 +v -45.444431 8.333335 -19.851706 +v -48.803837 8.333335 -18.988886 +v -53.999989 10.666674 -21.755770 +v -59.196140 8.333335 -18.988886 +v -62.999989 8.333335 -15.185039 +v -64.192299 7.533351 -9.988887 +v -37.199986 18.654428 -9.988887 +v -39.252125 18.654428 -19.871412 +v -43.644428 18.654428 -23.689688 +v -53.999989 14.333338 -21.988886 +v -61.410072 13.476199 -18.890669 +v -64.609299 13.476199 -13.566239 +v -66.399986 12.333346 -9.988887 +v -38.807682 21.886042 -9.988887 +v -40.644428 21.886042 -19.172621 +v -44.448277 21.886042 -22.479342 +v -53.999989 20.333338 -20.381189 +v -60.293266 19.476198 -17.734190 +v -63.063873 19.476198 -13.123098 +v -64.392296 20.333338 -9.988887 +v -43.199986 24.251795 -9.988887 +v -44.003834 24.251795 -12.596816 +v -46.644428 24.251795 -19.172621 +v -53.999989 24.725641 -15.988886 +v -56.999985 24.725641 -15.185040 +v -59.196140 24.725641 -12.988887 +v -59.999992 24.725641 -9.988887 +v -61.567451 17.809526 -17.389254 +v -61.859703 18.476198 -16.790060 +v -62.298088 18.642870 -15.891256 +v -62.736469 18.142870 -14.992473 +v -62.955631 16.976198 -14.543073 +v -63.247864 16.309526 -13.943875 +v -63.320908 15.142870 -13.794078 +v -62.955631 14.642870 -14.543073 +v -62.371128 14.476198 -15.741465 +v -61.640526 15.309526 -17.239454 +v -61.421349 16.642870 -17.688856 +v -61.724983 18.155695 -16.564070 +v -61.894066 18.041590 -15.974478 +v -62.070351 17.699663 -15.359674 +v -62.118629 16.981066 -15.191415 +v -62.201881 16.161669 -14.901052 +v -62.366032 15.399149 -14.328490 +v -62.332207 15.061815 -14.446509 +v -62.077385 15.070856 -15.335154 +v -61.738106 15.737185 -16.518419 +v -61.553413 16.745081 -17.162512 +v -61.582451 17.634455 -17.061182 +v -66.591156 -11.976528 -20.112152 +v -63.789349 3.570786 -16.484684 +v -61.314701 6.249245 -14.502876 +v -66.591156 -11.976528 -20.112152 +v -64.664154 4.277802 -18.239491 +v -61.265766 8.099188 -16.668116 +v -66.591156 -11.976528 -20.112152 +v -66.955276 4.531182 -18.783955 +v -62.375992 11.214703 -16.829237 +v -66.591156 -11.976528 -20.112152 +v -68.937363 4.140175 -17.708055 +v -63.809261 13.249859 -14.864899 +v -66.591156 -11.976528 -20.112152 +v -69.118042 3.399224 -15.821981 +v -64.486374 12.672115 -12.254288 +v -66.591156 -11.976528 -20.112152 +v -67.361160 2.866211 -14.545990 +v -63.897427 9.916485 -10.963255 +v -66.591156 -11.976528 -20.112152 +v -64.989639 2.942601 -14.840912 +v -62.485947 7.058069 -11.963966 +v -62.805038 9.779934 -14.006666 +v -66.591156 -11.976528 -20.112152 +v -66.724846 1.234471 -28.696123 +v -59.689461 8.199495 -20.528475 +v -58.212650 12.141348 -15.634542 +v -66.724846 1.234471 -28.696123 +v -57.915882 6.682923 -20.625532 +v -55.509857 10.334265 -15.690544 +v -66.724846 1.234471 -28.696123 +v -56.296860 6.242978 -22.023172 +v -52.637226 10.287817 -17.411816 +v -66.724846 1.234471 -28.696123 +v -56.051727 7.211011 -23.668943 +v -51.757839 12.036945 -19.502226 +v -66.724846 1.234471 -28.696123 +v -57.364841 8.858034 -24.323565 +v -53.533970 14.264591 -20.387682 +v -66.724846 1.234471 -28.696123 +v -59.247578 9.943792 -23.494139 +v -56.628082 15.293240 -19.401342 +v -66.724846 1.234471 -28.696123 +v -60.282143 9.650740 -21.805124 +v -58.710255 14.348293 -17.286026 +v -55.284286 12.672346 -17.902004 +v -66.724846 1.234471 -28.696123 +v -59.670547 17.670856 -1.853035 +v -58.743614 17.518467 -2.271704 +v -59.467049 18.406742 -2.538975 +v -60.637596 18.103474 -2.337921 +v -61.555885 18.154240 -3.372073 +v -60.575226 18.690861 -3.431842 +v -61.644852 18.262333 -4.609260 +v -61.384178 17.941105 -5.717274 +v -61.278061 15.979283 -6.500585 +v -61.481544 16.983921 -6.448156 +v -62.267357 17.284794 -5.621511 +v -62.614960 16.491169 -5.094203 +v -62.204987 16.131672 -6.081918 +v -62.267357 15.544271 -4.988010 +v -61.384178 14.979936 -4.639498 +v -61.481544 15.243386 -5.814656 +v -60.474304 15.084535 -3.543311 +v -59.564423 15.709020 -2.636348 +v -61.644852 15.446095 -3.584234 +v -61.555885 16.324146 -2.705970 +v -60.575226 15.874639 -2.406815 +v -60.637596 17.027775 -1.946398 +v -59.467049 16.666218 -1.905474 +v -61.745773 17.311893 -2.839265 +v -62.368286 17.410069 -4.243031 +v -62.368286 16.334370 -3.851508 +v -59.670547 17.404190 -17.880299 +v -58.743614 17.251801 -17.461630 +v -59.467049 18.140076 -17.194359 +v -60.637596 17.836807 -17.395412 +v -61.555885 17.887573 -16.361259 +v -60.575226 18.424194 -16.301491 +v -61.644852 17.995667 -15.124073 +v -61.384178 17.674438 -14.016060 +v -61.278061 15.712616 -13.232748 +v -61.481544 16.717255 -13.285177 +v -62.267357 17.018127 -14.111822 +v -62.614960 16.224503 -14.639130 +v -62.204987 15.865005 -13.651415 +v -62.267357 15.277603 -14.745323 +v -61.384178 14.713268 -15.093836 +v -61.481544 14.976719 -13.918678 +v -60.474304 14.817867 -16.190023 +v -59.564423 15.442352 -17.096985 +v -61.644852 15.179428 -16.149099 +v -61.555885 16.057480 -17.027363 +v -60.575226 15.607971 -17.326519 +v -60.637596 16.761108 -17.786934 +v -59.467049 16.399551 -17.827860 +v -61.745773 17.045227 -16.894068 +v -62.368286 17.143402 -15.490303 +v -62.368286 16.067703 -15.881825 +# 762 vertices + +vt 0.186192 0.222718 +vt 0.503180 0.039063 +vt 0.236448 0.237339 +vt 0.381464 0.276197 +vt 0.574917 0.134554 +vt 0.746941 0.113737 +vt 0.074073 0.345855 +vt 0.049334 0.521438 +vt 0.156004 0.412922 +vt 0.156004 0.629954 +vt 0.381464 0.801928 +vt 0.360095 0.539063 +vt 0.619252 0.384554 +vt 0.619252 0.693571 +vt 0.822369 0.539063 +vt 0.834074 0.289063 +vt 1.023438 0.539063 +vt 0.972818 0.539063 +vt 0.922506 0.289063 +vt 0.834074 0.789063 +vt 0.746941 0.964388 +vt 0.922506 0.789063 +vt 0.574917 0.943571 +vt 0.236448 0.805537 +vt 0.186192 0.820158 +vt 0.503180 1.039063 +vt 0.284677 0.805537 +vt 0.624896 0.801928 +vt 0.718002 0.943571 +vt 0.850769 0.693571 +vt 0.646266 0.539063 +vt 0.624896 0.276197 +vt 0.850769 0.384554 +vt 0.234041 0.629954 +vt 0.100045 0.521438 +vt 0.234041 0.412922 +vt 0.103881 0.345855 +vt 0.284677 0.237339 +vt 0.718002 0.134554 +vt 0.023438 0.521438 +vt 0.074073 0.697021 +vt 0.103881 0.697021 +vt -0.065871 -0.410016 +vt 0.403088 -0.109437 +vt 0.127441 -0.364995 +vt 0.403088 0.184267 +vt 0.678735 0.008835 +vt 1.058291 -0.016948 +vt -0.318566 -0.030837 +vt -0.355704 0.509840 +vt -0.042919 0.175683 +vt -0.042919 0.843998 +vt 0.403088 0.835414 +vt 0.403088 0.509840 +vt 1.035339 0.318473 +vt 1.035339 0.701207 +vt 1.348124 0.509840 +vt 1.310985 0.064592 +vt 1.481345 0.509840 +vt 1.310985 0.955089 +vt 1.058291 1.036629 +vt 0.678735 1.010846 +vt 0.127441 1.384675 +vt -0.065871 1.429696 +vt 0.403088 1.129117 +vt -0.488925 0.509840 +vt -0.318566 1.050518 +vt 0.000000 1.000000 +vt 0.000000 0.000000 +vt 0.000000 0.166667 +vt 0.142857 0.166667 +vt 0.142857 0.000000 +vt 0.000000 0.333333 +vt 0.142857 0.333333 +vt 0.000000 0.500000 +vt 0.142857 0.500000 +vt 0.000000 0.666667 +vt 0.142857 0.666667 +vt 0.000000 0.833333 +vt 0.142857 0.833333 +vt 0.142857 1.000000 +vt 0.285714 0.000000 +vt 0.285714 0.166667 +vt 0.285714 0.333333 +vt 0.285714 0.500000 +vt 0.285714 0.666667 +vt 0.285714 0.833333 +vt 0.285714 1.000000 +vt 0.428571 0.166667 +vt 0.428571 0.000000 +vt 0.428571 0.333333 +vt 0.428571 0.500000 +vt 0.428571 0.666667 +vt 0.428571 0.833333 +vt 0.428571 1.000000 +vt 0.571429 0.000000 +vt 0.571429 0.166667 +vt 0.571429 0.333333 +vt 0.571429 0.500000 +vt 0.571429 0.666667 +vt 0.571429 0.833333 +vt 0.571429 1.000000 +vt 0.714286 0.166667 +vt 0.714286 0.000000 +vt 0.714286 0.333333 +vt 0.714286 0.500000 +vt 0.714286 0.666667 +vt 0.714286 0.833333 +vt 0.714286 1.000000 +vt 0.857143 0.000000 +vt 0.857143 0.166667 +vt 0.857143 0.333333 +vt 0.857143 0.500000 +vt 0.857143 0.666667 +vt 0.857143 0.833333 +vt 0.857143 1.000000 +vt 1.000000 0.166667 +vt 1.000000 0.000000 +vt 1.000000 0.333333 +vt 1.000000 0.500000 +vt 1.000000 0.666667 +vt 1.000000 0.833333 +vt 1.000000 1.000000 +vt 0.332919 0.272694 +vt 0.446895 0.397773 +vt 0.456977 0.422004 +vt 0.402899 0.410469 +vt 0.406626 0.379392 +vt 0.370970 0.384244 +vt 0.399625 0.431850 +vt 0.359907 0.385983 +vt 0.439539 0.445817 +vt 0.381768 0.383299 +vt 0.492584 0.441852 +vt 0.420092 0.378214 +vt 0.518816 0.422941 +vt 0.446019 0.374556 +vt 0.498483 0.403324 +vt 0.440026 0.375080 +vt 0.344810 0.338084 +vt 0.488018 0.424091 +vt 0.463158 0.428278 +vt 0.487405 0.409841 +vt 0.434361 0.393007 +vt 0.433297 0.381048 +vt 0.468532 0.409475 +vt 0.417973 0.377579 +vt 0.445613 0.423268 +vt 0.399928 0.385213 +vt 0.435904 0.440834 +vt 0.392751 0.398200 +vt 0.446719 0.448945 +vt 0.401845 0.406762 +vt 0.469911 0.441494 +vt 0.420363 0.404451 +vt 0.190349 0.913269 +vt 0.000000 0.913269 +vt 0.670306 0.913269 +vt 0.379259 0.066987 +vt 0.437931 0.066987 +vt 0.437931 0.933013 +vt 0.379259 0.191987 +vt 0.379259 0.933013 +vt 0.218965 0.143376 +vt 0.218965 0.933013 +vt 0.000000 0.143376 +vt 0.000000 0.933013 +vt 0.719872 0.250000 +vt 0.656896 0.250000 +vt 0.858846 0.347222 +vt 0.379259 0.250000 +vt 0.000000 0.216667 +vt 0.000000 0.250000 +vt 0.000000 0.680045 +vt 0.721310 0.680045 +vt 1.000000 0.680045 +vt 0.875861 0.500000 +vt 0.649727 0.464286 +vt 0.261105 0.464286 +vt 0.000000 0.416667 +vt 0.000000 0.814696 +vt 0.670306 0.814696 +vt 0.911659 0.814696 +vt 0.758518 0.750000 +vt 0.565318 0.714286 +vt 0.228761 0.714286 +vt 0.000000 0.750000 +vt 0.277735 0.533731 +vt 0.316741 0.544409 +vt 0.325355 0.530353 +vt 0.332403 0.512897 +vt 0.419872 0.505953 +vt 0.390216 0.530730 +vt 0.476580 0.558494 +vt 0.529208 0.540675 +vt 0.523592 0.600489 +vt 0.562009 0.596231 +vt 0.516196 0.637547 +vt 0.540141 0.644841 +vt 0.479912 0.659265 +vt 0.496407 0.672619 +vt 0.430805 0.679564 +vt 0.436879 0.654511 +vt 0.365204 0.658731 +vt 0.392006 0.640264 +vt 0.379724 0.610322 +vt 0.332403 0.610119 +vt 0.358531 0.576181 +vt 0.288668 0.582341 +vt 0.445345 0.686077 +vt 0.607126 0.786343 +vt 0.816422 0.609373 +vt 0.978203 0.754476 +vt 0.445345 0.500000 +vt 0.445345 0.313923 +vt 0.816422 0.390627 +vt 0.183578 0.690983 +vt 0.183578 0.309017 +vt 0.021797 0.190983 +vt 0.283564 0.000000 +vt 0.607126 0.213657 +vt 0.978203 0.245524 +vt 0.283564 1.000000 +vt 0.021797 0.809017 +vt 1.000000 0.913269 +vt 0.809651 0.913269 +vt 0.329694 0.913269 +vt 0.562069 0.066987 +vt 0.620741 0.066987 +vt 0.562069 0.933013 +vt 0.620741 0.191987 +vt 0.620741 0.933013 +vt 0.781035 0.143376 +vt 0.781035 0.933013 +vt 1.000000 0.143376 +vt 1.000000 0.933013 +vt 0.343104 0.250000 +vt 0.280128 0.250000 +vt 0.141154 0.347222 +vt 0.620741 0.250000 +vt 1.000000 0.216667 +vt 1.000000 0.250000 +vt 0.278690 0.680045 +vt 0.124139 0.500000 +vt 0.350273 0.464286 +vt 0.738895 0.464286 +vt 1.000000 0.416667 +vt 0.329694 0.814696 +vt 1.000000 0.814696 +vt 0.088341 0.814696 +vt 0.241482 0.750000 +vt 0.434682 0.714286 +vt 0.771239 0.714286 +vt 1.000000 0.750000 +vt 0.674645 0.530353 +vt 0.683259 0.544409 +vt 0.722265 0.533731 +vt 0.667597 0.512897 +vt 0.580128 0.505953 +vt 0.609784 0.530730 +vt 0.523420 0.558494 +vt 0.470792 0.540675 +vt 0.437991 0.596231 +vt 0.476408 0.600489 +vt 0.459859 0.644841 +vt 0.483804 0.637547 +vt 0.520088 0.659265 +vt 0.503593 0.672619 +vt 0.569195 0.679564 +vt 0.563121 0.654511 +vt 0.634796 0.658731 +vt 0.607995 0.640264 +vt 0.620276 0.610322 +vt 0.667597 0.610119 +vt 0.641469 0.576181 +vt 0.711332 0.582341 +vt 1.046875 0.772010 +vt 0.956791 0.730945 +vt 0.899283 0.970312 +vt 0.942544 0.888589 +vt 0.720028 0.902269 +vt 0.707168 1.046875 +vt 0.453826 0.931398 +vt 0.215418 0.844835 +vt 0.058156 0.586898 +vt 0.236023 0.667976 +vt 0.349482 0.454114 +vt 0.136958 0.357239 +vt 0.046875 0.316174 +vt 0.372331 0.198949 +vt 0.447320 0.046875 +vt 0.194464 0.117868 +vt 0.683183 0.075062 +vt 0.674378 0.172493 +vt 0.863351 0.409106 +vt 0.927720 0.287975 +vt 0.878332 0.243345 +vt 1.026786 0.598716 +vt 1.035592 0.501285 +vt 0.834671 0.675278 +vt 0.532626 0.701734 +vt 0.616869 0.411861 +# 302 texture coordinates + +vn -0.537588 -0.071798 0.840146 +vn -0.151555 -0.017111 0.988301 +vn -0.510264 0.347193 0.786822 +vn -0.383883 0.724753 0.572160 +vn 0.006791 0.547083 0.837051 +vn 0.441964 0.160862 0.882492 +vn -0.810413 0.184718 0.555976 +vn -0.915534 0.402240 -0.000000 +vn -0.710113 0.620185 0.333331 +vn -0.721673 0.607891 -0.331145 +vn -0.413629 0.701858 -0.579920 +vn -0.409411 0.912350 0.000434 +vn 0.132323 0.938010 0.320355 +vn 0.132323 0.938010 -0.320355 +vn 0.339768 0.940509 -0.000000 +vn 0.481852 0.617859 0.621345 +vn 0.881337 0.472488 -0.000000 +vn 0.942952 -0.332930 -0.000000 +vn 0.795204 -0.092522 0.599242 +vn 0.481852 0.617859 -0.621345 +vn 0.441964 0.160862 -0.882492 +vn 0.795204 -0.092522 -0.599242 +vn -0.012521 0.539701 -0.841764 +vn -0.544858 0.327294 -0.772016 +vn -0.561303 -0.075179 -0.824189 +vn -0.195775 -0.027076 -0.980275 +vn -0.299847 -0.529265 -0.793707 +vn 0.144885 -0.802478 -0.578824 +vn 0.343163 -0.420370 -0.839957 +vn 0.704306 -0.633502 -0.320355 +vn 0.260986 -0.965343 0.000322 +vn 0.173226 -0.803252 0.569894 +vn 0.704306 -0.633502 0.320355 +vn -0.346230 -0.872998 -0.343510 +vn -0.769195 -0.639014 0.000000 +vn -0.334289 -0.877615 0.343575 +vn -0.728104 -0.400942 0.555976 +vn -0.264904 -0.527345 0.807300 +vn 0.359321 -0.413990 0.836362 +vn -0.990268 -0.139173 -0.000000 +vn -0.810413 0.184718 -0.555976 +vn -0.728104 -0.400942 -0.555976 +vn -0.236279 0.029185 0.971247 +vn 0.320907 -0.108176 0.940913 +vn 0.232851 0.492069 0.838838 +vn 0.401159 0.816009 0.416173 +vn 0.362076 0.383575 0.849571 +vn 0.126098 -0.040972 0.991171 +vn -0.604687 0.614896 0.506218 +vn -0.478910 0.877864 -0.000000 +vn 0.038576 0.969348 0.242645 +vn 0.038576 0.969348 -0.242645 +vn 0.401159 0.816009 -0.416173 +vn 0.360915 0.932599 0.000000 +vn 0.494411 0.798675 0.343038 +vn 0.494411 0.798675 -0.343038 +vn 0.861265 0.508156 -0.000000 +vn 0.647910 0.246087 0.720870 +vn 0.951057 -0.309017 -0.000000 +vn 0.743317 -0.668940 -0.000000 +vn 0.535463 -0.362827 0.762651 +vn 0.647910 0.246086 -0.720870 +vn 0.126098 -0.040972 -0.991171 +vn 0.535463 -0.362827 -0.762651 +vn 0.362076 0.383575 -0.849571 +vn 0.232851 0.492069 -0.838838 +vn -0.236279 0.029185 -0.971247 +vn 0.320907 -0.108176 -0.940913 +vn 0.132934 -0.415219 -0.899956 +vn 0.188857 -0.970911 -0.147192 +vn 0.199321 -0.435181 -0.878003 +vn -0.862018 0.083023 0.500032 +vn 0.132934 -0.415219 0.899956 +vn 0.199321 -0.435181 0.878002 +vn 0.188857 -0.970911 0.147192 +vn -0.930205 0.367040 -0.000000 +vn -0.997640 0.068658 -0.000000 +vn -0.604687 0.614896 -0.506218 +vn -0.862018 0.083023 -0.500032 +vn 0.021383 -0.916512 0.399436 +vn -0.781862 -0.431561 -0.449942 +vn 0.956336 0.228461 -0.182283 +vn 0.833901 -0.104561 -0.541919 +vn 0.767800 0.601842 0.219702 +vn 0.546124 0.782549 0.298940 +vn 0.910925 0.174919 -0.373656 +vn 0.748758 0.661676 -0.039313 +vn 0.949258 -0.047485 -0.310893 +vn 0.406836 0.802260 -0.436879 +vn 0.769156 0.182669 -0.612398 +vn 0.199512 0.609083 -0.767602 +vn 0.667603 0.001959 -0.744515 +vn -0.099388 0.414937 -0.904405 +vn 0.352774 0.079499 -0.932325 +vn -0.283318 0.420843 -0.861755 +vn -0.057479 0.857527 0.511218 +vn 0.131724 0.743022 0.656177 +vn -0.005809 0.859552 0.511016 +vn -0.350571 0.931431 -0.097655 +vn -0.647693 0.664816 -0.372173 +vn -0.898309 0.404808 -0.170794 +vn -0.866249 0.480043 -0.138459 +vn -0.715121 0.360250 0.599018 +vn -0.866625 0.341770 0.363530 +vn -0.662377 0.297013 0.687780 +vn -0.811725 0.388839 0.435782 +vn -0.950899 0.243388 0.191190 +vn -0.846773 0.078043 0.526199 +vn -0.759416 0.140950 0.635154 +vn -0.940011 -0.340515 -0.020693 +vn -0.972400 -0.204991 0.111430 +vn -0.817030 -0.331766 0.471585 +vn -0.616700 -0.385898 0.686122 +vn -0.565415 -0.413211 0.713837 +vn -0.342437 -0.316577 0.884599 +vn -0.263317 -0.310224 0.913469 +vn -0.492073 -0.677280 -0.546952 +vn -0.216535 -0.832588 -0.509814 +vn -0.336313 -0.936688 -0.097510 +vn 0.085084 -0.882948 0.461697 +vn 0.196057 -0.733951 0.650291 +vn 0.454815 -0.615703 0.643470 +vn 0.489338 -0.710824 0.505250 +vn 0.458185 -0.654603 -0.601300 +vn 0.273617 -0.575276 -0.770838 +vn 0.557258 -0.641859 -0.526765 +vn 0.770791 -0.636825 0.018306 +vn 0.873238 -0.487283 0.003170 +vn 0.878760 -0.285726 -0.382285 +vn 0.775252 -0.453136 -0.440060 +vn 0.076768 -0.902254 -0.424317 +vn -0.760858 -0.310029 0.570067 +vn 0.698983 0.632728 -0.333285 +vn 0.918945 -0.018611 0.393945 +vn 0.946923 0.242706 0.210787 +vn 0.597706 0.775902 -0.201801 +vn 0.898457 0.395975 0.189682 +vn 0.584977 0.777578 -0.230597 +vn 0.061121 0.865503 0.497161 +vn 0.814891 0.173456 0.553052 +vn 0.488324 0.052196 0.871100 +vn -0.073338 0.372458 0.925147 +vn -0.168557 0.420636 0.891433 +vn 0.562606 0.011650 0.826643 +vn 0.424549 0.220069 0.878253 +vn -0.202274 0.574889 0.792835 +vn -0.201495 0.870711 -0.448622 +vn -0.147519 0.700066 -0.698674 +vn -0.247406 0.680029 -0.690182 +vn -0.659229 0.742690 -0.117596 +vn -0.823828 0.514402 0.238115 +vn -0.880755 0.462224 0.103053 +vn -0.835446 0.538148 0.111476 +vn -0.835433 0.291149 -0.466138 +vn -0.799017 0.476863 -0.366296 +vn -0.796565 -0.008375 -0.604495 +vn -0.746076 0.124458 -0.654126 +vn -0.847027 0.257512 -0.465008 +vn -0.774335 0.094113 -0.625738 +vn -0.799434 0.067311 -0.596971 +vn -0.914826 -0.403289 0.021240 +vn -0.960708 -0.276547 0.023720 +vn -0.776094 -0.562737 -0.284613 +vn -0.248105 -0.514857 -0.820589 +vn -0.231599 -0.234207 -0.944198 +vn -0.235950 -0.324119 -0.916119 +vn -0.342337 -0.448272 -0.825747 +vn -0.389047 -0.677991 0.623675 +vn -0.286549 -0.868467 0.404542 +vn -0.058292 -0.911347 0.407491 +vn 0.455951 -0.795072 -0.399962 +vn 0.489715 -0.524665 -0.696352 +vn 0.515843 -0.636580 -0.573300 +vn 0.423912 -0.809501 -0.406210 +vn 0.535603 -0.635581 0.556027 +vn 0.490862 -0.467516 0.735176 +vn 0.731377 -0.368576 0.573793 +vn 0.890119 -0.387697 0.239538 +vn 0.883630 -0.404120 0.236399 +vn 0.822699 -0.324540 0.466733 +vn 0.789247 -0.408589 0.458414 +vn -0.072988 -0.902254 0.424984 +vn -0.288148 -0.512224 -0.809072 +vn 0.918806 0.383987 0.091372 +vn 0.993163 0.114096 -0.024688 +vn 0.434383 0.709098 0.555420 +vn 0.471863 0.805177 0.359216 +vn 0.868051 0.441893 0.226313 +vn 0.386966 0.811178 0.438461 +vn 0.971729 0.236044 0.005163 +vn 0.277939 0.903859 -0.325252 +vn 0.907561 0.183989 -0.377467 +vn 0.389798 0.457680 -0.799116 +vn 0.974181 -0.045977 -0.221037 +vn 0.441749 0.266583 -0.856616 +vn 0.886674 0.017475 -0.462065 +vn 0.372092 0.327554 -0.868479 +vn -0.385080 0.834046 0.395071 +vn -0.476106 0.659961 0.581185 +vn -0.556161 0.685573 0.469761 +vn -0.626859 0.745436 -0.226656 +vn -0.554271 0.436146 -0.708915 +vn -0.561559 0.310302 -0.767049 +vn -0.543810 0.416915 -0.728322 +vn -0.974714 0.176358 0.137223 +vn -0.917252 0.369282 0.149263 +vn -0.982764 -0.036304 0.181267 +vn -0.987205 0.070377 0.143084 +vn -0.988708 0.090661 -0.119319 +vn -0.995465 0.069805 -0.064628 +vn -0.986899 0.153108 -0.050882 +vn -0.785702 -0.546219 -0.290374 +vn -0.802167 -0.447423 -0.395400 +vn -0.788300 -0.609188 -0.086443 +vn -0.635308 -0.586832 0.502008 +vn -0.748920 -0.342648 0.567196 +vn -0.829075 -0.199820 0.522213 +vn -0.811409 -0.243593 0.531299 +vn -0.029726 -0.712976 -0.700558 +vn -0.121255 -0.870385 -0.477207 +vn 0.151176 -0.929851 -0.335445 +vn 0.202841 -0.825731 0.526331 +vn 0.080914 -0.528183 0.845266 +vn 0.010675 -0.474241 0.880330 +vn 0.014489 -0.635546 0.771927 +vn 0.742724 -0.545146 -0.388814 +vn 0.786510 -0.383302 -0.484233 +vn 0.920594 -0.358142 -0.155695 +vn 0.889767 -0.359426 0.281297 +vn 0.873005 -0.294226 0.388965 +vn 0.907656 -0.291730 0.301752 +vn 0.863097 -0.445709 0.237502 +vn 0.041443 -0.908865 -0.415027 +vn -0.109957 -0.084548 0.990334 +vn 0.245131 0.763260 -0.597783 +vn 0.955445 0.284327 -0.079261 +vn 0.823805 0.535171 -0.186913 +vn 0.285353 0.867913 -0.406571 +vn 0.750150 0.580981 -0.315809 +vn 0.193001 0.857724 -0.476509 +vn 0.122062 0.961258 0.247151 +vn 0.890764 0.429947 -0.147257 +vn 0.869360 0.404802 0.283458 +vn 0.342558 0.602318 0.721018 +vn 0.449593 0.557051 0.698255 +vn 0.979971 0.160598 0.117751 +vn 0.912952 0.330027 0.240004 +vn 0.396960 0.742707 0.539267 +vn -0.562652 0.747701 -0.352655 +vn -0.640733 0.557163 -0.528234 +vn -0.712118 0.570582 -0.409053 +vn -0.719414 0.632988 0.285953 +vn -0.541635 0.392908 0.743139 +vn -0.506872 0.445328 0.738081 +vn -0.530036 0.658014 0.534864 +vn -0.999398 0.002857 -0.034586 +vn -0.977859 0.202556 -0.052566 +vn -0.974887 -0.208763 -0.077548 +vn -0.990809 -0.134971 -0.008911 +vn -0.971468 -0.084083 0.221765 +vn -0.983987 -0.035832 0.174602 +vn -0.987930 0.055655 0.144559 +vn -0.644785 -0.668339 0.370912 +vn -0.667256 -0.571980 0.477084 +vn -0.657389 -0.734501 0.168369 +vn -0.560535 -0.736307 -0.379015 +vn -0.692904 -0.540327 -0.477421 +vn -0.805447 -0.450708 -0.384860 +vn -0.807097 -0.552297 -0.208715 +vn 0.166809 -0.694562 0.699828 +vn 0.081505 -0.869441 0.487268 +vn 0.344060 -0.883528 0.317807 +vn 0.303265 -0.806548 -0.507455 +vn 0.132506 -0.587487 -0.798312 +vn 0.022610 -0.693630 -0.719976 +vn 0.045100 -0.923914 -0.379933 +vn 0.862122 -0.401541 0.309048 +vn 0.886724 -0.232862 0.399368 +vn 0.979859 -0.190892 0.058615 +vn 0.901262 -0.198277 -0.385245 +vn 0.854374 -0.181939 -0.486768 +vn 0.901238 -0.252507 -0.352151 +vn 0.898278 -0.412999 -0.150093 +vn -0.272473 -0.916512 -0.292854 +vn 0.247462 -0.431597 0.867460 +vn 0.375319 0.601842 -0.704927 +vn 0.969100 -0.104559 -0.223412 +vn 0.795449 0.228463 -0.561307 +vn 0.164332 0.782548 -0.600511 +vn 0.901567 0.174919 -0.395701 +vn 0.548411 0.661676 -0.511303 +vn 0.596875 0.802261 0.010829 +vn 0.883048 -0.047484 -0.466875 +vn 0.975847 0.140489 -0.167289 +vn 0.695006 0.600563 0.395335 +vn 0.804391 0.375485 0.460397 +vn 0.950455 -0.062330 -0.304551 +vn 0.989975 0.079498 -0.116747 +vn 0.767612 0.420846 0.483385 +vn -0.407667 0.857527 -0.313775 +vn -0.380509 0.743022 -0.550574 +vn -0.371629 0.859552 -0.350803 +vn -0.173281 0.931431 0.320017 +vn -0.088344 0.681833 0.726154 +vn -0.097862 0.460784 0.882100 +vn -0.075217 0.480042 0.874015 +vn -0.927662 0.360250 0.098302 +vn -0.863510 0.341772 0.370868 +vn -0.954873 0.297012 -0.001297 +vn -0.877348 0.388838 0.281187 +vn -0.798205 0.258643 0.544033 +vn -0.830945 0.129933 0.540970 +vn -0.800009 0.140946 0.583197 +vn -0.638103 -0.340513 0.690562 +vn -0.755642 -0.204991 0.622080 +vn -0.906786 -0.331767 0.260133 +vn -0.921950 -0.385899 -0.033004 +vn -0.932303 -0.360848 -0.024508 +vn -0.971643 -0.236380 0.005919 +vn -0.950036 -0.310227 0.034503 +vn 0.051621 -0.677280 0.733912 +vn 0.216310 -0.832587 0.509910 +vn -0.163481 -0.936688 0.309662 +vn -0.273013 -0.882948 -0.381925 +vn -0.334489 -0.728676 -0.597619 +vn -0.408235 -0.602580 -0.685741 +vn -0.371857 -0.710825 -0.597035 +vn 0.750822 -0.654602 0.088107 +vn 0.744565 -0.575276 0.338646 +vn 0.766027 -0.641859 -0.034936 +vn 0.522268 -0.636825 -0.567176 +vn 0.527667 -0.527467 -0.665842 +vn 0.641037 -0.375221 -0.669538 +vn 0.614542 -0.453134 -0.645761 +vn -0.272476 -0.916512 0.292854 +vn 0.247445 -0.431549 -0.867488 +vn 0.795449 0.228463 0.561307 +vn 0.969100 -0.104559 0.223412 +vn 0.375318 0.601842 0.704927 +vn 0.164332 0.782548 0.600511 +vn 0.901567 0.174919 0.395701 +vn 0.548410 0.661676 0.511303 +vn 0.883047 -0.047485 0.466875 +vn 0.596875 0.802261 -0.010829 +vn 0.975847 0.140489 0.167289 +vn 0.695006 0.600564 -0.395336 +vn 0.950454 -0.062330 0.304551 +vn 0.804391 0.375485 -0.460397 +vn 0.989975 0.079498 0.116747 +vn 0.767611 0.420846 -0.483385 +vn -0.407667 0.857527 0.313775 +vn -0.380509 0.743022 0.550574 +vn -0.371629 0.859552 0.350803 +vn -0.173281 0.931431 -0.320017 +vn -0.088345 0.681833 -0.726154 +vn -0.097862 0.460784 -0.882100 +vn -0.075217 0.480042 -0.874015 +vn -0.927662 0.360250 -0.098302 +vn -0.863510 0.341772 -0.370868 +vn -0.954873 0.297012 0.001297 +vn -0.877348 0.388838 -0.281187 +vn -0.798205 0.258643 -0.544033 +vn -0.830945 0.129933 -0.540970 +vn -0.800010 0.140945 -0.583196 +vn -0.638103 -0.340513 -0.690562 +vn -0.755642 -0.204991 -0.622081 +vn -0.906786 -0.331767 -0.260133 +vn -0.921950 -0.385899 0.033004 +vn -0.932303 -0.360848 0.024508 +vn -0.971643 -0.236380 -0.005919 +vn -0.950036 -0.310227 -0.034503 +vn 0.051621 -0.677280 -0.733912 +vn 0.216310 -0.832587 -0.509910 +vn -0.163481 -0.936687 -0.309662 +vn -0.273013 -0.882948 0.381925 +vn -0.334488 -0.728676 0.597620 +vn -0.408235 -0.602580 0.685741 +vn -0.371857 -0.710825 0.597035 +vn 0.750822 -0.654602 -0.088107 +vn 0.744565 -0.575276 -0.338646 +vn 0.766027 -0.641859 0.034936 +vn 0.522268 -0.636825 0.567177 +vn 0.527667 -0.527467 0.665842 +vn 0.641037 -0.375221 0.669538 +vn 0.614542 -0.453134 0.645761 +vn -0.287103 -0.930941 -0.225656 +vn 0.184368 -0.421801 0.887746 +vn 0.074051 0.631917 -0.771490 +vn 0.855333 0.060647 -0.514517 +vn 0.730773 0.322890 -0.601426 +vn 0.209807 0.742786 -0.635807 +vn 0.616222 0.371327 -0.694540 +vn 0.095819 0.746431 -0.658528 +vn 0.408064 0.912344 0.033360 +vn 0.821336 0.180467 -0.541146 +vn 0.969682 0.166170 -0.179176 +vn 0.754037 0.504418 0.420704 +vn 0.828561 0.316590 0.461798 +vn 0.943283 -0.080094 -0.322182 +vn 0.996799 0.009221 -0.079417 +vn 0.775768 0.382141 0.502148 +vn -0.535922 0.815786 -0.217442 +vn -0.711742 0.631198 -0.308241 +vn -0.720586 0.670982 -0.174754 +vn -0.411496 0.796168 0.443607 +vn -0.094379 0.527301 0.844421 +vn -0.069752 0.407704 0.910446 +vn -0.075227 0.509317 0.857284 +vn -0.899322 0.217218 0.379522 +vn -0.856971 0.404836 0.318918 +vn -0.929488 0.002263 0.368846 +vn -0.913020 0.111991 0.392239 +vn -0.775244 0.155507 0.612221 +vn -0.809953 0.130294 0.571839 +vn -0.809970 0.211451 0.547026 +vn -0.512438 -0.473965 0.716075 +vn -0.470746 -0.365488 0.803005 +vn -0.622708 -0.554524 0.552030 +vn -0.804795 -0.592927 -0.027236 +vn -0.935688 -0.349566 -0.047865 +vn -0.979826 -0.199093 0.017388 +vn -0.969660 -0.244405 0.004995 +vn 0.346030 -0.645322 0.681045 +vn 0.150051 -0.816598 0.557361 +vn 0.305963 -0.903395 0.300439 +vn -0.106894 -0.879100 -0.464497 +vn -0.379304 -0.604701 -0.700332 +vn -0.457451 -0.550271 -0.698527 +vn -0.396771 -0.701295 -0.592249 +vn 0.835906 -0.548834 -0.006518 +vn 0.923602 -0.381844 0.033966 +vn 0.863214 -0.393372 -0.316418 +vn 0.605500 -0.431678 -0.668598 +vn 0.534229 -0.375452 -0.757387 +vn 0.609831 -0.367158 -0.702354 +vn 0.606094 -0.512127 -0.608586 +vn -0.287104 -0.930941 0.225655 +vn 0.184384 -0.421751 -0.887766 +vn 0.730773 0.322890 0.601426 +vn 0.855333 0.060647 0.514517 +vn 0.074051 0.631917 0.771490 +vn 0.209807 0.742786 0.635807 +vn 0.616222 0.371327 0.694540 +vn 0.095818 0.746431 0.658528 +vn 0.821336 0.180467 0.541145 +vn 0.408064 0.912344 -0.033360 +vn 0.969682 0.166170 0.179175 +vn 0.754037 0.504418 -0.420704 +vn 0.943283 -0.080094 0.322182 +vn 0.828560 0.316590 -0.461799 +vn 0.996799 0.009221 0.079417 +vn 0.775768 0.382141 -0.502148 +vn -0.535922 0.815786 0.217442 +vn -0.711742 0.631198 0.308241 +vn -0.720586 0.670982 0.174754 +vn -0.411496 0.796168 -0.443607 +vn -0.094380 0.527301 -0.844421 +vn -0.069752 0.407704 -0.910446 +vn -0.075227 0.509317 -0.857285 +vn -0.899322 0.217218 -0.379522 +vn -0.856971 0.404836 -0.318918 +vn -0.929488 0.002263 -0.368845 +vn -0.913020 0.111991 -0.392239 +vn -0.775244 0.155506 -0.612221 +vn -0.809952 0.130294 -0.571839 +vn -0.809969 0.211450 -0.547027 +vn -0.512438 -0.473965 -0.716075 +vn -0.470746 -0.365488 -0.803005 +vn -0.622708 -0.554524 -0.552030 +vn -0.804795 -0.592928 0.027236 +vn -0.935688 -0.349566 0.047865 +vn -0.979826 -0.199093 -0.017388 +vn -0.969660 -0.244405 -0.004995 +vn 0.346030 -0.645322 -0.681045 +vn 0.150051 -0.816598 -0.557361 +vn 0.305964 -0.903395 -0.300439 +vn -0.106895 -0.879100 0.464496 +vn -0.379305 -0.604701 0.700332 +vn -0.457451 -0.550271 0.698527 +vn -0.396771 -0.701294 0.592249 +vn 0.835906 -0.548834 0.006518 +vn 0.923602 -0.381844 -0.033966 +vn 0.863214 -0.393373 0.316418 +vn 0.605500 -0.431679 0.668598 +vn 0.534230 -0.375452 0.757387 +vn 0.609831 -0.367158 0.702354 +vn 0.606094 -0.512126 0.608586 +vn 0.000000 0.000000 0.000000 +vn 0.891945 0.333606 -0.305190 +vn 0.885286 -0.051708 0.462163 +vn 0.871701 -0.486404 -0.059574 +vn 0.602535 -0.114023 0.789906 +vn 0.767332 -0.613878 0.185353 +vn 0.615704 -0.238766 0.750932 +vn -0.132228 0.076598 0.988255 +vn -0.134483 0.218923 0.966430 +vn -0.082654 0.333036 0.939285 +vn -0.794263 0.362851 0.487325 +vn -0.686973 0.538875 0.487527 +vn -0.911656 -0.242414 -0.331840 +vn -0.903470 -0.005854 -0.428611 +vn -0.880207 0.284493 -0.379868 +vn -0.359072 -0.293407 -0.885991 +vn -0.531215 -0.161650 -0.831673 +vn 0.521710 -0.333452 -0.785257 +vn 0.498223 -0.518213 -0.695147 +vn 0.319252 -0.666930 -0.673263 +vn 0.417209 0.602930 -0.680009 +vn -0.390952 -0.506393 -0.768585 +vn -0.785847 -0.219916 -0.577999 +vn -0.112803 -0.767065 -0.631575 +vn -0.676852 -0.452073 -0.580948 +vn -0.070613 -0.785109 -0.615320 +vn 0.404464 -0.913005 -0.053206 +vn 0.510041 -0.851111 -0.124372 +vn 0.600863 -0.776753 -0.188727 +vn 0.734160 -0.298249 0.609964 +vn 0.802855 -0.245127 0.543449 +vn 0.203920 0.286548 0.936113 +vn 0.259058 0.346923 0.901407 +vn 0.305077 0.413607 0.857821 +vn -0.395140 0.672313 0.625987 +vn -0.388204 0.672327 0.630297 +vn -0.844407 0.508563 -0.168344 +vn -0.907377 0.410201 -0.091666 +vn -0.943128 0.331776 0.020840 +vn -0.032685 0.987521 0.154060 +vn 0.285617 0.953018 0.100890 +vn 0.356408 0.929723 0.092678 +vn 0.058045 0.915295 0.398579 +vn -0.438098 -0.839825 0.320570 +vn 0.039808 -0.749385 0.660937 +vn -0.436422 -0.758689 0.483660 +vn -0.144622 0.858467 0.492057 +vn -0.390508 -0.802547 0.451023 +vn -0.378955 0.768626 0.515371 +vn -0.351840 -0.855427 0.380071 +vn -0.503913 0.811284 0.296463 +vn -0.434503 -0.886238 0.160593 +vn -0.589554 0.766850 0.253707 +vn 0.461124 -0.566742 0.682765 +vn -0.033279 -0.530249 0.847189 +vn -0.155076 -0.479386 0.863794 +vn -0.332554 -0.675497 0.658112 +vn -0.624353 -0.649034 0.434671 +vn -0.640430 -0.723275 0.258307 +vn 0.839146 -0.520972 0.156274 +vn 0.979386 -0.047392 0.196359 +vn 0.859197 -0.013066 0.511478 +vn 0.169781 0.017978 0.985318 +vn -0.298124 0.093164 0.949970 +vn -0.602581 0.140795 0.785540 +vn -0.760623 0.356880 0.542300 +vn -0.916442 -0.012784 0.399964 +vn 0.709959 0.689780 0.141992 +vn 0.616328 0.711155 0.338227 +vn 0.121528 0.638102 0.760300 +vn -0.308158 0.474484 0.824563 +vn -0.584949 0.497866 0.640284 +vn -0.831395 0.369875 0.414699 +vn -0.777389 0.439755 0.449757 +vn -0.712098 0.074375 0.698130 +vn -0.522162 -0.582125 0.623279 +vn -0.536293 0.842625 0.048710 +vn -0.627855 0.740316 0.240274 +vn -0.817995 0.476796 0.321792 +vn -0.729171 0.655795 0.195555 +vn -0.958544 0.215108 0.186875 +vn -0.950592 0.163928 0.263634 +vn -0.983392 -0.022830 0.180052 +vn -0.891745 0.110754 0.438776 +vn -0.991858 -0.087830 0.092218 +vn -0.859104 0.044821 0.509835 +vn -0.894952 -0.402899 0.191658 +vn -0.903611 0.009093 0.428257 +vn -0.889320 0.017457 0.456952 +vn -0.731541 -0.492421 0.471561 +vn -0.794103 -0.178378 0.581017 +vn -0.625933 -0.373553 0.684592 +vn -0.584508 -0.184831 0.790056 +vn -0.801518 -0.104269 0.588809 +vn -0.642031 -0.296727 0.706929 +vn -0.820281 -0.123456 0.558478 +vn 0.016905 -0.936472 -0.350333 +vn -0.098795 -0.739900 -0.665423 +vn -0.069462 -0.936749 -0.343039 +vn 0.123931 -0.992291 -0.000000 +vn 0.035891 -0.855981 -0.515760 +vn -0.028951 -0.999581 0.000000 +vn 0.016905 -0.936472 0.350333 +vn -0.069462 -0.936749 0.343039 +vn -0.334402 -0.916161 -0.220964 +vn -0.790477 -0.612492 -0.000000 +vn -0.334402 -0.916161 0.220964 +vn -0.741010 -0.556660 0.375544 +vn -0.274313 -0.889661 0.365042 +vn -0.098795 -0.739900 0.665423 +vn 0.035891 -0.855981 0.515760 +vn -0.274313 -0.889661 -0.365042 +vn -0.741010 -0.556660 -0.375544 +vn 0.356408 0.929723 -0.092678 +vn 0.285617 0.953018 -0.100890 +vn -0.032685 0.987521 -0.154060 +vn 0.058045 0.915295 -0.398579 +vn -0.436422 -0.758689 -0.483660 +vn 0.039808 -0.749385 -0.660937 +vn -0.438098 -0.839825 -0.320570 +vn -0.144622 0.858467 -0.492057 +vn -0.390508 -0.802547 -0.451023 +vn -0.378955 0.768626 -0.515371 +vn -0.351840 -0.855427 -0.380071 +vn -0.503913 0.811284 -0.296463 +vn -0.434503 -0.886238 -0.160593 +vn -0.589554 0.766850 -0.253707 +vn -0.033279 -0.530249 -0.847189 +vn 0.461124 -0.566742 -0.682765 +vn -0.155076 -0.479386 -0.863794 +vn -0.332554 -0.675497 -0.658112 +vn -0.624352 -0.649034 -0.434671 +vn -0.640430 -0.723275 -0.258307 +vn 0.979386 -0.047392 -0.196359 +vn 0.839147 -0.520972 -0.156274 +vn 0.859197 -0.013067 -0.511478 +vn 0.169781 0.017978 -0.985318 +vn -0.298124 0.093164 -0.949970 +vn -0.602580 0.140795 -0.785540 +vn -0.760623 0.356880 -0.542300 +vn -0.916442 -0.012784 -0.399964 +vn 0.616328 0.711155 -0.338227 +vn 0.709959 0.689780 -0.141992 +vn 0.121527 0.638102 -0.760300 +vn -0.308158 0.474484 -0.824563 +vn -0.584949 0.497867 -0.640284 +vn -0.831395 0.369875 -0.414699 +vn -0.777389 0.439755 -0.449757 +vn -0.536292 0.842626 -0.048710 +vn -0.522164 -0.582123 -0.623280 +vn -0.712098 0.074377 -0.698129 +vn -0.627854 0.740316 -0.240274 +vn -0.817995 0.476797 -0.321792 +vn -0.729171 0.655796 -0.195555 +vn -0.958544 0.215108 -0.186875 +vn -0.950592 0.163928 -0.263634 +vn -0.891745 0.110753 -0.438776 +vn -0.983392 -0.022830 -0.180053 +vn -0.859104 0.044821 -0.509834 +vn -0.991858 -0.087831 -0.092217 +vn -0.894953 -0.402899 -0.191657 +vn -0.903611 0.009093 -0.428257 +vn -0.889320 0.017458 -0.456952 +vn -0.731541 -0.492420 -0.471561 +vn -0.794103 -0.178378 -0.581018 +vn -0.625932 -0.373553 -0.684593 +vn -0.584507 -0.184830 -0.790056 +vn -0.801518 -0.104269 -0.588809 +vn -0.642031 -0.296727 -0.706930 +vn -0.820281 -0.123456 -0.558478 +vn 0.891944 0.333618 0.305179 +vn 0.602535 -0.114021 -0.789905 +vn 0.871702 -0.486402 0.059575 +vn 0.885285 -0.051707 -0.462165 +vn 0.767335 -0.613875 -0.185352 +vn 0.615706 -0.238765 -0.750931 +vn -0.132228 0.076598 -0.988255 +vn -0.134482 0.218923 -0.966430 +vn -0.082654 0.333036 -0.939284 +vn -0.794263 0.362851 -0.487325 +vn -0.686973 0.538875 -0.487526 +vn -0.911656 -0.242414 0.331840 +vn -0.903470 -0.005854 0.428611 +vn -0.880207 0.284493 0.379868 +vn -0.359072 -0.293407 0.885991 +vn -0.531215 -0.161650 0.831673 +vn 0.521709 -0.333452 0.785258 +vn 0.498223 -0.518212 0.695148 +vn 0.319253 -0.666929 0.673264 +vn 0.417208 0.602931 0.680009 +vn -0.112803 -0.767065 0.631575 +vn -0.785847 -0.219916 0.577998 +vn -0.390952 -0.506392 0.768585 +vn -0.676852 -0.452073 0.580948 +vn -0.070613 -0.785108 0.615320 +vn 0.404464 -0.913005 0.053206 +vn 0.510042 -0.851111 0.124372 +vn 0.600863 -0.776753 0.188727 +vn 0.734160 -0.298249 -0.609964 +vn 0.802854 -0.245127 -0.543450 +vn 0.203920 0.286548 -0.936113 +vn 0.259058 0.346923 -0.901407 +vn 0.305077 0.413607 -0.857821 +vn -0.395140 0.672312 -0.625988 +vn -0.388204 0.672327 -0.630297 +vn -0.844407 0.508563 0.168344 +vn -0.907377 0.410201 0.091666 +vn -0.943128 0.331776 -0.020840 +vn 0.092832 0.340544 0.935634 +vn 0.433215 0.308260 0.846936 +vn 0.075136 0.741809 0.666389 +vn -0.375593 0.622444 0.686654 +vn -0.641388 0.689588 0.336288 +vn -0.353918 0.873123 0.335258 +vn -0.662764 0.746241 -0.062188 +vn -0.545563 0.658509 -0.518389 +vn -0.542286 0.268594 -0.796105 +vn -0.776382 0.468027 -0.422116 +vn -0.995559 -0.032197 -0.088459 +vn -0.738154 -0.230737 -0.633948 +vn -0.433216 -0.308258 -0.846936 +vn -0.776385 -0.629857 -0.022517 +vn -0.467564 -0.874397 0.129668 +vn -0.542292 -0.717476 -0.437204 +vn -0.189834 -0.854102 0.484223 +vn -0.545805 -0.711395 0.442735 +vn -0.641391 -0.312091 0.700868 +vn -0.215356 -0.623780 0.751346 +vn 0.037501 -0.724698 0.688046 +vn -0.375594 -0.035443 0.926107 +vn 0.078137 -0.268605 0.960076 +vn -0.757385 0.223328 0.613590 +vn -0.902417 0.400663 0.158468 +vn -0.902417 -0.205066 0.378934 +vn 0.075136 0.741809 -0.666389 +vn 0.433215 0.308260 -0.846936 +vn 0.092832 0.340544 -0.935635 +vn -0.375593 0.622444 -0.686654 +vn -0.353918 0.873123 -0.335257 +vn -0.641388 0.689588 -0.336288 +vn -0.662764 0.746241 0.062188 +vn -0.776382 0.468027 0.422116 +vn -0.542286 0.268594 0.796105 +vn -0.545562 0.658510 0.518389 +vn -0.738154 -0.230737 0.633948 +vn -0.995559 -0.032196 0.088459 +vn -0.433216 -0.308258 0.846936 +vn -0.776385 -0.629856 0.022517 +vn -0.542292 -0.717477 0.437204 +vn -0.467565 -0.874397 -0.129668 +vn -0.545805 -0.711394 -0.442736 +vn -0.189834 -0.854102 -0.484223 +vn -0.215356 -0.623779 -0.751346 +vn -0.641391 -0.312091 -0.700869 +vn 0.037501 -0.724698 -0.688046 +vn -0.375594 -0.035443 -0.926106 +vn 0.078136 -0.268605 -0.960076 +vn -0.757384 0.223328 -0.613590 +vn -0.902417 0.400663 -0.158468 +vn -0.902417 -0.205066 -0.378934 +# 747 normals + +g HLeib01 +usemtl HLeibTex +s 1 +f 1/1/1 2/2/2 3/3/3 +f 4/4/4 3/3/3 5/5/5 +f 6/6/6 5/5/5 2/2/2 +f 3/3/3 2/2/2 5/5/5 +f 1/1/1 3/3/3 7/7/7 +f 8/8/8 7/7/7 9/9/9 +f 4/4/4 9/9/9 3/3/3 +f 7/7/7 3/3/3 9/9/9 +f 8/8/8 9/9/9 10/10/10 +f 11/11/11 10/10/10 12/12/12 +f 4/4/4 12/12/12 9/9/9 +f 10/10/10 9/9/9 12/12/12 +f 4/4/4 13/13/13 12/12/12 +f 11/11/11 12/12/12 14/14/14 +f 15/15/15 14/14/14 13/13/13 +f 12/12/12 13/13/13 14/14/14 +f 4/4/4 5/5/5 13/13/13 +f 15/15/15 13/13/13 16/16/16 +f 6/6/6 16/16/16 5/5/5 +f 13/13/13 5/5/5 16/16/16 +f 15/15/15 16/16/16 17/17/17 +f 18/18/18 17/17/17 19/19/19 +f 6/6/6 19/19/19 16/16/16 +f 17/17/17 16/16/16 19/19/19 +f 15/15/15 17/17/17 20/20/20 +f 21/21/21 20/20/20 22/22/22 +f 18/18/18 22/22/22 17/17/17 +f 20/20/20 17/17/17 22/22/22 +f 11/11/11 14/14/14 23/23/23 +f 21/21/21 23/23/23 20/20/20 +f 15/15/15 20/20/20 14/14/14 +f 23/23/23 14/14/14 20/20/20 +f 11/11/11 23/23/23 24/24/24 +f 25/25/25 24/24/24 26/26/26 +f 21/21/21 26/26/26 23/23/23 +f 24/24/24 23/23/23 26/26/26 +f 25/25/25 26/26/26 27/27/27 +f 28/28/28 27/27/27 29/29/29 +f 21/21/21 29/29/29 26/26/26 +f 27/27/27 26/26/26 29/29/29 +f 28/28/28 29/29/29 30/30/30 +f 18/18/18 30/30/30 22/22/22 +f 21/21/21 22/22/22 29/29/29 +f 30/30/30 29/29/29 22/22/22 +f 28/28/28 30/30/30 31/31/31 +f 32/32/32 31/31/31 33/33/33 +f 18/18/18 33/33/33 30/30/30 +f 31/31/31 30/30/30 33/33/33 +f 28/28/28 31/31/31 34/34/34 +f 35/35/35 34/34/34 36/36/36 +f 32/32/32 36/36/36 31/31/31 +f 34/34/34 31/31/31 36/36/36 +f 35/35/35 36/36/36 37/37/37 +f 1/1/1 37/37/37 38/38/38 +f 32/32/32 38/38/38 36/36/36 +f 37/37/37 36/36/36 38/38/38 +f 1/1/1 38/38/38 2/2/2 +f 6/6/6 2/2/2 39/39/39 +f 32/32/32 39/39/39 38/38/38 +f 2/2/2 38/38/38 39/39/39 +f 32/32/32 33/33/33 39/39/39 +f 6/6/6 39/39/39 19/19/19 +f 18/18/18 19/19/19 33/33/33 +f 39/39/39 33/33/33 19/19/19 +f 8/8/8 40/40/40 7/7/7 +f 1/1/1 7/7/7 37/37/37 +f 35/35/35 37/37/37 40/40/40 +f 7/7/7 40/40/40 37/37/37 +f 8/8/8 41/41/41 40/40/40 +f 35/35/35 40/40/40 42/42/42 +f 25/25/25 42/42/42 41/41/41 +f 40/40/40 41/41/41 42/42/42 +f 8/8/8 10/10/10 41/41/41 +f 25/25/25 41/41/41 24/24/24 +f 11/11/11 24/24/24 10/10/10 +f 41/41/41 10/10/10 24/24/24 +f 28/28/28 34/34/34 27/27/27 +f 25/25/25 27/27/27 42/42/42 +f 35/35/35 42/42/42 34/34/34 +f 27/27/27 34/34/34 42/42/42 +# 80 triangles in group + +g OK +usemtl Skin +f 43/43/43 44/44/44 45/45/45 +f 46/46/46 45/45/45 47/47/47 +f 48/48/48 47/47/47 44/44/44 +f 45/45/45 44/44/44 47/47/47 +f 43/43/43 45/45/45 49/49/49 +f 50/50/50 49/49/49 51/51/51 +f 46/46/46 51/51/51 45/45/45 +f 49/49/49 45/45/45 51/51/51 +f 50/50/50 51/51/51 52/52/52 +f 53/53/53 52/52/52 54/54/54 +f 46/46/46 54/54/54 51/51/51 +f 52/52/52 51/51/51 54/54/54 +f 46/46/46 55/55/55 54/54/54 +f 53/53/53 54/54/54 56/56/56 +f 57/57/57 56/56/56 55/55/55 +f 54/54/54 55/55/55 56/56/56 +f 46/46/46 47/47/47 55/55/55 +f 57/57/57 55/55/55 58/58/58 +f 48/48/48 58/58/58 47/47/47 +f 55/55/55 47/47/47 58/58/58 +f 57/57/57 58/58/58 59/59/59 +f 60/57/60 59/59/59 61/58/61 +f 48/48/48 61/58/61 58/58/58 +f 59/59/59 58/58/58 61/58/61 +f 57/57/57 59/59/59 62/60/62 +f 63/61/63 62/60/62 64/60/64 +f 60/57/60 64/60/64 59/59/59 +f 62/60/62 59/59/59 64/60/64 +f 53/53/53 56/56/56 65/62/65 +f 63/61/63 65/62/65 62/60/62 +f 57/57/57 62/60/62 56/56/56 +f 65/62/65 56/56/56 62/60/62 +f 53/53/53 65/62/65 66/63/66 +f 67/64/67 66/63/66 68/65/68 +f 63/61/63 68/65/68 65/62/65 +f 66/63/66 65/62/65 68/65/68 +f 67/64/67 68/65/68 69/63/69 +f 70/53/70 69/63/69 71/62/71 +f 63/61/63 71/62/71 68/65/68 +f 69/63/69 68/65/68 71/62/71 +f 63/61/63 64/60/64 71/62/71 +f 43/43/43 74/49/72 75/45/73 +f 43/43/43 75/45/73 44/44/44 +f 48/48/48 44/44/44 76/47/74 +f 72/46/75 76/47/74 75/45/73 +f 44/44/44 75/45/73 76/47/74 +f 48/48/48 76/47/74 61/58/61 +f 50/50/50 77/66/76 49/49/49 +f 43/43/43 49/49/49 74/49/72 +f 73/50/77 74/49/72 77/66/76 +f 49/49/49 77/66/76 74/49/72 +f 50/50/50 78/67/78 77/66/76 +f 73/50/77 77/66/76 79/67/79 +f 67/64/67 79/67/79 78/67/78 +f 77/66/76 78/67/78 79/67/79 +f 50/50/50 52/52/52 78/67/78 +f 67/64/67 78/67/78 66/63/66 +f 53/53/53 66/63/66 52/52/52 +f 78/67/78 52/52/52 66/63/66 +f 67/64/67 69/63/69 79/67/79 +# 60 triangles in group + +g Bein1Li +usemtl BeinTex +s 2 +f 80/68/80 87/68/80 130/68/80 +f 86/68/81 129/68/81 93/68/81 +s 1 +f 80/69/82 81/70/83 88/71/84 +f 80/69/82 88/71/84 87/72/85 +f 81/70/83 82/73/86 88/71/84 +f 82/73/86 89/74/87 88/71/84 +f 82/73/86 83/75/88 90/76/89 +f 82/73/86 90/76/89 89/74/87 +f 83/75/88 84/77/90 90/76/89 +f 84/77/90 91/78/91 90/76/89 +f 84/77/90 85/79/92 92/80/93 +f 84/77/90 92/80/93 91/78/91 +f 85/79/92 86/68/94 92/80/93 +f 86/68/94 93/81/95 92/80/93 +s 2 +f 87/68/80 94/68/80 130/68/80 +f 93/68/81 129/68/81 100/68/81 +s 1 +f 87/72/85 88/71/84 94/82/96 +f 88/71/84 95/83/97 94/82/96 +f 88/71/84 89/74/87 96/84/98 +f 88/71/84 96/84/98 95/83/97 +f 89/74/87 90/76/89 96/84/98 +f 90/76/89 97/85/99 96/84/98 +f 90/76/89 91/78/91 98/86/100 +f 90/76/89 98/86/100 97/85/99 +f 91/78/91 92/80/93 98/86/100 +f 92/80/93 99/87/101 98/86/100 +f 92/80/93 93/81/95 100/88/102 +f 92/80/93 100/88/102 99/87/101 +s 2 +f 94/68/80 101/68/80 130/68/80 +f 100/68/81 129/68/81 107/68/81 +s 1 +f 94/82/96 95/83/97 102/89/103 +f 94/82/96 102/89/103 101/90/104 +f 95/83/97 96/84/98 102/89/103 +f 96/84/98 103/91/105 102/89/103 +f 96/84/98 97/85/99 104/92/106 +f 96/84/98 104/92/106 103/91/105 +f 97/85/99 98/86/100 104/92/106 +f 98/86/100 105/93/107 104/92/106 +f 98/86/100 99/87/101 106/94/108 +f 98/86/100 106/94/108 105/93/107 +f 99/87/101 100/88/102 106/94/108 +f 100/88/102 107/95/109 106/94/108 +s 2 +f 101/68/80 108/68/80 130/68/80 +f 107/68/81 129/68/81 114/68/81 +s 1 +f 101/90/104 102/89/103 108/96/110 +f 102/89/103 109/97/111 108/96/110 +f 102/89/103 103/91/105 110/98/112 +f 102/89/103 110/98/112 109/97/111 +f 103/91/105 104/92/106 110/98/112 +f 104/92/106 111/99/113 110/98/112 +f 104/92/106 105/93/107 112/100/114 +f 104/92/106 112/100/114 111/99/113 +f 105/93/107 106/94/108 112/100/114 +f 106/94/108 113/101/115 112/100/114 +f 106/94/108 107/95/109 114/102/116 +f 106/94/108 114/102/116 113/101/115 +s 2 +f 108/68/80 115/68/80 130/68/80 +f 114/68/81 129/68/81 121/68/81 +s 1 +f 108/96/110 109/97/111 116/103/117 +f 108/96/110 116/103/117 115/104/118 +f 109/97/111 110/98/112 116/103/117 +f 110/98/112 117/105/119 116/103/117 +f 110/98/112 111/99/113 118/106/120 +f 110/98/112 118/106/120 117/105/119 +f 111/99/113 112/100/114 118/106/120 +f 112/100/114 119/107/121 118/106/120 +f 112/100/114 113/101/115 120/108/122 +f 112/100/114 120/108/122 119/107/121 +f 113/101/115 114/102/116 120/108/122 +f 114/102/116 121/109/123 120/108/122 +s 2 +f 115/68/80 122/68/80 130/68/80 +f 121/68/81 129/68/81 128/68/81 +s 1 +f 115/104/118 116/103/117 122/110/124 +f 116/103/117 123/111/125 122/110/124 +f 116/103/117 117/105/119 124/112/126 +f 116/103/117 124/112/126 123/111/125 +f 117/105/119 118/106/120 124/112/126 +f 118/106/120 125/113/127 124/112/126 +f 118/106/120 119/107/121 126/114/128 +f 118/106/120 126/114/128 125/113/127 +f 119/107/121 120/108/122 126/114/128 +f 120/108/122 127/115/129 126/114/128 +f 120/108/122 121/109/123 128/116/130 +f 120/108/122 128/116/130 127/115/129 +s 2 +f 122/68/80 80/68/80 130/68/80 +f 128/68/81 129/68/81 86/68/81 +s 1 +f 122/110/124 123/111/125 81/117/83 +f 122/110/124 81/117/83 80/118/82 +f 123/111/125 124/112/126 81/117/83 +f 124/112/126 82/119/86 81/117/83 +f 124/112/126 125/113/127 83/120/88 +f 124/112/126 83/120/88 82/119/86 +f 125/113/127 126/114/128 83/120/88 +f 126/114/128 84/121/90 83/120/88 +f 126/114/128 127/115/129 85/122/92 +f 126/114/128 85/122/92 84/121/90 +f 127/115/129 128/116/130 85/122/92 +f 128/116/130 86/123/94 85/122/92 +# 98 triangles in group + +g Bein1Re +usemtl BeinTex +s 2 +f 181/68/131 138/68/131 131/68/131 +f 144/68/132 180/68/132 137/68/132 +s 1 +f 139/71/133 132/70/134 131/69/135 +f 138/72/136 139/71/133 131/69/135 +f 139/71/133 133/73/137 132/70/134 +f 139/71/133 140/74/138 133/73/137 +f 141/76/139 134/75/140 133/73/137 +f 140/74/138 141/76/139 133/73/137 +f 141/76/139 135/77/141 134/75/140 +f 141/76/139 142/78/142 135/77/141 +f 143/80/143 136/79/144 135/77/141 +f 142/78/142 143/80/143 135/77/141 +f 143/80/143 137/68/145 136/79/144 +f 143/80/143 144/81/146 137/68/145 +s 2 +f 181/68/131 145/68/131 138/68/131 +f 151/68/132 180/68/132 144/68/132 +s 1 +f 145/82/147 139/71/133 138/72/136 +f 145/82/147 146/83/148 139/71/133 +f 147/84/149 140/74/138 139/71/133 +f 146/83/148 147/84/149 139/71/133 +f 147/84/149 141/76/139 140/74/138 +f 147/84/149 148/85/150 141/76/139 +f 149/86/151 142/78/142 141/76/139 +f 148/85/150 149/86/151 141/76/139 +f 149/86/151 143/80/143 142/78/142 +f 149/86/151 150/87/152 143/80/143 +f 151/88/153 144/81/146 143/80/143 +f 150/87/152 151/88/153 143/80/143 +s 2 +f 181/68/131 152/68/131 145/68/131 +f 158/68/132 180/68/132 151/68/132 +s 1 +f 153/89/154 146/83/148 145/82/147 +f 152/90/155 153/89/154 145/82/147 +f 153/89/154 147/84/149 146/83/148 +f 153/89/154 154/91/156 147/84/149 +f 155/92/157 148/85/150 147/84/149 +f 154/91/156 155/92/157 147/84/149 +f 155/92/157 149/86/151 148/85/150 +f 155/92/157 156/93/158 149/86/151 +f 157/94/159 150/87/152 149/86/151 +f 156/93/158 157/94/159 149/86/151 +f 157/94/159 151/88/153 150/87/152 +f 157/94/159 158/95/160 151/88/153 +s 2 +f 181/68/131 159/68/131 152/68/131 +f 165/68/132 180/68/132 158/68/132 +s 1 +f 159/96/161 153/89/154 152/90/155 +f 159/96/161 160/97/162 153/89/154 +f 161/98/163 154/91/156 153/89/154 +f 160/97/162 161/98/163 153/89/154 +f 161/98/163 155/92/157 154/91/156 +f 161/98/163 162/99/164 155/92/157 +f 163/100/165 156/93/158 155/92/157 +f 162/99/164 163/100/165 155/92/157 +f 163/100/165 157/94/159 156/93/158 +f 163/100/165 164/101/166 157/94/159 +f 165/102/167 158/95/160 157/94/159 +f 164/101/166 165/102/167 157/94/159 +s 2 +f 181/68/131 166/68/131 159/68/131 +f 172/68/132 180/68/132 165/68/132 +s 1 +f 167/103/168 160/97/162 159/96/161 +f 166/104/169 167/103/168 159/96/161 +f 167/103/168 161/98/163 160/97/162 +f 167/103/168 168/105/170 161/98/163 +f 169/106/171 162/99/164 161/98/163 +f 168/105/170 169/106/171 161/98/163 +f 169/106/171 163/100/165 162/99/164 +f 169/106/171 170/107/172 163/100/165 +f 171/108/173 164/101/166 163/100/165 +f 170/107/172 171/108/173 163/100/165 +f 171/108/173 165/102/167 164/101/166 +f 171/108/173 172/109/174 165/102/167 +s 2 +f 181/68/131 173/68/131 166/68/131 +f 179/68/132 180/68/132 172/68/132 +s 1 +f 173/110/175 167/103/168 166/104/169 +f 173/110/175 174/111/176 167/103/168 +f 175/112/177 168/105/170 167/103/168 +f 174/111/176 175/112/177 167/103/168 +f 175/112/177 169/106/171 168/105/170 +f 175/112/177 176/113/178 169/106/171 +f 177/114/179 170/107/172 169/106/171 +f 176/113/178 177/114/179 169/106/171 +f 177/114/179 171/108/173 170/107/172 +f 177/114/179 178/115/180 171/108/173 +f 179/116/181 172/109/174 171/108/173 +f 178/115/180 179/116/181 171/108/173 +s 2 +f 181/68/131 131/68/131 173/68/131 +f 137/68/132 180/68/132 179/68/132 +s 1 +f 132/117/134 174/111/176 173/110/175 +f 131/118/135 132/117/134 173/110/175 +f 132/117/134 175/112/177 174/111/176 +f 132/117/134 133/119/137 175/112/177 +f 134/120/140 176/113/178 175/112/177 +f 133/119/137 134/120/140 175/112/177 +f 134/120/140 177/114/179 176/113/178 +f 134/120/140 135/121/141 177/114/179 +f 136/122/144 178/115/180 177/114/179 +f 135/121/141 136/122/144 177/114/179 +f 136/122/144 179/116/181 178/115/180 +f 136/122/144 137/123/145 179/116/181 +# 98 triangles in group + +g Bein2Li +usemtl BeinTex +s 2 +f 182/68/182 189/68/182 232/68/182 +f 188/68/183 231/68/183 195/68/183 +s 1 +f 182/69/184 183/70/185 190/71/186 +f 182/69/184 190/71/186 189/72/187 +f 183/70/185 184/73/188 190/71/186 +f 184/73/188 191/74/189 190/71/186 +f 184/73/188 185/75/190 192/76/191 +f 184/73/188 192/76/191 191/74/189 +f 185/75/190 186/77/192 192/76/191 +f 186/77/192 193/78/193 192/76/191 +f 186/77/192 187/79/194 194/80/195 +f 186/77/192 194/80/195 193/78/193 +f 187/79/194 188/68/196 194/80/195 +f 188/68/196 195/81/197 194/80/195 +s 2 +f 189/68/182 196/68/182 232/68/182 +f 195/68/183 231/68/183 202/68/183 +s 1 +f 189/72/187 190/71/186 196/82/198 +f 190/71/186 197/83/199 196/82/198 +f 190/71/186 191/74/189 198/84/200 +f 190/71/186 198/84/200 197/83/199 +f 191/74/189 192/76/191 198/84/200 +f 192/76/191 199/85/201 198/84/200 +f 192/76/191 193/78/193 200/86/202 +f 192/76/191 200/86/202 199/85/201 +f 193/78/193 194/80/195 200/86/202 +f 194/80/195 201/87/203 200/86/202 +f 194/80/195 195/81/197 202/88/204 +f 194/80/195 202/88/204 201/87/203 +s 2 +f 196/68/182 203/68/182 232/68/182 +f 202/68/183 231/68/183 209/68/183 +s 1 +f 196/82/198 197/83/199 204/89/205 +f 196/82/198 204/89/205 203/90/206 +f 197/83/199 198/84/200 204/89/205 +f 198/84/200 205/91/207 204/89/205 +f 198/84/200 199/85/201 206/92/208 +f 198/84/200 206/92/208 205/91/207 +f 199/85/201 200/86/202 206/92/208 +f 200/86/202 207/93/209 206/92/208 +f 200/86/202 201/87/203 208/94/210 +f 200/86/202 208/94/210 207/93/209 +f 201/87/203 202/88/204 208/94/210 +f 202/88/204 209/95/211 208/94/210 +s 2 +f 203/68/182 210/68/182 232/68/182 +f 209/68/183 231/68/183 216/68/183 +s 1 +f 203/90/206 204/89/205 210/96/212 +f 204/89/205 211/97/213 210/96/212 +f 204/89/205 205/91/207 212/98/214 +f 204/89/205 212/98/214 211/97/213 +f 205/91/207 206/92/208 212/98/214 +f 206/92/208 213/99/215 212/98/214 +f 206/92/208 207/93/209 214/100/216 +f 206/92/208 214/100/216 213/99/215 +f 207/93/209 208/94/210 214/100/216 +f 208/94/210 215/101/217 214/100/216 +f 208/94/210 209/95/211 216/102/218 +f 208/94/210 216/102/218 215/101/217 +s 2 +f 210/68/182 217/68/182 232/68/182 +f 216/68/183 231/68/183 223/68/183 +s 1 +f 210/96/212 211/97/213 218/103/219 +f 210/96/212 218/103/219 217/104/220 +f 211/97/213 212/98/214 218/103/219 +f 212/98/214 219/105/221 218/103/219 +f 212/98/214 213/99/215 220/106/222 +f 212/98/214 220/106/222 219/105/221 +f 213/99/215 214/100/216 220/106/222 +f 214/100/216 221/107/223 220/106/222 +f 214/100/216 215/101/217 222/108/224 +f 214/100/216 222/108/224 221/107/223 +f 215/101/217 216/102/218 222/108/224 +f 216/102/218 223/109/225 222/108/224 +s 2 +f 217/68/182 224/68/182 232/68/182 +f 223/68/183 231/68/183 230/68/183 +s 1 +f 217/104/220 218/103/219 224/110/226 +f 218/103/219 225/111/227 224/110/226 +f 218/103/219 219/105/221 226/112/228 +f 218/103/219 226/112/228 225/111/227 +f 219/105/221 220/106/222 226/112/228 +f 220/106/222 227/113/229 226/112/228 +f 220/106/222 221/107/223 228/114/230 +f 220/106/222 228/114/230 227/113/229 +f 221/107/223 222/108/224 228/114/230 +f 222/108/224 229/115/231 228/114/230 +f 222/108/224 223/109/225 230/116/232 +f 222/108/224 230/116/232 229/115/231 +s 2 +f 224/68/182 182/68/182 232/68/182 +f 230/68/183 231/68/183 188/68/183 +s 1 +f 224/110/226 225/111/227 183/117/185 +f 224/110/226 183/117/185 182/118/184 +f 225/111/227 226/112/228 183/117/185 +f 226/112/228 184/119/188 183/117/185 +f 226/112/228 227/113/229 185/120/190 +f 226/112/228 185/120/190 184/119/188 +f 227/113/229 228/114/230 185/120/190 +f 228/114/230 186/121/192 185/120/190 +f 228/114/230 229/115/231 187/122/194 +f 228/114/230 187/122/194 186/121/192 +f 229/115/231 230/116/232 187/122/194 +f 230/116/232 188/123/196 187/122/194 +# 98 triangles in group + +g Bein2Re +usemtl BeinTex +s 2 +f 283/68/233 240/68/233 233/68/233 +f 246/68/234 282/68/234 239/68/234 +s 1 +f 241/71/235 234/70/236 233/69/237 +f 240/72/238 241/71/235 233/69/237 +f 241/71/235 235/73/239 234/70/236 +f 241/71/235 242/74/240 235/73/239 +f 243/76/241 236/75/242 235/73/239 +f 242/74/240 243/76/241 235/73/239 +f 243/76/241 237/77/243 236/75/242 +f 243/76/241 244/78/244 237/77/243 +f 245/80/245 238/79/246 237/77/243 +f 244/78/244 245/80/245 237/77/243 +f 245/80/245 239/68/247 238/79/246 +f 245/80/245 246/81/248 239/68/247 +s 2 +f 283/68/233 247/68/233 240/68/233 +f 253/68/234 282/68/234 246/68/234 +s 1 +f 247/82/249 241/71/235 240/72/238 +f 247/82/249 248/83/250 241/71/235 +f 249/84/251 242/74/240 241/71/235 +f 248/83/250 249/84/251 241/71/235 +f 249/84/251 243/76/241 242/74/240 +f 249/84/251 250/85/252 243/76/241 +f 251/86/253 244/78/244 243/76/241 +f 250/85/252 251/86/253 243/76/241 +f 251/86/253 245/80/245 244/78/244 +f 251/86/253 252/87/254 245/80/245 +f 253/88/255 246/81/248 245/80/245 +f 252/87/254 253/88/255 245/80/245 +s 2 +f 283/68/233 254/68/233 247/68/233 +f 260/68/234 282/68/234 253/68/234 +s 1 +f 255/89/256 248/83/250 247/82/249 +f 254/90/257 255/89/256 247/82/249 +f 255/89/256 249/84/251 248/83/250 +f 255/89/256 256/91/258 249/84/251 +f 257/92/259 250/85/252 249/84/251 +f 256/91/258 257/92/259 249/84/251 +f 257/92/259 251/86/253 250/85/252 +f 257/92/259 258/93/260 251/86/253 +f 259/94/261 252/87/254 251/86/253 +f 258/93/260 259/94/261 251/86/253 +f 259/94/261 253/88/255 252/87/254 +f 259/94/261 260/95/262 253/88/255 +s 2 +f 283/68/233 261/68/233 254/68/233 +f 267/68/234 282/68/234 260/68/234 +s 1 +f 261/96/263 255/89/256 254/90/257 +f 261/96/263 262/97/264 255/89/256 +f 263/98/265 256/91/258 255/89/256 +f 262/97/264 263/98/265 255/89/256 +f 263/98/265 257/92/259 256/91/258 +f 263/98/265 264/99/266 257/92/259 +f 265/100/267 258/93/260 257/92/259 +f 264/99/266 265/100/267 257/92/259 +f 265/100/267 259/94/261 258/93/260 +f 265/100/267 266/101/268 259/94/261 +f 267/102/269 260/95/262 259/94/261 +f 266/101/268 267/102/269 259/94/261 +s 2 +f 283/68/233 268/68/233 261/68/233 +f 274/68/234 282/68/234 267/68/234 +s 1 +f 269/103/270 262/97/264 261/96/263 +f 268/104/271 269/103/270 261/96/263 +f 269/103/270 263/98/265 262/97/264 +f 269/103/270 270/105/272 263/98/265 +f 271/106/273 264/99/266 263/98/265 +f 270/105/272 271/106/273 263/98/265 +f 271/106/273 265/100/267 264/99/266 +f 271/106/273 272/107/274 265/100/267 +f 273/108/275 266/101/268 265/100/267 +f 272/107/274 273/108/275 265/100/267 +f 273/108/275 267/102/269 266/101/268 +f 273/108/275 274/109/276 267/102/269 +s 2 +f 283/68/233 275/68/233 268/68/233 +f 281/68/234 282/68/234 274/68/234 +s 1 +f 275/110/277 269/103/270 268/104/271 +f 275/110/277 276/111/278 269/103/270 +f 277/112/279 270/105/272 269/103/270 +f 276/111/278 277/112/279 269/103/270 +f 277/112/279 271/106/273 270/105/272 +f 277/112/279 278/113/280 271/106/273 +f 279/114/281 272/107/274 271/106/273 +f 278/113/280 279/114/281 271/106/273 +f 279/114/281 273/108/275 272/107/274 +f 279/114/281 280/115/282 273/108/275 +f 281/116/283 274/109/276 273/108/275 +f 280/115/282 281/116/283 273/108/275 +s 2 +f 283/68/233 233/68/233 275/68/233 +f 239/68/234 282/68/234 281/68/234 +s 1 +f 234/117/236 276/111/278 275/110/277 +f 233/118/237 234/117/236 275/110/277 +f 234/117/236 277/112/279 276/111/278 +f 234/117/236 235/119/239 277/112/279 +f 236/120/242 278/113/280 277/112/279 +f 235/119/239 236/120/242 277/112/279 +f 236/120/242 279/114/281 278/113/280 +f 236/120/242 237/121/243 279/114/281 +f 238/122/246 280/115/282 279/114/281 +f 237/121/243 238/122/246 279/114/281 +f 238/122/246 281/116/283 280/115/282 +f 238/122/246 239/123/247 281/116/283 +# 98 triangles in group + +g Bein3Re +usemtl BeinTex +s 2 +f 334/68/284 291/68/284 284/68/284 +f 297/68/285 333/68/285 290/68/285 +s 1 +f 292/71/286 285/70/287 284/69/288 +f 291/72/289 292/71/286 284/69/288 +f 292/71/286 286/73/290 285/70/287 +f 292/71/286 293/74/291 286/73/290 +f 294/76/292 287/75/293 286/73/290 +f 293/74/291 294/76/292 286/73/290 +f 294/76/292 288/77/294 287/75/293 +f 294/76/292 295/78/295 288/77/294 +f 296/80/296 289/79/297 288/77/294 +f 295/78/295 296/80/296 288/77/294 +f 296/80/296 290/68/298 289/79/297 +f 296/80/296 297/81/299 290/68/298 +s 2 +f 334/68/284 298/68/284 291/68/284 +f 304/68/285 333/68/285 297/68/285 +s 1 +f 298/82/300 292/71/286 291/72/289 +f 298/82/300 299/83/301 292/71/286 +f 300/84/302 293/74/291 292/71/286 +f 299/83/301 300/84/302 292/71/286 +f 300/84/302 294/76/292 293/74/291 +f 300/84/302 301/85/303 294/76/292 +f 302/86/304 295/78/295 294/76/292 +f 301/85/303 302/86/304 294/76/292 +f 302/86/304 296/80/296 295/78/295 +f 302/86/304 303/87/305 296/80/296 +f 304/88/306 297/81/299 296/80/296 +f 303/87/305 304/88/306 296/80/296 +s 2 +f 334/68/284 305/68/284 298/68/284 +f 311/68/285 333/68/285 304/68/285 +s 1 +f 306/89/307 299/83/301 298/82/300 +f 305/90/308 306/89/307 298/82/300 +f 306/89/307 300/84/302 299/83/301 +f 306/89/307 307/91/309 300/84/302 +f 308/92/310 301/85/303 300/84/302 +f 307/91/309 308/92/310 300/84/302 +f 308/92/310 302/86/304 301/85/303 +f 308/92/310 309/93/311 302/86/304 +f 310/94/312 303/87/305 302/86/304 +f 309/93/311 310/94/312 302/86/304 +f 310/94/312 304/88/306 303/87/305 +f 310/94/312 311/95/313 304/88/306 +s 2 +f 334/68/284 312/68/284 305/68/284 +f 318/68/285 333/68/285 311/68/285 +s 1 +f 312/96/314 306/89/307 305/90/308 +f 312/96/314 313/97/315 306/89/307 +f 314/98/316 307/91/309 306/89/307 +f 313/97/315 314/98/316 306/89/307 +f 314/98/316 308/92/310 307/91/309 +f 314/98/316 315/99/317 308/92/310 +f 316/100/318 309/93/311 308/92/310 +f 315/99/317 316/100/318 308/92/310 +f 316/100/318 310/94/312 309/93/311 +f 316/100/318 317/101/319 310/94/312 +f 318/102/320 311/95/313 310/94/312 +f 317/101/319 318/102/320 310/94/312 +s 2 +f 334/68/284 319/68/284 312/68/284 +f 325/68/285 333/68/285 318/68/285 +s 1 +f 320/103/321 313/97/315 312/96/314 +f 319/104/322 320/103/321 312/96/314 +f 320/103/321 314/98/316 313/97/315 +f 320/103/321 321/105/323 314/98/316 +f 322/106/324 315/99/317 314/98/316 +f 321/105/323 322/106/324 314/98/316 +f 322/106/324 316/100/318 315/99/317 +f 322/106/324 323/107/325 316/100/318 +f 324/108/326 317/101/319 316/100/318 +f 323/107/325 324/108/326 316/100/318 +f 324/108/326 318/102/320 317/101/319 +f 324/108/326 325/109/327 318/102/320 +s 2 +f 334/68/284 326/68/284 319/68/284 +f 332/68/285 333/68/285 325/68/285 +s 1 +f 326/110/328 320/103/321 319/104/322 +f 326/110/328 327/111/329 320/103/321 +f 328/112/330 321/105/323 320/103/321 +f 327/111/329 328/112/330 320/103/321 +f 328/112/330 322/106/324 321/105/323 +f 328/112/330 329/113/331 322/106/324 +f 330/114/332 323/107/325 322/106/324 +f 329/113/331 330/114/332 322/106/324 +f 330/114/332 324/108/326 323/107/325 +f 330/114/332 331/115/333 324/108/326 +f 332/116/334 325/109/327 324/108/326 +f 331/115/333 332/116/334 324/108/326 +s 2 +f 334/68/284 284/68/284 326/68/284 +f 290/68/285 333/68/285 332/68/285 +s 1 +f 285/117/287 327/111/329 326/110/328 +f 284/118/288 285/117/287 326/110/328 +f 285/117/287 328/112/330 327/111/329 +f 285/117/287 286/119/290 328/112/330 +f 287/120/293 329/113/331 328/112/330 +f 286/119/290 287/120/293 328/112/330 +f 287/120/293 330/114/332 329/113/331 +f 287/120/293 288/121/294 330/114/332 +f 289/122/297 331/115/333 330/114/332 +f 288/121/294 289/122/297 330/114/332 +f 289/122/297 332/116/334 331/115/333 +f 289/122/297 290/123/298 332/116/334 +# 98 triangles in group + +g Bein3Li +usemtl BeinTex +s 2 +f 335/68/335 342/68/335 385/68/335 +f 341/68/336 384/68/336 348/68/336 +s 1 +f 335/69/337 336/70/338 343/71/339 +f 335/69/337 343/71/339 342/72/340 +f 336/70/338 337/73/341 343/71/339 +f 337/73/341 344/74/342 343/71/339 +f 337/73/341 338/75/343 345/76/344 +f 337/73/341 345/76/344 344/74/342 +f 338/75/343 339/77/345 345/76/344 +f 339/77/345 346/78/346 345/76/344 +f 339/77/345 340/79/347 347/80/348 +f 339/77/345 347/80/348 346/78/346 +f 340/79/347 341/68/349 347/80/348 +f 341/68/349 348/81/350 347/80/348 +s 2 +f 342/68/335 349/68/335 385/68/335 +f 348/68/336 384/68/336 355/68/336 +s 1 +f 342/72/340 343/71/339 349/82/351 +f 343/71/339 350/83/352 349/82/351 +f 343/71/339 344/74/342 351/84/353 +f 343/71/339 351/84/353 350/83/352 +f 344/74/342 345/76/344 351/84/353 +f 345/76/344 352/85/354 351/84/353 +f 345/76/344 346/78/346 353/86/355 +f 345/76/344 353/86/355 352/85/354 +f 346/78/346 347/80/348 353/86/355 +f 347/80/348 354/87/356 353/86/355 +f 347/80/348 348/81/350 355/88/357 +f 347/80/348 355/88/357 354/87/356 +s 2 +f 349/68/335 356/68/335 385/68/335 +f 355/68/336 384/68/336 362/68/336 +s 1 +f 349/82/351 350/83/352 357/89/358 +f 349/82/351 357/89/358 356/90/359 +f 350/83/352 351/84/353 357/89/358 +f 351/84/353 358/91/360 357/89/358 +f 351/84/353 352/85/354 359/92/361 +f 351/84/353 359/92/361 358/91/360 +f 352/85/354 353/86/355 359/92/361 +f 353/86/355 360/93/362 359/92/361 +f 353/86/355 354/87/356 361/94/363 +f 353/86/355 361/94/363 360/93/362 +f 354/87/356 355/88/357 361/94/363 +f 355/88/357 362/95/364 361/94/363 +s 2 +f 356/68/335 363/68/335 385/68/335 +f 362/68/336 384/68/336 369/68/336 +s 1 +f 356/90/359 357/89/358 363/96/365 +f 357/89/358 364/97/366 363/96/365 +f 357/89/358 358/91/360 365/98/367 +f 357/89/358 365/98/367 364/97/366 +f 358/91/360 359/92/361 365/98/367 +f 359/92/361 366/99/368 365/98/367 +f 359/92/361 360/93/362 367/100/369 +f 359/92/361 367/100/369 366/99/368 +f 360/93/362 361/94/363 367/100/369 +f 361/94/363 368/101/370 367/100/369 +f 361/94/363 362/95/364 369/102/371 +f 361/94/363 369/102/371 368/101/370 +s 2 +f 363/68/335 370/68/335 385/68/335 +f 369/68/336 384/68/336 376/68/336 +s 1 +f 363/96/365 364/97/366 371/103/372 +f 363/96/365 371/103/372 370/104/373 +f 364/97/366 365/98/367 371/103/372 +f 365/98/367 372/105/374 371/103/372 +f 365/98/367 366/99/368 373/106/375 +f 365/98/367 373/106/375 372/105/374 +f 366/99/368 367/100/369 373/106/375 +f 367/100/369 374/107/376 373/106/375 +f 367/100/369 368/101/370 375/108/377 +f 367/100/369 375/108/377 374/107/376 +f 368/101/370 369/102/371 375/108/377 +f 369/102/371 376/109/378 375/108/377 +s 2 +f 370/68/335 377/68/335 385/68/335 +f 376/68/336 384/68/336 383/68/336 +s 1 +f 370/104/373 371/103/372 377/110/379 +f 371/103/372 378/111/380 377/110/379 +f 371/103/372 372/105/374 379/112/381 +f 371/103/372 379/112/381 378/111/380 +f 372/105/374 373/106/375 379/112/381 +f 373/106/375 380/113/382 379/112/381 +f 373/106/375 374/107/376 381/114/383 +f 373/106/375 381/114/383 380/113/382 +f 374/107/376 375/108/377 381/114/383 +f 375/108/377 382/115/384 381/114/383 +f 375/108/377 376/109/378 383/116/385 +f 375/108/377 383/116/385 382/115/384 +s 2 +f 377/68/335 335/68/335 385/68/335 +f 383/68/336 384/68/336 341/68/336 +s 1 +f 377/110/379 378/111/380 336/117/338 +f 377/110/379 336/117/338 335/118/337 +f 378/111/380 379/112/381 336/117/338 +f 379/112/381 337/119/341 336/117/338 +f 379/112/381 380/113/382 338/120/343 +f 379/112/381 338/120/343 337/119/341 +f 380/113/382 381/114/383 338/120/343 +f 381/114/383 339/121/345 338/120/343 +f 381/114/383 382/115/384 340/122/347 +f 381/114/383 340/122/347 339/121/345 +f 382/115/384 383/116/385 340/122/347 +f 383/116/385 341/123/349 340/122/347 +# 98 triangles in group + +g Bein4Re +usemtl BeinTex +s 2 +f 436/68/386 393/68/386 386/68/386 +f 399/68/387 435/68/387 392/68/387 +s 1 +f 394/71/388 387/70/389 386/69/390 +f 393/72/391 394/71/388 386/69/390 +f 394/71/388 388/73/392 387/70/389 +f 394/71/388 395/74/393 388/73/392 +f 396/76/394 389/75/395 388/73/392 +f 395/74/393 396/76/394 388/73/392 +f 396/76/394 390/77/396 389/75/395 +f 396/76/394 397/78/397 390/77/396 +f 398/80/398 391/79/399 390/77/396 +f 397/78/397 398/80/398 390/77/396 +f 398/80/398 392/68/400 391/79/399 +f 398/80/398 399/81/401 392/68/400 +s 2 +f 436/68/386 400/68/386 393/68/386 +f 406/68/387 435/68/387 399/68/387 +s 1 +f 400/82/402 394/71/388 393/72/391 +f 400/82/402 401/83/403 394/71/388 +f 402/84/404 395/74/393 394/71/388 +f 401/83/403 402/84/404 394/71/388 +f 402/84/404 396/76/394 395/74/393 +f 402/84/404 403/85/405 396/76/394 +f 404/86/406 397/78/397 396/76/394 +f 403/85/405 404/86/406 396/76/394 +f 404/86/406 398/80/398 397/78/397 +f 404/86/406 405/87/407 398/80/398 +f 406/88/408 399/81/401 398/80/398 +f 405/87/407 406/88/408 398/80/398 +s 2 +f 436/68/386 407/68/386 400/68/386 +f 413/68/387 435/68/387 406/68/387 +s 1 +f 408/89/409 401/83/403 400/82/402 +f 407/90/410 408/89/409 400/82/402 +f 408/89/409 402/84/404 401/83/403 +f 408/89/409 409/91/411 402/84/404 +f 410/92/412 403/85/405 402/84/404 +f 409/91/411 410/92/412 402/84/404 +f 410/92/412 404/86/406 403/85/405 +f 410/92/412 411/93/413 404/86/406 +f 412/94/414 405/87/407 404/86/406 +f 411/93/413 412/94/414 404/86/406 +f 412/94/414 406/88/408 405/87/407 +f 412/94/414 413/95/415 406/88/408 +s 2 +f 436/68/386 414/68/386 407/68/386 +f 420/68/387 435/68/387 413/68/387 +s 1 +f 414/96/416 408/89/409 407/90/410 +f 414/96/416 415/97/417 408/89/409 +f 416/98/418 409/91/411 408/89/409 +f 415/97/417 416/98/418 408/89/409 +f 416/98/418 410/92/412 409/91/411 +f 416/98/418 417/99/419 410/92/412 +f 418/100/420 411/93/413 410/92/412 +f 417/99/419 418/100/420 410/92/412 +f 418/100/420 412/94/414 411/93/413 +f 418/100/420 419/101/421 412/94/414 +f 420/102/422 413/95/415 412/94/414 +f 419/101/421 420/102/422 412/94/414 +s 2 +f 436/68/386 421/68/386 414/68/386 +f 427/68/387 435/68/387 420/68/387 +s 1 +f 422/103/423 415/97/417 414/96/416 +f 421/104/424 422/103/423 414/96/416 +f 422/103/423 416/98/418 415/97/417 +f 422/103/423 423/105/425 416/98/418 +f 424/106/426 417/99/419 416/98/418 +f 423/105/425 424/106/426 416/98/418 +f 424/106/426 418/100/420 417/99/419 +f 424/106/426 425/107/427 418/100/420 +f 426/108/428 419/101/421 418/100/420 +f 425/107/427 426/108/428 418/100/420 +f 426/108/428 420/102/422 419/101/421 +f 426/108/428 427/109/429 420/102/422 +s 2 +f 436/68/386 428/68/386 421/68/386 +f 434/68/387 435/68/387 427/68/387 +s 1 +f 428/110/430 422/103/423 421/104/424 +f 428/110/430 429/111/431 422/103/423 +f 430/112/432 423/105/425 422/103/423 +f 429/111/431 430/112/432 422/103/423 +f 430/112/432 424/106/426 423/105/425 +f 430/112/432 431/113/433 424/106/426 +f 432/114/434 425/107/427 424/106/426 +f 431/113/433 432/114/434 424/106/426 +f 432/114/434 426/108/428 425/107/427 +f 432/114/434 433/115/435 426/108/428 +f 434/116/436 427/109/429 426/108/428 +f 433/115/435 434/116/436 426/108/428 +s 2 +f 436/68/386 386/68/386 428/68/386 +f 392/68/387 435/68/387 434/68/387 +s 1 +f 387/117/389 429/111/431 428/110/430 +f 386/118/390 387/117/389 428/110/430 +f 387/117/389 430/112/432 429/111/431 +f 387/117/389 388/119/392 430/112/432 +f 389/120/395 431/113/433 430/112/432 +f 388/119/392 389/120/395 430/112/432 +f 389/120/395 432/114/434 431/113/433 +f 389/120/395 390/121/396 432/114/434 +f 391/122/399 433/115/435 432/114/434 +f 390/121/396 391/122/399 432/114/434 +f 391/122/399 434/116/436 433/115/435 +f 391/122/399 392/123/400 434/116/436 +# 98 triangles in group + +g Bein4Li +usemtl BeinTex +s 2 +f 437/68/437 444/68/437 487/68/437 +f 443/68/438 486/68/438 450/68/438 +s 1 +f 437/69/439 438/70/440 445/71/441 +f 437/69/439 445/71/441 444/72/442 +f 438/70/440 439/73/443 445/71/441 +f 439/73/443 446/74/444 445/71/441 +f 439/73/443 440/75/445 447/76/446 +f 439/73/443 447/76/446 446/74/444 +f 440/75/445 441/77/447 447/76/446 +f 441/77/447 448/78/448 447/76/446 +f 441/77/447 442/79/449 449/80/450 +f 441/77/447 449/80/450 448/78/448 +f 442/79/449 443/68/451 449/80/450 +f 443/68/451 450/81/452 449/80/450 +s 2 +f 444/68/437 451/68/437 487/68/437 +f 450/68/438 486/68/438 457/68/438 +s 1 +f 444/72/442 445/71/441 451/82/453 +f 445/71/441 452/83/454 451/82/453 +f 445/71/441 446/74/444 453/84/455 +f 445/71/441 453/84/455 452/83/454 +f 446/74/444 447/76/446 453/84/455 +f 447/76/446 454/85/456 453/84/455 +f 447/76/446 448/78/448 455/86/457 +f 447/76/446 455/86/457 454/85/456 +f 448/78/448 449/80/450 455/86/457 +f 449/80/450 456/87/458 455/86/457 +f 449/80/450 450/81/452 457/88/459 +f 449/80/450 457/88/459 456/87/458 +s 2 +f 451/68/437 458/68/437 487/68/437 +f 457/68/438 486/68/438 464/68/438 +s 1 +f 451/82/453 452/83/454 459/89/460 +f 451/82/453 459/89/460 458/90/461 +f 452/83/454 453/84/455 459/89/460 +f 453/84/455 460/91/462 459/89/460 +f 453/84/455 454/85/456 461/92/463 +f 453/84/455 461/92/463 460/91/462 +f 454/85/456 455/86/457 461/92/463 +f 455/86/457 462/93/464 461/92/463 +f 455/86/457 456/87/458 463/94/465 +f 455/86/457 463/94/465 462/93/464 +f 456/87/458 457/88/459 463/94/465 +f 457/88/459 464/95/466 463/94/465 +s 2 +f 458/68/437 465/68/437 487/68/437 +f 464/68/438 486/68/438 471/68/438 +s 1 +f 458/90/461 459/89/460 465/96/467 +f 459/89/460 466/97/468 465/96/467 +f 459/89/460 460/91/462 467/98/469 +f 459/89/460 467/98/469 466/97/468 +f 460/91/462 461/92/463 467/98/469 +f 461/92/463 468/99/470 467/98/469 +f 461/92/463 462/93/464 469/100/471 +f 461/92/463 469/100/471 468/99/470 +f 462/93/464 463/94/465 469/100/471 +f 463/94/465 470/101/472 469/100/471 +f 463/94/465 464/95/466 471/102/473 +f 463/94/465 471/102/473 470/101/472 +s 2 +f 465/68/437 472/68/437 487/68/437 +f 471/68/438 486/68/438 478/68/438 +s 1 +f 465/96/467 466/97/468 473/103/474 +f 465/96/467 473/103/474 472/104/475 +f 466/97/468 467/98/469 473/103/474 +f 467/98/469 474/105/476 473/103/474 +f 467/98/469 468/99/470 475/106/477 +f 467/98/469 475/106/477 474/105/476 +f 468/99/470 469/100/471 475/106/477 +f 469/100/471 476/107/478 475/106/477 +f 469/100/471 470/101/472 477/108/479 +f 469/100/471 477/108/479 476/107/478 +f 470/101/472 471/102/473 477/108/479 +f 471/102/473 478/109/480 477/108/479 +s 2 +f 472/68/437 479/68/437 487/68/437 +f 478/68/438 486/68/438 485/68/438 +s 1 +f 472/104/475 473/103/474 479/110/481 +f 473/103/474 480/111/482 479/110/481 +f 473/103/474 474/105/476 481/112/483 +f 473/103/474 481/112/483 480/111/482 +f 474/105/476 475/106/477 481/112/483 +f 475/106/477 482/113/484 481/112/483 +f 475/106/477 476/107/478 483/114/485 +f 475/106/477 483/114/485 482/113/484 +f 476/107/478 477/108/479 483/114/485 +f 477/108/479 484/115/486 483/114/485 +f 477/108/479 478/109/480 485/116/487 +f 477/108/479 485/116/487 484/115/486 +s 2 +f 479/68/437 437/68/437 487/68/437 +f 485/68/438 486/68/438 443/68/438 +s 1 +f 479/110/481 480/111/482 438/117/440 +f 479/110/481 438/117/440 437/118/439 +f 480/111/482 481/112/483 438/117/440 +f 481/112/483 439/119/443 438/117/440 +f 481/112/483 482/113/484 440/120/445 +f 481/112/483 440/120/445 439/119/443 +f 482/113/484 483/114/485 440/120/445 +f 483/114/485 441/121/447 440/120/445 +f 483/114/485 484/115/486 442/122/449 +f 483/114/485 442/122/449 441/121/447 +f 484/115/486 485/116/487 442/122/449 +f 485/116/487 443/123/451 442/122/449 +# 98 triangles in group + +g Zahn +usemtl BeinTex +s 2 +f 488/124/488 491/124/488 510/124/488 +f 490/125/489 509/126/489 493/127/489 +s 1 +f 488/124/490 489/128/491 492/129/492 +f 488/124/490 492/129/492 491/124/488 +f 489/128/491 490/125/493 492/129/492 +f 490/125/493 493/127/494 492/129/492 +s 2 +f 491/124/488 494/124/488 510/124/488 +f 493/127/489 509/126/489 496/130/489 +s 1 +f 491/124/488 492/129/492 494/124/495 +f 492/129/492 495/131/496 494/124/495 +f 492/129/492 493/127/494 496/130/497 +f 492/129/492 496/130/497 495/131/496 +s 2 +f 494/124/488 497/124/488 510/124/488 +f 496/130/489 509/126/489 499/132/489 +s 1 +f 494/124/495 495/131/496 498/133/498 +f 494/124/495 498/133/498 497/124/488 +f 495/131/496 496/130/497 498/133/498 +f 496/130/497 499/132/499 498/133/498 +s 2 +f 497/124/488 500/124/488 510/124/488 +f 499/132/489 509/126/489 502/134/489 +s 1 +f 497/124/488 498/133/498 500/124/500 +f 498/133/498 501/135/501 500/124/500 +f 498/133/498 499/132/499 502/134/502 +f 498/133/498 502/134/502 501/135/501 +s 2 +f 500/124/488 503/124/488 510/124/488 +f 502/134/489 509/126/489 505/136/489 +s 1 +f 500/124/500 501/135/501 504/137/503 +f 500/124/500 504/137/503 503/124/488 +f 501/135/501 502/134/502 504/137/503 +f 502/134/502 505/136/504 504/137/503 +s 2 +f 503/124/488 506/124/488 510/124/488 +f 505/136/489 509/126/489 508/138/489 +s 1 +f 503/124/488 504/137/503 506/124/505 +f 504/137/503 507/139/506 506/124/505 +f 504/137/503 505/136/504 508/138/507 +f 504/137/503 508/138/507 507/139/506 +s 2 +f 506/124/488 488/124/488 510/124/488 +f 508/138/489 509/126/489 490/125/489 +s 1 +f 506/124/505 507/139/506 489/128/491 +f 506/124/505 489/128/491 488/124/490 +f 507/139/506 508/138/507 489/128/491 +f 508/138/507 490/125/493 489/128/491 +# 42 triangles in group + +g klZahn +usemtl BeinTex +s 2 +f 511/140/488 514/140/488 533/140/488 +f 513/141/508 532/142/508 516/143/508 +s 1 +f 511/140/509 512/144/510 515/145/511 +f 511/140/509 515/145/511 514/140/488 +f 512/144/510 513/141/512 515/145/511 +f 513/141/512 516/143/513 515/145/511 +s 2 +f 514/140/488 517/140/488 533/140/488 +f 516/143/508 532/142/508 519/146/508 +s 1 +f 514/140/488 515/145/511 517/140/514 +f 515/145/511 518/147/515 517/140/514 +f 515/145/511 516/143/513 519/146/516 +f 515/145/511 519/146/516 518/147/515 +s 2 +f 517/140/488 520/140/488 533/140/488 +f 519/146/508 532/142/508 522/148/508 +s 1 +f 517/140/514 518/147/515 521/149/517 +f 517/140/514 521/149/517 520/140/488 +f 518/147/515 519/146/516 521/149/517 +f 519/146/516 522/148/518 521/149/517 +s 2 +f 520/140/488 523/140/488 533/140/488 +f 522/148/508 532/142/508 525/150/508 +s 1 +f 520/140/488 521/149/517 523/140/519 +f 521/149/517 524/151/520 523/140/519 +f 521/149/517 522/148/518 525/150/521 +f 521/149/517 525/150/521 524/151/520 +s 2 +f 523/140/488 526/140/488 533/140/488 +f 525/150/508 532/142/508 528/152/508 +s 1 +f 523/140/519 524/151/520 527/153/522 +f 523/140/519 527/153/522 526/140/488 +f 524/151/520 525/150/521 527/153/522 +f 525/150/521 528/152/523 527/153/522 +s 2 +f 526/140/488 529/140/488 533/140/488 +f 528/152/508 532/142/508 531/154/508 +s 1 +f 526/140/488 527/153/522 529/140/524 +f 527/153/522 530/155/525 529/140/524 +f 527/153/522 528/152/523 531/154/526 +f 527/153/522 531/154/526 530/155/525 +s 2 +f 529/140/488 511/140/488 533/140/488 +f 531/154/508 532/142/508 513/141/508 +s 1 +f 529/140/524 530/155/525 512/144/510 +f 529/140/524 512/144/510 511/140/509 +f 530/155/525 531/154/526 512/144/510 +f 531/154/526 513/141/512 512/144/510 +# 42 triangles in group + +g Kopf +usemtl Skin +f 534/68/527 563/156/528 562/157/529 +f 534/68/527 564/158/530 563/156/528 +f 535/69/531 536/159/532 537/160/533 +f 534/68/527 565/161/534 564/158/530 +f 535/69/531 537/160/533 538/162/535 +f 534/68/527 566/163/536 565/161/534 +f 535/69/531 538/162/535 539/164/537 +f 534/68/527 567/165/538 566/163/536 +f 535/69/531 539/164/537 540/166/539 +f 534/68/527 568/167/540 567/165/538 +f 542/168/541 543/169/542 536/159/532 +f 536/159/532 543/169/542 544/170/543 +f 536/159/532 544/170/543 537/160/533 +f 537/160/533 544/170/543 538/162/535 +f 544/170/543 545/169/544 538/162/535 +f 538/162/535 545/169/544 546/171/545 +f 538/162/535 546/171/545 539/164/537 +f 539/164/537 546/171/545 540/166/539 +f 546/171/545 547/172/546 540/166/539 +f 541/173/547 548/174/548 542/168/541 +f 548/174/548 549/175/549 542/168/541 +f 542/168/541 549/175/549 550/176/550 +f 542/168/541 550/176/550 543/169/542 +f 543/169/542 550/176/550 544/170/543 +f 550/176/550 551/177/551 544/170/543 +f 544/170/543 551/177/551 552/178/552 +f 544/170/543 552/178/552 545/169/544 +f 545/169/544 552/178/552 546/171/545 +f 552/178/552 553/179/553 546/171/545 +f 546/171/545 553/179/553 554/180/554 +f 546/171/545 554/180/554 547/172/546 +f 548/174/548 555/181/555 556/182/556 +f 548/174/548 556/182/556 549/175/549 +f 549/175/549 556/182/556 550/176/550 +f 556/182/556 557/183/557 550/176/550 +f 550/176/550 557/183/557 558/184/558 +f 550/176/550 558/184/558 551/177/551 +f 551/177/551 558/184/558 552/178/552 +f 558/184/558 559/185/559 552/178/552 +f 553/179/553 560/186/560 554/180/554 +f 560/186/560 561/187/561 554/180/554 +f 555/181/555 562/157/529 556/182/556 +f 562/157/529 563/156/528 556/182/556 +f 556/182/556 563/156/528 564/158/530 +f 556/182/556 564/158/530 557/183/557 +f 557/183/557 564/158/530 558/184/558 +f 564/158/530 565/161/534 558/184/558 +f 558/184/558 565/161/534 566/163/536 +f 558/184/558 566/163/536 559/185/559 +f 559/185/559 566/163/536 560/186/560 +f 566/163/536 567/165/538 560/186/560 +f 560/186/560 567/165/538 568/167/540 +f 560/186/560 568/167/540 561/187/561 +f 575/188/562 585/189/563 586/190/564 +f 553/179/553 576/191/565 586/190/564 +f 586/190/564 575/188/562 553/179/553 +f 577/192/566 576/191/565 553/179/553 +f 576/191/565 577/192/566 587/193/567 +f 587/193/567 586/190/564 576/191/565 +f 588/194/568 587/193/567 577/192/566 +f 577/192/566 578/195/569 588/194/568 +f 589/196/570 588/194/568 579/197/571 +f 578/195/569 579/197/571 588/194/568 +f 590/198/572 589/196/570 569/199/573 +f 589/196/570 579/197/571 569/199/573 +f 569/199/573 580/200/574 590/198/572 +f 569/199/573 570/201/575 580/200/574 +f 570/201/575 571/202/576 580/200/574 +f 581/203/577 580/200/574 571/202/576 +f 571/202/576 572/204/578 581/203/577 +f 582/205/579 581/203/577 572/204/578 +f 583/206/580 582/205/579 572/204/578 +f 572/204/578 573/207/581 583/206/580 +f 584/208/582 583/206/580 573/207/581 +f 573/207/581 574/209/583 584/208/582 +f 585/189/563 584/208/582 574/209/583 +f 574/209/583 575/188/562 585/189/563 +f 575/188/562 560/186/560 553/179/553 +f 575/188/562 574/209/583 560/186/560 +f 574/209/583 573/207/581 560/186/560 +f 573/207/581 572/204/578 560/186/560 +f 572/204/578 571/202/576 560/186/560 +f 559/185/559 560/186/560 571/202/576 +f 571/202/576 570/201/575 559/185/559 +f 570/201/575 569/199/573 559/185/559 +f 577/192/566 553/179/553 552/178/552 +f 578/195/569 577/192/566 552/178/552 +f 579/197/571 578/195/569 552/178/552 +f 552/178/552 559/185/559 569/199/573 +f 579/197/571 569/199/573 552/178/552 +# 90 triangles in group + +g Brust +usemtl Skin +f 595/210/584 596/211/585 597/212/586 +f 591/120/587 597/212/586 593/213/588 +f 597/212/586 596/211/585 593/213/588 +f 595/210/584 597/212/586 598/214/589 +f 599/215/590 598/214/589 600/216/591 +f 591/120/587 600/216/591 597/212/586 +f 598/214/589 597/212/586 600/216/591 +f 595/210/584 598/214/589 601/217/592 +f 602/75/593 601/217/592 603/218/594 +f 599/215/590 603/218/594 598/214/589 +f 601/217/592 598/214/589 603/218/594 +f 602/75/593 603/218/594 604/219/595 +f 599/215/590 605/220/596 603/218/594 +f 604/219/595 603/218/594 605/220/596 +f 599/215/590 600/216/591 606/221/597 +f 591/120/587 592/222/598 600/216/591 +f 606/221/597 600/216/591 592/222/598 +f 595/210/584 601/217/592 594/223/599 +f 602/75/593 607/224/600 601/217/592 +f 594/223/599 601/217/592 607/224/600 +# 20 triangles in group + +g Kopf2 +usemtl Skin +f 636/225/601 637/226/602 608/123/603 +f 637/226/602 638/227/604 608/123/603 +f 611/228/605 610/229/606 609/118/607 +f 638/227/604 639/230/608 608/123/603 +f 612/231/609 611/228/605 609/118/607 +f 639/230/608 640/232/610 608/123/603 +f 613/233/611 612/231/609 609/118/607 +f 640/232/610 641/234/612 608/123/603 +f 614/235/613 613/233/611 609/118/607 +f 641/234/612 642/236/614 608/123/603 +f 610/229/606 617/237/615 616/238/616 +f 618/239/617 617/237/615 610/229/606 +f 611/228/605 618/239/617 610/229/606 +f 612/231/609 618/239/617 611/228/605 +f 612/231/609 619/237/618 618/239/617 +f 620/240/619 619/237/618 612/231/609 +f 613/233/611 620/240/619 612/231/609 +f 614/235/613 620/240/619 613/233/611 +f 614/235/613 621/241/620 620/240/619 +f 616/238/616 622/176/621 615/242/622 +f 616/238/616 623/243/623 622/176/621 +f 624/174/624 623/243/623 616/238/616 +f 617/237/615 624/174/624 616/238/616 +f 618/239/617 624/174/624 617/237/615 +f 618/239/617 625/244/625 624/174/624 +f 626/245/626 625/244/625 618/239/617 +f 619/237/618 626/245/626 618/239/617 +f 620/240/619 626/245/626 619/237/618 +f 620/240/619 627/246/627 626/245/626 +f 628/247/628 627/246/627 620/240/619 +f 621/241/620 628/247/628 620/240/619 +f 630/248/629 629/249/630 622/176/621 +f 623/243/623 630/248/629 622/176/621 +f 624/174/624 630/248/629 623/243/623 +f 624/174/624 631/250/631 630/248/629 +f 632/251/632 631/250/631 624/174/624 +f 625/244/625 632/251/632 624/174/624 +f 626/245/626 632/251/632 625/244/625 +f 626/245/626 633/252/633 632/251/632 +f 628/247/628 634/253/634 627/246/627 +f 628/247/628 635/254/635 634/253/634 +f 630/248/629 636/225/601 629/249/630 +f 630/248/629 637/226/602 636/225/601 +f 638/227/604 637/226/602 630/248/629 +f 631/250/631 638/227/604 630/248/629 +f 632/251/632 638/227/604 631/250/631 +f 632/251/632 639/230/608 638/227/604 +f 640/232/610 639/230/608 632/251/632 +f 633/252/633 640/232/610 632/251/632 +f 634/253/634 640/232/610 633/252/633 +f 634/253/634 641/234/612 640/232/610 +f 642/236/614 641/234/612 634/253/634 +f 635/254/635 642/236/614 634/253/634 +f 660/255/636 659/256/637 649/257/638 +f 660/255/636 650/258/639 627/246/627 +f 627/246/627 649/257/638 660/255/636 +f 627/246/627 650/258/639 651/259/640 +f 661/260/641 651/259/640 650/258/639 +f 650/258/639 660/255/636 661/260/641 +f 651/259/640 661/260/641 662/261/642 +f 662/261/642 652/262/643 651/259/640 +f 653/263/644 662/261/642 663/264/645 +f 662/261/642 653/263/644 652/262/643 +f 643/265/646 663/264/645 664/266/647 +f 643/265/646 653/263/644 663/264/645 +f 664/266/647 654/267/648 643/265/646 +f 654/267/648 644/268/649 643/265/646 +f 654/267/648 645/269/650 644/268/649 +f 645/269/650 654/267/648 655/270/651 +f 655/270/651 646/271/652 645/269/650 +f 646/271/652 655/270/651 656/272/653 +f 646/271/652 656/272/653 657/273/654 +f 657/273/654 647/274/655 646/271/652 +f 647/274/655 657/273/654 658/275/656 +f 658/275/656 648/276/657 647/274/655 +f 648/276/657 658/275/656 659/256/637 +f 659/256/637 649/257/638 648/276/657 +f 627/246/627 634/253/634 649/257/638 +f 634/253/634 648/276/657 649/257/638 +f 634/253/634 647/274/655 648/276/657 +f 634/253/634 646/271/652 647/274/655 +f 634/253/634 645/269/650 646/271/652 +f 645/269/650 634/253/634 633/252/633 +f 633/252/633 644/268/649 645/269/650 +f 633/252/633 643/265/646 644/268/649 +f 626/245/626 627/246/627 651/259/640 +f 626/245/626 651/259/640 652/262/643 +f 626/245/626 652/262/643 653/263/644 +f 643/265/646 633/252/633 626/245/626 +f 626/245/626 643/265/646 653/263/644 +# 90 triangles in group + +g Zahn2 +usemtl BeinTex +s 2 +f 687/124/488 668/124/488 665/124/488 +f 670/127/658 686/126/658 667/125/658 +s 1 +f 669/129/659 666/128/660 665/124/661 +f 668/124/488 669/129/659 665/124/661 +f 669/129/659 667/125/662 666/128/660 +f 669/129/659 670/127/663 667/125/662 +s 2 +f 687/124/488 671/124/488 668/124/488 +f 673/130/658 686/126/658 670/127/658 +s 1 +f 671/124/664 669/129/659 668/124/488 +f 671/124/664 672/131/665 669/129/659 +f 673/130/666 670/127/663 669/129/659 +f 672/131/665 673/130/666 669/129/659 +s 2 +f 687/124/488 674/124/488 671/124/488 +f 676/132/658 686/126/658 673/130/658 +s 1 +f 675/133/667 672/131/665 671/124/664 +f 674/124/488 675/133/667 671/124/664 +f 675/133/667 673/130/666 672/131/665 +f 675/133/667 676/132/668 673/130/666 +s 2 +f 687/124/488 677/124/488 674/124/488 +f 679/134/658 686/126/658 676/132/658 +s 1 +f 677/124/669 675/133/667 674/124/488 +f 677/124/669 678/135/670 675/133/667 +f 679/134/671 676/132/668 675/133/667 +f 678/135/670 679/134/671 675/133/667 +s 2 +f 687/124/488 680/124/488 677/124/488 +f 682/136/658 686/126/658 679/134/658 +s 1 +f 681/137/672 678/135/670 677/124/669 +f 680/124/488 681/137/672 677/124/669 +f 681/137/672 679/134/671 678/135/670 +f 681/137/672 682/136/673 679/134/671 +s 2 +f 687/124/488 683/124/488 680/124/488 +f 685/138/658 686/126/658 682/136/658 +s 1 +f 683/124/674 681/137/672 680/124/488 +f 683/124/674 684/139/675 681/137/672 +f 685/138/676 682/136/673 681/137/672 +f 684/139/675 685/138/676 681/137/672 +s 2 +f 687/124/488 665/124/488 683/124/488 +f 667/125/658 686/126/658 685/138/658 +s 1 +f 666/128/660 684/139/675 683/124/674 +f 665/124/661 666/128/660 683/124/674 +f 666/128/660 685/138/676 684/139/675 +f 666/128/660 667/125/662 685/138/676 +# 42 triangles in group + +g klZahn2 +usemtl BeinTex +s 2 +f 710/140/488 691/140/488 688/140/488 +f 693/143/677 709/142/677 690/141/677 +s 1 +f 692/145/678 689/144/679 688/140/680 +f 691/140/488 692/145/678 688/140/680 +f 692/145/678 690/141/681 689/144/679 +f 692/145/678 693/143/682 690/141/681 +s 2 +f 710/140/488 694/140/488 691/140/488 +f 696/146/677 709/142/677 693/143/677 +s 1 +f 694/140/683 692/145/678 691/140/488 +f 694/140/683 695/147/684 692/145/678 +f 696/146/685 693/143/682 692/145/678 +f 695/147/684 696/146/685 692/145/678 +s 2 +f 710/140/488 697/140/488 694/140/488 +f 699/148/677 709/142/677 696/146/677 +s 1 +f 698/149/686 695/147/684 694/140/683 +f 697/140/488 698/149/686 694/140/683 +f 698/149/686 696/146/685 695/147/684 +f 698/149/686 699/148/687 696/146/685 +s 2 +f 710/140/488 700/140/488 697/140/488 +f 702/150/677 709/142/677 699/148/677 +s 1 +f 700/140/688 698/149/686 697/140/488 +f 700/140/688 701/151/689 698/149/686 +f 702/150/690 699/148/687 698/149/686 +f 701/151/689 702/150/690 698/149/686 +s 2 +f 710/140/488 703/140/488 700/140/488 +f 705/152/677 709/142/677 702/150/677 +s 1 +f 704/153/691 701/151/689 700/140/688 +f 703/140/488 704/153/691 700/140/688 +f 704/153/691 702/150/690 701/151/689 +f 704/153/691 705/152/692 702/150/690 +s 2 +f 710/140/488 706/140/488 703/140/488 +f 708/154/677 709/142/677 705/152/677 +s 1 +f 706/140/693 704/153/691 703/140/488 +f 706/140/693 707/155/694 704/153/691 +f 708/154/695 705/152/692 704/153/691 +f 707/155/694 708/154/695 704/153/691 +s 2 +f 710/140/488 688/140/488 706/140/488 +f 690/141/677 709/142/677 708/154/677 +s 1 +f 689/144/679 707/155/694 706/140/693 +f 688/140/680 689/144/679 706/140/693 +f 689/144/679 708/154/695 707/155/694 +f 689/144/679 690/141/681 708/154/695 +# 42 triangles in group + +g Auge +usemtl Augentex +f 711/277/696 712/278/697 713/279/698 +f 711/277/696 713/279/698 714/280/699 +f 715/281/700 714/280/699 716/282/701 +f 714/280/699 713/279/698 716/282/701 +f 715/281/700 716/282/701 717/283/702 +f 718/284/703 720/285/704 721/286/705 +f 722/287/706 721/286/705 723/288/707 +f 719/289/708 723/288/707 720/285/704 +f 721/286/705 720/285/704 723/288/707 +f 722/287/706 723/288/707 724/290/709 +f 725/291/710 724/290/709 726/292/711 +f 719/289/708 726/292/711 723/288/707 +f 724/290/709 723/288/707 726/292/711 +f 725/291/710 727/293/712 729/294/713 +f 730/295/714 729/294/713 731/296/715 +f 728/297/716 731/296/715 727/293/712 +f 729/294/713 727/293/712 731/296/715 +f 730/295/714 731/296/715 732/298/717 +f 711/277/696 732/298/717 733/299/718 +f 728/297/716 733/299/718 731/296/715 +f 732/298/717 731/296/715 733/299/718 +f 711/277/696 733/299/718 712/278/697 +f 715/281/700 734/300/719 714/280/699 +f 711/277/696 714/280/699 732/298/717 +f 730/295/714 732/298/717 734/300/719 +f 714/280/699 734/300/719 732/298/717 +f 715/281/700 735/301/720 734/300/719 +f 730/295/714 734/300/719 736/302/721 +f 722/287/706 736/302/721 735/301/720 +f 734/300/719 735/301/720 736/302/721 +f 715/281/700 717/283/702 735/301/720 +f 722/287/706 735/301/720 721/286/705 +f 718/284/703 721/286/705 717/283/702 +f 735/301/720 717/283/702 721/286/705 +f 725/291/710 729/294/713 724/290/709 +f 722/287/706 724/290/709 736/302/721 +f 730/295/714 736/302/721 729/294/713 +f 724/290/709 729/294/713 736/302/721 +# 38 triangles in group + +g Duplicate05 +usemtl Augentex +f 739/279/722 738/278/723 737/277/724 +f 740/280/725 739/279/722 737/277/724 +f 742/282/726 740/280/725 741/281/727 +f 742/282/726 739/279/722 740/280/725 +f 743/283/728 742/282/726 741/281/727 +f 747/286/729 746/285/730 744/284/731 +f 749/288/732 747/286/729 748/287/733 +f 746/285/730 749/288/732 745/289/734 +f 749/288/732 746/285/730 747/286/729 +f 750/290/735 749/288/732 748/287/733 +f 752/292/736 750/290/735 751/291/737 +f 749/288/732 752/292/736 745/289/734 +f 752/292/736 749/288/732 750/290/735 +f 755/294/738 753/293/739 751/291/737 +f 757/296/740 755/294/738 756/295/741 +f 753/293/739 757/296/740 754/297/742 +f 757/296/740 753/293/739 755/294/738 +f 758/298/743 757/296/740 756/295/741 +f 759/299/744 758/298/743 737/277/724 +f 757/296/740 759/299/744 754/297/742 +f 759/299/744 757/296/740 758/298/743 +f 738/278/723 759/299/744 737/277/724 +f 740/280/725 760/300/745 741/281/727 +f 758/298/743 740/280/725 737/277/724 +f 760/300/745 758/298/743 756/295/741 +f 758/298/743 760/300/745 740/280/725 +f 760/300/745 761/301/746 741/281/727 +f 762/302/747 760/300/745 756/295/741 +f 761/301/746 762/302/747 748/287/733 +f 762/302/747 761/301/746 760/300/745 +f 761/301/746 743/283/728 741/281/727 +f 747/286/729 761/301/746 748/287/733 +f 743/283/728 747/286/729 744/284/731 +f 747/286/729 743/283/728 761/301/746 +f 750/290/735 755/294/738 751/291/737 +f 762/302/747 750/290/735 748/287/733 +f 755/294/738 762/302/747 756/295/741 +f 762/302/747 755/294/738 750/290/735 +# 38 triangles in group + +# 1368 triangles total + diff --git a/test/models/OpenGEX/light_issue1262.ogex b/test/models/OpenGEX/light_issue1262.ogex new file mode 100644 index 000000000..da4723411 --- /dev/null +++ b/test/models/OpenGEX/light_issue1262.ogex @@ -0,0 +1,21 @@ +LightObject (type = "infinite") { + Param (attrib = "intensity") { + float { 3.0 } + } + + Color (attrib = "light") { + float[3] { { 0.7, 1.0, 0.1 } } + } +} + +LightObject (type = "point") { + Param (attrib = "intensity") { + float { 0.5 } + } +} + +LightObject (type = "spot") { + Color (attrib = "light") { + float[4] { { 0.1, 0.0, 0.1, 1.0 } } + } +} \ No newline at end of file diff --git a/test/models/PLY/float-color.ply b/test/models/PLY/float-color.ply new file mode 100644 index 000000000..34353ad53 --- /dev/null +++ b/test/models/PLY/float-color.ply @@ -0,0 +1,18 @@ +ply +format ascii 1.0 +comment VCGLIB generated +element vertex 3 +property float x +property float y +property float z +property float red +property float green +property float blue +property float alpha +element face 1 +property list uchar int vertex_indices +end_header +0.0 0.0 0.0 0 0 1 1 +100.0 0.0 0.0 0 0 1 1 +200.0 200.0 0.0 0 0 1 1 +3 0 1 2 \ No newline at end of file diff --git a/test/models/SMD/holy_grailref.smd b/test/models/SMD/holy_grailref.smd new file mode 100644 index 000000000..0a3a331aa --- /dev/null +++ b/test/models/SMD/holy_grailref.smd @@ -0,0 +1,3594 @@ +version 1 +nodes +0 "Cylinder01" -1 +end +skeleton +time 0 +0 0.000000 0.000000 6.268408 0.000000 -0.000000 0.000000 +end +triangles +holygrail.tga +0 4.642112 0.000006 0.109110 0.194769 0.000000 -0.980834 0.367188 0.382813 1 0 1.000000 +0 4.362156 -1.587696 0.109110 0.183020 -0.066591 -0.980834 0.382813 0.359375 1 0 1.000000 +0 3.556062 -2.983890 0.109111 0.149174 -0.125187 -0.980834 0.406250 0.335938 1 0 1.000000 +holygrail.tga +0 7.522307 0.000000 20.680813 0.997131 0.000000 -0.075381 0.773438 0.726563 1 0 1.000000 +0 7.068654 -2.572787 20.680813 0.937010 -0.341044 -0.075381 0.726563 0.726563 1 0 1.000000 +0 6.528368 -2.376138 18.269222 0.829829 -0.302042 -0.469131 0.726563 0.671875 1 0 1.000000 +holygrail.tga +0 -3.761152 6.514506 20.680819 -0.498550 0.863552 -0.075381 0.117188 0.726563 1 0 1.000000 +0 -1.306235 7.408025 20.680819 -0.173132 0.981994 -0.075381 0.058594 0.726563 1 0 1.000000 +0 -1.206394 6.841801 18.269226 -0.153325 0.869686 -0.469131 0.058594 0.671875 1 0 1.000000 +holygrail.tga +0 -2.863631 -1.042275 14.964446 -0.903104 -0.328684 0.276284 0.339844 0.578125 1 0 1.000000 +0 -2.334454 -1.958836 14.964447 -0.736198 -0.617756 0.276284 0.394531 0.578125 1 0 1.000000 +0 -2.195500 -1.842239 15.321719 -0.714652 -0.599658 -0.360088 0.394531 0.593750 1 0 1.000000 +holygrail.tga +0 -2.334451 1.958838 14.964448 -0.736198 0.617756 0.276284 0.171875 0.578125 1 0 1.000000 +0 -1.523703 2.639137 14.964448 -0.480514 0.832301 0.276284 0.117188 0.578125 1 0 1.000000 +0 -1.569052 2.717682 14.071264 -0.493851 0.855373 -0.156285 0.117188 0.539063 1 0 1.000000 +holygrail.tga +0 0.544927 3.090433 14.071264 0.171484 0.972686 -0.156285 1.000000 0.539063 1 0 1.000000 +0 1.569054 2.717682 14.071264 0.493851 0.855373 -0.156285 0.941406 0.539063 1 0 1.000000 +0 1.387662 2.403501 13.267400 0.420179 0.727775 -0.541978 0.941406 0.507813 1 0 1.000000 +holygrail.tga +0 -2.593930 0.000002 5.842322 -0.849239 0.000000 0.527940 0.289063 0.195313 1 0 1.000000 +0 -2.437499 -0.887174 5.842322 -0.798029 -0.290445 0.527940 0.339844 0.195313 1 0 1.000000 +0 -1.840913 -0.670035 7.003459 -0.935789 -0.340587 0.090976 0.339844 0.261719 1 0 1.000000 +holygrail.tga +0 -5.129199 -1.866871 0.823655 -0.888028 -0.323222 0.326945 0.339844 0.031250 1 0 1.000000 +0 -4.181361 -3.508573 0.823656 -0.723930 -0.607440 0.326945 0.394531 0.031250 1 0 1.000000 +0 -3.833975 -3.217081 1.180929 -0.615467 -0.516434 0.595355 0.394531 0.046875 1 0 1.000000 +holygrail.tga +0 7.868691 2.863969 23.281614 0.772057 0.280984 0.569994 0.832031 0.816406 1 0 1.000000 +0 8.373683 0.000000 23.281614 0.821619 0.000000 0.569994 0.773438 0.816406 1 0 1.000000 +0 8.373683 0.000000 22.962572 0.957976 0.000000 -0.286752 0.773438 0.804688 1 0 1.000000 +holygrail.tga +0 8.373683 0.000000 22.962572 0.957976 0.000000 -0.286752 0.773438 0.804688 1 0 1.000000 +0 7.868691 2.863969 22.962572 0.900204 0.327647 -0.286752 0.832031 0.804688 1 0 1.000000 +0 7.868691 2.863969 23.281614 0.772057 0.280984 0.569994 0.832031 0.816406 1 0 1.000000 +holygrail.tga +0 6.414617 5.382501 23.281618 0.629383 0.528123 0.569994 0.886719 0.816406 1 0 1.000000 +0 7.868691 2.863969 23.281614 0.772057 0.280984 0.569994 0.832031 0.816406 1 0 1.000000 +0 7.868691 2.863969 22.962572 0.900204 0.327647 -0.286752 0.832031 0.804688 1 0 1.000000 +holygrail.tga +0 7.868691 2.863969 22.962572 0.900204 0.327647 -0.286752 0.832031 0.804688 1 0 1.000000 +0 6.414617 5.382501 22.962572 0.733848 0.615772 -0.286752 0.886719 0.804688 1 0 1.000000 +0 6.414617 5.382501 23.281618 0.629383 0.528123 0.569994 0.886719 0.816406 1 0 1.000000 +holygrail.tga +0 4.186843 7.251825 23.281618 0.410810 0.711539 0.569994 0.941406 0.816406 1 0 1.000000 +0 6.414617 5.382501 23.281618 0.629383 0.528123 0.569994 0.886719 0.816406 1 0 1.000000 +0 6.414617 5.382501 22.962572 0.733848 0.615772 -0.286752 0.886719 0.804688 1 0 1.000000 +holygrail.tga +0 6.414617 5.382501 22.962572 0.733848 0.615772 -0.286752 0.886719 0.804688 1 0 1.000000 +0 4.186843 7.251825 22.962572 0.478988 0.829646 -0.286752 0.941406 0.804688 1 0 1.000000 +0 4.186843 7.251825 23.281618 0.410810 0.711539 0.569994 0.941406 0.816406 1 0 1.000000 +holygrail.tga +0 1.454075 8.246472 23.281618 0.142674 0.809137 0.569994 1.000000 0.816406 1 0 1.000000 +0 4.186843 7.251825 23.281618 0.410810 0.711539 0.569994 0.941406 0.816406 1 0 1.000000 +0 4.186843 7.251825 22.962572 0.478988 0.829646 -0.286752 0.941406 0.804688 1 0 1.000000 +holygrail.tga +0 4.186843 7.251825 22.962572 0.478988 0.829646 -0.286752 0.941406 0.804688 1 0 1.000000 +0 1.454075 8.246472 22.962572 0.166326 0.943419 -0.286752 1.000000 0.804688 1 0 1.000000 +0 1.454075 8.246472 23.281618 0.142674 0.809137 0.569994 1.000000 0.816406 1 0 1.000000 +holygrail.tga +0 -1.454076 8.246472 23.281618 -0.142674 0.809137 0.569994 0.058594 0.816406 1 0 1.000000 +0 1.454075 8.246472 23.281618 0.142674 0.809137 0.569994 0.000000 0.816406 1 0 1.000000 +0 1.454075 8.246472 22.962572 0.166326 0.943419 -0.286752 0.000000 0.804688 1 0 1.000000 +holygrail.tga +0 1.454075 8.246472 22.962572 0.166326 0.943419 -0.286752 0.000000 0.804688 1 0 1.000000 +0 -1.454076 8.246470 22.962572 -0.166326 0.943419 -0.286752 0.058594 0.804688 1 0 1.000000 +0 -1.454076 8.246472 23.281618 -0.142674 0.809137 0.569994 0.058594 0.816406 1 0 1.000000 +holygrail.tga +0 -4.186843 7.251825 23.281618 -0.410810 0.711539 0.569994 0.117188 0.816406 1 0 1.000000 +0 -1.454076 8.246472 23.281618 -0.142674 0.809137 0.569994 0.058594 0.816406 1 0 1.000000 +0 -1.454076 8.246470 22.962572 -0.166326 0.943419 -0.286752 0.058594 0.804688 1 0 1.000000 +holygrail.tga +0 -1.454076 8.246470 22.962572 -0.166326 0.943419 -0.286752 0.058594 0.804688 1 0 1.000000 +0 -4.186843 7.251825 22.962572 -0.478988 0.829646 -0.286752 0.117188 0.804688 1 0 1.000000 +0 -4.186843 7.251825 23.281618 -0.410810 0.711539 0.569994 0.117188 0.816406 1 0 1.000000 +holygrail.tga +0 -6.414615 5.382501 23.281618 -0.629383 0.528123 0.569994 0.171875 0.816406 1 0 1.000000 +0 -4.186843 7.251825 23.281618 -0.410810 0.711539 0.569994 0.117188 0.816406 1 0 1.000000 +0 -4.186843 7.251825 22.962572 -0.478988 0.829646 -0.286752 0.117188 0.804688 1 0 1.000000 +holygrail.tga +0 -4.186843 7.251825 22.962572 -0.478988 0.829646 -0.286752 0.117188 0.804688 1 0 1.000000 +0 -6.414615 5.382501 22.962572 -0.733848 0.615772 -0.286752 0.171875 0.804688 1 0 1.000000 +0 -6.414615 5.382501 23.281618 -0.629383 0.528123 0.569994 0.171875 0.816406 1 0 1.000000 +holygrail.tga +0 -7.868690 2.863969 23.281614 -0.772057 0.280984 0.569994 0.226563 0.816406 1 0 1.000000 +0 -6.414615 5.382501 23.281618 -0.629383 0.528123 0.569994 0.171875 0.816406 1 0 1.000000 +0 -6.414615 5.382501 22.962572 -0.733848 0.615772 -0.286752 0.171875 0.804688 1 0 1.000000 +holygrail.tga +0 -6.414615 5.382501 22.962572 -0.733848 0.615772 -0.286752 0.171875 0.804688 1 0 1.000000 +0 -7.868690 2.863969 22.962572 -0.900204 0.327647 -0.286752 0.226563 0.804688 1 0 1.000000 +0 -7.868690 2.863969 23.281614 -0.772057 0.280984 0.569994 0.226563 0.816406 1 0 1.000000 +holygrail.tga +0 -8.373686 0.000001 23.281614 -0.821619 0.000000 0.570025 0.289063 0.816406 1 0 1.000000 +0 -7.868690 2.863969 23.281614 -0.772057 0.280984 0.569994 0.226563 0.816406 1 0 1.000000 +0 -7.868690 2.863969 22.962572 -0.900204 0.327647 -0.286752 0.226563 0.804688 1 0 1.000000 +holygrail.tga +0 -7.868690 2.863969 22.962572 -0.900204 0.327647 -0.286752 0.226563 0.804688 1 0 1.000000 +0 -8.373686 0.000001 22.962572 -0.957976 0.000000 -0.286752 0.289063 0.804688 1 0 1.000000 +0 -8.373686 0.000001 23.281614 -0.821619 0.000000 0.570025 0.289063 0.816406 1 0 1.000000 +holygrail.tga +0 -7.868692 -2.863967 23.281614 -0.772057 -0.280984 0.569994 0.339844 0.816406 1 0 1.000000 +0 -8.373686 0.000001 23.281614 -0.821619 0.000000 0.570025 0.289063 0.816406 1 0 1.000000 +0 -8.373686 0.000001 22.962572 -0.957976 0.000000 -0.286752 0.289063 0.804688 1 0 1.000000 +holygrail.tga +0 -8.373686 0.000001 22.962572 -0.957976 0.000000 -0.286752 0.289063 0.804688 1 0 1.000000 +0 -7.868692 -2.863967 22.962572 -0.900204 -0.327647 -0.286752 0.339844 0.804688 1 0 1.000000 +0 -7.868692 -2.863967 23.281614 -0.772057 -0.280984 0.569994 0.339844 0.816406 1 0 1.000000 +holygrail.tga +0 -6.414616 -5.382501 23.281614 -0.629383 -0.528123 0.569994 0.394531 0.816406 1 0 1.000000 +0 -7.868692 -2.863967 23.281614 -0.772057 -0.280984 0.569994 0.339844 0.816406 1 0 1.000000 +0 -7.868692 -2.863967 22.962572 -0.900204 -0.327647 -0.286752 0.339844 0.804688 1 0 1.000000 +holygrail.tga +0 -7.868692 -2.863967 22.962572 -0.900204 -0.327647 -0.286752 0.339844 0.804688 1 0 1.000000 +0 -6.414616 -5.382500 22.962572 -0.733848 -0.615772 -0.286752 0.394531 0.804688 1 0 1.000000 +0 -6.414616 -5.382501 23.281614 -0.629383 -0.528123 0.569994 0.394531 0.816406 1 0 1.000000 +holygrail.tga +0 -4.186845 -7.251821 23.281614 -0.410810 -0.711539 0.570025 0.449219 0.816406 1 0 1.000000 +0 -6.414616 -5.382501 23.281614 -0.629383 -0.528123 0.569994 0.394531 0.816406 1 0 1.000000 +0 -6.414616 -5.382500 22.962572 -0.733848 -0.615772 -0.286752 0.394531 0.804688 1 0 1.000000 +holygrail.tga +0 -6.414616 -5.382500 22.962572 -0.733848 -0.615772 -0.286752 0.394531 0.804688 1 0 1.000000 +0 -4.186845 -7.251822 22.962572 -0.478988 -0.829646 -0.286752 0.449219 0.804688 1 0 1.000000 +0 -4.186845 -7.251821 23.281614 -0.410810 -0.711539 0.570025 0.449219 0.816406 1 0 1.000000 +holygrail.tga +0 -1.454078 -8.246469 23.281614 -0.142674 -0.809137 0.570025 0.503906 0.816406 1 0 1.000000 +0 -4.186845 -7.251821 23.281614 -0.410810 -0.711539 0.570025 0.449219 0.816406 1 0 1.000000 +0 -4.186845 -7.251822 22.962572 -0.478988 -0.829646 -0.286752 0.449219 0.804688 1 0 1.000000 +holygrail.tga +0 -4.186845 -7.251822 22.962572 -0.478988 -0.829646 -0.286752 0.449219 0.804688 1 0 1.000000 +0 -1.454079 -8.246470 22.962572 -0.166326 -0.943419 -0.286752 0.503906 0.804688 1 0 1.000000 +0 -1.454078 -8.246469 23.281614 -0.142674 -0.809137 0.570025 0.503906 0.816406 1 0 1.000000 +holygrail.tga +0 1.454071 -8.246470 23.281614 0.142644 -0.809137 0.569994 0.554688 0.816406 1 0 1.000000 +0 -1.454078 -8.246469 23.281614 -0.142674 -0.809137 0.570025 0.503906 0.816406 1 0 1.000000 +0 -1.454079 -8.246470 22.962572 -0.166326 -0.943419 -0.286752 0.503906 0.804688 1 0 1.000000 +holygrail.tga +0 -1.454079 -8.246470 22.962572 -0.166326 -0.943419 -0.286752 0.503906 0.804688 1 0 1.000000 +0 1.454071 -8.246470 22.962572 0.166326 -0.943419 -0.286752 0.554688 0.804688 1 0 1.000000 +0 1.454071 -8.246470 23.281614 0.142644 -0.809137 0.569994 0.554688 0.816406 1 0 1.000000 +holygrail.tga +0 4.186839 -7.251825 23.281614 0.410810 -0.711539 0.570025 0.613281 0.816406 1 0 1.000000 +0 1.454071 -8.246470 23.281614 0.142644 -0.809137 0.569994 0.554688 0.816406 1 0 1.000000 +0 1.454071 -8.246470 22.962572 0.166326 -0.943419 -0.286752 0.554688 0.804688 1 0 1.000000 +holygrail.tga +0 1.454071 -8.246470 22.962572 0.166326 -0.943419 -0.286752 0.554688 0.804688 1 0 1.000000 +0 4.186839 -7.251826 22.962572 0.478988 -0.829646 -0.286752 0.613281 0.804688 1 0 1.000000 +0 4.186839 -7.251825 23.281614 0.410810 -0.711539 0.570025 0.613281 0.816406 1 0 1.000000 +holygrail.tga +0 6.414613 -5.382505 23.281614 0.629383 -0.528123 0.569994 0.664063 0.816406 1 0 1.000000 +0 4.186839 -7.251825 23.281614 0.410810 -0.711539 0.570025 0.613281 0.816406 1 0 1.000000 +0 4.186839 -7.251826 22.962572 0.478988 -0.829646 -0.286752 0.613281 0.804688 1 0 1.000000 +holygrail.tga +0 4.186839 -7.251826 22.962572 0.478988 -0.829646 -0.286752 0.613281 0.804688 1 0 1.000000 +0 6.414613 -5.382505 22.962572 0.733848 -0.615772 -0.286752 0.664063 0.804688 1 0 1.000000 +0 6.414613 -5.382505 23.281614 0.629383 -0.528123 0.569994 0.664063 0.816406 1 0 1.000000 +holygrail.tga +0 7.868689 -2.863975 23.281614 0.772057 -0.280984 0.569994 0.726563 0.816406 1 0 1.000000 +0 6.414613 -5.382505 23.281614 0.629383 -0.528123 0.569994 0.664063 0.816406 1 0 1.000000 +0 6.414613 -5.382505 22.962572 0.733848 -0.615772 -0.286752 0.664063 0.804688 1 0 1.000000 +holygrail.tga +0 6.414613 -5.382505 22.962572 0.733848 -0.615772 -0.286752 0.664063 0.804688 1 0 1.000000 +0 7.868689 -2.863975 22.962572 0.900204 -0.327647 -0.286752 0.726563 0.804688 1 0 1.000000 +0 7.868689 -2.863975 23.281614 0.772057 -0.280984 0.569994 0.726563 0.816406 1 0 1.000000 +holygrail.tga +0 8.373683 0.000000 23.281614 0.821619 0.000000 0.569994 0.773438 0.816406 1 0 1.000000 +0 7.868689 -2.863975 23.281614 0.772057 -0.280984 0.569994 0.726563 0.816406 1 0 1.000000 +0 7.868689 -2.863975 22.962572 0.900204 -0.327647 -0.286752 0.726563 0.804688 1 0 1.000000 +holygrail.tga +0 7.868689 -2.863975 22.962572 0.900204 -0.327647 -0.286752 0.726563 0.804688 1 0 1.000000 +0 8.373683 0.000000 22.962572 0.957976 0.000000 -0.286752 0.773438 0.804688 1 0 1.000000 +0 8.373683 0.000000 23.281614 0.821619 0.000000 0.569994 0.773438 0.816406 1 0 1.000000 +holygrail.tga +0 3.556066 2.983894 0.109113 0.149174 0.125187 -0.980834 0.406250 0.429688 1 0 1.000000 +0 4.362160 1.587699 0.109111 0.183020 0.066591 -0.980834 0.382813 0.410156 1 0 1.000000 +0 4.642112 0.000006 0.109110 0.194769 0.000000 -0.980834 0.367188 0.382813 1 0 1.000000 +holygrail.tga +0 3.556062 -2.983890 0.109111 0.149174 -0.125187 -0.980834 0.406250 0.335938 1 0 1.000000 +0 2.321053 -4.020187 0.109110 0.097385 -0.168676 -0.980834 0.437500 0.320313 1 0 1.000000 +0 0.806092 -4.571585 0.109110 0.033815 -0.191809 -0.980834 0.480469 0.308594 1 0 1.000000 +holygrail.tga +0 4.642112 0.000006 0.109110 0.194769 0.000000 -0.980834 0.367188 0.382813 1 0 1.000000 +0 3.556062 -2.983890 0.109111 0.149174 -0.125187 -0.980834 0.406250 0.335938 1 0 1.000000 +0 0.806092 -4.571585 0.109110 0.033815 -0.191809 -0.980834 0.480469 0.308594 1 0 1.000000 +holygrail.tga +0 3.556066 2.983894 0.109113 0.149174 0.125187 -0.980834 0.406250 0.429688 1 0 1.000000 +0 4.642112 0.000006 0.109110 0.194769 0.000000 -0.980834 0.367188 0.382813 1 0 1.000000 +0 0.806092 -4.571585 0.109110 0.033815 -0.191809 -0.980834 0.480469 0.308594 1 0 1.000000 +holygrail.tga +0 0.806092 -4.571585 0.109110 0.033815 -0.191809 -0.980834 0.480469 0.308594 1 0 1.000000 +0 -0.806094 -4.571585 0.109110 -0.033815 -0.191809 -0.980834 0.527344 0.308594 1 0 1.000000 +0 -2.321057 -4.020183 0.109110 -0.097385 -0.168676 -0.980834 0.570313 0.320313 1 0 1.000000 +holygrail.tga +0 -2.321057 -4.020183 0.109110 -0.097385 -0.168676 -0.980834 0.570313 0.320313 1 0 1.000000 +0 -3.556065 -2.983887 0.109111 -0.149174 -0.125187 -0.980834 0.609375 0.335938 1 0 1.000000 +0 -4.362159 -1.587692 0.109110 -0.183020 -0.066591 -0.980834 0.632813 0.359375 1 0 1.000000 +holygrail.tga +0 0.806092 -4.571585 0.109110 0.033815 -0.191809 -0.980834 0.480469 0.308594 1 0 1.000000 +0 -2.321057 -4.020183 0.109110 -0.097385 -0.168676 -0.980834 0.570313 0.320313 1 0 1.000000 +0 -4.362159 -1.587692 0.109110 -0.183020 -0.066591 -0.980834 0.632813 0.359375 1 0 1.000000 +holygrail.tga +0 3.556066 2.983894 0.109113 0.149174 0.125187 -0.980834 0.406250 0.429688 1 0 1.000000 +0 0.806092 -4.571585 0.109110 0.033815 -0.191809 -0.980834 0.480469 0.308594 1 0 1.000000 +0 -4.362159 -1.587692 0.109110 -0.183020 -0.066591 -0.980834 0.632813 0.359375 1 0 1.000000 +holygrail.tga +0 -4.362159 -1.587692 0.109110 -0.183020 -0.066591 -0.980834 0.632813 0.359375 1 0 1.000000 +0 -4.642111 0.000003 0.109110 -0.194769 0.000000 -0.980834 0.644531 0.382813 1 0 1.000000 +0 -4.362158 1.587698 0.109111 -0.183020 0.066591 -0.980834 0.632813 0.410156 1 0 1.000000 +holygrail.tga +0 -4.362158 1.587698 0.109111 -0.183020 0.066591 -0.980834 0.632813 0.410156 1 0 1.000000 +0 -3.556063 2.983893 0.109113 -0.149174 0.125187 -0.980834 0.609375 0.429688 1 0 1.000000 +0 -2.321054 4.020190 0.109112 -0.097385 0.168676 -0.980834 0.570313 0.449219 1 0 1.000000 +holygrail.tga +0 -4.362159 -1.587692 0.109110 -0.183020 -0.066591 -0.980834 0.632813 0.359375 1 0 1.000000 +0 -4.362158 1.587698 0.109111 -0.183020 0.066591 -0.980834 0.632813 0.410156 1 0 1.000000 +0 -2.321054 4.020190 0.109112 -0.097385 0.168676 -0.980834 0.570313 0.449219 1 0 1.000000 +holygrail.tga +0 3.556066 2.983894 0.109113 0.149174 0.125187 -0.980834 0.406250 0.429688 1 0 1.000000 +0 -4.362159 -1.587692 0.109110 -0.183020 -0.066591 -0.980834 0.632813 0.359375 1 0 1.000000 +0 -2.321054 4.020190 0.109112 -0.097385 0.168676 -0.980834 0.570313 0.449219 1 0 1.000000 +holygrail.tga +0 -2.321054 4.020190 0.109112 -0.097385 0.168676 -0.980834 0.570313 0.449219 1 0 1.000000 +0 -0.806095 4.571591 0.109112 -0.033815 0.191809 -0.980834 0.527344 0.457031 1 0 1.000000 +0 0.806094 4.571591 0.109112 0.033815 0.191809 -0.980834 0.480469 0.457031 1 0 1.000000 +holygrail.tga +0 3.556066 2.983894 0.109113 0.149174 0.125187 -0.980834 0.406250 0.429688 1 0 1.000000 +0 -2.321054 4.020190 0.109112 -0.097385 0.168676 -0.980834 0.570313 0.449219 1 0 1.000000 +0 0.806094 4.571591 0.109112 0.033815 0.191809 -0.980834 0.480469 0.457031 1 0 1.000000 +holygrail.tga +0 3.556066 2.983894 0.109113 0.149174 0.125187 -0.980834 0.406250 0.429688 1 0 1.000000 +0 0.806094 4.571591 0.109112 0.033815 0.191809 -0.980834 0.480469 0.457031 1 0 1.000000 +0 2.321057 4.020190 0.109112 0.097385 0.168645 -0.980834 0.437500 0.449219 1 0 1.000000 +holygrail.tga +0 0.558996 -0.968207 15.421605 -0.090548 0.156835 0.983459 0.437500 0.449219 1 0 1.000000 +0 0.856433 -0.718628 15.421605 -0.138707 0.116398 0.983459 0.406250 0.429688 1 0 1.000000 +0 1.050567 -0.382379 15.421605 -0.170171 0.061922 0.983459 0.382813 0.410156 1 0 1.000000 +holygrail.tga +0 1.050567 -0.382379 15.421605 -0.170171 0.061922 0.983459 0.382813 0.410156 1 0 1.000000 +0 1.117992 0.000004 15.421604 -0.181097 0.000000 0.983459 0.367188 0.382813 1 0 1.000000 +0 1.050568 0.382381 15.421604 -0.170171 -0.061922 0.983459 0.382813 0.359375 1 0 1.000000 +holygrail.tga +0 1.050568 0.382381 15.421604 -0.170171 -0.061922 0.983459 0.382813 0.359375 1 0 1.000000 +0 0.856432 0.718634 15.421607 -0.138737 -0.116398 0.983459 0.406250 0.335938 1 0 1.000000 +0 0.558995 0.968213 15.421606 -0.090548 -0.156835 0.983459 0.437500 0.320313 1 0 1.000000 +holygrail.tga +0 1.050567 -0.382379 15.421605 -0.170171 0.061922 0.983459 0.382813 0.410156 1 0 1.000000 +0 1.050568 0.382381 15.421604 -0.170171 -0.061922 0.983459 0.382813 0.359375 1 0 1.000000 +0 0.558995 0.968213 15.421606 -0.090548 -0.156835 0.983459 0.437500 0.320313 1 0 1.000000 +holygrail.tga +0 0.558996 -0.968207 15.421605 -0.090548 0.156835 0.983459 0.437500 0.449219 1 0 1.000000 +0 1.050567 -0.382379 15.421605 -0.170171 0.061922 0.983459 0.382813 0.410156 1 0 1.000000 +0 0.558995 0.968213 15.421606 -0.090548 -0.156835 0.983459 0.437500 0.320313 1 0 1.000000 +holygrail.tga +0 0.558995 0.968213 15.421606 -0.090548 -0.156835 0.983459 0.437500 0.320313 1 0 1.000000 +0 0.194135 1.101012 15.421606 -0.031434 -0.178350 0.983459 0.480469 0.308594 1 0 1.000000 +0 -0.194137 1.101012 15.421606 0.031434 -0.178350 0.983459 0.527344 0.308594 1 0 1.000000 +holygrail.tga +0 -0.194137 1.101012 15.421606 0.031434 -0.178350 0.983459 0.527344 0.308594 1 0 1.000000 +0 -0.558994 0.968215 15.421606 0.090548 -0.156835 0.983459 0.570313 0.320313 1 0 1.000000 +0 -0.856431 0.718634 15.421607 0.138707 -0.116398 0.983459 0.609375 0.335938 1 0 1.000000 +holygrail.tga +0 0.558995 0.968213 15.421606 -0.090548 -0.156835 0.983459 0.437500 0.320313 1 0 1.000000 +0 -0.194137 1.101012 15.421606 0.031434 -0.178350 0.983459 0.527344 0.308594 1 0 1.000000 +0 -0.856431 0.718634 15.421607 0.138707 -0.116398 0.983459 0.609375 0.335938 1 0 1.000000 +holygrail.tga +0 0.558996 -0.968207 15.421605 -0.090548 0.156835 0.983459 0.437500 0.449219 1 0 1.000000 +0 0.558995 0.968213 15.421606 -0.090548 -0.156835 0.983459 0.437500 0.320313 1 0 1.000000 +0 -0.856431 0.718634 15.421607 0.138707 -0.116398 0.983459 0.609375 0.335938 1 0 1.000000 +holygrail.tga +0 -0.856431 0.718634 15.421607 0.138707 -0.116398 0.983459 0.609375 0.335938 1 0 1.000000 +0 -1.050570 0.382377 15.421604 0.170171 -0.061922 0.983459 0.632813 0.359375 1 0 1.000000 +0 -1.117993 0.000002 15.421604 0.181097 0.000000 0.983459 0.644531 0.382813 1 0 1.000000 +holygrail.tga +0 -1.117993 0.000002 15.421604 0.181097 0.000000 0.983459 0.644531 0.382813 1 0 1.000000 +0 -1.050570 -0.382374 15.421605 0.170171 0.061922 0.983459 0.632813 0.410156 1 0 1.000000 +0 -0.856433 -0.718628 15.421605 0.138707 0.116398 0.983459 0.609375 0.429688 1 0 1.000000 +holygrail.tga +0 -0.856431 0.718634 15.421607 0.138707 -0.116398 0.983459 0.609375 0.335938 1 0 1.000000 +0 -1.117993 0.000002 15.421604 0.181097 0.000000 0.983459 0.644531 0.382813 1 0 1.000000 +0 -0.856433 -0.718628 15.421605 0.138707 0.116398 0.983459 0.609375 0.429688 1 0 1.000000 +holygrail.tga +0 0.558996 -0.968207 15.421605 -0.090548 0.156835 0.983459 0.437500 0.449219 1 0 1.000000 +0 -0.856431 0.718634 15.421607 0.138707 -0.116398 0.983459 0.609375 0.335938 1 0 1.000000 +0 -0.856433 -0.718628 15.421605 0.138707 0.116398 0.983459 0.609375 0.429688 1 0 1.000000 +holygrail.tga +0 -0.856433 -0.718628 15.421605 0.138707 0.116398 0.983459 0.609375 0.429688 1 0 1.000000 +0 -0.558999 -0.968206 15.421605 0.090548 0.156835 0.983459 0.570313 0.449219 1 0 1.000000 +0 -0.194136 -1.101005 15.421605 0.031434 0.178350 0.983459 0.527344 0.457031 1 0 1.000000 +holygrail.tga +0 0.558996 -0.968207 15.421605 -0.090548 0.156835 0.983459 0.437500 0.449219 1 0 1.000000 +0 -0.856433 -0.718628 15.421605 0.138707 0.116398 0.983459 0.609375 0.429688 1 0 1.000000 +0 -0.194136 -1.101005 15.421605 0.031434 0.178350 0.983459 0.527344 0.457031 1 0 1.000000 +holygrail.tga +0 0.558996 -0.968207 15.421605 -0.090548 0.156835 0.983459 0.437500 0.449219 1 0 1.000000 +0 -0.194136 -1.101005 15.421605 0.031434 0.178350 0.983459 0.527344 0.457031 1 0 1.000000 +0 0.194136 -1.101005 15.421605 -0.031434 0.178350 0.983459 0.480469 0.457031 1 0 1.000000 +holygrail.tga +0 7.447392 0.000000 21.609118 0.963805 0.000000 -0.266549 0.773438 0.765625 1 0 1.000000 +0 6.998259 2.547157 21.609118 0.905667 0.329630 -0.266549 0.832031 0.765625 1 0 1.000000 +0 7.868691 2.863969 22.962572 0.900204 0.327647 -0.286752 0.832031 0.804688 1 0 1.000000 +holygrail.tga +0 7.868691 2.863969 22.962572 0.900204 0.327647 -0.286752 0.832031 0.804688 1 0 1.000000 +0 8.373683 0.000000 22.962572 0.957976 0.000000 -0.286752 0.773438 0.804688 1 0 1.000000 +0 7.447392 0.000000 21.609118 0.963805 0.000000 -0.266549 0.773438 0.765625 1 0 1.000000 +holygrail.tga +0 6.998256 -2.547163 21.609116 0.905667 -0.329630 -0.266549 0.726563 0.765625 1 0 1.000000 +0 7.447392 0.000000 21.609118 0.963805 0.000000 -0.266549 0.773438 0.765625 1 0 1.000000 +0 8.373683 0.000000 22.962572 0.957976 0.000000 -0.286752 0.773438 0.804688 1 0 1.000000 +holygrail.tga +0 8.373683 0.000000 22.962572 0.957976 0.000000 -0.286752 0.773438 0.804688 1 0 1.000000 +0 7.868689 -2.863975 22.962572 0.900204 -0.327647 -0.286752 0.726563 0.804688 1 0 1.000000 +0 6.998256 -2.547163 21.609116 0.905667 -0.329630 -0.266549 0.726563 0.765625 1 0 1.000000 +holygrail.tga +0 5.705028 -4.787095 21.609116 0.738304 -0.619526 -0.266549 0.664063 0.765625 1 0 1.000000 +0 6.998256 -2.547163 21.609116 0.905667 -0.329630 -0.266549 0.726563 0.765625 1 0 1.000000 +0 7.868689 -2.863975 22.962572 0.900204 -0.327647 -0.286752 0.726563 0.804688 1 0 1.000000 +holygrail.tga +0 7.868689 -2.863975 22.962572 0.900204 -0.327647 -0.286752 0.726563 0.804688 1 0 1.000000 +0 6.414613 -5.382505 22.962572 0.733848 -0.615772 -0.286752 0.664063 0.804688 1 0 1.000000 +0 5.705028 -4.787095 21.609116 0.738304 -0.619526 -0.266549 0.664063 0.765625 1 0 1.000000 +holygrail.tga +0 3.723691 -6.449633 21.609116 0.481887 -0.834681 -0.266549 0.613281 0.765625 1 0 1.000000 +0 5.705028 -4.787095 21.609116 0.738304 -0.619526 -0.266549 0.664063 0.765625 1 0 1.000000 +0 6.414613 -5.382505 22.962572 0.733848 -0.615772 -0.286752 0.664063 0.804688 1 0 1.000000 +holygrail.tga +0 6.414613 -5.382505 22.962572 0.733848 -0.615772 -0.286752 0.664063 0.804688 1 0 1.000000 +0 4.186839 -7.251826 22.962572 0.478988 -0.829646 -0.286752 0.613281 0.804688 1 0 1.000000 +0 3.723691 -6.449633 21.609116 0.481887 -0.834681 -0.266549 0.613281 0.765625 1 0 1.000000 +holygrail.tga +0 1.293223 -7.334250 21.609116 0.167364 -0.949156 -0.266549 0.554688 0.765625 1 0 1.000000 +0 3.723691 -6.449633 21.609116 0.481887 -0.834681 -0.266549 0.613281 0.765625 1 0 1.000000 +0 4.186839 -7.251826 22.962572 0.478988 -0.829646 -0.286752 0.613281 0.804688 1 0 1.000000 +holygrail.tga +0 4.186839 -7.251826 22.962572 0.478988 -0.829646 -0.286752 0.613281 0.804688 1 0 1.000000 +0 1.454071 -8.246470 22.962572 0.166326 -0.943419 -0.286752 0.554688 0.804688 1 0 1.000000 +0 1.293223 -7.334250 21.609116 0.167364 -0.949156 -0.266549 0.554688 0.765625 1 0 1.000000 +holygrail.tga +0 -1.293228 -7.334249 21.609116 -0.167364 -0.949156 -0.266549 0.503906 0.765625 1 0 1.000000 +0 1.293223 -7.334250 21.609116 0.167364 -0.949156 -0.266549 0.554688 0.765625 1 0 1.000000 +0 1.454071 -8.246470 22.962572 0.166326 -0.943419 -0.286752 0.554688 0.804688 1 0 1.000000 +holygrail.tga +0 1.454071 -8.246470 22.962572 0.166326 -0.943419 -0.286752 0.554688 0.804688 1 0 1.000000 +0 -1.454079 -8.246470 22.962572 -0.166326 -0.943419 -0.286752 0.503906 0.804688 1 0 1.000000 +0 -1.293228 -7.334249 21.609116 -0.167364 -0.949156 -0.266549 0.503906 0.765625 1 0 1.000000 +holygrail.tga +0 -3.723698 -6.449631 21.609116 -0.481887 -0.834681 -0.266549 0.449219 0.765625 1 0 1.000000 +0 -1.293228 -7.334249 21.609116 -0.167364 -0.949156 -0.266549 0.503906 0.765625 1 0 1.000000 +0 -1.454079 -8.246470 22.962572 -0.166326 -0.943419 -0.286752 0.503906 0.804688 1 0 1.000000 +holygrail.tga +0 -1.454079 -8.246470 22.962572 -0.166326 -0.943419 -0.286752 0.503906 0.804688 1 0 1.000000 +0 -4.186845 -7.251822 22.962572 -0.478988 -0.829646 -0.286752 0.449219 0.804688 1 0 1.000000 +0 -3.723698 -6.449631 21.609116 -0.481887 -0.834681 -0.266549 0.449219 0.765625 1 0 1.000000 +holygrail.tga +0 -5.705035 -4.787091 21.609116 -0.738304 -0.619526 -0.266549 0.394531 0.765625 1 0 1.000000 +0 -3.723698 -6.449631 21.609116 -0.481887 -0.834681 -0.266549 0.449219 0.765625 1 0 1.000000 +0 -4.186845 -7.251822 22.962572 -0.478988 -0.829646 -0.286752 0.449219 0.804688 1 0 1.000000 +holygrail.tga +0 -4.186845 -7.251822 22.962572 -0.478988 -0.829646 -0.286752 0.449219 0.804688 1 0 1.000000 +0 -6.414616 -5.382500 22.962572 -0.733848 -0.615772 -0.286752 0.394531 0.804688 1 0 1.000000 +0 -5.705035 -4.787091 21.609116 -0.738304 -0.619526 -0.266549 0.394531 0.765625 1 0 1.000000 +holygrail.tga +0 -6.998259 -2.547156 21.609116 -0.905667 -0.329630 -0.266549 0.339844 0.765625 1 0 1.000000 +0 -5.705035 -4.787091 21.609116 -0.738304 -0.619526 -0.266549 0.394531 0.765625 1 0 1.000000 +0 -6.414616 -5.382500 22.962572 -0.733848 -0.615772 -0.286752 0.394531 0.804688 1 0 1.000000 +holygrail.tga +0 -6.414616 -5.382500 22.962572 -0.733848 -0.615772 -0.286752 0.394531 0.804688 1 0 1.000000 +0 -7.868692 -2.863967 22.962572 -0.900204 -0.327647 -0.286752 0.339844 0.804688 1 0 1.000000 +0 -6.998259 -2.547156 21.609116 -0.905667 -0.329630 -0.266549 0.339844 0.765625 1 0 1.000000 +holygrail.tga +0 -7.447392 0.000001 21.609118 -0.963805 0.000000 -0.266549 0.289063 0.765625 1 0 1.000000 +0 -6.998259 -2.547156 21.609116 -0.905667 -0.329630 -0.266549 0.339844 0.765625 1 0 1.000000 +0 -7.868692 -2.863967 22.962572 -0.900204 -0.327647 -0.286752 0.339844 0.804688 1 0 1.000000 +holygrail.tga +0 -7.868692 -2.863967 22.962572 -0.900204 -0.327647 -0.286752 0.339844 0.804688 1 0 1.000000 +0 -8.373686 0.000001 22.962572 -0.957976 0.000000 -0.286752 0.289063 0.804688 1 0 1.000000 +0 -7.447392 0.000001 21.609118 -0.963805 0.000000 -0.266549 0.289063 0.765625 1 0 1.000000 +holygrail.tga +0 -6.998257 2.547158 21.609118 -0.905667 0.329630 -0.266549 0.226563 0.765625 1 0 1.000000 +0 -7.447392 0.000001 21.609118 -0.963805 0.000000 -0.266549 0.289063 0.765625 1 0 1.000000 +0 -8.373686 0.000001 22.962572 -0.957976 0.000000 -0.286752 0.289063 0.804688 1 0 1.000000 +holygrail.tga +0 -8.373686 0.000001 22.962572 -0.957976 0.000000 -0.286752 0.289063 0.804688 1 0 1.000000 +0 -7.868690 2.863969 22.962572 -0.900204 0.327647 -0.286752 0.226563 0.804688 1 0 1.000000 +0 -6.998257 2.547158 21.609118 -0.905667 0.329630 -0.266549 0.226563 0.765625 1 0 1.000000 +holygrail.tga +0 -5.705031 4.787089 21.609118 -0.738304 0.619526 -0.266549 0.171875 0.765625 1 0 1.000000 +0 -6.998257 2.547158 21.609118 -0.905667 0.329630 -0.266549 0.226563 0.765625 1 0 1.000000 +0 -7.868690 2.863969 22.962572 -0.900204 0.327647 -0.286752 0.226563 0.804688 1 0 1.000000 +holygrail.tga +0 -7.868690 2.863969 22.962572 -0.900204 0.327647 -0.286752 0.226563 0.804688 1 0 1.000000 +0 -6.414615 5.382501 22.962572 -0.733848 0.615772 -0.286752 0.171875 0.804688 1 0 1.000000 +0 -5.705031 4.787089 21.609118 -0.738304 0.619526 -0.266549 0.171875 0.765625 1 0 1.000000 +holygrail.tga +0 -3.723695 6.449628 21.609118 -0.481887 0.834681 -0.266549 0.117188 0.765625 1 0 1.000000 +0 -5.705031 4.787089 21.609118 -0.738304 0.619526 -0.266549 0.171875 0.765625 1 0 1.000000 +0 -6.414615 5.382501 22.962572 -0.733848 0.615772 -0.286752 0.171875 0.804688 1 0 1.000000 +holygrail.tga +0 -6.414615 5.382501 22.962572 -0.733848 0.615772 -0.286752 0.171875 0.804688 1 0 1.000000 +0 -4.186843 7.251825 22.962572 -0.478988 0.829646 -0.286752 0.117188 0.804688 1 0 1.000000 +0 -3.723695 6.449628 21.609118 -0.481887 0.834681 -0.266549 0.117188 0.765625 1 0 1.000000 +holygrail.tga +0 -1.293226 7.334247 21.609118 -0.167364 0.949156 -0.266549 0.058594 0.765625 1 0 1.000000 +0 -3.723695 6.449628 21.609118 -0.481887 0.834681 -0.266549 0.117188 0.765625 1 0 1.000000 +0 -4.186843 7.251825 22.962572 -0.478988 0.829646 -0.286752 0.117188 0.804688 1 0 1.000000 +holygrail.tga +0 -4.186843 7.251825 22.962572 -0.478988 0.829646 -0.286752 0.117188 0.804688 1 0 1.000000 +0 -1.454076 8.246470 22.962572 -0.166326 0.943419 -0.286752 0.058594 0.804688 1 0 1.000000 +0 -1.293226 7.334247 21.609118 -0.167364 0.949156 -0.266549 0.058594 0.765625 1 0 1.000000 +holygrail.tga +0 1.293226 7.334248 21.609118 0.167364 0.949156 -0.266549 0.000000 0.765625 1 0 1.000000 +0 -1.293226 7.334247 21.609118 -0.167364 0.949156 -0.266549 0.058594 0.765625 1 0 1.000000 +0 -1.454076 8.246470 22.962572 -0.166326 0.943419 -0.286752 0.058594 0.804688 1 0 1.000000 +holygrail.tga +0 -1.454076 8.246470 22.962572 -0.166326 0.943419 -0.286752 0.058594 0.804688 1 0 1.000000 +0 1.454075 8.246472 22.962572 0.166326 0.943419 -0.286752 0.000000 0.804688 1 0 1.000000 +0 1.293226 7.334248 21.609118 0.167364 0.949156 -0.266549 0.000000 0.765625 1 0 1.000000 +holygrail.tga +0 3.723696 6.449628 21.609118 0.481887 0.834681 -0.266549 0.941406 0.765625 1 0 1.000000 +0 1.293226 7.334248 21.609118 0.167364 0.949156 -0.266549 1.000000 0.765625 1 0 1.000000 +0 1.454075 8.246472 22.962572 0.166326 0.943419 -0.286752 1.000000 0.804688 1 0 1.000000 +holygrail.tga +0 1.454075 8.246472 22.962572 0.166326 0.943419 -0.286752 1.000000 0.804688 1 0 1.000000 +0 4.186843 7.251825 22.962572 0.478988 0.829646 -0.286752 0.941406 0.804688 1 0 1.000000 +0 3.723696 6.449628 21.609118 0.481887 0.834681 -0.266549 0.941406 0.765625 1 0 1.000000 +holygrail.tga +0 5.705034 4.787089 21.609118 0.738304 0.619526 -0.266549 0.886719 0.765625 1 0 1.000000 +0 3.723696 6.449628 21.609118 0.481887 0.834681 -0.266549 0.941406 0.765625 1 0 1.000000 +0 4.186843 7.251825 22.962572 0.478988 0.829646 -0.286752 0.941406 0.804688 1 0 1.000000 +holygrail.tga +0 4.186843 7.251825 22.962572 0.478988 0.829646 -0.286752 0.941406 0.804688 1 0 1.000000 +0 6.414617 5.382501 22.962572 0.733848 0.615772 -0.286752 0.886719 0.804688 1 0 1.000000 +0 5.705034 4.787089 21.609118 0.738304 0.619526 -0.266549 0.886719 0.765625 1 0 1.000000 +holygrail.tga +0 6.998259 2.547157 21.609118 0.905667 0.329630 -0.266549 0.832031 0.765625 1 0 1.000000 +0 5.705034 4.787089 21.609118 0.738304 0.619526 -0.266549 0.886719 0.765625 1 0 1.000000 +0 6.414617 5.382501 22.962572 0.733848 0.615772 -0.286752 0.886719 0.804688 1 0 1.000000 +holygrail.tga +0 6.414617 5.382501 22.962572 0.733848 0.615772 -0.286752 0.886719 0.804688 1 0 1.000000 +0 7.868691 2.863969 22.962572 0.900204 0.327647 -0.286752 0.832031 0.804688 1 0 1.000000 +0 6.998259 2.547157 21.609118 0.905667 0.329630 -0.266549 0.832031 0.765625 1 0 1.000000 +holygrail.tga +0 7.522307 0.000000 20.680813 0.997131 0.000000 -0.075381 0.773438 0.726563 1 0 1.000000 +0 7.068658 2.572779 20.680817 0.937010 0.341044 -0.075381 0.832031 0.726563 1 0 1.000000 +0 6.998259 2.547157 21.609118 0.905667 0.329630 -0.266549 0.832031 0.765625 1 0 1.000000 +holygrail.tga +0 6.998259 2.547157 21.609118 0.905667 0.329630 -0.266549 0.832031 0.765625 1 0 1.000000 +0 7.447392 0.000000 21.609118 0.963805 0.000000 -0.266549 0.773438 0.765625 1 0 1.000000 +0 7.522307 0.000000 20.680813 0.997131 0.000000 -0.075381 0.773438 0.726563 1 0 1.000000 +holygrail.tga +0 7.068654 -2.572787 20.680813 0.937010 -0.341044 -0.075381 0.726563 0.726563 1 0 1.000000 +0 7.522307 0.000000 20.680813 0.997131 0.000000 -0.075381 0.773438 0.726563 1 0 1.000000 +0 7.447392 0.000000 21.609118 0.963805 0.000000 -0.266549 0.773438 0.765625 1 0 1.000000 +holygrail.tga +0 7.447392 0.000000 21.609118 0.963805 0.000000 -0.266549 0.773438 0.765625 1 0 1.000000 +0 6.998256 -2.547163 21.609116 0.905667 -0.329630 -0.266549 0.726563 0.765625 1 0 1.000000 +0 7.068654 -2.572787 20.680813 0.937010 -0.341044 -0.075381 0.726563 0.726563 1 0 1.000000 +holygrail.tga +0 5.762416 -4.835249 20.680813 0.763848 -0.640950 -0.075381 0.664063 0.726563 1 0 1.000000 +0 7.068654 -2.572787 20.680813 0.937010 -0.341044 -0.075381 0.726563 0.726563 1 0 1.000000 +0 6.998256 -2.547163 21.609116 0.905667 -0.329630 -0.266549 0.726563 0.765625 1 0 1.000000 +holygrail.tga +0 6.998256 -2.547163 21.609116 0.905667 -0.329630 -0.266549 0.726563 0.765625 1 0 1.000000 +0 5.705028 -4.787095 21.609116 0.738304 -0.619526 -0.266549 0.664063 0.765625 1 0 1.000000 +0 5.762416 -4.835249 20.680813 0.763848 -0.640950 -0.075381 0.664063 0.726563 1 0 1.000000 +holygrail.tga +0 3.761149 -6.514512 20.680813 0.498550 -0.863552 -0.075381 0.613281 0.726563 1 0 1.000000 +0 5.762416 -4.835249 20.680813 0.763848 -0.640950 -0.075381 0.664063 0.726563 1 0 1.000000 +0 5.705028 -4.787095 21.609116 0.738304 -0.619526 -0.266549 0.664063 0.765625 1 0 1.000000 +holygrail.tga +0 5.705028 -4.787095 21.609116 0.738304 -0.619526 -0.266549 0.664063 0.765625 1 0 1.000000 +0 3.723691 -6.449633 21.609116 0.481887 -0.834681 -0.266549 0.613281 0.765625 1 0 1.000000 +0 3.761149 -6.514512 20.680813 0.498550 -0.863552 -0.075381 0.613281 0.726563 1 0 1.000000 +holygrail.tga +0 1.306232 -7.408028 20.680813 0.173132 -0.981994 -0.075381 0.554688 0.726563 1 0 1.000000 +0 3.761149 -6.514512 20.680813 0.498550 -0.863552 -0.075381 0.613281 0.726563 1 0 1.000000 +0 3.723691 -6.449633 21.609116 0.481887 -0.834681 -0.266549 0.613281 0.765625 1 0 1.000000 +holygrail.tga +0 3.723691 -6.449633 21.609116 0.481887 -0.834681 -0.266549 0.613281 0.765625 1 0 1.000000 +0 1.293223 -7.334250 21.609116 0.167364 -0.949156 -0.266549 0.554688 0.765625 1 0 1.000000 +0 1.306232 -7.408028 20.680813 0.173132 -0.981994 -0.075381 0.554688 0.726563 1 0 1.000000 +holygrail.tga +0 -1.306237 -7.408028 20.680813 -0.173132 -0.981994 -0.075381 0.503906 0.726563 1 0 1.000000 +0 1.306232 -7.408028 20.680813 0.173132 -0.981994 -0.075381 0.554688 0.726563 1 0 1.000000 +0 1.293223 -7.334250 21.609116 0.167364 -0.949156 -0.266549 0.554688 0.765625 1 0 1.000000 +holygrail.tga +0 1.293223 -7.334250 21.609116 0.167364 -0.949156 -0.266549 0.554688 0.765625 1 0 1.000000 +0 -1.293228 -7.334249 21.609116 -0.167364 -0.949156 -0.266549 0.503906 0.765625 1 0 1.000000 +0 -1.306237 -7.408028 20.680813 -0.173132 -0.981994 -0.075381 0.503906 0.726563 1 0 1.000000 +holygrail.tga +0 -3.761156 -6.514509 20.680813 -0.498550 -0.863552 -0.075381 0.449219 0.726563 1 0 1.000000 +0 -1.306237 -7.408028 20.680813 -0.173132 -0.981994 -0.075381 0.503906 0.726563 1 0 1.000000 +0 -1.293228 -7.334249 21.609116 -0.167364 -0.949156 -0.266549 0.503906 0.765625 1 0 1.000000 +holygrail.tga +0 -1.293228 -7.334249 21.609116 -0.167364 -0.949156 -0.266549 0.503906 0.765625 1 0 1.000000 +0 -3.723698 -6.449631 21.609116 -0.481887 -0.834681 -0.266549 0.449219 0.765625 1 0 1.000000 +0 -3.761156 -6.514509 20.680813 -0.498550 -0.863552 -0.075381 0.449219 0.726563 1 0 1.000000 +holygrail.tga +0 -5.762423 -4.835244 20.680813 -0.763848 -0.640950 -0.075381 0.394531 0.726563 1 0 1.000000 +0 -3.761156 -6.514509 20.680813 -0.498550 -0.863552 -0.075381 0.449219 0.726563 1 0 1.000000 +0 -3.723698 -6.449631 21.609116 -0.481887 -0.834681 -0.266549 0.449219 0.765625 1 0 1.000000 +holygrail.tga +0 -3.723698 -6.449631 21.609116 -0.481887 -0.834681 -0.266549 0.449219 0.765625 1 0 1.000000 +0 -5.705035 -4.787091 21.609116 -0.738304 -0.619526 -0.266549 0.394531 0.765625 1 0 1.000000 +0 -5.762423 -4.835244 20.680813 -0.763848 -0.640950 -0.075381 0.394531 0.726563 1 0 1.000000 +holygrail.tga +0 -7.068657 -2.572778 20.680813 -0.937010 -0.341044 -0.075381 0.339844 0.726563 1 0 1.000000 +0 -5.762423 -4.835244 20.680813 -0.763848 -0.640950 -0.075381 0.394531 0.726563 1 0 1.000000 +0 -5.705035 -4.787091 21.609116 -0.738304 -0.619526 -0.266549 0.394531 0.765625 1 0 1.000000 +holygrail.tga +0 -5.705035 -4.787091 21.609116 -0.738304 -0.619526 -0.266549 0.394531 0.765625 1 0 1.000000 +0 -6.998259 -2.547156 21.609116 -0.905667 -0.329630 -0.266549 0.339844 0.765625 1 0 1.000000 +0 -7.068657 -2.572778 20.680813 -0.937010 -0.341044 -0.075381 0.339844 0.726563 1 0 1.000000 +holygrail.tga +0 -7.522305 0.000001 20.680813 -0.997131 0.000000 -0.075381 0.289063 0.726563 1 0 1.000000 +0 -7.068657 -2.572778 20.680813 -0.937010 -0.341044 -0.075381 0.339844 0.726563 1 0 1.000000 +0 -6.998259 -2.547156 21.609116 -0.905667 -0.329630 -0.266549 0.339844 0.765625 1 0 1.000000 +holygrail.tga +0 -6.998259 -2.547156 21.609116 -0.905667 -0.329630 -0.266549 0.339844 0.765625 1 0 1.000000 +0 -7.447392 0.000001 21.609118 -0.963805 0.000000 -0.266549 0.289063 0.765625 1 0 1.000000 +0 -7.522305 0.000001 20.680813 -0.997131 0.000000 -0.075381 0.289063 0.726563 1 0 1.000000 +holygrail.tga +0 -7.068655 2.572781 20.680817 -0.937010 0.341044 -0.075381 0.226563 0.726563 1 0 1.000000 +0 -7.522305 0.000001 20.680813 -0.997131 0.000000 -0.075381 0.289063 0.726563 1 0 1.000000 +0 -7.447392 0.000001 21.609118 -0.963805 0.000000 -0.266549 0.289063 0.765625 1 0 1.000000 +holygrail.tga +0 -7.447392 0.000001 21.609118 -0.963805 0.000000 -0.266549 0.289063 0.765625 1 0 1.000000 +0 -6.998257 2.547158 21.609118 -0.905667 0.329630 -0.266549 0.226563 0.765625 1 0 1.000000 +0 -7.068655 2.572781 20.680817 -0.937010 0.341044 -0.075381 0.226563 0.726563 1 0 1.000000 +holygrail.tga +0 -5.762418 4.835245 20.680819 -0.763848 0.640950 -0.075381 0.171875 0.726563 1 0 1.000000 +0 -7.068655 2.572781 20.680817 -0.937010 0.341044 -0.075381 0.226563 0.726563 1 0 1.000000 +0 -6.998257 2.547158 21.609118 -0.905667 0.329630 -0.266549 0.226563 0.765625 1 0 1.000000 +holygrail.tga +0 -6.998257 2.547158 21.609118 -0.905667 0.329630 -0.266549 0.226563 0.765625 1 0 1.000000 +0 -5.705031 4.787089 21.609118 -0.738304 0.619526 -0.266549 0.171875 0.765625 1 0 1.000000 +0 -5.762418 4.835245 20.680819 -0.763848 0.640950 -0.075381 0.171875 0.726563 1 0 1.000000 +holygrail.tga +0 -3.761152 6.514506 20.680819 -0.498550 0.863552 -0.075381 0.117188 0.726563 1 0 1.000000 +0 -5.762418 4.835245 20.680819 -0.763848 0.640950 -0.075381 0.171875 0.726563 1 0 1.000000 +0 -5.705031 4.787089 21.609118 -0.738304 0.619526 -0.266549 0.171875 0.765625 1 0 1.000000 +holygrail.tga +0 -5.705031 4.787089 21.609118 -0.738304 0.619526 -0.266549 0.171875 0.765625 1 0 1.000000 +0 -3.723695 6.449628 21.609118 -0.481887 0.834681 -0.266549 0.117188 0.765625 1 0 1.000000 +0 -3.761152 6.514506 20.680819 -0.498550 0.863552 -0.075381 0.117188 0.726563 1 0 1.000000 +holygrail.tga +0 -1.306235 7.408025 20.680819 -0.173132 0.981994 -0.075381 0.058594 0.726563 1 0 1.000000 +0 -3.761152 6.514506 20.680819 -0.498550 0.863552 -0.075381 0.117188 0.726563 1 0 1.000000 +0 -3.723695 6.449628 21.609118 -0.481887 0.834681 -0.266549 0.117188 0.765625 1 0 1.000000 +holygrail.tga +0 -3.723695 6.449628 21.609118 -0.481887 0.834681 -0.266549 0.117188 0.765625 1 0 1.000000 +0 -1.293226 7.334247 21.609118 -0.167364 0.949156 -0.266549 0.058594 0.765625 1 0 1.000000 +0 -1.306235 7.408025 20.680819 -0.173132 0.981994 -0.075381 0.058594 0.726563 1 0 1.000000 +holygrail.tga +0 1.306234 7.408025 20.680819 0.173132 0.981994 -0.075381 0.000000 0.726563 1 0 1.000000 +0 -1.306235 7.408025 20.680819 -0.173132 0.981994 -0.075381 0.058594 0.726563 1 0 1.000000 +0 -1.293226 7.334247 21.609118 -0.167364 0.949156 -0.266549 0.058594 0.765625 1 0 1.000000 +holygrail.tga +0 -1.293226 7.334247 21.609118 -0.167364 0.949156 -0.266549 0.058594 0.765625 1 0 1.000000 +0 1.293226 7.334248 21.609118 0.167364 0.949156 -0.266549 0.000000 0.765625 1 0 1.000000 +0 1.306234 7.408025 20.680819 0.173132 0.981994 -0.075381 0.000000 0.726563 1 0 1.000000 +holygrail.tga +0 3.761154 6.514506 20.680819 0.498550 0.863552 -0.075381 0.941406 0.726563 1 0 1.000000 +0 1.306234 7.408025 20.680819 0.173132 0.981994 -0.075381 1.000000 0.726563 1 0 1.000000 +0 1.293226 7.334248 21.609118 0.167364 0.949156 -0.266549 1.000000 0.765625 1 0 1.000000 +holygrail.tga +0 1.293226 7.334248 21.609118 0.167364 0.949156 -0.266549 1.000000 0.765625 1 0 1.000000 +0 3.723696 6.449628 21.609118 0.481887 0.834681 -0.266549 0.941406 0.765625 1 0 1.000000 +0 3.761154 6.514506 20.680819 0.498550 0.863552 -0.075381 0.941406 0.726563 1 0 1.000000 +holygrail.tga +0 5.762424 4.835242 20.680819 0.763848 0.640950 -0.075381 0.886719 0.726563 1 0 1.000000 +0 3.761154 6.514506 20.680819 0.498550 0.863552 -0.075381 0.941406 0.726563 1 0 1.000000 +0 3.723696 6.449628 21.609118 0.481887 0.834681 -0.266549 0.941406 0.765625 1 0 1.000000 +holygrail.tga +0 3.723696 6.449628 21.609118 0.481887 0.834681 -0.266549 0.941406 0.765625 1 0 1.000000 +0 5.705034 4.787089 21.609118 0.738304 0.619526 -0.266549 0.886719 0.765625 1 0 1.000000 +0 5.762424 4.835242 20.680819 0.763848 0.640950 -0.075381 0.886719 0.726563 1 0 1.000000 +holygrail.tga +0 7.068658 2.572779 20.680817 0.937010 0.341044 -0.075381 0.832031 0.726563 1 0 1.000000 +0 5.762424 4.835242 20.680819 0.763848 0.640950 -0.075381 0.886719 0.726563 1 0 1.000000 +0 5.705034 4.787089 21.609118 0.738304 0.619526 -0.266549 0.886719 0.765625 1 0 1.000000 +holygrail.tga +0 5.705034 4.787089 21.609118 0.738304 0.619526 -0.266549 0.886719 0.765625 1 0 1.000000 +0 6.998259 2.547157 21.609118 0.905667 0.329630 -0.266549 0.832031 0.765625 1 0 1.000000 +0 7.068658 2.572779 20.680817 0.937010 0.341044 -0.075381 0.832031 0.726563 1 0 1.000000 +holygrail.tga +0 6.947347 0.000000 18.269222 0.883084 0.000000 -0.469131 0.773438 0.671875 1 0 1.000000 +0 6.528371 2.376132 18.269222 0.829829 0.302042 -0.469161 0.832031 0.671875 1 0 1.000000 +0 7.068658 2.572779 20.680817 0.937010 0.341044 -0.075381 0.832031 0.726563 1 0 1.000000 +holygrail.tga +0 7.068658 2.572779 20.680817 0.937010 0.341044 -0.075381 0.832031 0.726563 1 0 1.000000 +0 7.522307 0.000000 20.680813 0.997131 0.000000 -0.075381 0.773438 0.726563 1 0 1.000000 +0 6.947347 0.000000 18.269222 0.883084 0.000000 -0.469131 0.773438 0.671875 1 0 1.000000 +holygrail.tga +0 6.528368 -2.376138 18.269222 0.829829 -0.302042 -0.469131 0.726563 0.671875 1 0 1.000000 +0 6.947347 0.000000 18.269222 0.883084 0.000000 -0.469131 0.773438 0.671875 1 0 1.000000 +0 7.522307 0.000000 20.680813 0.997131 0.000000 -0.075381 0.773438 0.726563 1 0 1.000000 +holygrail.tga +0 5.321972 -4.465671 18.269222 0.676473 -0.567644 -0.469131 0.664063 0.671875 1 0 1.000000 +0 6.528368 -2.376138 18.269222 0.829829 -0.302042 -0.469131 0.726563 0.671875 1 0 1.000000 +0 7.068654 -2.572787 20.680813 0.937010 -0.341044 -0.075381 0.726563 0.726563 1 0 1.000000 +holygrail.tga +0 7.068654 -2.572787 20.680813 0.937010 -0.341044 -0.075381 0.726563 0.726563 1 0 1.000000 +0 5.762416 -4.835249 20.680813 0.763848 -0.640950 -0.075381 0.664063 0.726563 1 0 1.000000 +0 5.321972 -4.465671 18.269222 0.676473 -0.567644 -0.469131 0.664063 0.671875 1 0 1.000000 +holygrail.tga +0 3.473669 -6.016580 18.269222 0.441542 -0.764794 -0.469161 0.613281 0.671875 1 0 1.000000 +0 5.321972 -4.465671 18.269222 0.676473 -0.567644 -0.469131 0.664063 0.671875 1 0 1.000000 +0 5.762416 -4.835249 20.680813 0.763848 -0.640950 -0.075381 0.664063 0.726563 1 0 1.000000 +holygrail.tga +0 5.762416 -4.835249 20.680813 0.763848 -0.640950 -0.075381 0.664063 0.726563 1 0 1.000000 +0 3.761149 -6.514512 20.680813 0.498550 -0.863552 -0.075381 0.613281 0.726563 1 0 1.000000 +0 3.473669 -6.016580 18.269222 0.441542 -0.764794 -0.469161 0.613281 0.671875 1 0 1.000000 +holygrail.tga +0 1.206391 -6.841802 18.269222 0.153325 -0.869686 -0.469161 0.554688 0.671875 1 0 1.000000 +0 3.473669 -6.016580 18.269222 0.441542 -0.764794 -0.469161 0.613281 0.671875 1 0 1.000000 +0 3.761149 -6.514512 20.680813 0.498550 -0.863552 -0.075381 0.613281 0.726563 1 0 1.000000 +holygrail.tga +0 3.761149 -6.514512 20.680813 0.498550 -0.863552 -0.075381 0.613281 0.726563 1 0 1.000000 +0 1.306232 -7.408028 20.680813 0.173132 -0.981994 -0.075381 0.554688 0.726563 1 0 1.000000 +0 1.206391 -6.841802 18.269222 0.153325 -0.869686 -0.469161 0.554688 0.671875 1 0 1.000000 +holygrail.tga +0 -1.206396 -6.841800 18.269222 -0.153325 -0.869686 -0.469161 0.503906 0.671875 1 0 1.000000 +0 1.206391 -6.841802 18.269222 0.153325 -0.869686 -0.469161 0.554688 0.671875 1 0 1.000000 +0 1.306232 -7.408028 20.680813 0.173132 -0.981994 -0.075381 0.554688 0.726563 1 0 1.000000 +holygrail.tga +0 1.306232 -7.408028 20.680813 0.173132 -0.981994 -0.075381 0.554688 0.726563 1 0 1.000000 +0 -1.306237 -7.408028 20.680813 -0.173132 -0.981994 -0.075381 0.503906 0.726563 1 0 1.000000 +0 -1.206396 -6.841800 18.269222 -0.153325 -0.869686 -0.469161 0.503906 0.671875 1 0 1.000000 +holygrail.tga +0 -3.473675 -6.016577 18.269222 -0.441542 -0.764794 -0.469161 0.449219 0.671875 1 0 1.000000 +0 -1.206396 -6.841800 18.269222 -0.153325 -0.869686 -0.469161 0.503906 0.671875 1 0 1.000000 +0 -1.306237 -7.408028 20.680813 -0.173132 -0.981994 -0.075381 0.503906 0.726563 1 0 1.000000 +holygrail.tga +0 -1.306237 -7.408028 20.680813 -0.173132 -0.981994 -0.075381 0.503906 0.726563 1 0 1.000000 +0 -3.761156 -6.514509 20.680813 -0.498550 -0.863552 -0.075381 0.449219 0.726563 1 0 1.000000 +0 -3.473675 -6.016577 18.269222 -0.441542 -0.764794 -0.469161 0.449219 0.671875 1 0 1.000000 +holygrail.tga +0 -5.321978 -4.465666 18.269222 -0.676473 -0.567644 -0.469161 0.394531 0.671875 1 0 1.000000 +0 -3.473675 -6.016577 18.269222 -0.441542 -0.764794 -0.469161 0.449219 0.671875 1 0 1.000000 +0 -3.761156 -6.514509 20.680813 -0.498550 -0.863552 -0.075381 0.449219 0.726563 1 0 1.000000 +holygrail.tga +0 -3.761156 -6.514509 20.680813 -0.498550 -0.863552 -0.075381 0.449219 0.726563 1 0 1.000000 +0 -5.762423 -4.835244 20.680813 -0.763848 -0.640950 -0.075381 0.394531 0.726563 1 0 1.000000 +0 -5.321978 -4.465666 18.269222 -0.676473 -0.567644 -0.469161 0.394531 0.671875 1 0 1.000000 +holygrail.tga +0 -6.528372 -2.376130 18.269222 -0.829829 -0.302042 -0.469131 0.339844 0.671875 1 0 1.000000 +0 -5.321978 -4.465666 18.269222 -0.676473 -0.567644 -0.469161 0.394531 0.671875 1 0 1.000000 +0 -5.762423 -4.835244 20.680813 -0.763848 -0.640950 -0.075381 0.394531 0.726563 1 0 1.000000 +holygrail.tga +0 -5.762423 -4.835244 20.680813 -0.763848 -0.640950 -0.075381 0.394531 0.726563 1 0 1.000000 +0 -7.068657 -2.572778 20.680813 -0.937010 -0.341044 -0.075381 0.339844 0.726563 1 0 1.000000 +0 -6.528372 -2.376130 18.269222 -0.829829 -0.302042 -0.469131 0.339844 0.671875 1 0 1.000000 +holygrail.tga +0 -6.947345 0.000001 18.269222 -0.883084 0.000000 -0.469131 0.289063 0.671875 1 0 1.000000 +0 -6.528372 -2.376130 18.269222 -0.829829 -0.302042 -0.469131 0.339844 0.671875 1 0 1.000000 +0 -7.068657 -2.572778 20.680813 -0.937010 -0.341044 -0.075381 0.339844 0.726563 1 0 1.000000 +holygrail.tga +0 -7.068657 -2.572778 20.680813 -0.937010 -0.341044 -0.075381 0.339844 0.726563 1 0 1.000000 +0 -7.522305 0.000001 20.680813 -0.997131 0.000000 -0.075381 0.289063 0.726563 1 0 1.000000 +0 -6.947345 0.000001 18.269222 -0.883084 0.000000 -0.469131 0.289063 0.671875 1 0 1.000000 +holygrail.tga +0 -6.528370 2.376133 18.269222 -0.829829 0.302042 -0.469131 0.226563 0.671875 1 0 1.000000 +0 -6.947345 0.000001 18.269222 -0.883084 0.000000 -0.469131 0.289063 0.671875 1 0 1.000000 +0 -7.522305 0.000001 20.680813 -0.997131 0.000000 -0.075381 0.289063 0.726563 1 0 1.000000 +holygrail.tga +0 -7.522305 0.000001 20.680813 -0.997131 0.000000 -0.075381 0.289063 0.726563 1 0 1.000000 +0 -7.068655 2.572781 20.680817 -0.937010 0.341044 -0.075381 0.226563 0.726563 1 0 1.000000 +0 -6.528370 2.376133 18.269222 -0.829829 0.302042 -0.469131 0.226563 0.671875 1 0 1.000000 +holygrail.tga +0 -5.321973 4.465668 18.269226 -0.676473 0.567644 -0.469131 0.171875 0.671875 1 0 1.000000 +0 -6.528370 2.376133 18.269222 -0.829829 0.302042 -0.469131 0.226563 0.671875 1 0 1.000000 +0 -7.068655 2.572781 20.680817 -0.937010 0.341044 -0.075381 0.226563 0.726563 1 0 1.000000 +holygrail.tga +0 -7.068655 2.572781 20.680817 -0.937010 0.341044 -0.075381 0.226563 0.726563 1 0 1.000000 +0 -5.762418 4.835245 20.680819 -0.763848 0.640950 -0.075381 0.171875 0.726563 1 0 1.000000 +0 -5.321973 4.465668 18.269226 -0.676473 0.567644 -0.469131 0.171875 0.671875 1 0 1.000000 +holygrail.tga +0 -3.473672 6.016578 18.269226 -0.441542 0.764794 -0.469131 0.117188 0.671875 1 0 1.000000 +0 -5.321973 4.465668 18.269226 -0.676473 0.567644 -0.469131 0.171875 0.671875 1 0 1.000000 +0 -5.762418 4.835245 20.680819 -0.763848 0.640950 -0.075381 0.171875 0.726563 1 0 1.000000 +holygrail.tga +0 -5.762418 4.835245 20.680819 -0.763848 0.640950 -0.075381 0.171875 0.726563 1 0 1.000000 +0 -3.761152 6.514506 20.680819 -0.498550 0.863552 -0.075381 0.117188 0.726563 1 0 1.000000 +0 -3.473672 6.016578 18.269226 -0.441542 0.764794 -0.469131 0.117188 0.671875 1 0 1.000000 +holygrail.tga +0 -1.206394 6.841801 18.269226 -0.153325 0.869686 -0.469131 0.058594 0.671875 1 0 1.000000 +0 -3.473672 6.016578 18.269226 -0.441542 0.764794 -0.469131 0.117188 0.671875 1 0 1.000000 +0 -3.761152 6.514506 20.680819 -0.498550 0.863552 -0.075381 0.117188 0.726563 1 0 1.000000 +holygrail.tga +0 1.206393 6.841801 18.269226 0.153325 0.869686 -0.469131 0.000000 0.671875 1 0 1.000000 +0 -1.206394 6.841801 18.269226 -0.153325 0.869686 -0.469131 0.058594 0.671875 1 0 1.000000 +0 -1.306235 7.408025 20.680819 -0.173132 0.981994 -0.075381 0.058594 0.726563 1 0 1.000000 +holygrail.tga +0 -1.306235 7.408025 20.680819 -0.173132 0.981994 -0.075381 0.058594 0.726563 1 0 1.000000 +0 1.306234 7.408025 20.680819 0.173132 0.981994 -0.075381 0.000000 0.726563 1 0 1.000000 +0 1.206393 6.841801 18.269226 0.153325 0.869686 -0.469131 0.000000 0.671875 1 0 1.000000 +holygrail.tga +0 3.473674 6.016578 18.269226 0.441542 0.764794 -0.469131 0.941406 0.671875 1 0 1.000000 +0 1.206393 6.841801 18.269226 0.153325 0.869686 -0.469131 1.000000 0.671875 1 0 1.000000 +0 1.306234 7.408025 20.680819 0.173132 0.981994 -0.075381 1.000000 0.726563 1 0 1.000000 +holygrail.tga +0 1.306234 7.408025 20.680819 0.173132 0.981994 -0.075381 1.000000 0.726563 1 0 1.000000 +0 3.761154 6.514506 20.680819 0.498550 0.863552 -0.075381 0.941406 0.726563 1 0 1.000000 +0 3.473674 6.016578 18.269226 0.441542 0.764794 -0.469131 0.941406 0.671875 1 0 1.000000 +holygrail.tga +0 5.321978 4.465666 18.269226 0.676473 0.567644 -0.469131 0.886719 0.671875 1 0 1.000000 +0 3.473674 6.016578 18.269226 0.441542 0.764794 -0.469131 0.941406 0.671875 1 0 1.000000 +0 3.761154 6.514506 20.680819 0.498550 0.863552 -0.075381 0.941406 0.726563 1 0 1.000000 +holygrail.tga +0 3.761154 6.514506 20.680819 0.498550 0.863552 -0.075381 0.941406 0.726563 1 0 1.000000 +0 5.762424 4.835242 20.680819 0.763848 0.640950 -0.075381 0.886719 0.726563 1 0 1.000000 +0 5.321978 4.465666 18.269226 0.676473 0.567644 -0.469131 0.886719 0.671875 1 0 1.000000 +holygrail.tga +0 6.528371 2.376132 18.269222 0.829829 0.302042 -0.469161 0.832031 0.671875 1 0 1.000000 +0 5.321978 4.465666 18.269226 0.676473 0.567644 -0.469131 0.886719 0.671875 1 0 1.000000 +0 5.762424 4.835242 20.680819 0.763848 0.640950 -0.075381 0.886719 0.726563 1 0 1.000000 +holygrail.tga +0 5.762424 4.835242 20.680819 0.763848 0.640950 -0.075381 0.886719 0.726563 1 0 1.000000 +0 7.068658 2.572779 20.680817 0.937010 0.341044 -0.075381 0.832031 0.726563 1 0 1.000000 +0 6.528371 2.376132 18.269222 0.829829 0.302042 -0.469161 0.832031 0.671875 1 0 1.000000 +holygrail.tga +0 5.042727 0.000002 16.304220 0.588488 0.000000 -0.808466 0.773438 0.632813 1 0 1.000000 +0 4.738615 1.724714 16.304220 0.552995 0.201270 -0.808466 0.832031 0.632813 1 0 1.000000 +0 6.528371 2.376132 18.269222 0.829829 0.302042 -0.469161 0.832031 0.671875 1 0 1.000000 +holygrail.tga +0 6.528371 2.376132 18.269222 0.829829 0.302042 -0.469161 0.832031 0.671875 1 0 1.000000 +0 6.947347 0.000000 18.269222 0.883084 0.000000 -0.469131 0.773438 0.671875 1 0 1.000000 +0 5.042727 0.000002 16.304220 0.588488 0.000000 -0.808466 0.773438 0.632813 1 0 1.000000 +holygrail.tga +0 4.738611 -1.724718 16.304220 0.552995 -0.201270 -0.808466 0.726563 0.632813 1 0 1.000000 +0 5.042727 0.000002 16.304220 0.588488 0.000000 -0.808466 0.773438 0.632813 1 0 1.000000 +0 6.947347 0.000000 18.269222 0.883084 0.000000 -0.469131 0.773438 0.671875 1 0 1.000000 +holygrail.tga +0 6.947347 0.000000 18.269222 0.883084 0.000000 -0.469131 0.773438 0.671875 1 0 1.000000 +0 6.528368 -2.376138 18.269222 0.829829 -0.302042 -0.469131 0.726563 0.671875 1 0 1.000000 +0 4.738611 -1.724718 16.304220 0.552995 -0.201270 -0.808466 0.726563 0.632813 1 0 1.000000 +holygrail.tga +0 3.862950 -3.241404 16.304220 0.450819 -0.378277 -0.808466 0.664063 0.632813 1 0 1.000000 +0 4.738611 -1.724718 16.304220 0.552995 -0.201270 -0.808466 0.726563 0.632813 1 0 1.000000 +0 6.528368 -2.376138 18.269222 0.829829 -0.302042 -0.469131 0.726563 0.671875 1 0 1.000000 +holygrail.tga +0 6.528368 -2.376138 18.269222 0.829829 -0.302042 -0.469131 0.726563 0.671875 1 0 1.000000 +0 5.321972 -4.465671 18.269222 0.676473 -0.567644 -0.469131 0.664063 0.671875 1 0 1.000000 +0 3.862950 -3.241404 16.304220 0.450819 -0.378277 -0.808466 0.664063 0.632813 1 0 1.000000 +holygrail.tga +0 2.521360 -4.367131 16.304220 0.294229 -0.509659 -0.808466 0.613281 0.632813 1 0 1.000000 +0 3.862950 -3.241404 16.304220 0.450819 -0.378277 -0.808466 0.664063 0.632813 1 0 1.000000 +0 5.321972 -4.465671 18.269222 0.676473 -0.567644 -0.469131 0.664063 0.671875 1 0 1.000000 +holygrail.tga +0 5.321972 -4.465671 18.269222 0.676473 -0.567644 -0.469131 0.664063 0.671875 1 0 1.000000 +0 3.473669 -6.016580 18.269222 0.441542 -0.764794 -0.469161 0.613281 0.671875 1 0 1.000000 +0 2.521360 -4.367131 16.304220 0.294229 -0.509659 -0.808466 0.613281 0.632813 1 0 1.000000 +holygrail.tga +0 0.875658 -4.966117 16.304220 0.102176 -0.579547 -0.808466 0.554688 0.632813 1 0 1.000000 +0 2.521360 -4.367131 16.304220 0.294229 -0.509659 -0.808466 0.613281 0.632813 1 0 1.000000 +0 3.473669 -6.016580 18.269222 0.441542 -0.764794 -0.469161 0.613281 0.671875 1 0 1.000000 +holygrail.tga +0 3.473669 -6.016580 18.269222 0.441542 -0.764794 -0.469161 0.613281 0.671875 1 0 1.000000 +0 1.206391 -6.841802 18.269222 0.153325 -0.869686 -0.469161 0.554688 0.671875 1 0 1.000000 +0 0.875658 -4.966117 16.304220 0.102176 -0.579547 -0.808466 0.554688 0.632813 1 0 1.000000 +holygrail.tga +0 -0.875661 -4.966116 16.304220 -0.102176 -0.579547 -0.808466 0.503906 0.632813 1 0 1.000000 +0 0.875658 -4.966117 16.304220 0.102176 -0.579547 -0.808466 0.554688 0.632813 1 0 1.000000 +0 1.206391 -6.841802 18.269222 0.153325 -0.869686 -0.469161 0.554688 0.671875 1 0 1.000000 +holygrail.tga +0 1.206391 -6.841802 18.269222 0.153325 -0.869686 -0.469161 0.554688 0.671875 1 0 1.000000 +0 -1.206396 -6.841800 18.269222 -0.153325 -0.869686 -0.469161 0.503906 0.671875 1 0 1.000000 +0 -0.875661 -4.966116 16.304220 -0.102176 -0.579547 -0.808466 0.503906 0.632813 1 0 1.000000 +holygrail.tga +0 -2.521365 -4.367128 16.304220 -0.294229 -0.509629 -0.808466 0.449219 0.632813 1 0 1.000000 +0 -0.875661 -4.966116 16.304220 -0.102176 -0.579547 -0.808466 0.503906 0.632813 1 0 1.000000 +0 -1.206396 -6.841800 18.269222 -0.153325 -0.869686 -0.469161 0.503906 0.671875 1 0 1.000000 +holygrail.tga +0 -1.206396 -6.841800 18.269222 -0.153325 -0.869686 -0.469161 0.503906 0.671875 1 0 1.000000 +0 -3.473675 -6.016577 18.269222 -0.441542 -0.764794 -0.469161 0.449219 0.671875 1 0 1.000000 +0 -2.521365 -4.367128 16.304220 -0.294229 -0.509629 -0.808466 0.449219 0.632813 1 0 1.000000 +holygrail.tga +0 -3.862954 -3.241400 16.304220 -0.450819 -0.378277 -0.808466 0.394531 0.632813 1 0 1.000000 +0 -2.521365 -4.367128 16.304220 -0.294229 -0.509629 -0.808466 0.449219 0.632813 1 0 1.000000 +0 -3.473675 -6.016577 18.269222 -0.441542 -0.764794 -0.469161 0.449219 0.671875 1 0 1.000000 +holygrail.tga +0 -3.473675 -6.016577 18.269222 -0.441542 -0.764794 -0.469161 0.449219 0.671875 1 0 1.000000 +0 -5.321978 -4.465666 18.269222 -0.676473 -0.567644 -0.469161 0.394531 0.671875 1 0 1.000000 +0 -3.862954 -3.241400 16.304220 -0.450819 -0.378277 -0.808466 0.394531 0.632813 1 0 1.000000 +holygrail.tga +0 -4.738615 -1.724712 16.304220 -0.552995 -0.201270 -0.808466 0.339844 0.632813 1 0 1.000000 +0 -3.862954 -3.241400 16.304220 -0.450819 -0.378277 -0.808466 0.394531 0.632813 1 0 1.000000 +0 -5.321978 -4.465666 18.269222 -0.676473 -0.567644 -0.469161 0.394531 0.671875 1 0 1.000000 +holygrail.tga +0 -5.321978 -4.465666 18.269222 -0.676473 -0.567644 -0.469161 0.394531 0.671875 1 0 1.000000 +0 -6.528372 -2.376130 18.269222 -0.829829 -0.302042 -0.469131 0.339844 0.671875 1 0 1.000000 +0 -4.738615 -1.724712 16.304220 -0.552995 -0.201270 -0.808466 0.339844 0.632813 1 0 1.000000 +holygrail.tga +0 -5.042726 0.000001 16.304220 -0.588488 0.000000 -0.808466 0.289063 0.632813 1 0 1.000000 +0 -4.738615 -1.724712 16.304220 -0.552995 -0.201270 -0.808466 0.339844 0.632813 1 0 1.000000 +0 -6.528372 -2.376130 18.269222 -0.829829 -0.302042 -0.469131 0.339844 0.671875 1 0 1.000000 +holygrail.tga +0 -6.528372 -2.376130 18.269222 -0.829829 -0.302042 -0.469131 0.339844 0.671875 1 0 1.000000 +0 -6.947345 0.000001 18.269222 -0.883084 0.000000 -0.469131 0.289063 0.671875 1 0 1.000000 +0 -5.042726 0.000001 16.304220 -0.588488 0.000000 -0.808466 0.289063 0.632813 1 0 1.000000 +holygrail.tga +0 -4.738614 1.724714 16.304220 -0.552995 0.201270 -0.808466 0.226563 0.632813 1 0 1.000000 +0 -5.042726 0.000001 16.304220 -0.588488 0.000000 -0.808466 0.289063 0.632813 1 0 1.000000 +0 -6.947345 0.000001 18.269222 -0.883084 0.000000 -0.469131 0.289063 0.671875 1 0 1.000000 +holygrail.tga +0 -6.947345 0.000001 18.269222 -0.883084 0.000000 -0.469131 0.289063 0.671875 1 0 1.000000 +0 -6.528370 2.376133 18.269222 -0.829829 0.302042 -0.469131 0.226563 0.671875 1 0 1.000000 +0 -4.738614 1.724714 16.304220 -0.552995 0.201270 -0.808466 0.226563 0.632813 1 0 1.000000 +holygrail.tga +0 -3.862951 3.241403 16.304222 -0.450819 0.378277 -0.808466 0.171875 0.632813 1 0 1.000000 +0 -4.738614 1.724714 16.304220 -0.552995 0.201270 -0.808466 0.226563 0.632813 1 0 1.000000 +0 -6.528370 2.376133 18.269222 -0.829829 0.302042 -0.469131 0.226563 0.671875 1 0 1.000000 +holygrail.tga +0 -6.528370 2.376133 18.269222 -0.829829 0.302042 -0.469131 0.226563 0.671875 1 0 1.000000 +0 -5.321973 4.465668 18.269226 -0.676473 0.567644 -0.469131 0.171875 0.671875 1 0 1.000000 +0 -3.862951 3.241403 16.304222 -0.450819 0.378277 -0.808466 0.171875 0.632813 1 0 1.000000 +holygrail.tga +0 -2.521362 4.367130 16.304222 -0.294229 0.509659 -0.808466 0.117188 0.632813 1 0 1.000000 +0 -3.862951 3.241403 16.304222 -0.450819 0.378277 -0.808466 0.171875 0.632813 1 0 1.000000 +0 -5.321973 4.465668 18.269226 -0.676473 0.567644 -0.469131 0.171875 0.671875 1 0 1.000000 +holygrail.tga +0 -5.321973 4.465668 18.269226 -0.676473 0.567644 -0.469131 0.171875 0.671875 1 0 1.000000 +0 -3.473672 6.016578 18.269226 -0.441542 0.764794 -0.469131 0.117188 0.671875 1 0 1.000000 +0 -2.521362 4.367130 16.304222 -0.294229 0.509659 -0.808466 0.117188 0.632813 1 0 1.000000 +holygrail.tga +0 -0.875661 4.966117 16.304222 -0.102176 0.579547 -0.808466 0.058594 0.632813 1 0 1.000000 +0 -2.521362 4.367130 16.304222 -0.294229 0.509659 -0.808466 0.117188 0.632813 1 0 1.000000 +0 -3.473672 6.016578 18.269226 -0.441542 0.764794 -0.469131 0.117188 0.671875 1 0 1.000000 +holygrail.tga +0 -3.473672 6.016578 18.269226 -0.441542 0.764794 -0.469131 0.117188 0.671875 1 0 1.000000 +0 -1.206394 6.841801 18.269226 -0.153325 0.869686 -0.469131 0.058594 0.671875 1 0 1.000000 +0 -0.875661 4.966117 16.304222 -0.102176 0.579547 -0.808466 0.058594 0.632813 1 0 1.000000 +holygrail.tga +0 0.875660 4.966117 16.304222 0.102176 0.579547 -0.808466 0.000000 0.632813 1 0 1.000000 +0 -0.875661 4.966117 16.304222 -0.102176 0.579547 -0.808466 0.058594 0.632813 1 0 1.000000 +0 -1.206394 6.841801 18.269226 -0.153325 0.869686 -0.469131 0.058594 0.671875 1 0 1.000000 +holygrail.tga +0 -1.206394 6.841801 18.269226 -0.153325 0.869686 -0.469131 0.058594 0.671875 1 0 1.000000 +0 1.206393 6.841801 18.269226 0.153325 0.869686 -0.469131 0.000000 0.671875 1 0 1.000000 +0 0.875660 4.966117 16.304222 0.102176 0.579547 -0.808466 0.000000 0.632813 1 0 1.000000 +holygrail.tga +0 2.521364 4.367130 16.304222 0.294229 0.509659 -0.808466 0.941406 0.632813 1 0 1.000000 +0 0.875660 4.966117 16.304222 0.102176 0.579547 -0.808466 1.000000 0.632813 1 0 1.000000 +0 1.206393 6.841801 18.269226 0.153325 0.869686 -0.469131 1.000000 0.671875 1 0 1.000000 +holygrail.tga +0 1.206393 6.841801 18.269226 0.153325 0.869686 -0.469131 1.000000 0.671875 1 0 1.000000 +0 3.473674 6.016578 18.269226 0.441542 0.764794 -0.469131 0.941406 0.671875 1 0 1.000000 +0 2.521364 4.367130 16.304222 0.294229 0.509659 -0.808466 0.941406 0.632813 1 0 1.000000 +holygrail.tga +0 3.862955 3.241401 16.304222 0.450819 0.378277 -0.808466 0.886719 0.632813 1 0 1.000000 +0 2.521364 4.367130 16.304222 0.294229 0.509659 -0.808466 0.941406 0.632813 1 0 1.000000 +0 3.473674 6.016578 18.269226 0.441542 0.764794 -0.469131 0.941406 0.671875 1 0 1.000000 +holygrail.tga +0 3.473674 6.016578 18.269226 0.441542 0.764794 -0.469131 0.941406 0.671875 1 0 1.000000 +0 5.321978 4.465666 18.269226 0.676473 0.567644 -0.469131 0.886719 0.671875 1 0 1.000000 +0 3.862955 3.241401 16.304222 0.450819 0.378277 -0.808466 0.886719 0.632813 1 0 1.000000 +holygrail.tga +0 4.738615 1.724714 16.304220 0.552995 0.201270 -0.808466 0.832031 0.632813 1 0 1.000000 +0 3.862955 3.241401 16.304222 0.450819 0.378277 -0.808466 0.886719 0.632813 1 0 1.000000 +0 5.321978 4.465666 18.269226 0.676473 0.567644 -0.469131 0.886719 0.671875 1 0 1.000000 +holygrail.tga +0 5.321978 4.465666 18.269226 0.676473 0.567644 -0.469131 0.886719 0.671875 1 0 1.000000 +0 6.528371 2.376132 18.269222 0.829829 0.302042 -0.469161 0.832031 0.671875 1 0 1.000000 +0 4.738615 1.724714 16.304220 0.552995 0.201270 -0.808466 0.832031 0.632813 1 0 1.000000 +holygrail.tga +0 2.866019 0.000003 15.321719 0.932890 0.000000 -0.360088 0.773438 0.593750 1 0 1.000000 +0 2.693178 0.980237 15.321720 0.876644 0.319071 -0.360088 0.832031 0.593750 1 0 1.000000 +0 4.738615 1.724714 16.304220 0.552995 0.201270 -0.808466 0.832031 0.632813 1 0 1.000000 +holygrail.tga +0 4.738615 1.724714 16.304220 0.552995 0.201270 -0.808466 0.832031 0.632813 1 0 1.000000 +0 5.042727 0.000002 16.304220 0.588488 0.000000 -0.808466 0.773438 0.632813 1 0 1.000000 +0 2.866019 0.000003 15.321719 0.932890 0.000000 -0.360088 0.773438 0.593750 1 0 1.000000 +holygrail.tga +0 2.693176 -0.980238 15.321719 0.876644 -0.319071 -0.360088 0.726563 0.593750 1 0 1.000000 +0 2.866019 0.000003 15.321719 0.932890 0.000000 -0.360088 0.773438 0.593750 1 0 1.000000 +0 5.042727 0.000002 16.304220 0.588488 0.000000 -0.808466 0.773438 0.632813 1 0 1.000000 +holygrail.tga +0 5.042727 0.000002 16.304220 0.588488 0.000000 -0.808466 0.773438 0.632813 1 0 1.000000 +0 4.738611 -1.724718 16.304220 0.552995 -0.201270 -0.808466 0.726563 0.632813 1 0 1.000000 +0 2.693176 -0.980238 15.321719 0.876644 -0.319071 -0.360088 0.726563 0.593750 1 0 1.000000 +holygrail.tga +0 2.195496 -1.842242 15.321719 0.714652 -0.599658 -0.360088 0.664063 0.593750 1 0 1.000000 +0 2.693176 -0.980238 15.321719 0.876644 -0.319071 -0.360088 0.726563 0.593750 1 0 1.000000 +0 4.738611 -1.724718 16.304220 0.552995 -0.201270 -0.808466 0.726563 0.632813 1 0 1.000000 +holygrail.tga +0 4.738611 -1.724718 16.304220 0.552995 -0.201270 -0.808466 0.726563 0.632813 1 0 1.000000 +0 3.862950 -3.241404 16.304220 0.450819 -0.378277 -0.808466 0.664063 0.632813 1 0 1.000000 +0 2.195496 -1.842242 15.321719 0.714652 -0.599658 -0.360088 0.664063 0.593750 1 0 1.000000 +holygrail.tga +0 1.433007 -2.482047 15.321719 0.466445 -0.807917 -0.360088 0.613281 0.593750 1 0 1.000000 +0 2.195496 -1.842242 15.321719 0.714652 -0.599658 -0.360088 0.664063 0.593750 1 0 1.000000 +0 3.862950 -3.241404 16.304220 0.450819 -0.378277 -0.808466 0.664063 0.632813 1 0 1.000000 +holygrail.tga +0 3.862950 -3.241404 16.304220 0.450819 -0.378277 -0.808466 0.664063 0.632813 1 0 1.000000 +0 2.521360 -4.367131 16.304220 0.294229 -0.509659 -0.808466 0.613281 0.632813 1 0 1.000000 +0 1.433007 -2.482047 15.321719 0.466445 -0.807917 -0.360088 0.613281 0.593750 1 0 1.000000 +holygrail.tga +0 0.497677 -2.822478 15.321719 0.161992 -0.918729 -0.360088 0.554688 0.593750 1 0 1.000000 +0 1.433007 -2.482047 15.321719 0.466445 -0.807917 -0.360088 0.613281 0.593750 1 0 1.000000 +0 2.521360 -4.367131 16.304220 0.294229 -0.509659 -0.808466 0.613281 0.632813 1 0 1.000000 +holygrail.tga +0 2.521360 -4.367131 16.304220 0.294229 -0.509659 -0.808466 0.613281 0.632813 1 0 1.000000 +0 0.875658 -4.966117 16.304220 0.102176 -0.579547 -0.808466 0.554688 0.632813 1 0 1.000000 +0 0.497677 -2.822478 15.321719 0.161992 -0.918729 -0.360088 0.554688 0.593750 1 0 1.000000 +holygrail.tga +0 -0.497679 -2.822478 15.321719 -0.161992 -0.918729 -0.360088 0.503906 0.593750 1 0 1.000000 +0 0.497677 -2.822478 15.321719 0.161992 -0.918729 -0.360088 0.554688 0.593750 1 0 1.000000 +0 0.875658 -4.966117 16.304220 0.102176 -0.579547 -0.808466 0.554688 0.632813 1 0 1.000000 +holygrail.tga +0 0.875658 -4.966117 16.304220 0.102176 -0.579547 -0.808466 0.554688 0.632813 1 0 1.000000 +0 -0.875661 -4.966116 16.304220 -0.102176 -0.579547 -0.808466 0.503906 0.632813 1 0 1.000000 +0 -0.497679 -2.822478 15.321719 -0.161992 -0.918729 -0.360088 0.503906 0.593750 1 0 1.000000 +holygrail.tga +0 -1.433010 -2.482045 15.321719 -0.466445 -0.807917 -0.360088 0.449219 0.593750 1 0 1.000000 +0 -0.497679 -2.822478 15.321719 -0.161992 -0.918729 -0.360088 0.503906 0.593750 1 0 1.000000 +0 -0.875661 -4.966116 16.304220 -0.102176 -0.579547 -0.808466 0.503906 0.632813 1 0 1.000000 +holygrail.tga +0 -0.875661 -4.966116 16.304220 -0.102176 -0.579547 -0.808466 0.503906 0.632813 1 0 1.000000 +0 -2.521365 -4.367128 16.304220 -0.294229 -0.509629 -0.808466 0.449219 0.632813 1 0 1.000000 +0 -1.433010 -2.482045 15.321719 -0.466445 -0.807917 -0.360088 0.449219 0.593750 1 0 1.000000 +holygrail.tga +0 -2.195500 -1.842239 15.321719 -0.714652 -0.599658 -0.360088 0.394531 0.593750 1 0 1.000000 +0 -1.433010 -2.482045 15.321719 -0.466445 -0.807917 -0.360088 0.449219 0.593750 1 0 1.000000 +0 -2.521365 -4.367128 16.304220 -0.294229 -0.509629 -0.808466 0.449219 0.632813 1 0 1.000000 +holygrail.tga +0 -2.521365 -4.367128 16.304220 -0.294229 -0.509629 -0.808466 0.449219 0.632813 1 0 1.000000 +0 -3.862954 -3.241400 16.304220 -0.450819 -0.378277 -0.808466 0.394531 0.632813 1 0 1.000000 +0 -2.195500 -1.842239 15.321719 -0.714652 -0.599658 -0.360088 0.394531 0.593750 1 0 1.000000 +holygrail.tga +0 -2.693178 -0.980235 15.321719 -0.876644 -0.319071 -0.360088 0.339844 0.593750 1 0 1.000000 +0 -2.195500 -1.842239 15.321719 -0.714652 -0.599658 -0.360088 0.394531 0.593750 1 0 1.000000 +0 -3.862954 -3.241400 16.304220 -0.450819 -0.378277 -0.808466 0.394531 0.632813 1 0 1.000000 +holygrail.tga +0 -3.862954 -3.241400 16.304220 -0.450819 -0.378277 -0.808466 0.394531 0.632813 1 0 1.000000 +0 -4.738615 -1.724712 16.304220 -0.552995 -0.201270 -0.808466 0.339844 0.632813 1 0 1.000000 +0 -2.693178 -0.980235 15.321719 -0.876644 -0.319071 -0.360088 0.339844 0.593750 1 0 1.000000 +holygrail.tga +0 -2.866019 0.000000 15.321719 -0.932890 0.000000 -0.360088 0.289063 0.593750 1 0 1.000000 +0 -2.693178 -0.980235 15.321719 -0.876644 -0.319071 -0.360088 0.339844 0.593750 1 0 1.000000 +0 -4.738615 -1.724712 16.304220 -0.552995 -0.201270 -0.808466 0.339844 0.632813 1 0 1.000000 +holygrail.tga +0 -4.738615 -1.724712 16.304220 -0.552995 -0.201270 -0.808466 0.339844 0.632813 1 0 1.000000 +0 -5.042726 0.000001 16.304220 -0.588488 0.000000 -0.808466 0.289063 0.632813 1 0 1.000000 +0 -2.866019 0.000000 15.321719 -0.932890 0.000000 -0.360088 0.289063 0.593750 1 0 1.000000 +holygrail.tga +0 -2.693177 0.980236 15.321720 -0.876644 0.319071 -0.360088 0.226563 0.593750 1 0 1.000000 +0 -2.866019 0.000000 15.321719 -0.932890 0.000000 -0.360088 0.289063 0.593750 1 0 1.000000 +0 -5.042726 0.000001 16.304220 -0.588488 0.000000 -0.808466 0.289063 0.632813 1 0 1.000000 +holygrail.tga +0 -5.042726 0.000001 16.304220 -0.588488 0.000000 -0.808466 0.289063 0.632813 1 0 1.000000 +0 -4.738614 1.724714 16.304220 -0.552995 0.201270 -0.808466 0.226563 0.632813 1 0 1.000000 +0 -2.693177 0.980236 15.321720 -0.876644 0.319071 -0.360088 0.226563 0.593750 1 0 1.000000 +holygrail.tga +0 -2.195497 1.842241 15.321721 -0.714652 0.599658 -0.360088 0.171875 0.593750 1 0 1.000000 +0 -2.693177 0.980236 15.321720 -0.876644 0.319071 -0.360088 0.226563 0.593750 1 0 1.000000 +0 -4.738614 1.724714 16.304220 -0.552995 0.201270 -0.808466 0.226563 0.632813 1 0 1.000000 +holygrail.tga +0 -4.738614 1.724714 16.304220 -0.552995 0.201270 -0.808466 0.226563 0.632813 1 0 1.000000 +0 -3.862951 3.241403 16.304222 -0.450819 0.378277 -0.808466 0.171875 0.632813 1 0 1.000000 +0 -2.195497 1.842241 15.321721 -0.714652 0.599658 -0.360088 0.171875 0.593750 1 0 1.000000 +holygrail.tga +0 -1.433007 2.482047 15.321721 -0.466445 0.807917 -0.360088 0.117188 0.593750 1 0 1.000000 +0 -2.195497 1.842241 15.321721 -0.714652 0.599658 -0.360088 0.171875 0.593750 1 0 1.000000 +0 -3.862951 3.241403 16.304222 -0.450819 0.378277 -0.808466 0.171875 0.632813 1 0 1.000000 +holygrail.tga +0 -3.862951 3.241403 16.304222 -0.450819 0.378277 -0.808466 0.171875 0.632813 1 0 1.000000 +0 -2.521362 4.367130 16.304222 -0.294229 0.509659 -0.808466 0.117188 0.632813 1 0 1.000000 +0 -1.433007 2.482047 15.321721 -0.466445 0.807917 -0.360088 0.117188 0.593750 1 0 1.000000 +holygrail.tga +0 -0.497679 2.822479 15.321721 -0.161992 0.918729 -0.360088 0.058594 0.593750 1 0 1.000000 +0 -1.433007 2.482047 15.321721 -0.466445 0.807917 -0.360088 0.117188 0.593750 1 0 1.000000 +0 -2.521362 4.367130 16.304222 -0.294229 0.509659 -0.808466 0.117188 0.632813 1 0 1.000000 +holygrail.tga +0 -2.521362 4.367130 16.304222 -0.294229 0.509659 -0.808466 0.117188 0.632813 1 0 1.000000 +0 -0.875661 4.966117 16.304222 -0.102176 0.579547 -0.808466 0.058594 0.632813 1 0 1.000000 +0 -0.497679 2.822479 15.321721 -0.161992 0.918729 -0.360088 0.058594 0.593750 1 0 1.000000 +holygrail.tga +0 0.497679 2.822479 15.321721 0.161992 0.918729 -0.360088 0.000000 0.593750 1 0 1.000000 +0 -0.497679 2.822479 15.321721 -0.161992 0.918729 -0.360088 0.058594 0.593750 1 0 1.000000 +0 -0.875661 4.966117 16.304222 -0.102176 0.579547 -0.808466 0.058594 0.632813 1 0 1.000000 +holygrail.tga +0 -0.875661 4.966117 16.304222 -0.102176 0.579547 -0.808466 0.058594 0.632813 1 0 1.000000 +0 0.875660 4.966117 16.304222 0.102176 0.579547 -0.808466 0.000000 0.632813 1 0 1.000000 +0 0.497679 2.822479 15.321721 0.161992 0.918729 -0.360088 0.000000 0.593750 1 0 1.000000 +holygrail.tga +0 1.433010 2.482046 15.321721 0.466445 0.807917 -0.360088 0.941406 0.593750 1 0 1.000000 +0 0.497679 2.822479 15.321721 0.161992 0.918729 -0.360088 1.000000 0.593750 1 0 1.000000 +0 0.875660 4.966117 16.304222 0.102176 0.579547 -0.808466 1.000000 0.632813 1 0 1.000000 +holygrail.tga +0 0.875660 4.966117 16.304222 0.102176 0.579547 -0.808466 1.000000 0.632813 1 0 1.000000 +0 2.521364 4.367130 16.304222 0.294229 0.509659 -0.808466 0.941406 0.632813 1 0 1.000000 +0 1.433010 2.482046 15.321721 0.466445 0.807917 -0.360088 0.941406 0.593750 1 0 1.000000 +holygrail.tga +0 2.195500 1.842241 15.321721 0.714652 0.599658 -0.360088 0.886719 0.593750 1 0 1.000000 +0 1.433010 2.482046 15.321721 0.466445 0.807917 -0.360088 0.941406 0.593750 1 0 1.000000 +0 2.521364 4.367130 16.304222 0.294229 0.509659 -0.808466 0.941406 0.632813 1 0 1.000000 +holygrail.tga +0 2.521364 4.367130 16.304222 0.294229 0.509659 -0.808466 0.941406 0.632813 1 0 1.000000 +0 3.862955 3.241401 16.304222 0.450819 0.378277 -0.808466 0.886719 0.632813 1 0 1.000000 +0 2.195500 1.842241 15.321721 0.714652 0.599658 -0.360088 0.886719 0.593750 1 0 1.000000 +holygrail.tga +0 2.693178 0.980237 15.321720 0.876644 0.319071 -0.360088 0.832031 0.593750 1 0 1.000000 +0 2.195500 1.842241 15.321721 0.714652 0.599658 -0.360088 0.886719 0.593750 1 0 1.000000 +0 3.862955 3.241401 16.304222 0.450819 0.378277 -0.808466 0.886719 0.632813 1 0 1.000000 +holygrail.tga +0 3.862955 3.241401 16.304222 0.450819 0.378277 -0.808466 0.886719 0.632813 1 0 1.000000 +0 4.738615 1.724714 16.304220 0.552995 0.201270 -0.808466 0.832031 0.632813 1 0 1.000000 +0 2.693178 0.980237 15.321720 0.876644 0.319071 -0.360088 0.832031 0.593750 1 0 1.000000 +holygrail.tga +0 3.047412 0.000003 14.964446 0.961058 0.000000 0.276284 0.773438 0.578125 1 0 1.000000 +0 2.863631 1.042277 14.964447 0.903104 0.328684 0.276284 0.832031 0.578125 1 0 1.000000 +0 2.693178 0.980237 15.321720 0.876644 0.319071 -0.360088 0.832031 0.593750 1 0 1.000000 +holygrail.tga +0 2.693178 0.980237 15.321720 0.876644 0.319071 -0.360088 0.832031 0.593750 1 0 1.000000 +0 2.866019 0.000003 15.321719 0.932890 0.000000 -0.360088 0.773438 0.593750 1 0 1.000000 +0 3.047412 0.000003 14.964446 0.961058 0.000000 0.276284 0.773438 0.578125 1 0 1.000000 +holygrail.tga +0 2.863629 -1.042278 14.964446 0.903104 -0.328684 0.276284 0.726563 0.578125 1 0 1.000000 +0 3.047412 0.000003 14.964446 0.961058 0.000000 0.276284 0.773438 0.578125 1 0 1.000000 +0 2.866019 0.000003 15.321719 0.932890 0.000000 -0.360088 0.773438 0.593750 1 0 1.000000 +holygrail.tga +0 2.866019 0.000003 15.321719 0.932890 0.000000 -0.360088 0.773438 0.593750 1 0 1.000000 +0 2.693176 -0.980238 15.321719 0.876644 -0.319071 -0.360088 0.726563 0.593750 1 0 1.000000 +0 2.863629 -1.042278 14.964446 0.903104 -0.328684 0.276284 0.726563 0.578125 1 0 1.000000 +holygrail.tga +0 2.334451 -1.958839 14.964447 0.736198 -0.617756 0.276284 0.664063 0.578125 1 0 1.000000 +0 2.863629 -1.042278 14.964446 0.903104 -0.328684 0.276284 0.726563 0.578125 1 0 1.000000 +0 2.693176 -0.980238 15.321719 0.876644 -0.319071 -0.360088 0.726563 0.593750 1 0 1.000000 +holygrail.tga +0 2.693176 -0.980238 15.321719 0.876644 -0.319071 -0.360088 0.726563 0.593750 1 0 1.000000 +0 2.195496 -1.842242 15.321719 0.714652 -0.599658 -0.360088 0.664063 0.593750 1 0 1.000000 +0 2.334451 -1.958839 14.964447 0.736198 -0.617756 0.276284 0.664063 0.578125 1 0 1.000000 +holygrail.tga +0 1.523703 -2.639137 14.964447 0.480514 -0.832301 0.276284 0.613281 0.578125 1 0 1.000000 +0 2.334451 -1.958839 14.964447 0.736198 -0.617756 0.276284 0.664063 0.578125 1 0 1.000000 +0 2.195496 -1.842242 15.321719 0.714652 -0.599658 -0.360088 0.664063 0.593750 1 0 1.000000 +holygrail.tga +0 2.195496 -1.842242 15.321719 0.714652 -0.599658 -0.360088 0.664063 0.593750 1 0 1.000000 +0 1.433007 -2.482047 15.321719 0.466445 -0.807917 -0.360088 0.613281 0.593750 1 0 1.000000 +0 1.523703 -2.639137 14.964447 0.480514 -0.832301 0.276284 0.613281 0.578125 1 0 1.000000 +holygrail.tga +0 0.529176 -3.001114 14.964447 0.166875 -0.946440 0.276284 0.554688 0.578125 1 0 1.000000 +0 1.523703 -2.639137 14.964447 0.480514 -0.832301 0.276284 0.613281 0.578125 1 0 1.000000 +0 1.433007 -2.482047 15.321719 0.466445 -0.807917 -0.360088 0.613281 0.593750 1 0 1.000000 +holygrail.tga +0 1.433007 -2.482047 15.321719 0.466445 -0.807917 -0.360088 0.613281 0.593750 1 0 1.000000 +0 0.497677 -2.822478 15.321719 0.161992 -0.918729 -0.360088 0.554688 0.593750 1 0 1.000000 +0 0.529176 -3.001114 14.964447 0.166875 -0.946440 0.276284 0.554688 0.578125 1 0 1.000000 +holygrail.tga +0 -0.529177 -3.001114 14.964447 -0.166875 -0.946440 0.276284 0.503906 0.578125 1 0 1.000000 +0 0.529176 -3.001114 14.964447 0.166875 -0.946440 0.276284 0.554688 0.578125 1 0 1.000000 +0 0.497677 -2.822478 15.321719 0.161992 -0.918729 -0.360088 0.554688 0.593750 1 0 1.000000 +holygrail.tga +0 0.497677 -2.822478 15.321719 0.161992 -0.918729 -0.360088 0.554688 0.593750 1 0 1.000000 +0 -0.497679 -2.822478 15.321719 -0.161992 -0.918729 -0.360088 0.503906 0.593750 1 0 1.000000 +0 -0.529177 -3.001114 14.964447 -0.166875 -0.946440 0.276284 0.503906 0.578125 1 0 1.000000 +holygrail.tga +0 -1.523706 -2.639135 14.964447 -0.480514 -0.832301 0.276284 0.449219 0.578125 1 0 1.000000 +0 -0.529177 -3.001114 14.964447 -0.166875 -0.946440 0.276284 0.503906 0.578125 1 0 1.000000 +0 -0.497679 -2.822478 15.321719 -0.161992 -0.918729 -0.360088 0.503906 0.593750 1 0 1.000000 +holygrail.tga +0 -0.497679 -2.822478 15.321719 -0.161992 -0.918729 -0.360088 0.503906 0.593750 1 0 1.000000 +0 -1.433010 -2.482045 15.321719 -0.466445 -0.807917 -0.360088 0.449219 0.593750 1 0 1.000000 +0 -1.523706 -2.639135 14.964447 -0.480514 -0.832301 0.276284 0.449219 0.578125 1 0 1.000000 +holygrail.tga +0 -2.334454 -1.958836 14.964447 -0.736198 -0.617756 0.276284 0.394531 0.578125 1 0 1.000000 +0 -1.523706 -2.639135 14.964447 -0.480514 -0.832301 0.276284 0.449219 0.578125 1 0 1.000000 +0 -1.433010 -2.482045 15.321719 -0.466445 -0.807917 -0.360088 0.449219 0.593750 1 0 1.000000 +holygrail.tga +0 -1.433010 -2.482045 15.321719 -0.466445 -0.807917 -0.360088 0.449219 0.593750 1 0 1.000000 +0 -2.195500 -1.842239 15.321719 -0.714652 -0.599658 -0.360088 0.394531 0.593750 1 0 1.000000 +0 -2.334454 -1.958836 14.964447 -0.736198 -0.617756 0.276284 0.394531 0.578125 1 0 1.000000 +holygrail.tga +0 -2.195500 -1.842239 15.321719 -0.714652 -0.599658 -0.360088 0.394531 0.593750 1 0 1.000000 +0 -2.693178 -0.980235 15.321719 -0.876644 -0.319071 -0.360088 0.339844 0.593750 1 0 1.000000 +0 -2.863631 -1.042275 14.964446 -0.903104 -0.328684 0.276284 0.339844 0.578125 1 0 1.000000 +holygrail.tga +0 -3.047411 0.000000 14.964446 -0.961058 0.000000 0.276284 0.289063 0.578125 1 0 1.000000 +0 -2.863631 -1.042275 14.964446 -0.903104 -0.328684 0.276284 0.339844 0.578125 1 0 1.000000 +0 -2.693178 -0.980235 15.321719 -0.876644 -0.319071 -0.360088 0.339844 0.593750 1 0 1.000000 +holygrail.tga +0 -2.693178 -0.980235 15.321719 -0.876644 -0.319071 -0.360088 0.339844 0.593750 1 0 1.000000 +0 -2.866019 0.000000 15.321719 -0.932890 0.000000 -0.360088 0.289063 0.593750 1 0 1.000000 +0 -3.047411 0.000000 14.964446 -0.961058 0.000000 0.276284 0.289063 0.578125 1 0 1.000000 +holygrail.tga +0 -2.863631 1.042276 14.964447 -0.903104 0.328684 0.276284 0.226563 0.578125 1 0 1.000000 +0 -3.047411 0.000000 14.964446 -0.961058 0.000000 0.276284 0.289063 0.578125 1 0 1.000000 +0 -2.866019 0.000000 15.321719 -0.932890 0.000000 -0.360088 0.289063 0.593750 1 0 1.000000 +holygrail.tga +0 -2.866019 0.000000 15.321719 -0.932890 0.000000 -0.360088 0.289063 0.593750 1 0 1.000000 +0 -2.693177 0.980236 15.321720 -0.876644 0.319071 -0.360088 0.226563 0.593750 1 0 1.000000 +0 -2.863631 1.042276 14.964447 -0.903104 0.328684 0.276284 0.226563 0.578125 1 0 1.000000 +holygrail.tga +0 -2.334451 1.958838 14.964448 -0.736198 0.617756 0.276284 0.171875 0.578125 1 0 1.000000 +0 -2.863631 1.042276 14.964447 -0.903104 0.328684 0.276284 0.226563 0.578125 1 0 1.000000 +0 -2.693177 0.980236 15.321720 -0.876644 0.319071 -0.360088 0.226563 0.593750 1 0 1.000000 +holygrail.tga +0 -2.693177 0.980236 15.321720 -0.876644 0.319071 -0.360088 0.226563 0.593750 1 0 1.000000 +0 -2.195497 1.842241 15.321721 -0.714652 0.599658 -0.360088 0.171875 0.593750 1 0 1.000000 +0 -2.334451 1.958838 14.964448 -0.736198 0.617756 0.276284 0.171875 0.578125 1 0 1.000000 +holygrail.tga +0 -1.523703 2.639137 14.964448 -0.480514 0.832301 0.276284 0.117188 0.578125 1 0 1.000000 +0 -2.334451 1.958838 14.964448 -0.736198 0.617756 0.276284 0.171875 0.578125 1 0 1.000000 +0 -2.195497 1.842241 15.321721 -0.714652 0.599658 -0.360088 0.171875 0.593750 1 0 1.000000 +holygrail.tga +0 -2.195497 1.842241 15.321721 -0.714652 0.599658 -0.360088 0.171875 0.593750 1 0 1.000000 +0 -1.433007 2.482047 15.321721 -0.466445 0.807917 -0.360088 0.117188 0.593750 1 0 1.000000 +0 -1.523703 2.639137 14.964448 -0.480514 0.832301 0.276284 0.117188 0.578125 1 0 1.000000 +holygrail.tga +0 -0.529177 3.001115 14.964448 -0.166875 0.946440 0.276284 0.058594 0.578125 1 0 1.000000 +0 -1.523703 2.639137 14.964448 -0.480514 0.832301 0.276284 0.117188 0.578125 1 0 1.000000 +0 -1.433007 2.482047 15.321721 -0.466445 0.807917 -0.360088 0.117188 0.593750 1 0 1.000000 +holygrail.tga +0 -1.433007 2.482047 15.321721 -0.466445 0.807917 -0.360088 0.117188 0.593750 1 0 1.000000 +0 -0.497679 2.822479 15.321721 -0.161992 0.918729 -0.360088 0.058594 0.593750 1 0 1.000000 +0 -0.529177 3.001115 14.964448 -0.166875 0.946440 0.276284 0.058594 0.578125 1 0 1.000000 +holygrail.tga +0 0.529177 3.001115 14.964448 0.166875 0.946440 0.276284 0.000000 0.578125 1 0 1.000000 +0 -0.529177 3.001115 14.964448 -0.166875 0.946440 0.276284 0.058594 0.578125 1 0 1.000000 +0 -0.497679 2.822479 15.321721 -0.161992 0.918729 -0.360088 0.058594 0.593750 1 0 1.000000 +holygrail.tga +0 -0.497679 2.822479 15.321721 -0.161992 0.918729 -0.360088 0.058594 0.593750 1 0 1.000000 +0 0.497679 2.822479 15.321721 0.161992 0.918729 -0.360088 0.000000 0.593750 1 0 1.000000 +0 0.529177 3.001115 14.964448 0.166875 0.946440 0.276284 0.000000 0.578125 1 0 1.000000 +holygrail.tga +0 1.523706 2.639137 14.964448 0.480514 0.832301 0.276284 0.941406 0.578125 1 0 1.000000 +0 0.529177 3.001115 14.964448 0.166875 0.946440 0.276284 1.000000 0.578125 1 0 1.000000 +0 0.497679 2.822479 15.321721 0.161992 0.918729 -0.360088 1.000000 0.593750 1 0 1.000000 +holygrail.tga +0 0.497679 2.822479 15.321721 0.161992 0.918729 -0.360088 1.000000 0.593750 1 0 1.000000 +0 1.433010 2.482046 15.321721 0.466445 0.807917 -0.360088 0.941406 0.593750 1 0 1.000000 +0 1.523706 2.639137 14.964448 0.480514 0.832301 0.276284 0.941406 0.578125 1 0 1.000000 +holygrail.tga +0 2.334455 1.958838 14.964448 0.736198 0.617756 0.276284 0.886719 0.578125 1 0 1.000000 +0 1.523706 2.639137 14.964448 0.480514 0.832301 0.276284 0.941406 0.578125 1 0 1.000000 +0 1.433010 2.482046 15.321721 0.466445 0.807917 -0.360088 0.941406 0.593750 1 0 1.000000 +holygrail.tga +0 1.433010 2.482046 15.321721 0.466445 0.807917 -0.360088 0.941406 0.593750 1 0 1.000000 +0 2.195500 1.842241 15.321721 0.714652 0.599658 -0.360088 0.886719 0.593750 1 0 1.000000 +0 2.334455 1.958838 14.964448 0.736198 0.617756 0.276284 0.886719 0.578125 1 0 1.000000 +holygrail.tga +0 2.863631 1.042277 14.964447 0.903104 0.328684 0.276284 0.832031 0.578125 1 0 1.000000 +0 2.334455 1.958838 14.964448 0.736198 0.617756 0.276284 0.886719 0.578125 1 0 1.000000 +0 2.195500 1.842241 15.321721 0.714652 0.599658 -0.360088 0.886719 0.593750 1 0 1.000000 +holygrail.tga +0 2.195500 1.842241 15.321721 0.714652 0.599658 -0.360088 0.886719 0.593750 1 0 1.000000 +0 2.693178 0.980237 15.321720 0.876644 0.319071 -0.360088 0.832031 0.593750 1 0 1.000000 +0 2.863631 1.042277 14.964447 0.903104 0.328684 0.276284 0.832031 0.578125 1 0 1.000000 +holygrail.tga +0 3.138108 0.000003 14.071262 0.987701 0.000000 -0.156285 0.773438 0.539063 1 0 1.000000 +0 2.948858 1.073297 14.071264 0.928129 0.337809 -0.156285 0.832031 0.539063 1 0 1.000000 +0 2.863631 1.042277 14.964447 0.903104 0.328684 0.276284 0.832031 0.578125 1 0 1.000000 +holygrail.tga +0 2.863631 1.042277 14.964447 0.903104 0.328684 0.276284 0.832031 0.578125 1 0 1.000000 +0 3.047412 0.000003 14.964446 0.961058 0.000000 0.276284 0.773438 0.578125 1 0 1.000000 +0 3.138108 0.000003 14.071262 0.987701 0.000000 -0.156285 0.773438 0.539063 1 0 1.000000 +holygrail.tga +0 2.948855 -1.073298 14.071262 0.928129 -0.337809 -0.156285 0.726563 0.539063 1 0 1.000000 +0 3.138108 0.000003 14.071262 0.987701 0.000000 -0.156285 0.773438 0.539063 1 0 1.000000 +0 3.047412 0.000003 14.964446 0.961058 0.000000 0.276284 0.773438 0.578125 1 0 1.000000 +holygrail.tga +0 3.047412 0.000003 14.964446 0.961058 0.000000 0.276284 0.773438 0.578125 1 0 1.000000 +0 2.863629 -1.042278 14.964446 0.903104 -0.328684 0.276284 0.726563 0.578125 1 0 1.000000 +0 2.948855 -1.073298 14.071262 0.928129 -0.337809 -0.156285 0.726563 0.539063 1 0 1.000000 +holygrail.tga +0 2.403928 -2.017137 14.071264 0.756615 -0.634877 -0.156285 0.664063 0.539063 1 0 1.000000 +0 2.948855 -1.073298 14.071262 0.928129 -0.337809 -0.156285 0.726563 0.539063 1 0 1.000000 +0 2.863629 -1.042278 14.964446 0.903104 -0.328684 0.276284 0.726563 0.578125 1 0 1.000000 +holygrail.tga +0 2.863629 -1.042278 14.964446 0.903104 -0.328684 0.276284 0.726563 0.578125 1 0 1.000000 +0 2.334451 -1.958839 14.964447 0.736198 -0.617756 0.276284 0.664063 0.578125 1 0 1.000000 +0 2.403928 -2.017137 14.071264 0.756615 -0.634877 -0.156285 0.664063 0.539063 1 0 1.000000 +holygrail.tga +0 1.569051 -2.717682 14.071264 0.493851 -0.855373 -0.156285 0.613281 0.539063 1 0 1.000000 +0 2.403928 -2.017137 14.071264 0.756615 -0.634877 -0.156285 0.664063 0.539063 1 0 1.000000 +0 2.334451 -1.958839 14.964447 0.736198 -0.617756 0.276284 0.664063 0.578125 1 0 1.000000 +holygrail.tga +0 2.334451 -1.958839 14.964447 0.736198 -0.617756 0.276284 0.664063 0.578125 1 0 1.000000 +0 1.523703 -2.639137 14.964447 0.480514 -0.832301 0.276284 0.613281 0.578125 1 0 1.000000 +0 1.569051 -2.717682 14.071264 0.493851 -0.855373 -0.156285 0.613281 0.539063 1 0 1.000000 +holygrail.tga +0 0.544925 -3.090432 14.071264 0.171484 -0.972686 -0.156285 0.554688 0.539063 1 0 1.000000 +0 1.569051 -2.717682 14.071264 0.493851 -0.855373 -0.156285 0.613281 0.539063 1 0 1.000000 +0 1.523703 -2.639137 14.964447 0.480514 -0.832301 0.276284 0.613281 0.578125 1 0 1.000000 +holygrail.tga +0 1.523703 -2.639137 14.964447 0.480514 -0.832301 0.276284 0.613281 0.578125 1 0 1.000000 +0 0.529176 -3.001114 14.964447 0.166875 -0.946440 0.276284 0.554688 0.578125 1 0 1.000000 +0 0.544925 -3.090432 14.071264 0.171484 -0.972686 -0.156285 0.554688 0.539063 1 0 1.000000 +holygrail.tga +0 -0.544927 -3.090432 14.071264 -0.171484 -0.972686 -0.156285 0.503906 0.539063 1 0 1.000000 +0 0.544925 -3.090432 14.071264 0.171484 -0.972686 -0.156285 0.554688 0.539063 1 0 1.000000 +0 0.529176 -3.001114 14.964447 0.166875 -0.946440 0.276284 0.554688 0.578125 1 0 1.000000 +holygrail.tga +0 0.529176 -3.001114 14.964447 0.166875 -0.946440 0.276284 0.554688 0.578125 1 0 1.000000 +0 -0.529177 -3.001114 14.964447 -0.166875 -0.946440 0.276284 0.503906 0.578125 1 0 1.000000 +0 -0.544927 -3.090432 14.071264 -0.171484 -0.972686 -0.156285 0.503906 0.539063 1 0 1.000000 +holygrail.tga +0 -1.569054 -2.717680 14.071264 -0.493851 -0.855373 -0.156285 0.449219 0.539063 1 0 1.000000 +0 -0.544927 -3.090432 14.071264 -0.171484 -0.972686 -0.156285 0.503906 0.539063 1 0 1.000000 +0 -0.529177 -3.001114 14.964447 -0.166875 -0.946440 0.276284 0.503906 0.578125 1 0 1.000000 +holygrail.tga +0 -0.529177 -3.001114 14.964447 -0.166875 -0.946440 0.276284 0.503906 0.578125 1 0 1.000000 +0 -1.523706 -2.639135 14.964447 -0.480514 -0.832301 0.276284 0.449219 0.578125 1 0 1.000000 +0 -1.569054 -2.717680 14.071264 -0.493851 -0.855373 -0.156285 0.449219 0.539063 1 0 1.000000 +holygrail.tga +0 -2.403931 -2.017134 14.071264 -0.756615 -0.634877 -0.156285 0.394531 0.539063 1 0 1.000000 +0 -1.569054 -2.717680 14.071264 -0.493851 -0.855373 -0.156285 0.449219 0.539063 1 0 1.000000 +0 -1.523706 -2.639135 14.964447 -0.480514 -0.832301 0.276284 0.449219 0.578125 1 0 1.000000 +holygrail.tga +0 -1.523706 -2.639135 14.964447 -0.480514 -0.832301 0.276284 0.449219 0.578125 1 0 1.000000 +0 -2.334454 -1.958836 14.964447 -0.736198 -0.617756 0.276284 0.394531 0.578125 1 0 1.000000 +0 -2.403931 -2.017134 14.071264 -0.756615 -0.634877 -0.156285 0.394531 0.539063 1 0 1.000000 +holygrail.tga +0 -2.948857 -1.073294 14.071262 -0.928129 -0.337809 -0.156285 0.339844 0.539063 1 0 1.000000 +0 -2.403931 -2.017134 14.071264 -0.756615 -0.634877 -0.156285 0.394531 0.539063 1 0 1.000000 +0 -2.334454 -1.958836 14.964447 -0.736198 -0.617756 0.276284 0.394531 0.578125 1 0 1.000000 +holygrail.tga +0 -2.334454 -1.958836 14.964447 -0.736198 -0.617756 0.276284 0.394531 0.578125 1 0 1.000000 +0 -2.863631 -1.042275 14.964446 -0.903104 -0.328684 0.276284 0.339844 0.578125 1 0 1.000000 +0 -2.948857 -1.073294 14.071262 -0.928129 -0.337809 -0.156285 0.339844 0.539063 1 0 1.000000 +holygrail.tga +0 -3.138107 0.000001 14.071262 -0.987701 0.000000 -0.156285 0.289063 0.539063 1 0 1.000000 +0 -2.948857 -1.073294 14.071262 -0.928129 -0.337809 -0.156285 0.339844 0.539063 1 0 1.000000 +0 -2.863631 -1.042275 14.964446 -0.903104 -0.328684 0.276284 0.339844 0.578125 1 0 1.000000 +holygrail.tga +0 -2.863631 -1.042275 14.964446 -0.903104 -0.328684 0.276284 0.339844 0.578125 1 0 1.000000 +0 -3.047411 0.000000 14.964446 -0.961058 0.000000 0.276284 0.289063 0.578125 1 0 1.000000 +0 -3.138107 0.000001 14.071262 -0.987701 0.000000 -0.156285 0.289063 0.539063 1 0 1.000000 +holygrail.tga +0 -2.948857 1.073296 14.071264 -0.928129 0.337809 -0.156285 0.226563 0.539063 1 0 1.000000 +0 -3.138107 0.000001 14.071262 -0.987701 0.000000 -0.156285 0.289063 0.539063 1 0 1.000000 +0 -3.047411 0.000000 14.964446 -0.961058 0.000000 0.276284 0.289063 0.578125 1 0 1.000000 +holygrail.tga +0 -3.047411 0.000000 14.964446 -0.961058 0.000000 0.276284 0.289063 0.578125 1 0 1.000000 +0 -2.863631 1.042276 14.964447 -0.903104 0.328684 0.276284 0.226563 0.578125 1 0 1.000000 +0 -2.948857 1.073296 14.071264 -0.928129 0.337809 -0.156285 0.226563 0.539063 1 0 1.000000 +holygrail.tga +0 -2.403929 2.017137 14.071265 -0.756615 0.634877 -0.156285 0.171875 0.539063 1 0 1.000000 +0 -2.948857 1.073296 14.071264 -0.928129 0.337809 -0.156285 0.226563 0.539063 1 0 1.000000 +0 -2.863631 1.042276 14.964447 -0.903104 0.328684 0.276284 0.226563 0.578125 1 0 1.000000 +holygrail.tga +0 -2.863631 1.042276 14.964447 -0.903104 0.328684 0.276284 0.226563 0.578125 1 0 1.000000 +0 -2.334451 1.958838 14.964448 -0.736198 0.617756 0.276284 0.171875 0.578125 1 0 1.000000 +0 -2.403929 2.017137 14.071265 -0.756615 0.634877 -0.156285 0.171875 0.539063 1 0 1.000000 +holygrail.tga +0 -1.569052 2.717682 14.071264 -0.493851 0.855373 -0.156285 0.117188 0.539063 1 0 1.000000 +0 -2.403929 2.017137 14.071265 -0.756615 0.634877 -0.156285 0.171875 0.539063 1 0 1.000000 +0 -2.334451 1.958838 14.964448 -0.736198 0.617756 0.276284 0.171875 0.578125 1 0 1.000000 +holygrail.tga +0 -0.544927 3.090433 14.071264 -0.171514 0.972686 -0.156285 0.058594 0.539063 1 0 1.000000 +0 -1.569052 2.717682 14.071264 -0.493851 0.855373 -0.156285 0.117188 0.539063 1 0 1.000000 +0 -1.523703 2.639137 14.964448 -0.480514 0.832301 0.276284 0.117188 0.578125 1 0 1.000000 +holygrail.tga +0 -1.523703 2.639137 14.964448 -0.480514 0.832301 0.276284 0.117188 0.578125 1 0 1.000000 +0 -0.529177 3.001115 14.964448 -0.166875 0.946440 0.276284 0.058594 0.578125 1 0 1.000000 +0 -0.544927 3.090433 14.071264 -0.171514 0.972686 -0.156285 0.058594 0.539063 1 0 1.000000 +holygrail.tga +0 0.544927 3.090433 14.071264 0.171484 0.972686 -0.156285 0.000000 0.539063 1 0 1.000000 +0 -0.544927 3.090433 14.071264 -0.171514 0.972686 -0.156285 0.058594 0.539063 1 0 1.000000 +0 -0.529177 3.001115 14.964448 -0.166875 0.946440 0.276284 0.058594 0.578125 1 0 1.000000 +holygrail.tga +0 -0.529177 3.001115 14.964448 -0.166875 0.946440 0.276284 0.058594 0.578125 1 0 1.000000 +0 0.529177 3.001115 14.964448 0.166875 0.946440 0.276284 0.000000 0.578125 1 0 1.000000 +0 0.544927 3.090433 14.071264 0.171484 0.972686 -0.156285 0.000000 0.539063 1 0 1.000000 +holygrail.tga +0 1.569054 2.717682 14.071264 0.493851 0.855373 -0.156285 0.941406 0.539063 1 0 1.000000 +0 0.544927 3.090433 14.071264 0.171484 0.972686 -0.156285 1.000000 0.539063 1 0 1.000000 +0 0.529177 3.001115 14.964448 0.166875 0.946440 0.276284 1.000000 0.578125 1 0 1.000000 +holygrail.tga +0 0.529177 3.001115 14.964448 0.166875 0.946440 0.276284 1.000000 0.578125 1 0 1.000000 +0 1.523706 2.639137 14.964448 0.480514 0.832301 0.276284 0.941406 0.578125 1 0 1.000000 +0 1.569054 2.717682 14.071264 0.493851 0.855373 -0.156285 0.941406 0.539063 1 0 1.000000 +holygrail.tga +0 2.403932 2.017136 14.071265 0.756615 0.634877 -0.156285 0.886719 0.539063 1 0 1.000000 +0 1.569054 2.717682 14.071264 0.493851 0.855373 -0.156285 0.941406 0.539063 1 0 1.000000 +0 1.523706 2.639137 14.964448 0.480514 0.832301 0.276284 0.941406 0.578125 1 0 1.000000 +holygrail.tga +0 1.523706 2.639137 14.964448 0.480514 0.832301 0.276284 0.941406 0.578125 1 0 1.000000 +0 2.334455 1.958838 14.964448 0.736198 0.617756 0.276284 0.886719 0.578125 1 0 1.000000 +0 2.403932 2.017136 14.071265 0.756615 0.634877 -0.156285 0.886719 0.539063 1 0 1.000000 +holygrail.tga +0 2.948858 1.073297 14.071264 0.928129 0.337809 -0.156285 0.832031 0.539063 1 0 1.000000 +0 2.403932 2.017136 14.071265 0.756615 0.634877 -0.156285 0.886719 0.539063 1 0 1.000000 +0 2.334455 1.958838 14.964448 0.736198 0.617756 0.276284 0.886719 0.578125 1 0 1.000000 +holygrail.tga +0 2.334455 1.958838 14.964448 0.736198 0.617756 0.276284 0.886719 0.578125 1 0 1.000000 +0 2.863631 1.042277 14.964447 0.903104 0.328684 0.276284 0.832031 0.578125 1 0 1.000000 +0 2.948858 1.073297 14.071264 0.928129 0.337809 -0.156285 0.832031 0.539063 1 0 1.000000 +holygrail.tga +0 2.775323 0.000004 13.267398 0.840388 0.000000 -0.541978 0.773438 0.507813 1 0 1.000000 +0 2.607951 0.949218 13.267399 0.789697 0.287423 -0.541978 0.832031 0.507813 1 0 1.000000 +0 2.948858 1.073297 14.071264 0.928129 0.337809 -0.156285 0.832031 0.539063 1 0 1.000000 +holygrail.tga +0 2.948858 1.073297 14.071264 0.928129 0.337809 -0.156285 0.832031 0.539063 1 0 1.000000 +0 3.138108 0.000003 14.071262 0.987701 0.000000 -0.156285 0.773438 0.539063 1 0 1.000000 +0 2.775323 0.000004 13.267398 0.840388 0.000000 -0.541978 0.773438 0.507813 1 0 1.000000 +holygrail.tga +0 2.607949 -0.949218 13.267398 0.789697 -0.287423 -0.541978 0.726563 0.507813 1 0 1.000000 +0 2.775323 0.000004 13.267398 0.840388 0.000000 -0.541978 0.773438 0.507813 1 0 1.000000 +0 3.138108 0.000003 14.071262 0.987701 0.000000 -0.156285 0.773438 0.539063 1 0 1.000000 +holygrail.tga +0 3.138108 0.000003 14.071262 0.987701 0.000000 -0.156285 0.773438 0.539063 1 0 1.000000 +0 2.948855 -1.073298 14.071262 0.928129 -0.337809 -0.156285 0.726563 0.539063 1 0 1.000000 +0 2.607949 -0.949218 13.267398 0.789697 -0.287423 -0.541978 0.726563 0.507813 1 0 1.000000 +holygrail.tga +0 2.126019 -1.783943 13.267399 0.643757 -0.540178 -0.541978 0.664063 0.507813 1 0 1.000000 +0 2.607949 -0.949218 13.267398 0.789697 -0.287423 -0.541978 0.726563 0.507813 1 0 1.000000 +0 2.948855 -1.073298 14.071262 0.928129 -0.337809 -0.156285 0.726563 0.539063 1 0 1.000000 +holygrail.tga +0 2.948855 -1.073298 14.071262 0.928129 -0.337809 -0.156285 0.726563 0.539063 1 0 1.000000 +0 2.403928 -2.017137 14.071264 0.756615 -0.634877 -0.156285 0.664063 0.539063 1 0 1.000000 +0 2.126019 -1.783943 13.267399 0.643757 -0.540178 -0.541978 0.664063 0.507813 1 0 1.000000 +holygrail.tga +0 1.387658 -2.403501 13.267399 0.420179 -0.727775 -0.541978 0.613281 0.507813 1 0 1.000000 +0 2.126019 -1.783943 13.267399 0.643757 -0.540178 -0.541978 0.664063 0.507813 1 0 1.000000 +0 2.403928 -2.017137 14.071264 0.756615 -0.634877 -0.156285 0.664063 0.539063 1 0 1.000000 +holygrail.tga +0 2.403928 -2.017137 14.071264 0.756615 -0.634877 -0.156285 0.664063 0.539063 1 0 1.000000 +0 1.569051 -2.717682 14.071264 0.493851 -0.855373 -0.156285 0.613281 0.539063 1 0 1.000000 +0 1.387658 -2.403501 13.267399 0.420179 -0.727775 -0.541978 0.613281 0.507813 1 0 1.000000 +holygrail.tga +0 0.481928 -2.733159 13.267399 0.145909 -0.827601 -0.541978 0.554688 0.507813 1 0 1.000000 +0 1.387658 -2.403501 13.267399 0.420179 -0.727775 -0.541978 0.613281 0.507813 1 0 1.000000 +0 1.569051 -2.717682 14.071264 0.493851 -0.855373 -0.156285 0.613281 0.539063 1 0 1.000000 +holygrail.tga +0 1.569051 -2.717682 14.071264 0.493851 -0.855373 -0.156285 0.613281 0.539063 1 0 1.000000 +0 0.544925 -3.090432 14.071264 0.171484 -0.972686 -0.156285 0.554688 0.539063 1 0 1.000000 +0 0.481928 -2.733159 13.267399 0.145909 -0.827601 -0.541978 0.554688 0.507813 1 0 1.000000 +holygrail.tga +0 -0.481930 -2.733159 13.267399 -0.145909 -0.827601 -0.541978 0.503906 0.507813 1 0 1.000000 +0 0.481928 -2.733159 13.267399 0.145909 -0.827601 -0.541978 0.554688 0.507813 1 0 1.000000 +0 0.544925 -3.090432 14.071264 0.171484 -0.972686 -0.156285 0.554688 0.539063 1 0 1.000000 +holygrail.tga +0 0.544925 -3.090432 14.071264 0.171484 -0.972686 -0.156285 0.554688 0.539063 1 0 1.000000 +0 -0.544927 -3.090432 14.071264 -0.171484 -0.972686 -0.156285 0.503906 0.539063 1 0 1.000000 +0 -0.481930 -2.733159 13.267399 -0.145909 -0.827601 -0.541978 0.503906 0.507813 1 0 1.000000 +holygrail.tga +0 -1.387662 -2.403499 13.267399 -0.420179 -0.727775 -0.541978 0.449219 0.507813 1 0 1.000000 +0 -0.481930 -2.733159 13.267399 -0.145909 -0.827601 -0.541978 0.503906 0.507813 1 0 1.000000 +0 -0.544927 -3.090432 14.071264 -0.171484 -0.972686 -0.156285 0.503906 0.539063 1 0 1.000000 +holygrail.tga +0 -0.544927 -3.090432 14.071264 -0.171484 -0.972686 -0.156285 0.503906 0.539063 1 0 1.000000 +0 -1.569054 -2.717680 14.071264 -0.493851 -0.855373 -0.156285 0.449219 0.539063 1 0 1.000000 +0 -1.387662 -2.403499 13.267399 -0.420179 -0.727775 -0.541978 0.449219 0.507813 1 0 1.000000 +holygrail.tga +0 -2.126022 -1.783940 13.267399 -0.643757 -0.540178 -0.541978 0.394531 0.507813 1 0 1.000000 +0 -1.387662 -2.403499 13.267399 -0.420179 -0.727775 -0.541978 0.449219 0.507813 1 0 1.000000 +0 -1.569054 -2.717680 14.071264 -0.493851 -0.855373 -0.156285 0.449219 0.539063 1 0 1.000000 +holygrail.tga +0 -1.569054 -2.717680 14.071264 -0.493851 -0.855373 -0.156285 0.449219 0.539063 1 0 1.000000 +0 -2.403931 -2.017134 14.071264 -0.756615 -0.634877 -0.156285 0.394531 0.539063 1 0 1.000000 +0 -2.126022 -1.783940 13.267399 -0.643757 -0.540178 -0.541978 0.394531 0.507813 1 0 1.000000 +holygrail.tga +0 -2.607951 -0.949215 13.267398 -0.789697 -0.287423 -0.541978 0.339844 0.507813 1 0 1.000000 +0 -2.126022 -1.783940 13.267399 -0.643757 -0.540178 -0.541978 0.394531 0.507813 1 0 1.000000 +0 -2.403931 -2.017134 14.071264 -0.756615 -0.634877 -0.156285 0.394531 0.539063 1 0 1.000000 +holygrail.tga +0 -2.403931 -2.017134 14.071264 -0.756615 -0.634877 -0.156285 0.394531 0.539063 1 0 1.000000 +0 -2.948857 -1.073294 14.071262 -0.928129 -0.337809 -0.156285 0.339844 0.539063 1 0 1.000000 +0 -2.607951 -0.949215 13.267398 -0.789697 -0.287423 -0.541978 0.339844 0.507813 1 0 1.000000 +holygrail.tga +0 -2.775322 0.000001 13.267398 -0.840388 0.000000 -0.541978 0.289063 0.507813 1 0 1.000000 +0 -2.607951 -0.949215 13.267398 -0.789697 -0.287423 -0.541978 0.339844 0.507813 1 0 1.000000 +0 -2.948857 -1.073294 14.071262 -0.928129 -0.337809 -0.156285 0.339844 0.539063 1 0 1.000000 +holygrail.tga +0 -2.948857 -1.073294 14.071262 -0.928129 -0.337809 -0.156285 0.339844 0.539063 1 0 1.000000 +0 -3.138107 0.000001 14.071262 -0.987701 0.000000 -0.156285 0.289063 0.539063 1 0 1.000000 +0 -2.775322 0.000001 13.267398 -0.840388 0.000000 -0.541978 0.289063 0.507813 1 0 1.000000 +holygrail.tga +0 -2.607951 0.949216 13.267399 -0.789697 0.287423 -0.541978 0.226563 0.507813 1 0 1.000000 +0 -2.775322 0.000001 13.267398 -0.840388 0.000000 -0.541978 0.289063 0.507813 1 0 1.000000 +0 -3.138107 0.000001 14.071262 -0.987701 0.000000 -0.156285 0.289063 0.539063 1 0 1.000000 +holygrail.tga +0 -3.138107 0.000001 14.071262 -0.987701 0.000000 -0.156285 0.289063 0.539063 1 0 1.000000 +0 -2.948857 1.073296 14.071264 -0.928129 0.337809 -0.156285 0.226563 0.539063 1 0 1.000000 +0 -2.607951 0.949216 13.267399 -0.789697 0.287423 -0.541978 0.226563 0.507813 1 0 1.000000 +holygrail.tga +0 -2.126019 1.783943 13.267401 -0.643757 0.540178 -0.541978 0.171875 0.507813 1 0 1.000000 +0 -2.607951 0.949216 13.267399 -0.789697 0.287423 -0.541978 0.226563 0.507813 1 0 1.000000 +0 -2.948857 1.073296 14.071264 -0.928129 0.337809 -0.156285 0.226563 0.539063 1 0 1.000000 +holygrail.tga +0 -2.948857 1.073296 14.071264 -0.928129 0.337809 -0.156285 0.226563 0.539063 1 0 1.000000 +0 -2.403929 2.017137 14.071265 -0.756615 0.634877 -0.156285 0.171875 0.539063 1 0 1.000000 +0 -2.126019 1.783943 13.267401 -0.643757 0.540178 -0.541978 0.171875 0.507813 1 0 1.000000 +holygrail.tga +0 -1.387659 2.403502 13.267400 -0.420179 0.727775 -0.541978 0.117188 0.507813 1 0 1.000000 +0 -2.126019 1.783943 13.267401 -0.643757 0.540178 -0.541978 0.171875 0.507813 1 0 1.000000 +0 -2.403929 2.017137 14.071265 -0.756615 0.634877 -0.156285 0.171875 0.539063 1 0 1.000000 +holygrail.tga +0 -2.403929 2.017137 14.071265 -0.756615 0.634877 -0.156285 0.171875 0.539063 1 0 1.000000 +0 -1.569052 2.717682 14.071264 -0.493851 0.855373 -0.156285 0.117188 0.539063 1 0 1.000000 +0 -1.387659 2.403502 13.267400 -0.420179 0.727775 -0.541978 0.117188 0.507813 1 0 1.000000 +holygrail.tga +0 -0.481930 2.733161 13.267400 -0.145909 0.827601 -0.541978 0.058594 0.507813 1 0 1.000000 +0 -1.387659 2.403502 13.267400 -0.420179 0.727775 -0.541978 0.117188 0.507813 1 0 1.000000 +0 -1.569052 2.717682 14.071264 -0.493851 0.855373 -0.156285 0.117188 0.539063 1 0 1.000000 +holygrail.tga +0 -1.569052 2.717682 14.071264 -0.493851 0.855373 -0.156285 0.117188 0.539063 1 0 1.000000 +0 -0.544927 3.090433 14.071264 -0.171514 0.972686 -0.156285 0.058594 0.539063 1 0 1.000000 +0 -0.481930 2.733161 13.267400 -0.145909 0.827601 -0.541978 0.058594 0.507813 1 0 1.000000 +holygrail.tga +0 0.481930 2.733161 13.267400 0.145909 0.827601 -0.541978 0.000000 0.507813 1 0 1.000000 +0 -0.481930 2.733161 13.267400 -0.145909 0.827601 -0.541978 0.058594 0.507813 1 0 1.000000 +0 -0.544927 3.090433 14.071264 -0.171514 0.972686 -0.156285 0.058594 0.539063 1 0 1.000000 +holygrail.tga +0 -0.544927 3.090433 14.071264 -0.171514 0.972686 -0.156285 0.058594 0.539063 1 0 1.000000 +0 0.544927 3.090433 14.071264 0.171484 0.972686 -0.156285 0.000000 0.539063 1 0 1.000000 +0 0.481930 2.733161 13.267400 0.145909 0.827601 -0.541978 0.000000 0.507813 1 0 1.000000 +holygrail.tga +0 1.387662 2.403501 13.267400 0.420179 0.727775 -0.541978 0.941406 0.507813 1 0 1.000000 +0 0.481930 2.733161 13.267400 0.145909 0.827601 -0.541978 1.000000 0.507813 1 0 1.000000 +0 0.544927 3.090433 14.071264 0.171484 0.972686 -0.156285 1.000000 0.539063 1 0 1.000000 +holygrail.tga +0 2.126023 1.783943 13.267401 0.643757 0.540178 -0.541978 0.886719 0.507813 1 0 1.000000 +0 1.387662 2.403501 13.267400 0.420179 0.727775 -0.541978 0.941406 0.507813 1 0 1.000000 +0 1.569054 2.717682 14.071264 0.493851 0.855373 -0.156285 0.941406 0.539063 1 0 1.000000 +holygrail.tga +0 1.569054 2.717682 14.071264 0.493851 0.855373 -0.156285 0.941406 0.539063 1 0 1.000000 +0 2.403932 2.017136 14.071265 0.756615 0.634877 -0.156285 0.886719 0.539063 1 0 1.000000 +0 2.126023 1.783943 13.267401 0.643757 0.540178 -0.541978 0.886719 0.507813 1 0 1.000000 +holygrail.tga +0 2.607951 0.949218 13.267399 0.789697 0.287423 -0.541978 0.832031 0.507813 1 0 1.000000 +0 2.126023 1.783943 13.267401 0.643757 0.540178 -0.541978 0.886719 0.507813 1 0 1.000000 +0 2.403932 2.017136 14.071265 0.756615 0.634877 -0.156285 0.886719 0.539063 1 0 1.000000 +holygrail.tga +0 2.403932 2.017136 14.071265 0.756615 0.634877 -0.156285 0.886719 0.539063 1 0 1.000000 +0 2.948858 1.073297 14.071264 0.928129 0.337809 -0.156285 0.832031 0.539063 1 0 1.000000 +0 2.607951 0.949218 13.267399 0.789697 0.287423 -0.541978 0.832031 0.507813 1 0 1.000000 +holygrail.tga +0 1.959057 0.000004 12.374216 0.918821 0.000000 -0.394635 0.773438 0.468750 1 0 1.000000 +0 1.840913 0.670039 12.374216 0.863399 0.314249 -0.394635 0.832031 0.468750 1 0 1.000000 +0 2.607951 0.949218 13.267399 0.789697 0.287423 -0.541978 0.832031 0.507813 1 0 1.000000 +holygrail.tga +0 2.607951 0.949218 13.267399 0.789697 0.287423 -0.541978 0.832031 0.507813 1 0 1.000000 +0 2.775323 0.000004 13.267398 0.840388 0.000000 -0.541978 0.773438 0.507813 1 0 1.000000 +0 1.959057 0.000004 12.374216 0.918821 0.000000 -0.394635 0.773438 0.468750 1 0 1.000000 +holygrail.tga +0 1.840911 -0.670037 12.374216 0.863399 -0.314249 -0.394635 0.726563 0.468750 1 0 1.000000 +0 1.959057 0.000004 12.374216 0.918821 0.000000 -0.394635 0.773438 0.468750 1 0 1.000000 +0 2.775323 0.000004 13.267398 0.840388 0.000000 -0.541978 0.773438 0.507813 1 0 1.000000 +holygrail.tga +0 2.775323 0.000004 13.267398 0.840388 0.000000 -0.541978 0.773438 0.507813 1 0 1.000000 +0 2.607949 -0.949218 13.267398 0.789697 -0.287423 -0.541978 0.726563 0.507813 1 0 1.000000 +0 1.840911 -0.670037 12.374216 0.863399 -0.314249 -0.394635 0.726563 0.468750 1 0 1.000000 +holygrail.tga +0 1.500723 -1.259257 12.374216 0.703848 -0.590594 -0.394635 0.664063 0.468750 1 0 1.000000 +0 1.840911 -0.670037 12.374216 0.863399 -0.314249 -0.394635 0.726563 0.468750 1 0 1.000000 +0 2.607949 -0.949218 13.267398 0.789697 -0.287423 -0.541978 0.726563 0.507813 1 0 1.000000 +holygrail.tga +0 2.607949 -0.949218 13.267398 0.789697 -0.287423 -0.541978 0.726563 0.507813 1 0 1.000000 +0 2.126019 -1.783943 13.267399 0.643757 -0.540178 -0.541978 0.664063 0.507813 1 0 1.000000 +0 1.500723 -1.259257 12.374216 0.703848 -0.590594 -0.394635 0.664063 0.468750 1 0 1.000000 +holygrail.tga +0 0.979526 -1.696594 12.374216 0.459395 -0.795709 -0.394635 0.613281 0.468750 1 0 1.000000 +0 1.500723 -1.259257 12.374216 0.703848 -0.590594 -0.394635 0.664063 0.468750 1 0 1.000000 +0 2.126019 -1.783943 13.267399 0.643757 -0.540178 -0.541978 0.664063 0.507813 1 0 1.000000 +holygrail.tga +0 2.126019 -1.783943 13.267399 0.643757 -0.540178 -0.541978 0.664063 0.507813 1 0 1.000000 +0 1.387658 -2.403501 13.267399 0.420179 -0.727775 -0.541978 0.613281 0.507813 1 0 1.000000 +0 0.979526 -1.696594 12.374216 0.459395 -0.795709 -0.394635 0.613281 0.468750 1 0 1.000000 +holygrail.tga +0 0.340186 -1.929294 12.374216 0.159551 -0.904874 -0.394635 0.554688 0.468750 1 0 1.000000 +0 0.979526 -1.696594 12.374216 0.459395 -0.795709 -0.394635 0.613281 0.468750 1 0 1.000000 +0 1.387658 -2.403501 13.267399 0.420179 -0.727775 -0.541978 0.613281 0.507813 1 0 1.000000 +holygrail.tga +0 1.387658 -2.403501 13.267399 0.420179 -0.727775 -0.541978 0.613281 0.507813 1 0 1.000000 +0 0.481928 -2.733159 13.267399 0.145909 -0.827601 -0.541978 0.554688 0.507813 1 0 1.000000 +0 0.340186 -1.929294 12.374216 0.159551 -0.904874 -0.394635 0.554688 0.468750 1 0 1.000000 +holygrail.tga +0 -0.340186 -1.929294 12.374216 -0.159551 -0.904874 -0.394635 0.503906 0.468750 1 0 1.000000 +0 0.340186 -1.929294 12.374216 0.159551 -0.904874 -0.394635 0.554688 0.468750 1 0 1.000000 +0 0.481928 -2.733159 13.267399 0.145909 -0.827601 -0.541978 0.554688 0.507813 1 0 1.000000 +holygrail.tga +0 0.481928 -2.733159 13.267399 0.145909 -0.827601 -0.541978 0.554688 0.507813 1 0 1.000000 +0 -0.481930 -2.733159 13.267399 -0.145909 -0.827601 -0.541978 0.503906 0.507813 1 0 1.000000 +0 -0.340186 -1.929294 12.374216 -0.159551 -0.904874 -0.394635 0.503906 0.468750 1 0 1.000000 +holygrail.tga +0 -0.979529 -1.696592 12.374216 -0.459395 -0.795709 -0.394635 0.449219 0.468750 1 0 1.000000 +0 -0.340186 -1.929294 12.374216 -0.159551 -0.904874 -0.394635 0.503906 0.468750 1 0 1.000000 +0 -0.481930 -2.733159 13.267399 -0.145909 -0.827601 -0.541978 0.503906 0.507813 1 0 1.000000 +holygrail.tga +0 -0.481930 -2.733159 13.267399 -0.145909 -0.827601 -0.541978 0.503906 0.507813 1 0 1.000000 +0 -1.387662 -2.403499 13.267399 -0.420179 -0.727775 -0.541978 0.449219 0.507813 1 0 1.000000 +0 -0.979529 -1.696592 12.374216 -0.459395 -0.795709 -0.394635 0.449219 0.468750 1 0 1.000000 +holygrail.tga +0 -1.500727 -1.259255 12.374216 -0.703848 -0.590594 -0.394635 0.394531 0.468750 1 0 1.000000 +0 -0.979529 -1.696592 12.374216 -0.459395 -0.795709 -0.394635 0.449219 0.468750 1 0 1.000000 +0 -1.387662 -2.403499 13.267399 -0.420179 -0.727775 -0.541978 0.449219 0.507813 1 0 1.000000 +holygrail.tga +0 -1.387662 -2.403499 13.267399 -0.420179 -0.727775 -0.541978 0.449219 0.507813 1 0 1.000000 +0 -2.126022 -1.783940 13.267399 -0.643757 -0.540178 -0.541978 0.394531 0.507813 1 0 1.000000 +0 -1.500727 -1.259255 12.374216 -0.703848 -0.590594 -0.394635 0.394531 0.468750 1 0 1.000000 +holygrail.tga +0 -1.840912 -0.670036 12.374216 -0.863399 -0.314249 -0.394635 0.339844 0.468750 1 0 1.000000 +0 -1.500727 -1.259255 12.374216 -0.703848 -0.590594 -0.394635 0.394531 0.468750 1 0 1.000000 +0 -2.126022 -1.783940 13.267399 -0.643757 -0.540178 -0.541978 0.394531 0.507813 1 0 1.000000 +holygrail.tga +0 -2.126022 -1.783940 13.267399 -0.643757 -0.540178 -0.541978 0.394531 0.507813 1 0 1.000000 +0 -2.607951 -0.949215 13.267398 -0.789697 -0.287423 -0.541978 0.339844 0.507813 1 0 1.000000 +0 -1.840912 -0.670036 12.374216 -0.863399 -0.314249 -0.394635 0.339844 0.468750 1 0 1.000000 +holygrail.tga +0 -1.959057 0.000001 12.374216 -0.918821 0.000000 -0.394635 0.289063 0.468750 1 0 1.000000 +0 -1.840912 -0.670036 12.374216 -0.863399 -0.314249 -0.394635 0.339844 0.468750 1 0 1.000000 +0 -2.607951 -0.949215 13.267398 -0.789697 -0.287423 -0.541978 0.339844 0.507813 1 0 1.000000 +holygrail.tga +0 -2.607951 -0.949215 13.267398 -0.789697 -0.287423 -0.541978 0.339844 0.507813 1 0 1.000000 +0 -2.775322 0.000001 13.267398 -0.840388 0.000000 -0.541978 0.289063 0.507813 1 0 1.000000 +0 -1.959057 0.000001 12.374216 -0.918821 0.000000 -0.394635 0.289063 0.468750 1 0 1.000000 +holygrail.tga +0 -1.840912 0.670037 12.374216 -0.863399 0.314249 -0.394635 0.226563 0.468750 1 0 1.000000 +0 -1.959057 0.000001 12.374216 -0.918821 0.000000 -0.394635 0.289063 0.468750 1 0 1.000000 +0 -2.775322 0.000001 13.267398 -0.840388 0.000000 -0.541978 0.289063 0.507813 1 0 1.000000 +holygrail.tga +0 -2.775322 0.000001 13.267398 -0.840388 0.000000 -0.541978 0.289063 0.507813 1 0 1.000000 +0 -2.607951 0.949216 13.267399 -0.789697 0.287423 -0.541978 0.226563 0.507813 1 0 1.000000 +0 -1.840912 0.670037 12.374216 -0.863399 0.314249 -0.394635 0.226563 0.468750 1 0 1.000000 +holygrail.tga +0 -1.500724 1.259258 12.374218 -0.703848 0.590594 -0.394635 0.171875 0.468750 1 0 1.000000 +0 -1.840912 0.670037 12.374216 -0.863399 0.314249 -0.394635 0.226563 0.468750 1 0 1.000000 +0 -2.607951 0.949216 13.267399 -0.789697 0.287423 -0.541978 0.226563 0.507813 1 0 1.000000 +holygrail.tga +0 -2.607951 0.949216 13.267399 -0.789697 0.287423 -0.541978 0.226563 0.507813 1 0 1.000000 +0 -2.126019 1.783943 13.267401 -0.643757 0.540178 -0.541978 0.171875 0.507813 1 0 1.000000 +0 -1.500724 1.259258 12.374218 -0.703848 0.590594 -0.394635 0.171875 0.468750 1 0 1.000000 +holygrail.tga +0 -0.979526 1.696596 12.374216 -0.459395 0.795709 -0.394635 0.117188 0.468750 1 0 1.000000 +0 -1.500724 1.259258 12.374218 -0.703848 0.590594 -0.394635 0.171875 0.468750 1 0 1.000000 +0 -2.126019 1.783943 13.267401 -0.643757 0.540178 -0.541978 0.171875 0.507813 1 0 1.000000 +holygrail.tga +0 -2.126019 1.783943 13.267401 -0.643757 0.540178 -0.541978 0.171875 0.507813 1 0 1.000000 +0 -1.387659 2.403502 13.267400 -0.420179 0.727775 -0.541978 0.117188 0.507813 1 0 1.000000 +0 -0.979526 1.696596 12.374216 -0.459395 0.795709 -0.394635 0.117188 0.468750 1 0 1.000000 +holygrail.tga +0 -0.340187 1.929296 12.374216 -0.159551 0.904874 -0.394635 0.058594 0.468750 1 0 1.000000 +0 -0.979526 1.696596 12.374216 -0.459395 0.795709 -0.394635 0.117188 0.468750 1 0 1.000000 +0 -1.387659 2.403502 13.267400 -0.420179 0.727775 -0.541978 0.117188 0.507813 1 0 1.000000 +holygrail.tga +0 -1.387659 2.403502 13.267400 -0.420179 0.727775 -0.541978 0.117188 0.507813 1 0 1.000000 +0 -0.481930 2.733161 13.267400 -0.145909 0.827601 -0.541978 0.058594 0.507813 1 0 1.000000 +0 -0.340187 1.929296 12.374216 -0.159551 0.904874 -0.394635 0.058594 0.468750 1 0 1.000000 +holygrail.tga +0 0.340187 1.929296 12.374216 0.159551 0.904874 -0.394635 0.000000 0.468750 1 0 1.000000 +0 -0.340187 1.929296 12.374216 -0.159551 0.904874 -0.394635 0.058594 0.468750 1 0 1.000000 +0 -0.481930 2.733161 13.267400 -0.145909 0.827601 -0.541978 0.058594 0.507813 1 0 1.000000 +holygrail.tga +0 -0.481930 2.733161 13.267400 -0.145909 0.827601 -0.541978 0.058594 0.507813 1 0 1.000000 +0 0.481930 2.733161 13.267400 0.145909 0.827601 -0.541978 0.000000 0.507813 1 0 1.000000 +0 0.340187 1.929296 12.374216 0.159551 0.904874 -0.394635 0.000000 0.468750 1 0 1.000000 +holygrail.tga +0 0.979529 1.696595 12.374216 0.459395 0.795709 -0.394635 0.941406 0.468750 1 0 1.000000 +0 0.340187 1.929296 12.374216 0.159551 0.904874 -0.394635 1.000000 0.468750 1 0 1.000000 +0 0.481930 2.733161 13.267400 0.145909 0.827601 -0.541978 1.000000 0.507813 1 0 1.000000 +holygrail.tga +0 0.481930 2.733161 13.267400 0.145909 0.827601 -0.541978 1.000000 0.507813 1 0 1.000000 +0 1.387662 2.403501 13.267400 0.420179 0.727775 -0.541978 0.941406 0.507813 1 0 1.000000 +0 0.979529 1.696595 12.374216 0.459395 0.795709 -0.394635 0.941406 0.468750 1 0 1.000000 +holygrail.tga +0 1.500727 1.259258 12.374218 0.703848 0.590594 -0.394635 0.886719 0.468750 1 0 1.000000 +0 0.979529 1.696595 12.374216 0.459395 0.795709 -0.394635 0.941406 0.468750 1 0 1.000000 +0 1.387662 2.403501 13.267400 0.420179 0.727775 -0.541978 0.941406 0.507813 1 0 1.000000 +holygrail.tga +0 1.387662 2.403501 13.267400 0.420179 0.727775 -0.541978 0.941406 0.507813 1 0 1.000000 +0 2.126023 1.783943 13.267401 0.643757 0.540178 -0.541978 0.886719 0.507813 1 0 1.000000 +0 1.500727 1.259258 12.374218 0.703848 0.590594 -0.394635 0.886719 0.468750 1 0 1.000000 +holygrail.tga +0 1.840913 0.670039 12.374216 0.863399 0.314249 -0.394635 0.832031 0.468750 1 0 1.000000 +0 1.500727 1.259258 12.374218 0.703848 0.590594 -0.394635 0.886719 0.468750 1 0 1.000000 +0 2.126023 1.783943 13.267401 0.643757 0.540178 -0.541978 0.886719 0.507813 1 0 1.000000 +holygrail.tga +0 2.126023 1.783943 13.267401 0.643757 0.540178 -0.541978 0.886719 0.507813 1 0 1.000000 +0 2.607951 0.949218 13.267399 0.789697 0.287423 -0.541978 0.832031 0.507813 1 0 1.000000 +0 1.840913 0.670039 12.374216 0.863399 0.314249 -0.394635 0.832031 0.468750 1 0 1.000000 +holygrail.tga +0 1.777665 0.000005 7.896642 0.923429 0.000000 0.383679 0.773438 0.300781 1 0 1.000000 +0 1.670460 0.607999 7.896643 0.867763 0.315836 0.383679 0.832031 0.300781 1 0 1.000000 +0 1.840913 0.670039 12.374216 0.863399 0.314249 -0.394635 0.832031 0.468750 1 0 1.000000 +holygrail.tga +0 1.840913 0.670039 12.374216 0.863399 0.314249 -0.394635 0.832031 0.468750 1 0 1.000000 +0 1.959057 0.000004 12.374216 0.918821 0.000000 -0.394635 0.773438 0.468750 1 0 1.000000 +0 1.777665 0.000005 7.896642 0.923429 0.000000 0.383679 0.773438 0.300781 1 0 1.000000 +holygrail.tga +0 1.670458 -0.607997 7.896642 0.867733 -0.315836 0.383679 0.726563 0.300781 1 0 1.000000 +0 1.777665 0.000005 7.896642 0.923429 0.000000 0.383679 0.773438 0.300781 1 0 1.000000 +0 1.959057 0.000004 12.374216 0.918821 0.000000 -0.394635 0.773438 0.468750 1 0 1.000000 +holygrail.tga +0 1.959057 0.000004 12.374216 0.918821 0.000000 -0.394635 0.773438 0.468750 1 0 1.000000 +0 1.840911 -0.670037 12.374216 0.863399 -0.314249 -0.394635 0.726563 0.468750 1 0 1.000000 +0 1.670458 -0.607997 7.896642 0.867733 -0.315836 0.383679 0.726563 0.300781 1 0 1.000000 +holygrail.tga +0 1.361769 -1.142660 7.896643 0.707389 -0.593585 0.383679 0.664063 0.300781 1 0 1.000000 +0 1.670458 -0.607997 7.896642 0.867733 -0.315836 0.383679 0.726563 0.300781 1 0 1.000000 +0 1.840911 -0.670037 12.374216 0.863399 -0.314249 -0.394635 0.726563 0.468750 1 0 1.000000 +holygrail.tga +0 1.840911 -0.670037 12.374216 0.863399 -0.314249 -0.394635 0.726563 0.468750 1 0 1.000000 +0 1.500723 -1.259257 12.374216 0.703848 -0.590594 -0.394635 0.664063 0.468750 1 0 1.000000 +0 1.361769 -1.142660 7.896643 0.707389 -0.593585 0.383679 0.664063 0.300781 1 0 1.000000 +holygrail.tga +0 0.888830 -1.539503 7.896643 0.461715 -0.799707 0.383679 0.613281 0.300781 1 0 1.000000 +0 1.361769 -1.142660 7.896643 0.707389 -0.593585 0.383679 0.664063 0.300781 1 0 1.000000 +0 1.500723 -1.259257 12.374216 0.703848 -0.590594 -0.394635 0.664063 0.468750 1 0 1.000000 +holygrail.tga +0 1.500723 -1.259257 12.374216 0.703848 -0.590594 -0.394635 0.664063 0.468750 1 0 1.000000 +0 0.979526 -1.696594 12.374216 0.459395 -0.795709 -0.394635 0.613281 0.468750 1 0 1.000000 +0 0.888830 -1.539503 7.896643 0.461715 -0.799707 0.383679 0.613281 0.300781 1 0 1.000000 +holygrail.tga +0 0.308687 -1.750657 7.896643 0.160344 -0.909421 0.383679 0.554688 0.300781 1 0 1.000000 +0 0.888830 -1.539503 7.896643 0.461715 -0.799707 0.383679 0.613281 0.300781 1 0 1.000000 +0 0.979526 -1.696594 12.374216 0.459395 -0.795709 -0.394635 0.613281 0.468750 1 0 1.000000 +holygrail.tga +0 0.979526 -1.696594 12.374216 0.459395 -0.795709 -0.394635 0.613281 0.468750 1 0 1.000000 +0 0.340186 -1.929294 12.374216 0.159551 -0.904874 -0.394635 0.554688 0.468750 1 0 1.000000 +0 0.308687 -1.750657 7.896643 0.160344 -0.909421 0.383679 0.554688 0.300781 1 0 1.000000 +holygrail.tga +0 -0.308688 -1.750657 7.896643 -0.160344 -0.909421 0.383679 0.503906 0.300781 1 0 1.000000 +0 0.308687 -1.750657 7.896643 0.160344 -0.909421 0.383679 0.554688 0.300781 1 0 1.000000 +0 0.340186 -1.929294 12.374216 0.159551 -0.904874 -0.394635 0.554688 0.468750 1 0 1.000000 +holygrail.tga +0 0.340186 -1.929294 12.374216 0.159551 -0.904874 -0.394635 0.554688 0.468750 1 0 1.000000 +0 -0.340186 -1.929294 12.374216 -0.159551 -0.904874 -0.394635 0.503906 0.468750 1 0 1.000000 +0 -0.308688 -1.750657 7.896643 -0.160344 -0.909421 0.383679 0.503906 0.300781 1 0 1.000000 +holygrail.tga +0 -0.888833 -1.539501 7.896643 -0.461715 -0.799707 0.383679 0.449219 0.300781 1 0 1.000000 +0 -0.308688 -1.750657 7.896643 -0.160344 -0.909421 0.383679 0.503906 0.300781 1 0 1.000000 +0 -0.340186 -1.929294 12.374216 -0.159551 -0.904874 -0.394635 0.503906 0.468750 1 0 1.000000 +holygrail.tga +0 -0.340186 -1.929294 12.374216 -0.159551 -0.904874 -0.394635 0.503906 0.468750 1 0 1.000000 +0 -0.979529 -1.696592 12.374216 -0.459395 -0.795709 -0.394635 0.449219 0.468750 1 0 1.000000 +0 -0.888833 -1.539501 7.896643 -0.461715 -0.799707 0.383679 0.449219 0.300781 1 0 1.000000 +holygrail.tga +0 -1.361772 -1.142658 7.896643 -0.707389 -0.593585 0.383679 0.394531 0.300781 1 0 1.000000 +0 -0.888833 -1.539501 7.896643 -0.461715 -0.799707 0.383679 0.449219 0.300781 1 0 1.000000 +0 -0.979529 -1.696592 12.374216 -0.459395 -0.795709 -0.394635 0.449219 0.468750 1 0 1.000000 +holygrail.tga +0 -0.979529 -1.696592 12.374216 -0.459395 -0.795709 -0.394635 0.449219 0.468750 1 0 1.000000 +0 -1.500727 -1.259255 12.374216 -0.703848 -0.590594 -0.394635 0.394531 0.468750 1 0 1.000000 +0 -1.361772 -1.142658 7.896643 -0.707389 -0.593585 0.383679 0.394531 0.300781 1 0 1.000000 +holygrail.tga +0 -1.670460 -0.607996 7.896642 -0.867763 -0.315836 0.383679 0.339844 0.300781 1 0 1.000000 +0 -1.361772 -1.142658 7.896643 -0.707389 -0.593585 0.383679 0.394531 0.300781 1 0 1.000000 +0 -1.500727 -1.259255 12.374216 -0.703848 -0.590594 -0.394635 0.394531 0.468750 1 0 1.000000 +holygrail.tga +0 -1.500727 -1.259255 12.374216 -0.703848 -0.590594 -0.394635 0.394531 0.468750 1 0 1.000000 +0 -1.840912 -0.670036 12.374216 -0.863399 -0.314249 -0.394635 0.339844 0.468750 1 0 1.000000 +0 -1.670460 -0.607996 7.896642 -0.867763 -0.315836 0.383679 0.339844 0.300781 1 0 1.000000 +holygrail.tga +0 -1.777665 0.000001 7.896642 -0.923429 0.000000 0.383679 0.289063 0.300781 1 0 1.000000 +0 -1.670460 -0.607996 7.896642 -0.867763 -0.315836 0.383679 0.339844 0.300781 1 0 1.000000 +0 -1.840912 -0.670036 12.374216 -0.863399 -0.314249 -0.394635 0.339844 0.468750 1 0 1.000000 +holygrail.tga +0 -1.840912 -0.670036 12.374216 -0.863399 -0.314249 -0.394635 0.339844 0.468750 1 0 1.000000 +0 -1.959057 0.000001 12.374216 -0.918821 0.000000 -0.394635 0.289063 0.468750 1 0 1.000000 +0 -1.777665 0.000001 7.896642 -0.923429 0.000000 0.383679 0.289063 0.300781 1 0 1.000000 +holygrail.tga +0 -1.670459 0.607998 7.896643 -0.867763 0.315836 0.383679 0.226563 0.300781 1 0 1.000000 +0 -1.777665 0.000001 7.896642 -0.923429 0.000000 0.383679 0.289063 0.300781 1 0 1.000000 +0 -1.959057 0.000001 12.374216 -0.918821 0.000000 -0.394635 0.289063 0.468750 1 0 1.000000 +holygrail.tga +0 -1.959057 0.000001 12.374216 -0.918821 0.000000 -0.394635 0.289063 0.468750 1 0 1.000000 +0 -1.840912 0.670037 12.374216 -0.863399 0.314249 -0.394635 0.226563 0.468750 1 0 1.000000 +0 -1.670459 0.607998 7.896643 -0.867763 0.315836 0.383679 0.226563 0.300781 1 0 1.000000 +holygrail.tga +0 -1.361770 1.142662 7.896644 -0.707389 0.593585 0.383679 0.171875 0.300781 1 0 1.000000 +0 -1.670459 0.607998 7.896643 -0.867763 0.315836 0.383679 0.226563 0.300781 1 0 1.000000 +0 -1.840912 0.670037 12.374216 -0.863399 0.314249 -0.394635 0.226563 0.468750 1 0 1.000000 +holygrail.tga +0 -1.840912 0.670037 12.374216 -0.863399 0.314249 -0.394635 0.226563 0.468750 1 0 1.000000 +0 -1.500724 1.259258 12.374218 -0.703848 0.590594 -0.394635 0.171875 0.468750 1 0 1.000000 +0 -1.361770 1.142662 7.896644 -0.707389 0.593585 0.383679 0.171875 0.300781 1 0 1.000000 +holygrail.tga +0 -0.888830 1.539506 7.896644 -0.461715 0.799707 0.383679 0.117188 0.300781 1 0 1.000000 +0 -1.361770 1.142662 7.896644 -0.707389 0.593585 0.383679 0.171875 0.300781 1 0 1.000000 +0 -1.500724 1.259258 12.374218 -0.703848 0.590594 -0.394635 0.171875 0.468750 1 0 1.000000 +holygrail.tga +0 -1.500724 1.259258 12.374218 -0.703848 0.590594 -0.394635 0.171875 0.468750 1 0 1.000000 +0 -0.979526 1.696596 12.374216 -0.459395 0.795709 -0.394635 0.117188 0.468750 1 0 1.000000 +0 -0.888830 1.539506 7.896644 -0.461715 0.799707 0.383679 0.117188 0.300781 1 0 1.000000 +holygrail.tga +0 -0.308688 1.750661 7.896644 -0.160344 0.909421 0.383679 0.058594 0.300781 1 0 1.000000 +0 -0.888830 1.539506 7.896644 -0.461715 0.799707 0.383679 0.117188 0.300781 1 0 1.000000 +0 -0.979526 1.696596 12.374216 -0.459395 0.795709 -0.394635 0.117188 0.468750 1 0 1.000000 +holygrail.tga +0 -0.979526 1.696596 12.374216 -0.459395 0.795709 -0.394635 0.117188 0.468750 1 0 1.000000 +0 -0.340187 1.929296 12.374216 -0.159551 0.904874 -0.394635 0.058594 0.468750 1 0 1.000000 +0 -0.308688 1.750661 7.896644 -0.160344 0.909421 0.383679 0.058594 0.300781 1 0 1.000000 +holygrail.tga +0 0.308688 1.750661 7.896644 0.160344 0.909421 0.383679 0.000000 0.300781 1 0 1.000000 +0 -0.308688 1.750661 7.896644 -0.160344 0.909421 0.383679 0.058594 0.300781 1 0 1.000000 +0 -0.340187 1.929296 12.374216 -0.159551 0.904874 -0.394635 0.058594 0.468750 1 0 1.000000 +holygrail.tga +0 -0.340187 1.929296 12.374216 -0.159551 0.904874 -0.394635 0.058594 0.468750 1 0 1.000000 +0 0.340187 1.929296 12.374216 0.159551 0.904874 -0.394635 0.000000 0.468750 1 0 1.000000 +0 0.308688 1.750661 7.896644 0.160344 0.909421 0.383679 0.000000 0.300781 1 0 1.000000 +holygrail.tga +0 0.888833 1.539505 7.896644 0.461715 0.799707 0.383679 0.941406 0.300781 1 0 1.000000 +0 0.308688 1.750661 7.896644 0.160344 0.909421 0.383679 1.000000 0.300781 1 0 1.000000 +0 0.340187 1.929296 12.374216 0.159551 0.904874 -0.394635 1.000000 0.468750 1 0 1.000000 +holygrail.tga +0 0.340187 1.929296 12.374216 0.159551 0.904874 -0.394635 1.000000 0.468750 1 0 1.000000 +0 0.979529 1.696595 12.374216 0.459395 0.795709 -0.394635 0.941406 0.468750 1 0 1.000000 +0 0.888833 1.539505 7.896644 0.461715 0.799707 0.383679 0.941406 0.300781 1 0 1.000000 +holygrail.tga +0 1.361772 1.142662 7.896644 0.707389 0.593554 0.383679 0.886719 0.300781 1 0 1.000000 +0 0.888833 1.539505 7.896644 0.461715 0.799707 0.383679 0.941406 0.300781 1 0 1.000000 +0 0.979529 1.696595 12.374216 0.459395 0.795709 -0.394635 0.941406 0.468750 1 0 1.000000 +holygrail.tga +0 0.979529 1.696595 12.374216 0.459395 0.795709 -0.394635 0.941406 0.468750 1 0 1.000000 +0 1.500727 1.259258 12.374218 0.703848 0.590594 -0.394635 0.886719 0.468750 1 0 1.000000 +0 1.361772 1.142662 7.896644 0.707389 0.593554 0.383679 0.886719 0.300781 1 0 1.000000 +holygrail.tga +0 1.670460 0.607999 7.896643 0.867763 0.315836 0.383679 0.832031 0.300781 1 0 1.000000 +0 1.361772 1.142662 7.896644 0.707389 0.593554 0.383679 0.886719 0.300781 1 0 1.000000 +0 1.500727 1.259258 12.374218 0.703848 0.590594 -0.394635 0.886719 0.468750 1 0 1.000000 +holygrail.tga +0 1.500727 1.259258 12.374218 0.703848 0.590594 -0.394635 0.886719 0.468750 1 0 1.000000 +0 1.840913 0.670039 12.374216 0.863399 0.314249 -0.394635 0.832031 0.468750 1 0 1.000000 +0 1.670460 0.607999 7.896643 0.867763 0.315836 0.383679 0.832031 0.300781 1 0 1.000000 +holygrail.tga +0 2.140450 0.000005 7.539369 0.975707 0.000000 0.219001 0.773438 0.285156 1 0 1.000000 +0 2.011366 0.732079 7.539370 0.916868 0.333689 0.219001 0.832031 0.285156 1 0 1.000000 +0 1.670460 0.607999 7.896643 0.867763 0.315836 0.383679 0.832031 0.300781 1 0 1.000000 +holygrail.tga +0 1.670460 0.607999 7.896643 0.867763 0.315836 0.383679 0.832031 0.300781 1 0 1.000000 +0 1.777665 0.000005 7.896642 0.923429 0.000000 0.383679 0.773438 0.300781 1 0 1.000000 +0 2.140450 0.000005 7.539369 0.975707 0.000000 0.219001 0.773438 0.285156 1 0 1.000000 +holygrail.tga +0 2.011364 -0.732077 7.539369 0.916868 -0.333689 0.219001 0.726563 0.285156 1 0 1.000000 +0 2.140450 0.000005 7.539369 0.975707 0.000000 0.219001 0.773438 0.285156 1 0 1.000000 +0 1.777665 0.000005 7.896642 0.923429 0.000000 0.383679 0.773438 0.300781 1 0 1.000000 +holygrail.tga +0 1.777665 0.000005 7.896642 0.923429 0.000000 0.383679 0.773438 0.300781 1 0 1.000000 +0 1.670458 -0.607997 7.896642 0.867733 -0.315836 0.383679 0.726563 0.300781 1 0 1.000000 +0 2.011364 -0.732077 7.539369 0.916868 -0.333689 0.219001 0.726563 0.285156 1 0 1.000000 +holygrail.tga +0 1.639678 -1.375854 7.539370 0.747429 -0.627155 0.219001 0.664063 0.285156 1 0 1.000000 +0 2.011364 -0.732077 7.539369 0.916868 -0.333689 0.219001 0.726563 0.285156 1 0 1.000000 +0 1.670458 -0.607997 7.896642 0.867733 -0.315836 0.383679 0.726563 0.300781 1 0 1.000000 +holygrail.tga +0 1.670458 -0.607997 7.896642 0.867733 -0.315836 0.383679 0.726563 0.300781 1 0 1.000000 +0 1.361769 -1.142660 7.896643 0.707389 -0.593585 0.383679 0.664063 0.300781 1 0 1.000000 +0 1.639678 -1.375854 7.539370 0.747429 -0.627155 0.219001 0.664063 0.285156 1 0 1.000000 +holygrail.tga +0 1.070222 -1.853684 7.539370 0.487838 -0.844997 0.219001 0.613281 0.285156 1 0 1.000000 +0 1.639678 -1.375854 7.539370 0.747429 -0.627155 0.219001 0.664063 0.285156 1 0 1.000000 +0 1.361769 -1.142660 7.896643 0.707389 -0.593585 0.383679 0.664063 0.300781 1 0 1.000000 +holygrail.tga +0 1.361769 -1.142660 7.896643 0.707389 -0.593585 0.383679 0.664063 0.300781 1 0 1.000000 +0 0.888830 -1.539503 7.896643 0.461715 -0.799707 0.383679 0.613281 0.300781 1 0 1.000000 +0 1.070222 -1.853684 7.539370 0.487838 -0.844997 0.219001 0.613281 0.285156 1 0 1.000000 +holygrail.tga +0 0.371684 -2.107931 7.539370 0.169408 -0.960875 0.219001 0.554688 0.285156 1 0 1.000000 +0 1.070222 -1.853684 7.539370 0.487838 -0.844997 0.219001 0.613281 0.285156 1 0 1.000000 +0 0.888830 -1.539503 7.896643 0.461715 -0.799707 0.383679 0.613281 0.300781 1 0 1.000000 +holygrail.tga +0 0.888830 -1.539503 7.896643 0.461715 -0.799707 0.383679 0.613281 0.300781 1 0 1.000000 +0 0.308687 -1.750657 7.896643 0.160344 -0.909421 0.383679 0.554688 0.300781 1 0 1.000000 +0 0.371684 -2.107931 7.539370 0.169408 -0.960875 0.219001 0.554688 0.285156 1 0 1.000000 +holygrail.tga +0 -0.371685 -2.107930 7.539370 -0.169408 -0.960875 0.219001 0.503906 0.285156 1 0 1.000000 +0 0.371684 -2.107931 7.539370 0.169408 -0.960875 0.219001 0.554688 0.285156 1 0 1.000000 +0 0.308687 -1.750657 7.896643 0.160344 -0.909421 0.383679 0.554688 0.300781 1 0 1.000000 +holygrail.tga +0 0.308687 -1.750657 7.896643 0.160344 -0.909421 0.383679 0.554688 0.300781 1 0 1.000000 +0 -0.308688 -1.750657 7.896643 -0.160344 -0.909421 0.383679 0.503906 0.300781 1 0 1.000000 +0 -0.371685 -2.107930 7.539370 -0.169408 -0.960875 0.219001 0.503906 0.285156 1 0 1.000000 +holygrail.tga +0 -1.070225 -1.853682 7.539370 -0.487838 -0.844997 0.219001 0.449219 0.285156 1 0 1.000000 +0 -0.371685 -2.107930 7.539370 -0.169408 -0.960875 0.219001 0.503906 0.285156 1 0 1.000000 +0 -0.308688 -1.750657 7.896643 -0.160344 -0.909421 0.383679 0.503906 0.300781 1 0 1.000000 +holygrail.tga +0 -0.308688 -1.750657 7.896643 -0.160344 -0.909421 0.383679 0.503906 0.300781 1 0 1.000000 +0 -0.888833 -1.539501 7.896643 -0.461715 -0.799707 0.383679 0.449219 0.300781 1 0 1.000000 +0 -1.070225 -1.853682 7.539370 -0.487838 -0.844997 0.219001 0.449219 0.285156 1 0 1.000000 +holygrail.tga +0 -1.639682 -1.375851 7.539370 -0.747429 -0.627155 0.219001 0.394531 0.285156 1 0 1.000000 +0 -1.070225 -1.853682 7.539370 -0.487838 -0.844997 0.219001 0.449219 0.285156 1 0 1.000000 +0 -0.888833 -1.539501 7.896643 -0.461715 -0.799707 0.383679 0.449219 0.300781 1 0 1.000000 +holygrail.tga +0 -0.888833 -1.539501 7.896643 -0.461715 -0.799707 0.383679 0.449219 0.300781 1 0 1.000000 +0 -1.361772 -1.142658 7.896643 -0.707389 -0.593585 0.383679 0.394531 0.300781 1 0 1.000000 +0 -1.639682 -1.375851 7.539370 -0.747429 -0.627155 0.219001 0.394531 0.285156 1 0 1.000000 +holygrail.tga +0 -2.011366 -0.732075 7.539369 -0.916868 -0.333689 0.219001 0.339844 0.285156 1 0 1.000000 +0 -1.639682 -1.375851 7.539370 -0.747429 -0.627155 0.219001 0.394531 0.285156 1 0 1.000000 +0 -1.361772 -1.142658 7.896643 -0.707389 -0.593585 0.383679 0.394531 0.300781 1 0 1.000000 +holygrail.tga +0 -1.361772 -1.142658 7.896643 -0.707389 -0.593585 0.383679 0.394531 0.300781 1 0 1.000000 +0 -1.670460 -0.607996 7.896642 -0.867763 -0.315836 0.383679 0.339844 0.300781 1 0 1.000000 +0 -2.011366 -0.732075 7.539369 -0.916868 -0.333689 0.219001 0.339844 0.285156 1 0 1.000000 +holygrail.tga +0 -2.140450 0.000001 7.539369 -0.975707 0.000000 0.219001 0.289063 0.285156 1 0 1.000000 +0 -2.011366 -0.732075 7.539369 -0.916868 -0.333689 0.219001 0.339844 0.285156 1 0 1.000000 +0 -1.670460 -0.607996 7.896642 -0.867763 -0.315836 0.383679 0.339844 0.300781 1 0 1.000000 +holygrail.tga +0 -1.670460 -0.607996 7.896642 -0.867763 -0.315836 0.383679 0.339844 0.300781 1 0 1.000000 +0 -1.777665 0.000001 7.896642 -0.923429 0.000000 0.383679 0.289063 0.300781 1 0 1.000000 +0 -2.140450 0.000001 7.539369 -0.975707 0.000000 0.219001 0.289063 0.285156 1 0 1.000000 +holygrail.tga +0 -2.011365 0.732077 7.539370 -0.916868 0.333689 0.219001 0.226563 0.285156 1 0 1.000000 +0 -2.140450 0.000001 7.539369 -0.975707 0.000000 0.219001 0.289063 0.285156 1 0 1.000000 +0 -1.777665 0.000001 7.896642 -0.923429 0.000000 0.383679 0.289063 0.300781 1 0 1.000000 +holygrail.tga +0 -1.777665 0.000001 7.896642 -0.923429 0.000000 0.383679 0.289063 0.300781 1 0 1.000000 +0 -1.670459 0.607998 7.896643 -0.867763 0.315836 0.383679 0.226563 0.300781 1 0 1.000000 +0 -2.011365 0.732077 7.539370 -0.916868 0.333689 0.219001 0.226563 0.285156 1 0 1.000000 +holygrail.tga +0 -1.639679 1.375856 7.539371 -0.747429 0.627155 0.219001 0.171875 0.285156 1 0 1.000000 +0 -2.011365 0.732077 7.539370 -0.916868 0.333689 0.219001 0.226563 0.285156 1 0 1.000000 +0 -1.670459 0.607998 7.896643 -0.867763 0.315836 0.383679 0.226563 0.300781 1 0 1.000000 +holygrail.tga +0 -1.670459 0.607998 7.896643 -0.867763 0.315836 0.383679 0.226563 0.300781 1 0 1.000000 +0 -1.361770 1.142662 7.896644 -0.707389 0.593585 0.383679 0.171875 0.300781 1 0 1.000000 +0 -1.639679 1.375856 7.539371 -0.747429 0.627155 0.219001 0.171875 0.285156 1 0 1.000000 +holygrail.tga +0 -1.070222 1.853687 7.539371 -0.487838 0.844997 0.219001 0.117188 0.285156 1 0 1.000000 +0 -1.639679 1.375856 7.539371 -0.747429 0.627155 0.219001 0.171875 0.285156 1 0 1.000000 +0 -1.361770 1.142662 7.896644 -0.707389 0.593585 0.383679 0.171875 0.300781 1 0 1.000000 +holygrail.tga +0 -1.361770 1.142662 7.896644 -0.707389 0.593585 0.383679 0.171875 0.300781 1 0 1.000000 +0 -0.888830 1.539506 7.896644 -0.461715 0.799707 0.383679 0.117188 0.300781 1 0 1.000000 +0 -1.070222 1.853687 7.539371 -0.487838 0.844997 0.219001 0.117188 0.285156 1 0 1.000000 +holygrail.tga +0 -0.371685 2.107934 7.539371 -0.169408 0.960875 0.219001 0.058594 0.285156 1 0 1.000000 +0 -1.070222 1.853687 7.539371 -0.487838 0.844997 0.219001 0.117188 0.285156 1 0 1.000000 +0 -0.888830 1.539506 7.896644 -0.461715 0.799707 0.383679 0.117188 0.300781 1 0 1.000000 +holygrail.tga +0 -0.888830 1.539506 7.896644 -0.461715 0.799707 0.383679 0.117188 0.300781 1 0 1.000000 +0 -0.308688 1.750661 7.896644 -0.160344 0.909421 0.383679 0.058594 0.300781 1 0 1.000000 +0 -0.371685 2.107934 7.539371 -0.169408 0.960875 0.219001 0.058594 0.285156 1 0 1.000000 +holygrail.tga +0 0.371685 2.107934 7.539371 0.169408 0.960875 0.219001 0.000000 0.285156 1 0 1.000000 +0 -0.371685 2.107934 7.539371 -0.169408 0.960875 0.219001 0.058594 0.285156 1 0 1.000000 +0 -0.308688 1.750661 7.896644 -0.160344 0.909421 0.383679 0.058594 0.300781 1 0 1.000000 +holygrail.tga +0 -0.308688 1.750661 7.896644 -0.160344 0.909421 0.383679 0.058594 0.300781 1 0 1.000000 +0 0.308688 1.750661 7.896644 0.160344 0.909421 0.383679 0.000000 0.300781 1 0 1.000000 +0 0.371685 2.107934 7.539371 0.169408 0.960875 0.219001 0.000000 0.285156 1 0 1.000000 +holygrail.tga +0 1.070225 1.853686 7.539371 0.487838 0.844997 0.219001 0.941406 0.285156 1 0 1.000000 +0 0.371685 2.107934 7.539371 0.169408 0.960875 0.219001 1.000000 0.285156 1 0 1.000000 +0 0.308688 1.750661 7.896644 0.160344 0.909421 0.383679 1.000000 0.300781 1 0 1.000000 +holygrail.tga +0 0.308688 1.750661 7.896644 0.160344 0.909421 0.383679 1.000000 0.300781 1 0 1.000000 +0 0.888833 1.539505 7.896644 0.461715 0.799707 0.383679 0.941406 0.300781 1 0 1.000000 +0 1.070225 1.853686 7.539371 0.487838 0.844997 0.219001 0.941406 0.285156 1 0 1.000000 +holygrail.tga +0 1.639682 1.375855 7.539371 0.747429 0.627155 0.219001 0.886719 0.285156 1 0 1.000000 +0 1.070225 1.853686 7.539371 0.487838 0.844997 0.219001 0.941406 0.285156 1 0 1.000000 +0 0.888833 1.539505 7.896644 0.461715 0.799707 0.383679 0.941406 0.300781 1 0 1.000000 +holygrail.tga +0 0.888833 1.539505 7.896644 0.461715 0.799707 0.383679 0.941406 0.300781 1 0 1.000000 +0 1.361772 1.142662 7.896644 0.707389 0.593554 0.383679 0.886719 0.300781 1 0 1.000000 +0 1.639682 1.375855 7.539371 0.747429 0.627155 0.219001 0.886719 0.285156 1 0 1.000000 +holygrail.tga +0 2.011366 0.732079 7.539370 0.916868 0.333689 0.219001 0.832031 0.285156 1 0 1.000000 +0 1.639682 1.375855 7.539371 0.747429 0.627155 0.219001 0.886719 0.285156 1 0 1.000000 +0 1.361772 1.142662 7.896644 0.707389 0.593554 0.383679 0.886719 0.300781 1 0 1.000000 +holygrail.tga +0 1.361772 1.142662 7.896644 0.707389 0.593554 0.383679 0.886719 0.300781 1 0 1.000000 +0 1.670460 0.607999 7.896643 0.867763 0.315836 0.383679 0.832031 0.300781 1 0 1.000000 +0 2.011366 0.732079 7.539370 0.916868 0.333689 0.219001 0.832031 0.285156 1 0 1.000000 +holygrail.tga +0 1.959058 0.000005 7.003459 0.995849 0.000000 0.090976 0.773438 0.261719 1 0 1.000000 +0 1.840913 0.670040 7.003460 0.935789 0.340587 0.090976 0.832031 0.261719 1 0 1.000000 +0 2.011366 0.732079 7.539370 0.916868 0.333689 0.219001 0.832031 0.285156 1 0 1.000000 +holygrail.tga +0 2.011366 0.732079 7.539370 0.916868 0.333689 0.219001 0.832031 0.285156 1 0 1.000000 +0 2.140450 0.000005 7.539369 0.975707 0.000000 0.219001 0.773438 0.285156 1 0 1.000000 +0 1.959058 0.000005 7.003459 0.995849 0.000000 0.090976 0.773438 0.261719 1 0 1.000000 +holygrail.tga +0 1.840911 -0.670037 7.003459 0.935789 -0.340587 0.090976 0.726563 0.261719 1 0 1.000000 +0 1.959058 0.000005 7.003459 0.995849 0.000000 0.090976 0.773438 0.261719 1 0 1.000000 +0 2.140450 0.000005 7.539369 0.975707 0.000000 0.219001 0.773438 0.285156 1 0 1.000000 +holygrail.tga +0 2.140450 0.000005 7.539369 0.975707 0.000000 0.219001 0.773438 0.285156 1 0 1.000000 +0 2.011364 -0.732077 7.539369 0.916868 -0.333689 0.219001 0.726563 0.285156 1 0 1.000000 +0 1.840911 -0.670037 7.003459 0.935789 -0.340587 0.090976 0.726563 0.261719 1 0 1.000000 +holygrail.tga +0 1.500724 -1.259257 7.003460 0.762841 -0.640095 0.090976 0.664063 0.261719 1 0 1.000000 +0 1.840911 -0.670037 7.003459 0.935789 -0.340587 0.090976 0.726563 0.261719 1 0 1.000000 +0 2.011364 -0.732077 7.539369 0.916868 -0.333689 0.219001 0.726563 0.285156 1 0 1.000000 +holygrail.tga +0 2.011364 -0.732077 7.539369 0.916868 -0.333689 0.219001 0.726563 0.285156 1 0 1.000000 +0 1.639678 -1.375854 7.539370 0.747429 -0.627155 0.219001 0.664063 0.285156 1 0 1.000000 +0 1.500724 -1.259257 7.003460 0.762841 -0.640095 0.090976 0.664063 0.261719 1 0 1.000000 +holygrail.tga +0 0.979526 -1.696594 7.003460 0.497909 -0.862423 0.090976 0.613281 0.261719 1 0 1.000000 +0 1.500724 -1.259257 7.003460 0.762841 -0.640095 0.090976 0.664063 0.261719 1 0 1.000000 +0 1.639678 -1.375854 7.539370 0.747429 -0.627155 0.219001 0.664063 0.285156 1 0 1.000000 +holygrail.tga +0 1.639678 -1.375854 7.539370 0.747429 -0.627155 0.219001 0.664063 0.285156 1 0 1.000000 +0 1.070222 -1.853684 7.539370 0.487838 -0.844997 0.219001 0.613281 0.285156 1 0 1.000000 +0 0.979526 -1.696594 7.003460 0.497909 -0.862423 0.090976 0.613281 0.261719 1 0 1.000000 +holygrail.tga +0 0.340186 -1.929294 7.003460 0.172918 -0.980712 0.090976 0.554688 0.261719 1 0 1.000000 +0 0.979526 -1.696594 7.003460 0.497909 -0.862423 0.090976 0.613281 0.261719 1 0 1.000000 +0 1.070222 -1.853684 7.539370 0.487838 -0.844997 0.219001 0.613281 0.285156 1 0 1.000000 +holygrail.tga +0 1.070222 -1.853684 7.539370 0.487838 -0.844997 0.219001 0.613281 0.285156 1 0 1.000000 +0 0.371684 -2.107931 7.539370 0.169408 -0.960875 0.219001 0.554688 0.285156 1 0 1.000000 +0 0.340186 -1.929294 7.003460 0.172918 -0.980712 0.090976 0.554688 0.261719 1 0 1.000000 +holygrail.tga +0 -0.340186 -1.929294 7.003460 -0.172918 -0.980712 0.090976 0.503906 0.261719 1 0 1.000000 +0 0.340186 -1.929294 7.003460 0.172918 -0.980712 0.090976 0.554688 0.261719 1 0 1.000000 +0 0.371684 -2.107931 7.539370 0.169408 -0.960875 0.219001 0.554688 0.285156 1 0 1.000000 +holygrail.tga +0 0.371684 -2.107931 7.539370 0.169408 -0.960875 0.219001 0.554688 0.285156 1 0 1.000000 +0 -0.371685 -2.107930 7.539370 -0.169408 -0.960875 0.219001 0.503906 0.285156 1 0 1.000000 +0 -0.340186 -1.929294 7.003460 -0.172918 -0.980712 0.090976 0.503906 0.261719 1 0 1.000000 +holygrail.tga +0 -0.979529 -1.696592 7.003460 -0.497909 -0.862423 0.090976 0.449219 0.261719 1 0 1.000000 +0 -0.340186 -1.929294 7.003460 -0.172918 -0.980712 0.090976 0.503906 0.261719 1 0 1.000000 +0 -0.371685 -2.107930 7.539370 -0.169408 -0.960875 0.219001 0.503906 0.285156 1 0 1.000000 +holygrail.tga +0 -0.371685 -2.107930 7.539370 -0.169408 -0.960875 0.219001 0.503906 0.285156 1 0 1.000000 +0 -1.070225 -1.853682 7.539370 -0.487838 -0.844997 0.219001 0.449219 0.285156 1 0 1.000000 +0 -0.979529 -1.696592 7.003460 -0.497909 -0.862423 0.090976 0.449219 0.261719 1 0 1.000000 +holygrail.tga +0 -1.500727 -1.259254 7.003460 -0.762841 -0.640095 0.090976 0.394531 0.261719 1 0 1.000000 +0 -0.979529 -1.696592 7.003460 -0.497909 -0.862423 0.090976 0.449219 0.261719 1 0 1.000000 +0 -1.070225 -1.853682 7.539370 -0.487838 -0.844997 0.219001 0.449219 0.285156 1 0 1.000000 +holygrail.tga +0 -1.070225 -1.853682 7.539370 -0.487838 -0.844997 0.219001 0.449219 0.285156 1 0 1.000000 +0 -1.639682 -1.375851 7.539370 -0.747429 -0.627155 0.219001 0.394531 0.285156 1 0 1.000000 +0 -1.500727 -1.259254 7.003460 -0.762841 -0.640095 0.090976 0.394531 0.261719 1 0 1.000000 +holygrail.tga +0 -1.840913 -0.670035 7.003459 -0.935789 -0.340587 0.090976 0.339844 0.261719 1 0 1.000000 +0 -1.500727 -1.259254 7.003460 -0.762841 -0.640095 0.090976 0.394531 0.261719 1 0 1.000000 +0 -1.639682 -1.375851 7.539370 -0.747429 -0.627155 0.219001 0.394531 0.285156 1 0 1.000000 +holygrail.tga +0 -1.639682 -1.375851 7.539370 -0.747429 -0.627155 0.219001 0.394531 0.285156 1 0 1.000000 +0 -2.011366 -0.732075 7.539369 -0.916868 -0.333689 0.219001 0.339844 0.285156 1 0 1.000000 +0 -1.840913 -0.670035 7.003459 -0.935789 -0.340587 0.090976 0.339844 0.261719 1 0 1.000000 +holygrail.tga +0 -1.959058 0.000001 7.003459 -0.995849 0.000000 0.090976 0.289063 0.261719 1 0 1.000000 +0 -1.840913 -0.670035 7.003459 -0.935789 -0.340587 0.090976 0.339844 0.261719 1 0 1.000000 +0 -2.011366 -0.732075 7.539369 -0.916868 -0.333689 0.219001 0.339844 0.285156 1 0 1.000000 +holygrail.tga +0 -2.011366 -0.732075 7.539369 -0.916868 -0.333689 0.219001 0.339844 0.285156 1 0 1.000000 +0 -2.140450 0.000001 7.539369 -0.975707 0.000000 0.219001 0.289063 0.285156 1 0 1.000000 +0 -1.959058 0.000001 7.003459 -0.995849 0.000000 0.090976 0.289063 0.261719 1 0 1.000000 +holygrail.tga +0 -1.840912 0.670038 7.003460 -0.935789 0.340587 0.090976 0.226563 0.261719 1 0 1.000000 +0 -1.959058 0.000001 7.003459 -0.995849 0.000000 0.090976 0.289063 0.261719 1 0 1.000000 +0 -2.140450 0.000001 7.539369 -0.975707 0.000000 0.219001 0.289063 0.285156 1 0 1.000000 +holygrail.tga +0 -2.140450 0.000001 7.539369 -0.975707 0.000000 0.219001 0.289063 0.285156 1 0 1.000000 +0 -2.011365 0.732077 7.539370 -0.916868 0.333689 0.219001 0.226563 0.285156 1 0 1.000000 +0 -1.840912 0.670038 7.003460 -0.935789 0.340587 0.090976 0.226563 0.261719 1 0 1.000000 +holygrail.tga +0 -1.500725 1.259259 7.003461 -0.762841 0.640095 0.090976 0.171875 0.261719 1 0 1.000000 +0 -1.840912 0.670038 7.003460 -0.935789 0.340587 0.090976 0.226563 0.261719 1 0 1.000000 +0 -2.011365 0.732077 7.539370 -0.916868 0.333689 0.219001 0.226563 0.285156 1 0 1.000000 +holygrail.tga +0 -2.011365 0.732077 7.539370 -0.916868 0.333689 0.219001 0.226563 0.285156 1 0 1.000000 +0 -1.639679 1.375856 7.539371 -0.747429 0.627155 0.219001 0.171875 0.285156 1 0 1.000000 +0 -1.500725 1.259259 7.003461 -0.762841 0.640095 0.090976 0.171875 0.261719 1 0 1.000000 +holygrail.tga +0 -0.979526 1.696597 7.003461 -0.497909 0.862423 0.090976 0.117188 0.261719 1 0 1.000000 +0 -1.500725 1.259259 7.003461 -0.762841 0.640095 0.090976 0.171875 0.261719 1 0 1.000000 +0 -1.639679 1.375856 7.539371 -0.747429 0.627155 0.219001 0.171875 0.285156 1 0 1.000000 +holygrail.tga +0 -1.639679 1.375856 7.539371 -0.747429 0.627155 0.219001 0.171875 0.285156 1 0 1.000000 +0 -1.070222 1.853687 7.539371 -0.487838 0.844997 0.219001 0.117188 0.285156 1 0 1.000000 +0 -0.979526 1.696597 7.003461 -0.497909 0.862423 0.090976 0.117188 0.261719 1 0 1.000000 +holygrail.tga +0 -0.340187 1.929298 7.003461 -0.172918 0.980712 0.090976 0.058594 0.261719 1 0 1.000000 +0 -0.979526 1.696597 7.003461 -0.497909 0.862423 0.090976 0.117188 0.261719 1 0 1.000000 +0 -1.070222 1.853687 7.539371 -0.487838 0.844997 0.219001 0.117188 0.285156 1 0 1.000000 +holygrail.tga +0 -1.070222 1.853687 7.539371 -0.487838 0.844997 0.219001 0.117188 0.285156 1 0 1.000000 +0 -0.371685 2.107934 7.539371 -0.169408 0.960875 0.219001 0.058594 0.285156 1 0 1.000000 +0 -0.340187 1.929298 7.003461 -0.172918 0.980712 0.090976 0.058594 0.261719 1 0 1.000000 +holygrail.tga +0 0.340187 1.929298 7.003461 0.172918 0.980712 0.090976 0.000000 0.261719 1 0 1.000000 +0 -0.340187 1.929298 7.003461 -0.172918 0.980712 0.090976 0.058594 0.261719 1 0 1.000000 +0 -0.371685 2.107934 7.539371 -0.169408 0.960875 0.219001 0.058594 0.285156 1 0 1.000000 +holygrail.tga +0 -0.371685 2.107934 7.539371 -0.169408 0.960875 0.219001 0.058594 0.285156 1 0 1.000000 +0 0.371685 2.107934 7.539371 0.169408 0.960875 0.219001 0.000000 0.285156 1 0 1.000000 +0 0.340187 1.929298 7.003461 0.172918 0.980712 0.090976 0.000000 0.261719 1 0 1.000000 +holygrail.tga +0 0.979529 1.696596 7.003461 0.497909 0.862423 0.090976 0.941406 0.261719 1 0 1.000000 +0 0.340187 1.929298 7.003461 0.172918 0.980712 0.090976 1.000000 0.261719 1 0 1.000000 +0 0.371685 2.107934 7.539371 0.169408 0.960875 0.219001 1.000000 0.285156 1 0 1.000000 +holygrail.tga +0 0.371685 2.107934 7.539371 0.169408 0.960875 0.219001 1.000000 0.285156 1 0 1.000000 +0 1.070225 1.853686 7.539371 0.487838 0.844997 0.219001 0.941406 0.285156 1 0 1.000000 +0 0.979529 1.696596 7.003461 0.497909 0.862423 0.090976 0.941406 0.261719 1 0 1.000000 +holygrail.tga +0 1.500727 1.259259 7.003461 0.762841 0.640095 0.090976 0.886719 0.261719 1 0 1.000000 +0 0.979529 1.696596 7.003461 0.497909 0.862423 0.090976 0.941406 0.261719 1 0 1.000000 +0 1.070225 1.853686 7.539371 0.487838 0.844997 0.219001 0.941406 0.285156 1 0 1.000000 +holygrail.tga +0 1.070225 1.853686 7.539371 0.487838 0.844997 0.219001 0.941406 0.285156 1 0 1.000000 +0 1.639682 1.375855 7.539371 0.747429 0.627155 0.219001 0.886719 0.285156 1 0 1.000000 +0 1.500727 1.259259 7.003461 0.762841 0.640095 0.090976 0.886719 0.261719 1 0 1.000000 +holygrail.tga +0 1.840913 0.670040 7.003460 0.935789 0.340587 0.090976 0.832031 0.261719 1 0 1.000000 +0 1.500727 1.259259 7.003461 0.762841 0.640095 0.090976 0.886719 0.261719 1 0 1.000000 +0 1.639682 1.375855 7.539371 0.747429 0.627155 0.219001 0.886719 0.285156 1 0 1.000000 +holygrail.tga +0 1.639682 1.375855 7.539371 0.747429 0.627155 0.219001 0.886719 0.285156 1 0 1.000000 +0 2.011366 0.732079 7.539370 0.916868 0.333689 0.219001 0.832031 0.285156 1 0 1.000000 +0 1.840913 0.670040 7.003460 0.935789 0.340587 0.090976 0.832031 0.261719 1 0 1.000000 +holygrail.tga +0 2.593931 0.000005 5.842322 0.849239 0.000000 0.527940 0.773438 0.195313 1 0 1.000000 +0 2.437499 0.887179 5.842322 0.798029 0.290445 0.527940 0.832031 0.195313 1 0 1.000000 +0 1.840913 0.670040 7.003460 0.935789 0.340587 0.090976 0.832031 0.261719 1 0 1.000000 +holygrail.tga +0 1.840913 0.670040 7.003460 0.935789 0.340587 0.090976 0.832031 0.261719 1 0 1.000000 +0 1.959058 0.000005 7.003459 0.995849 0.000000 0.090976 0.773438 0.261719 1 0 1.000000 +0 2.593931 0.000005 5.842322 0.849239 0.000000 0.527940 0.773438 0.195313 1 0 1.000000 +holygrail.tga +0 2.437497 -0.887177 5.842322 0.798029 -0.290445 0.527940 0.726563 0.195313 1 0 1.000000 +0 2.593931 0.000005 5.842322 0.849239 0.000000 0.527940 0.773438 0.195313 1 0 1.000000 +0 1.959058 0.000005 7.003459 0.995849 0.000000 0.090976 0.773438 0.261719 1 0 1.000000 +holygrail.tga +0 1.959058 0.000005 7.003459 0.995849 0.000000 0.090976 0.773438 0.261719 1 0 1.000000 +0 1.840911 -0.670037 7.003459 0.935789 -0.340587 0.090976 0.726563 0.261719 1 0 1.000000 +0 2.437497 -0.887177 5.842322 0.798029 -0.290445 0.527940 0.726563 0.195313 1 0 1.000000 +holygrail.tga +0 1.987065 -1.667345 5.842322 0.650563 -0.545885 0.527940 0.664063 0.195313 1 0 1.000000 +0 2.437497 -0.887177 5.842322 0.798029 -0.290445 0.527940 0.726563 0.195313 1 0 1.000000 +0 1.840911 -0.670037 7.003459 0.935789 -0.340587 0.090976 0.726563 0.261719 1 0 1.000000 +holygrail.tga +0 1.840911 -0.670037 7.003459 0.935789 -0.340587 0.090976 0.726563 0.261719 1 0 1.000000 +0 1.500724 -1.259257 7.003460 0.762841 -0.640095 0.090976 0.664063 0.261719 1 0 1.000000 +0 1.987065 -1.667345 5.842322 0.650563 -0.545885 0.527940 0.664063 0.195313 1 0 1.000000 +holygrail.tga +0 1.296963 -2.246410 5.842322 0.424604 -0.735466 0.527940 0.613281 0.195313 1 0 1.000000 +0 1.987065 -1.667345 5.842322 0.650563 -0.545885 0.527940 0.664063 0.195313 1 0 1.000000 +0 1.500724 -1.259257 7.003460 0.762841 -0.640095 0.090976 0.664063 0.261719 1 0 1.000000 +holygrail.tga +0 1.500724 -1.259257 7.003460 0.762841 -0.640095 0.090976 0.664063 0.261719 1 0 1.000000 +0 0.979526 -1.696594 7.003460 0.497909 -0.862423 0.090976 0.613281 0.261719 1 0 1.000000 +0 1.296963 -2.246410 5.842322 0.424604 -0.735466 0.527940 0.613281 0.195313 1 0 1.000000 +holygrail.tga +0 0.450430 -2.554522 5.842322 0.147465 -0.836360 0.527940 0.554688 0.195313 1 0 1.000000 +0 1.296963 -2.246410 5.842322 0.424604 -0.735466 0.527940 0.613281 0.195313 1 0 1.000000 +0 0.979526 -1.696594 7.003460 0.497909 -0.862423 0.090976 0.613281 0.261719 1 0 1.000000 +holygrail.tga +0 0.979526 -1.696594 7.003460 0.497909 -0.862423 0.090976 0.613281 0.261719 1 0 1.000000 +0 0.340186 -1.929294 7.003460 0.172918 -0.980712 0.090976 0.554688 0.261719 1 0 1.000000 +0 0.450430 -2.554522 5.842322 0.147465 -0.836360 0.527940 0.554688 0.195313 1 0 1.000000 +holygrail.tga +0 -0.450431 -2.554522 5.842322 -0.147465 -0.836360 0.527940 0.503906 0.195313 1 0 1.000000 +0 0.450430 -2.554522 5.842322 0.147465 -0.836360 0.527940 0.554688 0.195313 1 0 1.000000 +0 0.340186 -1.929294 7.003460 0.172918 -0.980712 0.090976 0.554688 0.261719 1 0 1.000000 +holygrail.tga +0 0.340186 -1.929294 7.003460 0.172918 -0.980712 0.090976 0.554688 0.261719 1 0 1.000000 +0 -0.340186 -1.929294 7.003460 -0.172918 -0.980712 0.090976 0.503906 0.261719 1 0 1.000000 +0 -0.450431 -2.554522 5.842322 -0.147465 -0.836360 0.527940 0.503906 0.195313 1 0 1.000000 +holygrail.tga +0 -1.296966 -2.246408 5.842322 -0.424604 -0.735466 0.527940 0.449219 0.195313 1 0 1.000000 +0 -0.450431 -2.554522 5.842322 -0.147465 -0.836360 0.527940 0.503906 0.195313 1 0 1.000000 +0 -0.340186 -1.929294 7.003460 -0.172918 -0.980712 0.090976 0.503906 0.261719 1 0 1.000000 +holygrail.tga +0 -0.340186 -1.929294 7.003460 -0.172918 -0.980712 0.090976 0.503906 0.261719 1 0 1.000000 +0 -0.979529 -1.696592 7.003460 -0.497909 -0.862423 0.090976 0.449219 0.261719 1 0 1.000000 +0 -1.296966 -2.246408 5.842322 -0.424604 -0.735466 0.527940 0.449219 0.195313 1 0 1.000000 +holygrail.tga +0 -1.987068 -1.667343 5.842322 -0.650563 -0.545885 0.527940 0.394531 0.195313 1 0 1.000000 +0 -1.296966 -2.246408 5.842322 -0.424604 -0.735466 0.527940 0.449219 0.195313 1 0 1.000000 +0 -0.979529 -1.696592 7.003460 -0.497909 -0.862423 0.090976 0.449219 0.261719 1 0 1.000000 +holygrail.tga +0 -0.979529 -1.696592 7.003460 -0.497909 -0.862423 0.090976 0.449219 0.261719 1 0 1.000000 +0 -1.500727 -1.259254 7.003460 -0.762841 -0.640095 0.090976 0.394531 0.261719 1 0 1.000000 +0 -1.987068 -1.667343 5.842322 -0.650563 -0.545885 0.527940 0.394531 0.195313 1 0 1.000000 +holygrail.tga +0 -2.437499 -0.887174 5.842322 -0.798029 -0.290445 0.527940 0.339844 0.195313 1 0 1.000000 +0 -1.987068 -1.667343 5.842322 -0.650563 -0.545885 0.527940 0.394531 0.195313 1 0 1.000000 +0 -1.500727 -1.259254 7.003460 -0.762841 -0.640095 0.090976 0.394531 0.261719 1 0 1.000000 +holygrail.tga +0 -1.500727 -1.259254 7.003460 -0.762841 -0.640095 0.090976 0.394531 0.261719 1 0 1.000000 +0 -1.840913 -0.670035 7.003459 -0.935789 -0.340587 0.090976 0.339844 0.261719 1 0 1.000000 +0 -2.437499 -0.887174 5.842322 -0.798029 -0.290445 0.527940 0.339844 0.195313 1 0 1.000000 +holygrail.tga +0 -1.840913 -0.670035 7.003459 -0.935789 -0.340587 0.090976 0.339844 0.261719 1 0 1.000000 +0 -1.959058 0.000001 7.003459 -0.995849 0.000000 0.090976 0.289063 0.261719 1 0 1.000000 +0 -2.593930 0.000002 5.842322 -0.849239 0.000000 0.527940 0.289063 0.195313 1 0 1.000000 +holygrail.tga +0 -2.437498 0.887178 5.842322 -0.798029 0.290445 0.527940 0.226563 0.195313 1 0 1.000000 +0 -2.593930 0.000002 5.842322 -0.849239 0.000000 0.527940 0.289063 0.195313 1 0 1.000000 +0 -1.959058 0.000001 7.003459 -0.995849 0.000000 0.090976 0.289063 0.261719 1 0 1.000000 +holygrail.tga +0 -1.959058 0.000001 7.003459 -0.995849 0.000000 0.090976 0.289063 0.261719 1 0 1.000000 +0 -1.840912 0.670038 7.003460 -0.935789 0.340587 0.090976 0.226563 0.261719 1 0 1.000000 +0 -2.437498 0.887178 5.842322 -0.798029 0.290445 0.527940 0.226563 0.195313 1 0 1.000000 +holygrail.tga +0 -1.987065 1.667348 5.842324 -0.650563 0.545885 0.527940 0.171875 0.195313 1 0 1.000000 +0 -2.437498 0.887178 5.842322 -0.798029 0.290445 0.527940 0.226563 0.195313 1 0 1.000000 +0 -1.840912 0.670038 7.003460 -0.935789 0.340587 0.090976 0.226563 0.261719 1 0 1.000000 +holygrail.tga +0 -1.840912 0.670038 7.003460 -0.935789 0.340587 0.090976 0.226563 0.261719 1 0 1.000000 +0 -1.500725 1.259259 7.003461 -0.762841 0.640095 0.090976 0.171875 0.261719 1 0 1.000000 +0 -1.987065 1.667348 5.842324 -0.650563 0.545885 0.527940 0.171875 0.195313 1 0 1.000000 +holygrail.tga +0 -1.296963 2.246413 5.842323 -0.424604 0.735466 0.527940 0.117188 0.195313 1 0 1.000000 +0 -1.987065 1.667348 5.842324 -0.650563 0.545885 0.527940 0.171875 0.195313 1 0 1.000000 +0 -1.500725 1.259259 7.003461 -0.762841 0.640095 0.090976 0.171875 0.261719 1 0 1.000000 +holygrail.tga +0 -1.500725 1.259259 7.003461 -0.762841 0.640095 0.090976 0.171875 0.261719 1 0 1.000000 +0 -0.979526 1.696597 7.003461 -0.497909 0.862423 0.090976 0.117188 0.261719 1 0 1.000000 +0 -1.296963 2.246413 5.842323 -0.424604 0.735466 0.527940 0.117188 0.195313 1 0 1.000000 +holygrail.tga +0 -0.450431 2.554526 5.842323 -0.147465 0.836360 0.527940 0.058594 0.195313 1 0 1.000000 +0 -1.296963 2.246413 5.842323 -0.424604 0.735466 0.527940 0.117188 0.195313 1 0 1.000000 +0 -0.979526 1.696597 7.003461 -0.497909 0.862423 0.090976 0.117188 0.261719 1 0 1.000000 +holygrail.tga +0 -0.979526 1.696597 7.003461 -0.497909 0.862423 0.090976 0.117188 0.261719 1 0 1.000000 +0 -0.340187 1.929298 7.003461 -0.172918 0.980712 0.090976 0.058594 0.261719 1 0 1.000000 +0 -0.450431 2.554526 5.842323 -0.147465 0.836360 0.527940 0.058594 0.195313 1 0 1.000000 +holygrail.tga +0 0.450431 2.554526 5.842323 0.147465 0.836360 0.527940 0.000000 0.195313 1 0 1.000000 +0 -0.450431 2.554526 5.842323 -0.147465 0.836360 0.527940 0.058594 0.195313 1 0 1.000000 +0 -0.340187 1.929298 7.003461 -0.172918 0.980712 0.090976 0.058594 0.261719 1 0 1.000000 +holygrail.tga +0 -0.340187 1.929298 7.003461 -0.172918 0.980712 0.090976 0.058594 0.261719 1 0 1.000000 +0 0.340187 1.929298 7.003461 0.172918 0.980712 0.090976 0.000000 0.261719 1 0 1.000000 +0 0.450431 2.554526 5.842323 0.147465 0.836360 0.527940 0.000000 0.195313 1 0 1.000000 +holygrail.tga +0 1.296966 2.246413 5.842323 0.424604 0.735466 0.527940 0.941406 0.195313 1 0 1.000000 +0 0.450431 2.554526 5.842323 0.147465 0.836360 0.527940 1.000000 0.195313 1 0 1.000000 +0 0.340187 1.929298 7.003461 0.172918 0.980712 0.090976 1.000000 0.261719 1 0 1.000000 +holygrail.tga +0 0.340187 1.929298 7.003461 0.172918 0.980712 0.090976 1.000000 0.261719 1 0 1.000000 +0 0.979529 1.696596 7.003461 0.497909 0.862423 0.090976 0.941406 0.261719 1 0 1.000000 +0 1.296966 2.246413 5.842323 0.424604 0.735466 0.527940 0.941406 0.195313 1 0 1.000000 +holygrail.tga +0 1.987068 1.667347 5.842324 0.650563 0.545885 0.527940 0.886719 0.195313 1 0 1.000000 +0 1.296966 2.246413 5.842323 0.424604 0.735466 0.527940 0.941406 0.195313 1 0 1.000000 +0 0.979529 1.696596 7.003461 0.497909 0.862423 0.090976 0.941406 0.261719 1 0 1.000000 +holygrail.tga +0 0.979529 1.696596 7.003461 0.497909 0.862423 0.090976 0.941406 0.261719 1 0 1.000000 +0 1.500727 1.259259 7.003461 0.762841 0.640095 0.090976 0.886719 0.261719 1 0 1.000000 +0 1.987068 1.667347 5.842324 0.650563 0.545885 0.527940 0.886719 0.195313 1 0 1.000000 +holygrail.tga +0 2.437499 0.887179 5.842322 0.798029 0.290445 0.527940 0.832031 0.195313 1 0 1.000000 +0 1.987068 1.667347 5.842324 0.650563 0.545885 0.527940 0.886719 0.195313 1 0 1.000000 +0 1.500727 1.259259 7.003461 0.762841 0.640095 0.090976 0.886719 0.261719 1 0 1.000000 +holygrail.tga +0 1.500727 1.259259 7.003461 0.762841 0.640095 0.090976 0.886719 0.261719 1 0 1.000000 +0 1.840913 0.670040 7.003460 0.935789 0.340587 0.090976 0.832031 0.261719 1 0 1.000000 +0 2.437499 0.887179 5.842322 0.798029 0.290445 0.527940 0.832031 0.195313 1 0 1.000000 +holygrail.tga +0 4.181049 0.000005 3.551379 0.894467 0.000000 0.447096 0.773438 0.113281 1 0 1.000000 +0 3.928904 1.430006 3.551379 0.840510 0.305918 0.447096 0.832031 0.113281 1 0 1.000000 +0 2.437499 0.887179 5.842322 0.798029 0.290445 0.527940 0.832031 0.195313 1 0 1.000000 +holygrail.tga +0 2.437499 0.887179 5.842322 0.798029 0.290445 0.527940 0.832031 0.195313 1 0 1.000000 +0 2.593931 0.000005 5.842322 0.849239 0.000000 0.527940 0.773438 0.195313 1 0 1.000000 +0 4.181049 0.000005 3.551379 0.894467 0.000000 0.447096 0.773438 0.113281 1 0 1.000000 +holygrail.tga +0 3.928901 -1.430004 3.551379 0.840510 -0.305918 0.447096 0.726563 0.113281 1 0 1.000000 +0 4.181049 0.000005 3.551379 0.894467 0.000000 0.447096 0.773438 0.113281 1 0 1.000000 +0 2.593931 0.000005 5.842322 0.849239 0.000000 0.527940 0.773438 0.195313 1 0 1.000000 +holygrail.tga +0 2.593931 0.000005 5.842322 0.849239 0.000000 0.527940 0.773438 0.195313 1 0 1.000000 +0 2.437497 -0.887177 5.842322 0.798029 -0.290445 0.527940 0.726563 0.195313 1 0 1.000000 +0 3.928901 -1.430004 3.551379 0.840510 -0.305918 0.447096 0.726563 0.113281 1 0 1.000000 +holygrail.tga +0 3.202868 -2.687525 3.551379 0.685202 -0.574938 0.447096 0.664063 0.113281 1 0 1.000000 +0 3.928901 -1.430004 3.551379 0.840510 -0.305918 0.447096 0.726563 0.113281 1 0 1.000000 +0 2.437497 -0.887177 5.842322 0.798029 -0.290445 0.527940 0.726563 0.195313 1 0 1.000000 +holygrail.tga +0 2.437497 -0.887177 5.842322 0.798029 -0.290445 0.527940 0.726563 0.195313 1 0 1.000000 +0 1.987065 -1.667345 5.842322 0.650563 -0.545885 0.527940 0.664063 0.195313 1 0 1.000000 +0 3.202868 -2.687525 3.551379 0.685202 -0.574938 0.447096 0.664063 0.113281 1 0 1.000000 +holygrail.tga +0 2.090522 -3.620895 3.551380 0.447218 -0.774621 0.447096 0.613281 0.113281 1 0 1.000000 +0 3.202868 -2.687525 3.551379 0.685202 -0.574938 0.447096 0.664063 0.113281 1 0 1.000000 +0 1.987065 -1.667345 5.842322 0.650563 -0.545885 0.527940 0.664063 0.195313 1 0 1.000000 +holygrail.tga +0 1.987065 -1.667345 5.842322 0.650563 -0.545885 0.527940 0.664063 0.195313 1 0 1.000000 +0 1.296963 -2.246410 5.842322 0.424604 -0.735466 0.527940 0.613281 0.195313 1 0 1.000000 +0 2.090522 -3.620895 3.551380 0.447218 -0.774621 0.447096 0.613281 0.113281 1 0 1.000000 +holygrail.tga +0 0.726029 -4.117528 3.551379 0.155309 -0.880886 0.447096 0.554688 0.113281 1 0 1.000000 +0 2.090522 -3.620895 3.551380 0.447218 -0.774621 0.447096 0.613281 0.113281 1 0 1.000000 +0 1.296963 -2.246410 5.842322 0.424604 -0.735466 0.527940 0.613281 0.195313 1 0 1.000000 +holygrail.tga +0 1.296963 -2.246410 5.842322 0.424604 -0.735466 0.527940 0.613281 0.195313 1 0 1.000000 +0 0.450430 -2.554522 5.842322 0.147465 -0.836360 0.527940 0.554688 0.195313 1 0 1.000000 +0 0.726029 -4.117528 3.551379 0.155309 -0.880886 0.447096 0.554688 0.113281 1 0 1.000000 +holygrail.tga +0 -0.726032 -4.117528 3.551379 -0.155309 -0.880886 0.447096 0.503906 0.113281 1 0 1.000000 +0 0.726029 -4.117528 3.551379 0.155309 -0.880886 0.447096 0.554688 0.113281 1 0 1.000000 +0 0.450430 -2.554522 5.842322 0.147465 -0.836360 0.527940 0.554688 0.195313 1 0 1.000000 +holygrail.tga +0 0.450430 -2.554522 5.842322 0.147465 -0.836360 0.527940 0.554688 0.195313 1 0 1.000000 +0 -0.450431 -2.554522 5.842322 -0.147465 -0.836360 0.527940 0.503906 0.195313 1 0 1.000000 +0 -0.726032 -4.117528 3.551379 -0.155309 -0.880886 0.447096 0.503906 0.113281 1 0 1.000000 +holygrail.tga +0 -2.090525 -3.620892 3.551380 -0.447218 -0.774621 0.447096 0.449219 0.113281 1 0 1.000000 +0 -0.726032 -4.117528 3.551379 -0.155309 -0.880886 0.447096 0.503906 0.113281 1 0 1.000000 +0 -0.450431 -2.554522 5.842322 -0.147465 -0.836360 0.527940 0.503906 0.195313 1 0 1.000000 +holygrail.tga +0 -0.450431 -2.554522 5.842322 -0.147465 -0.836360 0.527940 0.503906 0.195313 1 0 1.000000 +0 -1.296966 -2.246408 5.842322 -0.424604 -0.735466 0.527940 0.449219 0.195313 1 0 1.000000 +0 -2.090525 -3.620892 3.551380 -0.447218 -0.774621 0.447096 0.449219 0.113281 1 0 1.000000 +holygrail.tga +0 -3.202872 -2.687522 3.551379 -0.685202 -0.574938 0.447096 0.394531 0.113281 1 0 1.000000 +0 -2.090525 -3.620892 3.551380 -0.447218 -0.774621 0.447096 0.449219 0.113281 1 0 1.000000 +0 -1.296966 -2.246408 5.842322 -0.424604 -0.735466 0.527940 0.449219 0.195313 1 0 1.000000 +holygrail.tga +0 -1.296966 -2.246408 5.842322 -0.424604 -0.735466 0.527940 0.449219 0.195313 1 0 1.000000 +0 -1.987068 -1.667343 5.842322 -0.650563 -0.545885 0.527940 0.394531 0.195313 1 0 1.000000 +0 -3.202872 -2.687522 3.551379 -0.685202 -0.574938 0.447096 0.394531 0.113281 1 0 1.000000 +holygrail.tga +0 -3.928903 -1.429999 3.551379 -0.840510 -0.305918 0.447096 0.339844 0.113281 1 0 1.000000 +0 -3.202872 -2.687522 3.551379 -0.685202 -0.574938 0.447096 0.394531 0.113281 1 0 1.000000 +0 -1.987068 -1.667343 5.842322 -0.650563 -0.545885 0.527940 0.394531 0.195313 1 0 1.000000 +holygrail.tga +0 -1.987068 -1.667343 5.842322 -0.650563 -0.545885 0.527940 0.394531 0.195313 1 0 1.000000 +0 -2.437499 -0.887174 5.842322 -0.798029 -0.290445 0.527940 0.339844 0.195313 1 0 1.000000 +0 -3.928903 -1.429999 3.551379 -0.840510 -0.305918 0.447096 0.339844 0.113281 1 0 1.000000 +holygrail.tga +0 -4.181049 0.000003 3.551379 -0.894467 0.000000 0.447096 0.289063 0.113281 1 0 1.000000 +0 -3.928903 -1.429999 3.551379 -0.840510 -0.305918 0.447096 0.339844 0.113281 1 0 1.000000 +0 -2.437499 -0.887174 5.842322 -0.798029 -0.290445 0.527940 0.339844 0.195313 1 0 1.000000 +holygrail.tga +0 -2.437499 -0.887174 5.842322 -0.798029 -0.290445 0.527940 0.339844 0.195313 1 0 1.000000 +0 -2.593930 0.000002 5.842322 -0.849239 0.000000 0.527940 0.289063 0.195313 1 0 1.000000 +0 -4.181049 0.000003 3.551379 -0.894467 0.000000 0.447096 0.289063 0.113281 1 0 1.000000 +holygrail.tga +0 -3.928902 1.430005 3.551379 -0.840510 0.305918 0.447096 0.226563 0.113281 1 0 1.000000 +0 -4.181049 0.000003 3.551379 -0.894467 0.000000 0.447096 0.289063 0.113281 1 0 1.000000 +0 -2.593930 0.000002 5.842322 -0.849239 0.000000 0.527940 0.289063 0.195313 1 0 1.000000 +holygrail.tga +0 -2.593930 0.000002 5.842322 -0.849239 0.000000 0.527940 0.289063 0.195313 1 0 1.000000 +0 -2.437498 0.887178 5.842322 -0.798029 0.290445 0.527940 0.226563 0.195313 1 0 1.000000 +0 -3.928902 1.430005 3.551379 -0.840510 0.305918 0.447096 0.226563 0.113281 1 0 1.000000 +holygrail.tga +0 -3.202868 2.687529 3.551382 -0.685202 0.574938 0.447096 0.171875 0.113281 1 0 1.000000 +0 -3.928902 1.430005 3.551379 -0.840510 0.305918 0.447096 0.226563 0.113281 1 0 1.000000 +0 -2.437498 0.887178 5.842322 -0.798029 0.290445 0.527940 0.226563 0.195313 1 0 1.000000 +holygrail.tga +0 -2.437498 0.887178 5.842322 -0.798029 0.290445 0.527940 0.226563 0.195313 1 0 1.000000 +0 -1.987065 1.667348 5.842324 -0.650563 0.545885 0.527940 0.171875 0.195313 1 0 1.000000 +0 -3.202868 2.687529 3.551382 -0.685202 0.574938 0.447096 0.171875 0.113281 1 0 1.000000 +holygrail.tga +0 -2.090523 3.620899 3.551381 -0.447218 0.774621 0.447096 0.117188 0.113281 1 0 1.000000 +0 -3.202868 2.687529 3.551382 -0.685202 0.574938 0.447096 0.171875 0.113281 1 0 1.000000 +0 -1.987065 1.667348 5.842324 -0.650563 0.545885 0.527940 0.171875 0.195313 1 0 1.000000 +holygrail.tga +0 -1.987065 1.667348 5.842324 -0.650563 0.545885 0.527940 0.171875 0.195313 1 0 1.000000 +0 -1.296963 2.246413 5.842323 -0.424604 0.735466 0.527940 0.117188 0.195313 1 0 1.000000 +0 -2.090523 3.620899 3.551381 -0.447218 0.774621 0.447096 0.117188 0.113281 1 0 1.000000 +holygrail.tga +0 -0.726032 4.117534 3.551381 -0.155309 0.880886 0.447096 0.058594 0.113281 1 0 1.000000 +0 -2.090523 3.620899 3.551381 -0.447218 0.774621 0.447096 0.117188 0.113281 1 0 1.000000 +0 -1.296963 2.246413 5.842323 -0.424604 0.735466 0.527940 0.117188 0.195313 1 0 1.000000 +holygrail.tga +0 -1.296963 2.246413 5.842323 -0.424604 0.735466 0.527940 0.117188 0.195313 1 0 1.000000 +0 -0.450431 2.554526 5.842323 -0.147465 0.836360 0.527940 0.058594 0.195313 1 0 1.000000 +0 -0.726032 4.117534 3.551381 -0.155309 0.880886 0.447096 0.058594 0.113281 1 0 1.000000 +holygrail.tga +0 0.726032 4.117534 3.551381 0.155309 0.880886 0.447096 0.000000 0.113281 1 0 1.000000 +0 -0.726032 4.117534 3.551381 -0.155309 0.880886 0.447096 0.058594 0.113281 1 0 1.000000 +0 -0.450431 2.554526 5.842323 -0.147465 0.836360 0.527940 0.058594 0.195313 1 0 1.000000 +holygrail.tga +0 -0.450431 2.554526 5.842323 -0.147465 0.836360 0.527940 0.058594 0.195313 1 0 1.000000 +0 0.450431 2.554526 5.842323 0.147465 0.836360 0.527940 0.000000 0.195313 1 0 1.000000 +0 0.726032 4.117534 3.551381 0.155309 0.880886 0.447096 0.000000 0.113281 1 0 1.000000 +holygrail.tga +0 2.090526 3.620899 3.551381 0.447218 0.774621 0.447096 0.941406 0.113281 1 0 1.000000 +0 0.726032 4.117534 3.551381 0.155309 0.880886 0.447096 1.000000 0.113281 1 0 1.000000 +0 0.450431 2.554526 5.842323 0.147465 0.836360 0.527940 1.000000 0.195313 1 0 1.000000 +holygrail.tga +0 0.450431 2.554526 5.842323 0.147465 0.836360 0.527940 1.000000 0.195313 1 0 1.000000 +0 1.296966 2.246413 5.842323 0.424604 0.735466 0.527940 0.941406 0.195313 1 0 1.000000 +0 2.090526 3.620899 3.551381 0.447218 0.774621 0.447096 0.941406 0.113281 1 0 1.000000 +holygrail.tga +0 3.202872 2.687529 3.551382 0.685202 0.574938 0.447096 0.886719 0.113281 1 0 1.000000 +0 2.090526 3.620899 3.551381 0.447218 0.774621 0.447096 0.941406 0.113281 1 0 1.000000 +0 1.296966 2.246413 5.842323 0.424604 0.735466 0.527940 0.941406 0.195313 1 0 1.000000 +holygrail.tga +0 1.296966 2.246413 5.842323 0.424604 0.735466 0.527940 0.941406 0.195313 1 0 1.000000 +0 1.987068 1.667347 5.842324 0.650563 0.545885 0.527940 0.886719 0.195313 1 0 1.000000 +0 3.202872 2.687529 3.551382 0.685202 0.574938 0.447096 0.886719 0.113281 1 0 1.000000 +holygrail.tga +0 3.928904 1.430006 3.551379 0.840510 0.305918 0.447096 0.832031 0.113281 1 0 1.000000 +0 3.202872 2.687529 3.551382 0.685202 0.574938 0.447096 0.886719 0.113281 1 0 1.000000 +0 1.987068 1.667347 5.842324 0.650563 0.545885 0.527940 0.886719 0.195313 1 0 1.000000 +holygrail.tga +0 1.987068 1.667347 5.842324 0.650563 0.545885 0.527940 0.886719 0.195313 1 0 1.000000 +0 2.437499 0.887179 5.842322 0.798029 0.290445 0.527940 0.832031 0.195313 1 0 1.000000 +0 3.928904 1.430006 3.551379 0.840510 0.305918 0.447096 0.832031 0.113281 1 0 1.000000 +holygrail.tga +0 5.004897 0.000005 1.180928 0.803430 0.000000 0.595355 0.773438 0.046875 1 0 1.000000 +0 4.703067 1.711779 1.180930 0.754967 0.274789 0.595355 0.832031 0.046875 1 0 1.000000 +0 3.928904 1.430006 3.551379 0.840510 0.305918 0.447096 0.832031 0.113281 1 0 1.000000 +holygrail.tga +0 3.928904 1.430006 3.551379 0.840510 0.305918 0.447096 0.832031 0.113281 1 0 1.000000 +0 4.181049 0.000005 3.551379 0.894467 0.000000 0.447096 0.773438 0.113281 1 0 1.000000 +0 5.004897 0.000005 1.180928 0.803430 0.000000 0.595355 0.773438 0.046875 1 0 1.000000 +holygrail.tga +0 4.703063 -1.711777 1.180928 0.754967 -0.274789 0.595355 0.726563 0.046875 1 0 1.000000 +0 5.004897 0.000005 1.180928 0.803430 0.000000 0.595355 0.773438 0.046875 1 0 1.000000 +0 4.181049 0.000005 3.551379 0.894467 0.000000 0.447096 0.773438 0.113281 1 0 1.000000 +holygrail.tga +0 4.181049 0.000005 3.551379 0.894467 0.000000 0.447096 0.773438 0.113281 1 0 1.000000 +0 3.928901 -1.430004 3.551379 0.840510 -0.305918 0.447096 0.726563 0.113281 1 0 1.000000 +0 4.703063 -1.711777 1.180928 0.754967 -0.274789 0.595355 0.726563 0.046875 1 0 1.000000 +holygrail.tga +0 3.833971 -3.217084 1.180929 0.615467 -0.516434 0.595355 0.664063 0.046875 1 0 1.000000 +0 4.703063 -1.711777 1.180928 0.754967 -0.274789 0.595355 0.726563 0.046875 1 0 1.000000 +0 3.928901 -1.430004 3.551379 0.840510 -0.305918 0.447096 0.726563 0.113281 1 0 1.000000 +holygrail.tga +0 3.928901 -1.430004 3.551379 0.840510 -0.305918 0.447096 0.726563 0.113281 1 0 1.000000 +0 3.202868 -2.687525 3.551379 0.685202 -0.574938 0.447096 0.664063 0.113281 1 0 1.000000 +0 3.833971 -3.217084 1.180929 0.615467 -0.516434 0.595355 0.664063 0.046875 1 0 1.000000 +holygrail.tga +0 2.502445 -4.334369 1.180929 0.401715 -0.695791 0.595355 0.613281 0.046875 1 0 1.000000 +0 3.833971 -3.217084 1.180929 0.615467 -0.516434 0.595355 0.664063 0.046875 1 0 1.000000 +0 3.202868 -2.687525 3.551379 0.685202 -0.574938 0.447096 0.664063 0.113281 1 0 1.000000 +holygrail.tga +0 3.202868 -2.687525 3.551379 0.685202 -0.574938 0.447096 0.664063 0.113281 1 0 1.000000 +0 2.090522 -3.620895 3.551380 0.447218 -0.774621 0.447096 0.613281 0.113281 1 0 1.000000 +0 2.502445 -4.334369 1.180929 0.401715 -0.695791 0.595355 0.613281 0.046875 1 0 1.000000 +holygrail.tga +0 0.869089 -4.928859 1.180929 0.139500 -0.791223 0.595355 0.554688 0.046875 1 0 1.000000 +0 2.502445 -4.334369 1.180929 0.401715 -0.695791 0.595355 0.613281 0.046875 1 0 1.000000 +0 2.090522 -3.620895 3.551380 0.447218 -0.774621 0.447096 0.613281 0.113281 1 0 1.000000 +holygrail.tga +0 2.090522 -3.620895 3.551380 0.447218 -0.774621 0.447096 0.613281 0.113281 1 0 1.000000 +0 0.726029 -4.117528 3.551379 0.155309 -0.880886 0.447096 0.554688 0.113281 1 0 1.000000 +0 0.869089 -4.928859 1.180929 0.139500 -0.791223 0.595355 0.554688 0.046875 1 0 1.000000 +holygrail.tga +0 -0.869091 -4.928859 1.180929 -0.139500 -0.791223 0.595355 0.503906 0.046875 1 0 1.000000 +0 0.869089 -4.928859 1.180929 0.139500 -0.791223 0.595355 0.554688 0.046875 1 0 1.000000 +0 0.726029 -4.117528 3.551379 0.155309 -0.880886 0.447096 0.554688 0.113281 1 0 1.000000 +holygrail.tga +0 0.726029 -4.117528 3.551379 0.155309 -0.880886 0.447096 0.554688 0.113281 1 0 1.000000 +0 -0.726032 -4.117528 3.551379 -0.155309 -0.880886 0.447096 0.503906 0.113281 1 0 1.000000 +0 -0.869091 -4.928859 1.180929 -0.139500 -0.791223 0.595355 0.503906 0.046875 1 0 1.000000 +holygrail.tga +0 -2.502449 -4.334364 1.180929 -0.401715 -0.695791 0.595355 0.449219 0.046875 1 0 1.000000 +0 -0.869091 -4.928859 1.180929 -0.139500 -0.791223 0.595355 0.503906 0.046875 1 0 1.000000 +0 -0.726032 -4.117528 3.551379 -0.155309 -0.880886 0.447096 0.503906 0.113281 1 0 1.000000 +holygrail.tga +0 -0.726032 -4.117528 3.551379 -0.155309 -0.880886 0.447096 0.503906 0.113281 1 0 1.000000 +0 -2.090525 -3.620892 3.551380 -0.447218 -0.774621 0.447096 0.449219 0.113281 1 0 1.000000 +0 -2.502449 -4.334364 1.180929 -0.401715 -0.695791 0.595355 0.449219 0.046875 1 0 1.000000 +holygrail.tga +0 -3.833975 -3.217081 1.180929 -0.615467 -0.516434 0.595355 0.394531 0.046875 1 0 1.000000 +0 -2.502449 -4.334364 1.180929 -0.401715 -0.695791 0.595355 0.449219 0.046875 1 0 1.000000 +0 -2.090525 -3.620892 3.551380 -0.447218 -0.774621 0.447096 0.449219 0.113281 1 0 1.000000 +holygrail.tga +0 -2.090525 -3.620892 3.551380 -0.447218 -0.774621 0.447096 0.449219 0.113281 1 0 1.000000 +0 -3.202872 -2.687522 3.551379 -0.685202 -0.574938 0.447096 0.394531 0.113281 1 0 1.000000 +0 -3.833975 -3.217081 1.180929 -0.615467 -0.516434 0.595355 0.394531 0.046875 1 0 1.000000 +holygrail.tga +0 -4.703066 -1.711772 1.180928 -0.754967 -0.274789 0.595355 0.339844 0.046875 1 0 1.000000 +0 -3.833975 -3.217081 1.180929 -0.615467 -0.516434 0.595355 0.394531 0.046875 1 0 1.000000 +0 -3.202872 -2.687522 3.551379 -0.685202 -0.574938 0.447096 0.394531 0.113281 1 0 1.000000 +holygrail.tga +0 -3.202872 -2.687522 3.551379 -0.685202 -0.574938 0.447096 0.394531 0.113281 1 0 1.000000 +0 -3.928903 -1.429999 3.551379 -0.840510 -0.305918 0.447096 0.339844 0.113281 1 0 1.000000 +0 -4.703066 -1.711772 1.180928 -0.754967 -0.274789 0.595355 0.339844 0.046875 1 0 1.000000 +holygrail.tga +0 -5.004897 0.000003 1.180928 -0.803430 0.000000 0.595355 0.289063 0.046875 1 0 1.000000 +0 -4.703066 -1.711772 1.180928 -0.754967 -0.274789 0.595355 0.339844 0.046875 1 0 1.000000 +0 -3.928903 -1.429999 3.551379 -0.840510 -0.305918 0.447096 0.339844 0.113281 1 0 1.000000 +holygrail.tga +0 -3.928903 -1.429999 3.551379 -0.840510 -0.305918 0.447096 0.339844 0.113281 1 0 1.000000 +0 -4.181049 0.000003 3.551379 -0.894467 0.000000 0.447096 0.289063 0.113281 1 0 1.000000 +0 -5.004897 0.000003 1.180928 -0.803430 0.000000 0.595355 0.289063 0.046875 1 0 1.000000 +holygrail.tga +0 -4.703065 1.711778 1.180930 -0.754967 0.274789 0.595355 0.226563 0.046875 1 0 1.000000 +0 -5.004897 0.000003 1.180928 -0.803430 0.000000 0.595355 0.289063 0.046875 1 0 1.000000 +0 -4.181049 0.000003 3.551379 -0.894467 0.000000 0.447096 0.289063 0.113281 1 0 1.000000 +holygrail.tga +0 -4.181049 0.000003 3.551379 -0.894467 0.000000 0.447096 0.289063 0.113281 1 0 1.000000 +0 -3.928902 1.430005 3.551379 -0.840510 0.305918 0.447096 0.226563 0.113281 1 0 1.000000 +0 -4.703065 1.711778 1.180930 -0.754967 0.274789 0.595355 0.226563 0.046875 1 0 1.000000 +holygrail.tga +0 -3.833973 3.217087 1.180931 -0.615467 0.516434 0.595355 0.171875 0.046875 1 0 1.000000 +0 -4.703065 1.711778 1.180930 -0.754967 0.274789 0.595355 0.226563 0.046875 1 0 1.000000 +0 -3.928902 1.430005 3.551379 -0.840510 0.305918 0.447096 0.226563 0.113281 1 0 1.000000 +holygrail.tga +0 -3.928902 1.430005 3.551379 -0.840510 0.305918 0.447096 0.226563 0.113281 1 0 1.000000 +0 -3.202868 2.687529 3.551382 -0.685202 0.574938 0.447096 0.171875 0.113281 1 0 1.000000 +0 -3.833973 3.217087 1.180931 -0.615467 0.516434 0.595355 0.171875 0.046875 1 0 1.000000 +holygrail.tga +0 -2.502447 4.334371 1.180930 -0.401715 0.695791 0.595355 0.117188 0.046875 1 0 1.000000 +0 -3.833973 3.217087 1.180931 -0.615467 0.516434 0.595355 0.171875 0.046875 1 0 1.000000 +0 -3.202868 2.687529 3.551382 -0.685202 0.574938 0.447096 0.171875 0.113281 1 0 1.000000 +holygrail.tga +0 -3.202868 2.687529 3.551382 -0.685202 0.574938 0.447096 0.171875 0.113281 1 0 1.000000 +0 -2.090523 3.620899 3.551381 -0.447218 0.774621 0.447096 0.117188 0.113281 1 0 1.000000 +0 -2.502447 4.334371 1.180930 -0.401715 0.695791 0.595355 0.117188 0.046875 1 0 1.000000 +holygrail.tga +0 -0.869092 4.928864 1.180930 -0.139500 0.791223 0.595355 0.058594 0.046875 1 0 1.000000 +0 -2.502447 4.334371 1.180930 -0.401715 0.695791 0.595355 0.117188 0.046875 1 0 1.000000 +0 -2.090523 3.620899 3.551381 -0.447218 0.774621 0.447096 0.117188 0.113281 1 0 1.000000 +holygrail.tga +0 -2.090523 3.620899 3.551381 -0.447218 0.774621 0.447096 0.117188 0.113281 1 0 1.000000 +0 -0.726032 4.117534 3.551381 -0.155309 0.880886 0.447096 0.058594 0.113281 1 0 1.000000 +0 -0.869092 4.928864 1.180930 -0.139500 0.791223 0.595355 0.058594 0.046875 1 0 1.000000 +holygrail.tga +0 0.869091 4.928864 1.180930 0.139500 0.791223 0.595355 0.000000 0.046875 1 0 1.000000 +0 -0.869092 4.928864 1.180930 -0.139500 0.791223 0.595355 0.058594 0.046875 1 0 1.000000 +0 -0.726032 4.117534 3.551381 -0.155309 0.880886 0.447096 0.058594 0.113281 1 0 1.000000 +holygrail.tga +0 -0.726032 4.117534 3.551381 -0.155309 0.880886 0.447096 0.058594 0.113281 1 0 1.000000 +0 0.726032 4.117534 3.551381 0.155309 0.880886 0.447096 0.000000 0.113281 1 0 1.000000 +0 0.869091 4.928864 1.180930 0.139500 0.791223 0.595355 0.000000 0.046875 1 0 1.000000 +holygrail.tga +0 2.502450 4.334371 1.180930 0.401715 0.695791 0.595355 0.941406 0.046875 1 0 1.000000 +0 0.869091 4.928864 1.180930 0.139500 0.791223 0.595355 1.000000 0.046875 1 0 1.000000 +0 0.726032 4.117534 3.551381 0.155309 0.880886 0.447096 1.000000 0.113281 1 0 1.000000 +holygrail.tga +0 0.726032 4.117534 3.551381 0.155309 0.880886 0.447096 1.000000 0.113281 1 0 1.000000 +0 2.090526 3.620899 3.551381 0.447218 0.774621 0.447096 0.941406 0.113281 1 0 1.000000 +0 2.502450 4.334371 1.180930 0.401715 0.695791 0.595355 0.941406 0.046875 1 0 1.000000 +holygrail.tga +0 3.833976 3.217088 1.180931 0.615467 0.516434 0.595355 0.886719 0.046875 1 0 1.000000 +0 2.502450 4.334371 1.180930 0.401715 0.695791 0.595355 0.941406 0.046875 1 0 1.000000 +0 2.090526 3.620899 3.551381 0.447218 0.774621 0.447096 0.941406 0.113281 1 0 1.000000 +holygrail.tga +0 2.090526 3.620899 3.551381 0.447218 0.774621 0.447096 0.941406 0.113281 1 0 1.000000 +0 3.202872 2.687529 3.551382 0.685202 0.574938 0.447096 0.886719 0.113281 1 0 1.000000 +0 3.833976 3.217088 1.180931 0.615467 0.516434 0.595355 0.886719 0.046875 1 0 1.000000 +holygrail.tga +0 4.703067 1.711779 1.180930 0.754967 0.274789 0.595355 0.832031 0.046875 1 0 1.000000 +0 3.833976 3.217088 1.180931 0.615467 0.516434 0.595355 0.886719 0.046875 1 0 1.000000 +0 3.202872 2.687529 3.551382 0.685202 0.574938 0.447096 0.886719 0.113281 1 0 1.000000 +holygrail.tga +0 3.202872 2.687529 3.551382 0.685202 0.574938 0.447096 0.886719 0.113281 1 0 1.000000 +0 3.928904 1.430006 3.551379 0.840510 0.305918 0.447096 0.832031 0.113281 1 0 1.000000 +0 4.703067 1.711779 1.180930 0.754967 0.274789 0.595355 0.832031 0.046875 1 0 1.000000 +holygrail.tga +0 5.458378 0.000005 0.823655 0.945036 0.000000 0.326945 0.773438 0.031250 1 0 1.000000 +0 5.129200 1.866878 0.823657 0.888028 0.323222 0.326945 0.832031 0.031250 1 0 1.000000 +0 4.703067 1.711779 1.180930 0.754967 0.274789 0.595355 0.832031 0.046875 1 0 1.000000 +holygrail.tga +0 4.703067 1.711779 1.180930 0.754967 0.274789 0.595355 0.832031 0.046875 1 0 1.000000 +0 5.004897 0.000005 1.180928 0.803430 0.000000 0.595355 0.773438 0.046875 1 0 1.000000 +0 5.458378 0.000005 0.823655 0.945036 0.000000 0.326945 0.773438 0.031250 1 0 1.000000 +holygrail.tga +0 5.129196 -1.866876 0.823655 0.888028 -0.323222 0.326945 0.726563 0.031250 1 0 1.000000 +0 5.458378 0.000005 0.823655 0.945036 0.000000 0.326945 0.773438 0.031250 1 0 1.000000 +0 5.004897 0.000005 1.180928 0.803430 0.000000 0.595355 0.773438 0.046875 1 0 1.000000 +holygrail.tga +0 5.004897 0.000005 1.180928 0.803430 0.000000 0.595355 0.773438 0.046875 1 0 1.000000 +0 4.703063 -1.711777 1.180928 0.754967 -0.274789 0.595355 0.726563 0.046875 1 0 1.000000 +0 5.129196 -1.866876 0.823655 0.888028 -0.323222 0.326945 0.726563 0.031250 1 0 1.000000 +holygrail.tga +0 4.181357 -3.508576 0.823656 0.723930 -0.607440 0.326945 0.664063 0.031250 1 0 1.000000 +0 5.129196 -1.866876 0.823655 0.888028 -0.323222 0.326945 0.726563 0.031250 1 0 1.000000 +0 4.703063 -1.711777 1.180928 0.754967 -0.274789 0.595355 0.726563 0.046875 1 0 1.000000 +holygrail.tga +0 4.703063 -1.711777 1.180928 0.754967 -0.274789 0.595355 0.726563 0.046875 1 0 1.000000 +0 3.833971 -3.217084 1.180929 0.615467 -0.516434 0.595355 0.664063 0.046875 1 0 1.000000 +0 4.181357 -3.508576 0.823656 0.723930 -0.607440 0.326945 0.664063 0.031250 1 0 1.000000 +holygrail.tga +0 2.729186 -4.727095 0.823656 0.472518 -0.818415 0.326945 0.613281 0.031250 1 0 1.000000 +0 4.181357 -3.508576 0.823656 0.723930 -0.607440 0.326945 0.664063 0.031250 1 0 1.000000 +0 3.833971 -3.217084 1.180929 0.615467 -0.516434 0.595355 0.664063 0.046875 1 0 1.000000 +holygrail.tga +0 3.833971 -3.217084 1.180929 0.615467 -0.516434 0.595355 0.664063 0.046875 1 0 1.000000 +0 2.502445 -4.334369 1.180929 0.401715 -0.695791 0.595355 0.613281 0.046875 1 0 1.000000 +0 2.729186 -4.727095 0.823656 0.472518 -0.818415 0.326945 0.613281 0.031250 1 0 1.000000 +holygrail.tga +0 0.947835 -5.375450 0.823656 0.164098 -0.930662 0.326945 0.554688 0.031250 1 0 1.000000 +0 2.729186 -4.727095 0.823656 0.472518 -0.818415 0.326945 0.613281 0.031250 1 0 1.000000 +0 2.502445 -4.334369 1.180929 0.401715 -0.695791 0.595355 0.613281 0.046875 1 0 1.000000 +holygrail.tga +0 2.502445 -4.334369 1.180929 0.401715 -0.695791 0.595355 0.613281 0.046875 1 0 1.000000 +0 0.869089 -4.928859 1.180929 0.139500 -0.791223 0.595355 0.554688 0.046875 1 0 1.000000 +0 0.947835 -5.375450 0.823656 0.164098 -0.930662 0.326945 0.554688 0.031250 1 0 1.000000 +holygrail.tga +0 -0.947838 -5.375450 0.823656 -0.164098 -0.930662 0.326945 0.503906 0.031250 1 0 1.000000 +0 0.947835 -5.375450 0.823656 0.164098 -0.930662 0.326945 0.554688 0.031250 1 0 1.000000 +0 0.869089 -4.928859 1.180929 0.139500 -0.791223 0.595355 0.554688 0.046875 1 0 1.000000 +holygrail.tga +0 0.869089 -4.928859 1.180929 0.139500 -0.791223 0.595355 0.554688 0.046875 1 0 1.000000 +0 -0.869091 -4.928859 1.180929 -0.139500 -0.791223 0.595355 0.503906 0.046875 1 0 1.000000 +0 -0.947838 -5.375450 0.823656 -0.164098 -0.930662 0.326945 0.503906 0.031250 1 0 1.000000 +holygrail.tga +0 -2.729190 -4.727090 0.823656 -0.472518 -0.818415 0.326945 0.449219 0.031250 1 0 1.000000 +0 -0.947838 -5.375450 0.823656 -0.164098 -0.930662 0.326945 0.503906 0.031250 1 0 1.000000 +0 -0.869091 -4.928859 1.180929 -0.139500 -0.791223 0.595355 0.503906 0.046875 1 0 1.000000 +holygrail.tga +0 -0.869091 -4.928859 1.180929 -0.139500 -0.791223 0.595355 0.503906 0.046875 1 0 1.000000 +0 -2.502449 -4.334364 1.180929 -0.401715 -0.695791 0.595355 0.449219 0.046875 1 0 1.000000 +0 -2.729190 -4.727090 0.823656 -0.472518 -0.818415 0.326945 0.449219 0.031250 1 0 1.000000 +holygrail.tga +0 -4.181361 -3.508573 0.823656 -0.723930 -0.607440 0.326945 0.394531 0.031250 1 0 1.000000 +0 -2.729190 -4.727090 0.823656 -0.472518 -0.818415 0.326945 0.449219 0.031250 1 0 1.000000 +0 -2.502449 -4.334364 1.180929 -0.401715 -0.695791 0.595355 0.449219 0.046875 1 0 1.000000 +holygrail.tga +0 -2.502449 -4.334364 1.180929 -0.401715 -0.695791 0.595355 0.449219 0.046875 1 0 1.000000 +0 -3.833975 -3.217081 1.180929 -0.615467 -0.516434 0.595355 0.394531 0.046875 1 0 1.000000 +0 -4.181361 -3.508573 0.823656 -0.723930 -0.607440 0.326945 0.394531 0.031250 1 0 1.000000 +holygrail.tga +0 -3.833975 -3.217081 1.180929 -0.615467 -0.516434 0.595355 0.394531 0.046875 1 0 1.000000 +0 -4.703066 -1.711772 1.180928 -0.754967 -0.274789 0.595355 0.339844 0.046875 1 0 1.000000 +0 -5.129199 -1.866871 0.823655 -0.888028 -0.323222 0.326945 0.339844 0.031250 1 0 1.000000 +holygrail.tga +0 -5.458377 0.000004 0.823655 -0.945036 0.000000 0.326945 0.289063 0.031250 1 0 1.000000 +0 -5.129199 -1.866871 0.823655 -0.888028 -0.323222 0.326945 0.339844 0.031250 1 0 1.000000 +0 -4.703066 -1.711772 1.180928 -0.754967 -0.274789 0.595355 0.339844 0.046875 1 0 1.000000 +holygrail.tga +0 -4.703066 -1.711772 1.180928 -0.754967 -0.274789 0.595355 0.339844 0.046875 1 0 1.000000 +0 -5.004897 0.000003 1.180928 -0.803430 0.000000 0.595355 0.289063 0.046875 1 0 1.000000 +0 -5.458377 0.000004 0.823655 -0.945036 0.000000 0.326945 0.289063 0.031250 1 0 1.000000 +holygrail.tga +0 -5.129197 1.866878 0.823657 -0.888028 0.323222 0.326945 0.226563 0.031250 1 0 1.000000 +0 -5.458377 0.000004 0.823655 -0.945036 0.000000 0.326945 0.289063 0.031250 1 0 1.000000 +0 -5.004897 0.000003 1.180928 -0.803430 0.000000 0.595355 0.289063 0.046875 1 0 1.000000 +holygrail.tga +0 -5.004897 0.000003 1.180928 -0.803430 0.000000 0.595355 0.289063 0.046875 1 0 1.000000 +0 -4.703065 1.711778 1.180930 -0.754967 0.274789 0.595355 0.226563 0.046875 1 0 1.000000 +0 -5.129197 1.866878 0.823657 -0.888028 0.323222 0.326945 0.226563 0.031250 1 0 1.000000 +holygrail.tga +0 -4.181359 3.508579 0.823658 -0.723930 0.607440 0.326945 0.171875 0.031250 1 0 1.000000 +0 -5.129197 1.866878 0.823657 -0.888028 0.323222 0.326945 0.226563 0.031250 1 0 1.000000 +0 -4.703065 1.711778 1.180930 -0.754967 0.274789 0.595355 0.226563 0.046875 1 0 1.000000 +holygrail.tga +0 -4.703065 1.711778 1.180930 -0.754967 0.274789 0.595355 0.226563 0.046875 1 0 1.000000 +0 -3.833973 3.217087 1.180931 -0.615467 0.516434 0.595355 0.171875 0.046875 1 0 1.000000 +0 -4.181359 3.508579 0.823658 -0.723930 0.607440 0.326945 0.171875 0.031250 1 0 1.000000 +holygrail.tga +0 -2.729187 4.727097 0.823657 -0.472518 0.818415 0.326945 0.117188 0.031250 1 0 1.000000 +0 -4.181359 3.508579 0.823658 -0.723930 0.607440 0.326945 0.171875 0.031250 1 0 1.000000 +0 -3.833973 3.217087 1.180931 -0.615467 0.516434 0.595355 0.171875 0.046875 1 0 1.000000 +holygrail.tga +0 -3.833973 3.217087 1.180931 -0.615467 0.516434 0.595355 0.171875 0.046875 1 0 1.000000 +0 -2.502447 4.334371 1.180930 -0.401715 0.695791 0.595355 0.117188 0.046875 1 0 1.000000 +0 -2.729187 4.727097 0.823657 -0.472518 0.818415 0.326945 0.117188 0.031250 1 0 1.000000 +holygrail.tga +0 -0.947838 5.375456 0.823657 -0.164098 0.930662 0.326945 0.058594 0.031250 1 0 1.000000 +0 -2.729187 4.727097 0.823657 -0.472518 0.818415 0.326945 0.117188 0.031250 1 0 1.000000 +0 -2.502447 4.334371 1.180930 -0.401715 0.695791 0.595355 0.117188 0.046875 1 0 1.000000 +holygrail.tga +0 -2.502447 4.334371 1.180930 -0.401715 0.695791 0.595355 0.117188 0.046875 1 0 1.000000 +0 -0.869092 4.928864 1.180930 -0.139500 0.791223 0.595355 0.058594 0.046875 1 0 1.000000 +0 -0.947838 5.375456 0.823657 -0.164098 0.930662 0.326945 0.058594 0.031250 1 0 1.000000 +holygrail.tga +0 0.947837 5.375456 0.823657 0.164098 0.930662 0.326945 0.000000 0.031250 1 0 1.000000 +0 -0.947838 5.375456 0.823657 -0.164098 0.930662 0.326945 0.058594 0.031250 1 0 1.000000 +0 -0.869092 4.928864 1.180930 -0.139500 0.791223 0.595355 0.058594 0.046875 1 0 1.000000 +holygrail.tga +0 -0.869092 4.928864 1.180930 -0.139500 0.791223 0.595355 0.058594 0.046875 1 0 1.000000 +0 0.869091 4.928864 1.180930 0.139500 0.791223 0.595355 0.000000 0.046875 1 0 1.000000 +0 0.947837 5.375456 0.823657 0.164098 0.930662 0.326945 0.000000 0.031250 1 0 1.000000 +holygrail.tga +0 2.729190 4.727097 0.823657 0.472518 0.818415 0.326945 0.941406 0.031250 1 0 1.000000 +0 0.947837 5.375456 0.823657 0.164098 0.930662 0.326945 1.000000 0.031250 1 0 1.000000 +0 0.869091 4.928864 1.180930 0.139500 0.791223 0.595355 1.000000 0.046875 1 0 1.000000 +holygrail.tga +0 0.869091 4.928864 1.180930 0.139500 0.791223 0.595355 1.000000 0.046875 1 0 1.000000 +0 2.502450 4.334371 1.180930 0.401715 0.695791 0.595355 0.941406 0.046875 1 0 1.000000 +0 2.729190 4.727097 0.823657 0.472518 0.818415 0.326945 0.941406 0.031250 1 0 1.000000 +holygrail.tga +0 4.181362 3.508579 0.823658 0.723930 0.607440 0.326945 0.886719 0.031250 1 0 1.000000 +0 2.729190 4.727097 0.823657 0.472518 0.818415 0.326945 0.941406 0.031250 1 0 1.000000 +0 2.502450 4.334371 1.180930 0.401715 0.695791 0.595355 0.941406 0.046875 1 0 1.000000 +holygrail.tga +0 2.502450 4.334371 1.180930 0.401715 0.695791 0.595355 0.941406 0.046875 1 0 1.000000 +0 3.833976 3.217088 1.180931 0.615467 0.516434 0.595355 0.886719 0.046875 1 0 1.000000 +0 4.181362 3.508579 0.823658 0.723930 0.607440 0.326945 0.886719 0.031250 1 0 1.000000 +holygrail.tga +0 5.129200 1.866878 0.823657 0.888028 0.323222 0.326945 0.832031 0.031250 1 0 1.000000 +0 4.181362 3.508579 0.823658 0.723930 0.607440 0.326945 0.886719 0.031250 1 0 1.000000 +0 3.833976 3.217088 1.180931 0.615467 0.516434 0.595355 0.886719 0.046875 1 0 1.000000 +holygrail.tga +0 3.833976 3.217088 1.180931 0.615467 0.516434 0.595355 0.886719 0.046875 1 0 1.000000 +0 4.703067 1.711779 1.180930 0.754967 0.274789 0.595355 0.832031 0.046875 1 0 1.000000 +0 5.129200 1.866878 0.823657 0.888028 0.323222 0.326945 0.832031 0.031250 1 0 1.000000 +holygrail.tga +0 5.367682 0.000005 0.377064 0.780297 0.000000 -0.625355 0.773438 0.011719 1 0 1.000000 +0 5.043973 1.835858 0.377065 0.733238 0.266884 -0.625355 0.832031 0.011719 1 0 1.000000 +0 5.129200 1.866878 0.823657 0.888028 0.323222 0.326945 0.832031 0.031250 1 0 1.000000 +holygrail.tga +0 5.129200 1.866878 0.823657 0.888028 0.323222 0.326945 0.832031 0.031250 1 0 1.000000 +0 5.458378 0.000005 0.823655 0.945036 0.000000 0.326945 0.773438 0.031250 1 0 1.000000 +0 5.367682 0.000005 0.377064 0.780297 0.000000 -0.625355 0.773438 0.011719 1 0 1.000000 +holygrail.tga +0 5.043969 -1.835857 0.377064 0.733238 -0.266884 -0.625355 0.726563 0.011719 1 0 1.000000 +0 5.367682 0.000005 0.377064 0.780297 0.000000 -0.625355 0.773438 0.011719 1 0 1.000000 +0 5.458378 0.000005 0.823655 0.945036 0.000000 0.326945 0.773438 0.031250 1 0 1.000000 +holygrail.tga +0 5.458378 0.000005 0.823655 0.945036 0.000000 0.326945 0.773438 0.031250 1 0 1.000000 +0 5.129196 -1.866876 0.823655 0.888028 -0.323222 0.326945 0.726563 0.031250 1 0 1.000000 +0 5.043969 -1.835857 0.377064 0.733238 -0.266884 -0.625355 0.726563 0.011719 1 0 1.000000 +holygrail.tga +0 4.111880 -3.450277 0.377065 0.597736 -0.501572 -0.625355 0.664063 0.011719 1 0 1.000000 +0 5.043969 -1.835857 0.377064 0.733238 -0.266884 -0.625355 0.726563 0.011719 1 0 1.000000 +0 5.129196 -1.866876 0.823655 0.888028 -0.323222 0.326945 0.726563 0.031250 1 0 1.000000 +holygrail.tga +0 5.129196 -1.866876 0.823655 0.888028 -0.323222 0.326945 0.726563 0.031250 1 0 1.000000 +0 4.181357 -3.508576 0.823656 0.723930 -0.607440 0.326945 0.664063 0.031250 1 0 1.000000 +0 4.111880 -3.450277 0.377065 0.597736 -0.501572 -0.625355 0.664063 0.011719 1 0 1.000000 +holygrail.tga +0 2.683838 -4.648550 0.377065 0.390149 -0.675771 -0.625355 0.613281 0.011719 1 0 1.000000 +0 4.111880 -3.450277 0.377065 0.597736 -0.501572 -0.625355 0.664063 0.011719 1 0 1.000000 +0 4.181357 -3.508576 0.823656 0.723930 -0.607440 0.326945 0.664063 0.031250 1 0 1.000000 +holygrail.tga +0 4.181357 -3.508576 0.823656 0.723930 -0.607440 0.326945 0.664063 0.031250 1 0 1.000000 +0 2.729186 -4.727095 0.823656 0.472518 -0.818415 0.326945 0.613281 0.031250 1 0 1.000000 +0 2.683838 -4.648550 0.377065 0.390149 -0.675771 -0.625355 0.613281 0.011719 1 0 1.000000 +holygrail.tga +0 0.932086 -5.286132 0.377065 0.135472 -0.768456 -0.625355 0.554688 0.011719 1 0 1.000000 +0 2.683838 -4.648550 0.377065 0.390149 -0.675771 -0.625355 0.613281 0.011719 1 0 1.000000 +0 2.729186 -4.727095 0.823656 0.472518 -0.818415 0.326945 0.613281 0.031250 1 0 1.000000 +holygrail.tga +0 2.729186 -4.727095 0.823656 0.472518 -0.818415 0.326945 0.613281 0.031250 1 0 1.000000 +0 0.947835 -5.375450 0.823656 0.164098 -0.930662 0.326945 0.554688 0.031250 1 0 1.000000 +0 0.932086 -5.286132 0.377065 0.135472 -0.768456 -0.625355 0.554688 0.011719 1 0 1.000000 +holygrail.tga +0 -0.932088 -5.286132 0.377065 -0.135472 -0.768456 -0.625355 0.503906 0.011719 1 0 1.000000 +0 0.932086 -5.286132 0.377065 0.135472 -0.768456 -0.625355 0.554688 0.011719 1 0 1.000000 +0 0.947835 -5.375450 0.823656 0.164098 -0.930662 0.326945 0.554688 0.031250 1 0 1.000000 +holygrail.tga +0 0.947835 -5.375450 0.823656 0.164098 -0.930662 0.326945 0.554688 0.031250 1 0 1.000000 +0 -0.947838 -5.375450 0.823656 -0.164098 -0.930662 0.326945 0.503906 0.031250 1 0 1.000000 +0 -0.932088 -5.286132 0.377065 -0.135472 -0.768456 -0.625355 0.503906 0.011719 1 0 1.000000 +holygrail.tga +0 -2.683842 -4.648545 0.377065 -0.390149 -0.675771 -0.625355 0.449219 0.011719 1 0 1.000000 +0 -0.932088 -5.286132 0.377065 -0.135472 -0.768456 -0.625355 0.503906 0.011719 1 0 1.000000 +0 -0.947838 -5.375450 0.823656 -0.164098 -0.930662 0.326945 0.503906 0.031250 1 0 1.000000 +holygrail.tga +0 -0.947838 -5.375450 0.823656 -0.164098 -0.930662 0.326945 0.503906 0.031250 1 0 1.000000 +0 -2.729190 -4.727090 0.823656 -0.472518 -0.818415 0.326945 0.449219 0.031250 1 0 1.000000 +0 -2.683842 -4.648545 0.377065 -0.390149 -0.675771 -0.625355 0.449219 0.011719 1 0 1.000000 +holygrail.tga +0 -4.111884 -3.450274 0.377065 -0.597736 -0.501572 -0.625355 0.394531 0.011719 1 0 1.000000 +0 -2.683842 -4.648545 0.377065 -0.390149 -0.675771 -0.625355 0.449219 0.011719 1 0 1.000000 +0 -2.729190 -4.727090 0.823656 -0.472518 -0.818415 0.326945 0.449219 0.031250 1 0 1.000000 +holygrail.tga +0 -2.729190 -4.727090 0.823656 -0.472518 -0.818415 0.326945 0.449219 0.031250 1 0 1.000000 +0 -4.181361 -3.508573 0.823656 -0.723930 -0.607440 0.326945 0.394531 0.031250 1 0 1.000000 +0 -4.111884 -3.450274 0.377065 -0.597736 -0.501572 -0.625355 0.394531 0.011719 1 0 1.000000 +holygrail.tga +0 -5.043972 -1.835851 0.377064 -0.733238 -0.266884 -0.625355 0.339844 0.011719 1 0 1.000000 +0 -4.111884 -3.450274 0.377065 -0.597736 -0.501572 -0.625355 0.394531 0.011719 1 0 1.000000 +0 -4.181361 -3.508573 0.823656 -0.723930 -0.607440 0.326945 0.394531 0.031250 1 0 1.000000 +holygrail.tga +0 -4.181361 -3.508573 0.823656 -0.723930 -0.607440 0.326945 0.394531 0.031250 1 0 1.000000 +0 -5.129199 -1.866871 0.823655 -0.888028 -0.323222 0.326945 0.339844 0.031250 1 0 1.000000 +0 -5.043972 -1.835851 0.377064 -0.733238 -0.266884 -0.625355 0.339844 0.011719 1 0 1.000000 +holygrail.tga +0 -5.367681 0.000004 0.377064 -0.780297 0.000000 -0.625355 0.289063 0.011719 1 0 1.000000 +0 -5.043972 -1.835851 0.377064 -0.733238 -0.266884 -0.625355 0.339844 0.011719 1 0 1.000000 +0 -5.129199 -1.866871 0.823655 -0.888028 -0.323222 0.326945 0.339844 0.031250 1 0 1.000000 +holygrail.tga +0 -5.129199 -1.866871 0.823655 -0.888028 -0.323222 0.326945 0.339844 0.031250 1 0 1.000000 +0 -5.458377 0.000004 0.823655 -0.945036 0.000000 0.326945 0.289063 0.031250 1 0 1.000000 +0 -5.367681 0.000004 0.377064 -0.780297 0.000000 -0.625355 0.289063 0.011719 1 0 1.000000 +holygrail.tga +0 -5.043971 1.835858 0.377065 -0.733238 0.266884 -0.625355 0.226563 0.011719 1 0 1.000000 +0 -5.367681 0.000004 0.377064 -0.780297 0.000000 -0.625355 0.289063 0.011719 1 0 1.000000 +0 -5.458377 0.000004 0.823655 -0.945036 0.000000 0.326945 0.289063 0.031250 1 0 1.000000 +holygrail.tga +0 -5.458377 0.000004 0.823655 -0.945036 0.000000 0.326945 0.289063 0.031250 1 0 1.000000 +0 -5.129197 1.866878 0.823657 -0.888028 0.323222 0.326945 0.226563 0.031250 1 0 1.000000 +0 -5.043971 1.835858 0.377065 -0.733238 0.266884 -0.625355 0.226563 0.011719 1 0 1.000000 +holygrail.tga +0 -4.111882 3.450281 0.377067 -0.597736 0.501572 -0.625355 0.171875 0.011719 1 0 1.000000 +0 -5.043971 1.835858 0.377065 -0.733238 0.266884 -0.625355 0.226563 0.011719 1 0 1.000000 +0 -5.129197 1.866878 0.823657 -0.888028 0.323222 0.326945 0.226563 0.031250 1 0 1.000000 +holygrail.tga +0 -5.129197 1.866878 0.823657 -0.888028 0.323222 0.326945 0.226563 0.031250 1 0 1.000000 +0 -4.181359 3.508579 0.823658 -0.723930 0.607440 0.326945 0.171875 0.031250 1 0 1.000000 +0 -4.111882 3.450281 0.377067 -0.597736 0.501572 -0.625355 0.171875 0.011719 1 0 1.000000 +holygrail.tga +0 -2.683839 4.648551 0.377066 -0.390149 0.675771 -0.625355 0.117188 0.011719 1 0 1.000000 +0 -4.111882 3.450281 0.377067 -0.597736 0.501572 -0.625355 0.171875 0.011719 1 0 1.000000 +0 -4.181359 3.508579 0.823658 -0.723930 0.607440 0.326945 0.171875 0.031250 1 0 1.000000 +holygrail.tga +0 -4.181359 3.508579 0.823658 -0.723930 0.607440 0.326945 0.171875 0.031250 1 0 1.000000 +0 -2.729187 4.727097 0.823657 -0.472518 0.818415 0.326945 0.117188 0.031250 1 0 1.000000 +0 -2.683839 4.648551 0.377066 -0.390149 0.675771 -0.625355 0.117188 0.011719 1 0 1.000000 +holygrail.tga +0 -0.932089 5.286138 0.377066 -0.135472 0.768456 -0.625355 0.058594 0.011719 1 0 1.000000 +0 -2.683839 4.648551 0.377066 -0.390149 0.675771 -0.625355 0.117188 0.011719 1 0 1.000000 +0 -2.729187 4.727097 0.823657 -0.472518 0.818415 0.326945 0.117188 0.031250 1 0 1.000000 +holygrail.tga +0 -2.729187 4.727097 0.823657 -0.472518 0.818415 0.326945 0.117188 0.031250 1 0 1.000000 +0 -0.947838 5.375456 0.823657 -0.164098 0.930662 0.326945 0.058594 0.031250 1 0 1.000000 +0 -0.932089 5.286138 0.377066 -0.135472 0.768456 -0.625355 0.058594 0.011719 1 0 1.000000 +holygrail.tga +0 0.932088 5.286138 0.377066 0.135472 0.768456 -0.625355 0.000000 0.011719 1 0 1.000000 +0 -0.932089 5.286138 0.377066 -0.135472 0.768456 -0.625355 0.058594 0.011719 1 0 1.000000 +0 -0.947838 5.375456 0.823657 -0.164098 0.930662 0.326945 0.058594 0.031250 1 0 1.000000 +holygrail.tga +0 -0.947838 5.375456 0.823657 -0.164098 0.930662 0.326945 0.058594 0.031250 1 0 1.000000 +0 0.947837 5.375456 0.823657 0.164098 0.930662 0.326945 0.000000 0.031250 1 0 1.000000 +0 0.932088 5.286138 0.377066 0.135472 0.768456 -0.625355 0.000000 0.011719 1 0 1.000000 +holygrail.tga +0 2.683842 4.648551 0.377066 0.390149 0.675771 -0.625355 0.941406 0.011719 1 0 1.000000 +0 0.932088 5.286138 0.377066 0.135472 0.768456 -0.625355 1.000000 0.011719 1 0 1.000000 +0 0.947837 5.375456 0.823657 0.164098 0.930662 0.326945 1.000000 0.031250 1 0 1.000000 +holygrail.tga +0 0.947837 5.375456 0.823657 0.164098 0.930662 0.326945 1.000000 0.031250 1 0 1.000000 +0 2.729190 4.727097 0.823657 0.472518 0.818415 0.326945 0.941406 0.031250 1 0 1.000000 +0 2.683842 4.648551 0.377066 0.390149 0.675771 -0.625355 0.941406 0.011719 1 0 1.000000 +holygrail.tga +0 4.111885 3.450281 0.377067 0.597736 0.501572 -0.625355 0.886719 0.011719 1 0 1.000000 +0 2.683842 4.648551 0.377066 0.390149 0.675771 -0.625355 0.941406 0.011719 1 0 1.000000 +0 2.729190 4.727097 0.823657 0.472518 0.818415 0.326945 0.941406 0.031250 1 0 1.000000 +holygrail.tga +0 2.729190 4.727097 0.823657 0.472518 0.818415 0.326945 0.941406 0.031250 1 0 1.000000 +0 4.181362 3.508579 0.823658 0.723930 0.607440 0.326945 0.886719 0.031250 1 0 1.000000 +0 4.111885 3.450281 0.377067 0.597736 0.501572 -0.625355 0.886719 0.011719 1 0 1.000000 +holygrail.tga +0 5.043973 1.835858 0.377065 0.733238 0.266884 -0.625355 0.832031 0.011719 1 0 1.000000 +0 4.111885 3.450281 0.377067 0.597736 0.501572 -0.625355 0.886719 0.011719 1 0 1.000000 +0 4.181362 3.508579 0.823658 0.723930 0.607440 0.326945 0.886719 0.031250 1 0 1.000000 +holygrail.tga +0 4.181362 3.508579 0.823658 0.723930 0.607440 0.326945 0.886719 0.031250 1 0 1.000000 +0 5.129200 1.866878 0.823657 0.888028 0.323222 0.326945 0.832031 0.031250 1 0 1.000000 +0 5.043973 1.835858 0.377065 0.733238 0.266884 -0.625355 0.832031 0.011719 1 0 1.000000 +holygrail.tga +0 4.642112 0.000006 0.109110 0.194769 0.000000 -0.980834 0.773438 0.000000 1 0 1.000000 +0 4.362160 1.587699 0.109111 0.183020 0.066591 -0.980834 0.832031 0.000000 1 0 1.000000 +0 5.043973 1.835858 0.377065 0.733238 0.266884 -0.625355 0.832031 0.011719 1 0 1.000000 +holygrail.tga +0 5.043973 1.835858 0.377065 0.733238 0.266884 -0.625355 0.832031 0.011719 1 0 1.000000 +0 5.367682 0.000005 0.377064 0.780297 0.000000 -0.625355 0.773438 0.011719 1 0 1.000000 +0 4.642112 0.000006 0.109110 0.194769 0.000000 -0.980834 0.773438 0.000000 1 0 1.000000 +holygrail.tga +0 4.362156 -1.587696 0.109110 0.183020 -0.066591 -0.980834 0.726563 0.000000 1 0 1.000000 +0 4.642112 0.000006 0.109110 0.194769 0.000000 -0.980834 0.773438 0.000000 1 0 1.000000 +0 5.367682 0.000005 0.377064 0.780297 0.000000 -0.625355 0.773438 0.011719 1 0 1.000000 +holygrail.tga +0 5.367682 0.000005 0.377064 0.780297 0.000000 -0.625355 0.773438 0.011719 1 0 1.000000 +0 5.043969 -1.835857 0.377064 0.733238 -0.266884 -0.625355 0.726563 0.011719 1 0 1.000000 +0 4.362156 -1.587696 0.109110 0.183020 -0.066591 -0.980834 0.726563 0.000000 1 0 1.000000 +holygrail.tga +0 3.556062 -2.983890 0.109111 0.149174 -0.125187 -0.980834 0.664063 0.000000 1 0 1.000000 +0 4.362156 -1.587696 0.109110 0.183020 -0.066591 -0.980834 0.726563 0.000000 1 0 1.000000 +0 5.043969 -1.835857 0.377064 0.733238 -0.266884 -0.625355 0.726563 0.011719 1 0 1.000000 +holygrail.tga +0 5.043969 -1.835857 0.377064 0.733238 -0.266884 -0.625355 0.726563 0.011719 1 0 1.000000 +0 4.111880 -3.450277 0.377065 0.597736 -0.501572 -0.625355 0.664063 0.011719 1 0 1.000000 +0 3.556062 -2.983890 0.109111 0.149174 -0.125187 -0.980834 0.664063 0.000000 1 0 1.000000 +holygrail.tga +0 2.321053 -4.020187 0.109110 0.097385 -0.168676 -0.980834 0.613281 0.000000 1 0 1.000000 +0 3.556062 -2.983890 0.109111 0.149174 -0.125187 -0.980834 0.664063 0.000000 1 0 1.000000 +0 4.111880 -3.450277 0.377065 0.597736 -0.501572 -0.625355 0.664063 0.011719 1 0 1.000000 +holygrail.tga +0 4.111880 -3.450277 0.377065 0.597736 -0.501572 -0.625355 0.664063 0.011719 1 0 1.000000 +0 2.683838 -4.648550 0.377065 0.390149 -0.675771 -0.625355 0.613281 0.011719 1 0 1.000000 +0 2.321053 -4.020187 0.109110 0.097385 -0.168676 -0.980834 0.613281 0.000000 1 0 1.000000 +holygrail.tga +0 0.806092 -4.571585 0.109110 0.033815 -0.191809 -0.980834 0.554688 0.000000 1 0 1.000000 +0 2.321053 -4.020187 0.109110 0.097385 -0.168676 -0.980834 0.613281 0.000000 1 0 1.000000 +0 2.683838 -4.648550 0.377065 0.390149 -0.675771 -0.625355 0.613281 0.011719 1 0 1.000000 +holygrail.tga +0 2.683838 -4.648550 0.377065 0.390149 -0.675771 -0.625355 0.613281 0.011719 1 0 1.000000 +0 0.932086 -5.286132 0.377065 0.135472 -0.768456 -0.625355 0.554688 0.011719 1 0 1.000000 +0 0.806092 -4.571585 0.109110 0.033815 -0.191809 -0.980834 0.554688 0.000000 1 0 1.000000 +holygrail.tga +0 -0.806094 -4.571585 0.109110 -0.033815 -0.191809 -0.980834 0.503906 0.000000 1 0 1.000000 +0 0.806092 -4.571585 0.109110 0.033815 -0.191809 -0.980834 0.554688 0.000000 1 0 1.000000 +0 0.932086 -5.286132 0.377065 0.135472 -0.768456 -0.625355 0.554688 0.011719 1 0 1.000000 +holygrail.tga +0 0.932086 -5.286132 0.377065 0.135472 -0.768456 -0.625355 0.554688 0.011719 1 0 1.000000 +0 -0.932088 -5.286132 0.377065 -0.135472 -0.768456 -0.625355 0.503906 0.011719 1 0 1.000000 +0 -0.806094 -4.571585 0.109110 -0.033815 -0.191809 -0.980834 0.503906 0.000000 1 0 1.000000 +holygrail.tga +0 -2.321057 -4.020183 0.109110 -0.097385 -0.168676 -0.980834 0.449219 0.000000 1 0 1.000000 +0 -0.806094 -4.571585 0.109110 -0.033815 -0.191809 -0.980834 0.503906 0.000000 1 0 1.000000 +0 -0.932088 -5.286132 0.377065 -0.135472 -0.768456 -0.625355 0.503906 0.011719 1 0 1.000000 +holygrail.tga +0 -0.932088 -5.286132 0.377065 -0.135472 -0.768456 -0.625355 0.503906 0.011719 1 0 1.000000 +0 -2.683842 -4.648545 0.377065 -0.390149 -0.675771 -0.625355 0.449219 0.011719 1 0 1.000000 +0 -2.321057 -4.020183 0.109110 -0.097385 -0.168676 -0.980834 0.449219 0.000000 1 0 1.000000 +holygrail.tga +0 -3.556065 -2.983887 0.109111 -0.149174 -0.125187 -0.980834 0.394531 0.000000 1 0 1.000000 +0 -2.321057 -4.020183 0.109110 -0.097385 -0.168676 -0.980834 0.449219 0.000000 1 0 1.000000 +0 -2.683842 -4.648545 0.377065 -0.390149 -0.675771 -0.625355 0.449219 0.011719 1 0 1.000000 +holygrail.tga +0 -2.683842 -4.648545 0.377065 -0.390149 -0.675771 -0.625355 0.449219 0.011719 1 0 1.000000 +0 -4.111884 -3.450274 0.377065 -0.597736 -0.501572 -0.625355 0.394531 0.011719 1 0 1.000000 +0 -3.556065 -2.983887 0.109111 -0.149174 -0.125187 -0.980834 0.394531 0.000000 1 0 1.000000 +holygrail.tga +0 -4.362159 -1.587692 0.109110 -0.183020 -0.066591 -0.980834 0.339844 0.000000 1 0 1.000000 +0 -3.556065 -2.983887 0.109111 -0.149174 -0.125187 -0.980834 0.394531 0.000000 1 0 1.000000 +0 -4.111884 -3.450274 0.377065 -0.597736 -0.501572 -0.625355 0.394531 0.011719 1 0 1.000000 +holygrail.tga +0 -4.111884 -3.450274 0.377065 -0.597736 -0.501572 -0.625355 0.394531 0.011719 1 0 1.000000 +0 -5.043972 -1.835851 0.377064 -0.733238 -0.266884 -0.625355 0.339844 0.011719 1 0 1.000000 +0 -4.362159 -1.587692 0.109110 -0.183020 -0.066591 -0.980834 0.339844 0.000000 1 0 1.000000 +holygrail.tga +0 -4.642111 0.000003 0.109110 -0.194769 0.000000 -0.980834 0.289063 0.000000 1 0 1.000000 +0 -4.362159 -1.587692 0.109110 -0.183020 -0.066591 -0.980834 0.339844 0.000000 1 0 1.000000 +0 -5.043972 -1.835851 0.377064 -0.733238 -0.266884 -0.625355 0.339844 0.011719 1 0 1.000000 +holygrail.tga +0 -5.043972 -1.835851 0.377064 -0.733238 -0.266884 -0.625355 0.339844 0.011719 1 0 1.000000 +0 -5.367681 0.000004 0.377064 -0.780297 0.000000 -0.625355 0.289063 0.011719 1 0 1.000000 +0 -4.642111 0.000003 0.109110 -0.194769 0.000000 -0.980834 0.289063 0.000000 1 0 1.000000 +holygrail.tga +0 -4.362158 1.587698 0.109111 -0.183020 0.066591 -0.980834 0.226563 0.000000 1 0 1.000000 +0 -4.642111 0.000003 0.109110 -0.194769 0.000000 -0.980834 0.289063 0.000000 1 0 1.000000 +0 -5.367681 0.000004 0.377064 -0.780297 0.000000 -0.625355 0.289063 0.011719 1 0 1.000000 +holygrail.tga +0 -5.367681 0.000004 0.377064 -0.780297 0.000000 -0.625355 0.289063 0.011719 1 0 1.000000 +0 -5.043971 1.835858 0.377065 -0.733238 0.266884 -0.625355 0.226563 0.011719 1 0 1.000000 +0 -4.362158 1.587698 0.109111 -0.183020 0.066591 -0.980834 0.226563 0.000000 1 0 1.000000 +holygrail.tga +0 -3.556063 2.983893 0.109113 -0.149174 0.125187 -0.980834 0.171875 0.000000 1 0 1.000000 +0 -4.362158 1.587698 0.109111 -0.183020 0.066591 -0.980834 0.226563 0.000000 1 0 1.000000 +0 -5.043971 1.835858 0.377065 -0.733238 0.266884 -0.625355 0.226563 0.011719 1 0 1.000000 +holygrail.tga +0 -5.043971 1.835858 0.377065 -0.733238 0.266884 -0.625355 0.226563 0.011719 1 0 1.000000 +0 -4.111882 3.450281 0.377067 -0.597736 0.501572 -0.625355 0.171875 0.011719 1 0 1.000000 +0 -3.556063 2.983893 0.109113 -0.149174 0.125187 -0.980834 0.171875 0.000000 1 0 1.000000 +holygrail.tga +0 -2.321054 4.020190 0.109112 -0.097385 0.168676 -0.980834 0.117188 0.000000 1 0 1.000000 +0 -3.556063 2.983893 0.109113 -0.149174 0.125187 -0.980834 0.171875 0.000000 1 0 1.000000 +0 -4.111882 3.450281 0.377067 -0.597736 0.501572 -0.625355 0.171875 0.011719 1 0 1.000000 +holygrail.tga +0 -4.111882 3.450281 0.377067 -0.597736 0.501572 -0.625355 0.171875 0.011719 1 0 1.000000 +0 -2.683839 4.648551 0.377066 -0.390149 0.675771 -0.625355 0.117188 0.011719 1 0 1.000000 +0 -2.321054 4.020190 0.109112 -0.097385 0.168676 -0.980834 0.117188 0.000000 1 0 1.000000 +holygrail.tga +0 -0.806095 4.571591 0.109112 -0.033815 0.191809 -0.980834 0.058594 0.000000 1 0 1.000000 +0 -2.321054 4.020190 0.109112 -0.097385 0.168676 -0.980834 0.117188 0.000000 1 0 1.000000 +0 -2.683839 4.648551 0.377066 -0.390149 0.675771 -0.625355 0.117188 0.011719 1 0 1.000000 +holygrail.tga +0 -2.683839 4.648551 0.377066 -0.390149 0.675771 -0.625355 0.117188 0.011719 1 0 1.000000 +0 -0.932089 5.286138 0.377066 -0.135472 0.768456 -0.625355 0.058594 0.011719 1 0 1.000000 +0 -0.806095 4.571591 0.109112 -0.033815 0.191809 -0.980834 0.058594 0.000000 1 0 1.000000 +holygrail.tga +0 0.806094 4.571591 0.109112 0.033815 0.191809 -0.980834 0.000000 0.000000 1 0 1.000000 +0 -0.806095 4.571591 0.109112 -0.033815 0.191809 -0.980834 0.058594 0.000000 1 0 1.000000 +0 -0.932089 5.286138 0.377066 -0.135472 0.768456 -0.625355 0.058594 0.011719 1 0 1.000000 +holygrail.tga +0 -0.932089 5.286138 0.377066 -0.135472 0.768456 -0.625355 0.058594 0.011719 1 0 1.000000 +0 0.932088 5.286138 0.377066 0.135472 0.768456 -0.625355 0.000000 0.011719 1 0 1.000000 +0 0.806094 4.571591 0.109112 0.033815 0.191809 -0.980834 0.000000 0.000000 1 0 1.000000 +holygrail.tga +0 2.321057 4.020190 0.109112 0.097385 0.168645 -0.980834 0.941406 0.000000 1 0 1.000000 +0 0.806094 4.571591 0.109112 0.033815 0.191809 -0.980834 1.000000 0.000000 1 0 1.000000 +0 0.932088 5.286138 0.377066 0.135472 0.768456 -0.625355 1.000000 0.011719 1 0 1.000000 +holygrail.tga +0 0.932088 5.286138 0.377066 0.135472 0.768456 -0.625355 1.000000 0.011719 1 0 1.000000 +0 2.683842 4.648551 0.377066 0.390149 0.675771 -0.625355 0.941406 0.011719 1 0 1.000000 +0 2.321057 4.020190 0.109112 0.097385 0.168645 -0.980834 0.941406 0.000000 1 0 1.000000 +holygrail.tga +0 3.556066 2.983894 0.109113 0.149174 0.125187 -0.980834 0.886719 0.000000 1 0 1.000000 +0 2.321057 4.020190 0.109112 0.097385 0.168645 -0.980834 0.941406 0.000000 1 0 1.000000 +0 2.683842 4.648551 0.377066 0.390149 0.675771 -0.625355 0.941406 0.011719 1 0 1.000000 +holygrail.tga +0 2.683842 4.648551 0.377066 0.390149 0.675771 -0.625355 0.941406 0.011719 1 0 1.000000 +0 4.111885 3.450281 0.377067 0.597736 0.501572 -0.625355 0.886719 0.011719 1 0 1.000000 +0 3.556066 2.983894 0.109113 0.149174 0.125187 -0.980834 0.886719 0.000000 1 0 1.000000 +holygrail.tga +0 4.362160 1.587699 0.109111 0.183020 0.066591 -0.980834 0.832031 0.000000 1 0 1.000000 +0 3.556066 2.983894 0.109113 0.149174 0.125187 -0.980834 0.886719 0.000000 1 0 1.000000 +0 4.111885 3.450281 0.377067 0.597736 0.501572 -0.625355 0.886719 0.011719 1 0 1.000000 +holygrail.tga +0 4.111885 3.450281 0.377067 0.597736 0.501572 -0.625355 0.886719 0.011719 1 0 1.000000 +0 5.043973 1.835858 0.377065 0.733238 0.266884 -0.625355 0.832031 0.011719 1 0 1.000000 +0 4.362160 1.587699 0.109111 0.183020 0.066591 -0.980834 0.832031 0.000000 1 0 1.000000 +holygrail.tga +0 7.441395 2.708446 23.414263 -0.256661 -0.093417 0.961974 0.832031 0.835938 1 0 1.000000 +0 7.918965 0.000000 23.414259 -0.273141 0.000000 0.961943 0.773438 0.835938 1 0 1.000000 +0 8.373683 0.000000 23.281614 0.821619 0.000000 0.569994 0.773438 0.816406 1 0 1.000000 +holygrail.tga +0 8.373683 0.000000 23.281614 0.821619 0.000000 0.569994 0.773438 0.816406 1 0 1.000000 +0 7.868691 2.863969 23.281614 0.772057 0.280984 0.569994 0.832031 0.816406 1 0 1.000000 +0 7.441395 2.708446 23.414263 -0.256661 -0.093417 0.961974 0.832031 0.835938 1 0 1.000000 +holygrail.tga +0 6.066281 5.090213 23.414265 -0.209235 -0.175542 0.961943 0.886719 0.835938 1 0 1.000000 +0 7.441395 2.708446 23.414263 -0.256661 -0.093417 0.961974 0.832031 0.835938 1 0 1.000000 +0 7.868691 2.863969 23.281614 0.772057 0.280984 0.569994 0.832031 0.816406 1 0 1.000000 +holygrail.tga +0 7.868691 2.863969 23.281614 0.772057 0.280984 0.569994 0.832031 0.816406 1 0 1.000000 +0 6.414617 5.382501 23.281618 0.629383 0.528123 0.569994 0.886719 0.816406 1 0 1.000000 +0 6.066281 5.090213 23.414265 -0.209235 -0.175542 0.961943 0.886719 0.835938 1 0 1.000000 +holygrail.tga +0 3.959483 6.858027 23.414265 -0.136540 -0.236518 0.961974 0.941406 0.835938 1 0 1.000000 +0 6.066281 5.090213 23.414265 -0.209235 -0.175542 0.961943 0.886719 0.835938 1 0 1.000000 +0 6.414617 5.382501 23.281618 0.629383 0.528123 0.569994 0.886719 0.816406 1 0 1.000000 +holygrail.tga +0 6.414617 5.382501 23.281618 0.629383 0.528123 0.569994 0.886719 0.816406 1 0 1.000000 +0 4.186843 7.251825 23.281618 0.410810 0.711539 0.569994 0.941406 0.816406 1 0 1.000000 +0 3.959483 6.858027 23.414265 -0.136540 -0.236518 0.961974 0.941406 0.835938 1 0 1.000000 +holygrail.tga +0 1.375114 7.798662 23.414265 -0.047426 -0.268960 0.961974 1.000000 0.835938 1 0 1.000000 +0 3.959483 6.858027 23.414265 -0.136540 -0.236518 0.961974 0.941406 0.835938 1 0 1.000000 +0 4.186843 7.251825 23.281618 0.410810 0.711539 0.569994 0.941406 0.816406 1 0 1.000000 +holygrail.tga +0 4.186843 7.251825 23.281618 0.410810 0.711539 0.569994 0.941406 0.816406 1 0 1.000000 +0 1.454075 8.246472 23.281618 0.142674 0.809137 0.569994 1.000000 0.816406 1 0 1.000000 +0 1.375114 7.798662 23.414265 -0.047426 -0.268960 0.961974 1.000000 0.835938 1 0 1.000000 +holygrail.tga +0 -1.375114 7.798662 23.414265 0.047426 -0.268960 0.961974 0.058594 0.835938 1 0 1.000000 +0 1.375114 7.798662 23.414265 -0.047426 -0.268960 0.961974 0.000000 0.835938 1 0 1.000000 +0 1.454075 8.246472 23.281618 0.142674 0.809137 0.569994 0.000000 0.816406 1 0 1.000000 +holygrail.tga +0 1.454075 8.246472 23.281618 0.142674 0.809137 0.569994 0.000000 0.816406 1 0 1.000000 +0 -1.454076 8.246472 23.281618 -0.142674 0.809137 0.569994 0.058594 0.816406 1 0 1.000000 +0 -1.375114 7.798662 23.414265 0.047426 -0.268960 0.961974 0.058594 0.835938 1 0 1.000000 +holygrail.tga +0 -3.959483 6.858027 23.414265 0.136570 -0.236518 0.961974 0.117188 0.835938 1 0 1.000000 +0 -1.375114 7.798662 23.414265 0.047426 -0.268960 0.961974 0.058594 0.835938 1 0 1.000000 +0 -1.454076 8.246472 23.281618 -0.142674 0.809137 0.569994 0.058594 0.816406 1 0 1.000000 +holygrail.tga +0 -1.454076 8.246472 23.281618 -0.142674 0.809137 0.569994 0.058594 0.816406 1 0 1.000000 +0 -4.186843 7.251825 23.281618 -0.410810 0.711539 0.569994 0.117188 0.816406 1 0 1.000000 +0 -3.959483 6.858027 23.414265 0.136570 -0.236518 0.961974 0.117188 0.835938 1 0 1.000000 +holygrail.tga +0 -6.066280 5.090213 23.414265 0.209204 -0.175542 0.961974 0.171875 0.835938 1 0 1.000000 +0 -3.959483 6.858027 23.414265 0.136570 -0.236518 0.961974 0.117188 0.835938 1 0 1.000000 +0 -4.186843 7.251825 23.281618 -0.410810 0.711539 0.569994 0.117188 0.816406 1 0 1.000000 +holygrail.tga +0 -4.186843 7.251825 23.281618 -0.410810 0.711539 0.569994 0.117188 0.816406 1 0 1.000000 +0 -6.414615 5.382501 23.281618 -0.629383 0.528123 0.569994 0.171875 0.816406 1 0 1.000000 +0 -6.066280 5.090213 23.414265 0.209204 -0.175542 0.961974 0.171875 0.835938 1 0 1.000000 +holygrail.tga +0 -7.441395 2.708446 23.414263 0.256661 -0.093417 0.961974 0.226563 0.835938 1 0 1.000000 +0 -6.066280 5.090213 23.414265 0.209204 -0.175542 0.961974 0.171875 0.835938 1 0 1.000000 +0 -6.414615 5.382501 23.281618 -0.629383 0.528123 0.569994 0.171875 0.816406 1 0 1.000000 +holygrail.tga +0 -6.414615 5.382501 23.281618 -0.629383 0.528123 0.569994 0.171875 0.816406 1 0 1.000000 +0 -7.868690 2.863969 23.281614 -0.772057 0.280984 0.569994 0.226563 0.816406 1 0 1.000000 +0 -7.441395 2.708446 23.414263 0.256661 -0.093417 0.961974 0.226563 0.835938 1 0 1.000000 +holygrail.tga +0 -7.918966 0.000001 23.414259 0.273141 0.000000 0.961943 0.289063 0.835938 1 0 1.000000 +0 -7.441395 2.708446 23.414263 0.256661 -0.093417 0.961974 0.226563 0.835938 1 0 1.000000 +0 -7.868690 2.863969 23.281614 -0.772057 0.280984 0.569994 0.226563 0.816406 1 0 1.000000 +holygrail.tga +0 -7.868690 2.863969 23.281614 -0.772057 0.280984 0.569994 0.226563 0.816406 1 0 1.000000 +0 -8.373686 0.000001 23.281614 -0.821619 0.000000 0.570025 0.289063 0.816406 1 0 1.000000 +0 -7.918966 0.000001 23.414259 0.273141 0.000000 0.961943 0.289063 0.835938 1 0 1.000000 +holygrail.tga +0 -7.441395 -2.708445 23.414259 0.256661 0.093417 0.961943 0.339844 0.835938 1 0 1.000000 +0 -7.918966 0.000001 23.414259 0.273141 0.000000 0.961943 0.289063 0.835938 1 0 1.000000 +0 -8.373686 0.000001 23.281614 -0.821619 0.000000 0.570025 0.289063 0.816406 1 0 1.000000 +holygrail.tga +0 -8.373686 0.000001 23.281614 -0.821619 0.000000 0.570025 0.289063 0.816406 1 0 1.000000 +0 -7.868692 -2.863967 23.281614 -0.772057 -0.280984 0.569994 0.339844 0.816406 1 0 1.000000 +0 -7.441395 -2.708445 23.414259 0.256661 0.093417 0.961943 0.339844 0.835938 1 0 1.000000 +holygrail.tga +0 -6.066282 -5.090212 23.414259 0.209235 0.175542 0.961943 0.394531 0.835938 1 0 1.000000 +0 -7.441395 -2.708445 23.414259 0.256661 0.093417 0.961943 0.339844 0.835938 1 0 1.000000 +0 -7.868692 -2.863967 23.281614 -0.772057 -0.280984 0.569994 0.339844 0.816406 1 0 1.000000 +holygrail.tga +0 -7.868692 -2.863967 23.281614 -0.772057 -0.280984 0.569994 0.339844 0.816406 1 0 1.000000 +0 -6.414616 -5.382501 23.281614 -0.629383 -0.528123 0.569994 0.394531 0.816406 1 0 1.000000 +0 -6.066282 -5.090212 23.414259 0.209235 0.175542 0.961943 0.394531 0.835938 1 0 1.000000 +holygrail.tga +0 -3.959486 -6.858022 23.414259 0.136570 0.236518 0.961943 0.449219 0.835938 1 0 1.000000 +0 -6.066282 -5.090212 23.414259 0.209235 0.175542 0.961943 0.394531 0.835938 1 0 1.000000 +0 -6.414616 -5.382501 23.281614 -0.629383 -0.528123 0.569994 0.394531 0.816406 1 0 1.000000 +holygrail.tga +0 -6.414616 -5.382501 23.281614 -0.629383 -0.528123 0.569994 0.394531 0.816406 1 0 1.000000 +0 -4.186845 -7.251821 23.281614 -0.410810 -0.711539 0.570025 0.449219 0.816406 1 0 1.000000 +0 -3.959486 -6.858022 23.414259 0.136570 0.236518 0.961943 0.449219 0.835938 1 0 1.000000 +holygrail.tga +0 -1.375116 -7.798658 23.414259 0.047426 0.268990 0.961974 0.503906 0.835938 1 0 1.000000 +0 -3.959486 -6.858022 23.414259 0.136570 0.236518 0.961943 0.449219 0.835938 1 0 1.000000 +0 -4.186845 -7.251821 23.281614 -0.410810 -0.711539 0.570025 0.449219 0.816406 1 0 1.000000 +holygrail.tga +0 -4.186845 -7.251821 23.281614 -0.410810 -0.711539 0.570025 0.449219 0.816406 1 0 1.000000 +0 -1.454078 -8.246469 23.281614 -0.142674 -0.809137 0.570025 0.503906 0.816406 1 0 1.000000 +0 -1.375116 -7.798658 23.414259 0.047426 0.268990 0.961974 0.503906 0.835938 1 0 1.000000 +holygrail.tga +0 1.375110 -7.798660 23.414259 -0.047426 0.268990 0.961943 0.554688 0.835938 1 0 1.000000 +0 -1.375116 -7.798658 23.414259 0.047426 0.268990 0.961974 0.503906 0.835938 1 0 1.000000 +0 -1.454078 -8.246469 23.281614 -0.142674 -0.809137 0.570025 0.503906 0.816406 1 0 1.000000 +holygrail.tga +0 -1.454078 -8.246469 23.281614 -0.142674 -0.809137 0.570025 0.503906 0.816406 1 0 1.000000 +0 1.454071 -8.246470 23.281614 0.142644 -0.809137 0.569994 0.554688 0.816406 1 0 1.000000 +0 1.375110 -7.798660 23.414259 -0.047426 0.268990 0.961943 0.554688 0.835938 1 0 1.000000 +holygrail.tga +0 3.959481 -6.858026 23.414259 -0.136570 0.236518 0.961943 0.613281 0.835938 1 0 1.000000 +0 1.375110 -7.798660 23.414259 -0.047426 0.268990 0.961943 0.554688 0.835938 1 0 1.000000 +0 1.454071 -8.246470 23.281614 0.142644 -0.809137 0.569994 0.554688 0.816406 1 0 1.000000 +holygrail.tga +0 1.454071 -8.246470 23.281614 0.142644 -0.809137 0.569994 0.554688 0.816406 1 0 1.000000 +0 4.186839 -7.251825 23.281614 0.410810 -0.711539 0.570025 0.613281 0.816406 1 0 1.000000 +0 3.959481 -6.858026 23.414259 -0.136570 0.236518 0.961943 0.613281 0.835938 1 0 1.000000 +holygrail.tga +0 6.066278 -5.090217 23.414259 -0.209235 0.175542 0.961943 0.664063 0.835938 1 0 1.000000 +0 3.959481 -6.858026 23.414259 -0.136570 0.236518 0.961943 0.613281 0.835938 1 0 1.000000 +0 4.186839 -7.251825 23.281614 0.410810 -0.711539 0.570025 0.613281 0.816406 1 0 1.000000 +holygrail.tga +0 4.186839 -7.251825 23.281614 0.410810 -0.711539 0.570025 0.613281 0.816406 1 0 1.000000 +0 6.414613 -5.382505 23.281614 0.629383 -0.528123 0.569994 0.664063 0.816406 1 0 1.000000 +0 6.066278 -5.090217 23.414259 -0.209235 0.175542 0.961943 0.664063 0.835938 1 0 1.000000 +holygrail.tga +0 7.441392 -2.708453 23.414259 -0.256661 0.093417 0.961974 0.726563 0.835938 1 0 1.000000 +0 6.066278 -5.090217 23.414259 -0.209235 0.175542 0.961943 0.664063 0.835938 1 0 1.000000 +0 6.414613 -5.382505 23.281614 0.629383 -0.528123 0.569994 0.664063 0.816406 1 0 1.000000 +holygrail.tga +0 6.414613 -5.382505 23.281614 0.629383 -0.528123 0.569994 0.664063 0.816406 1 0 1.000000 +0 7.868689 -2.863975 23.281614 0.772057 -0.280984 0.569994 0.726563 0.816406 1 0 1.000000 +0 7.441392 -2.708453 23.414259 -0.256661 0.093417 0.961974 0.726563 0.835938 1 0 1.000000 +holygrail.tga +0 7.918965 0.000000 23.414259 -0.273141 0.000000 0.961943 0.773438 0.835938 1 0 1.000000 +0 7.441392 -2.708453 23.414259 -0.256661 0.093417 0.961974 0.726563 0.835938 1 0 1.000000 +0 7.868689 -2.863975 23.281614 0.772057 -0.280984 0.569994 0.726563 0.816406 1 0 1.000000 +holygrail.tga +0 7.868689 -2.863975 23.281614 0.772057 -0.280984 0.569994 0.726563 0.816406 1 0 1.000000 +0 8.373683 0.000000 23.281614 0.821619 0.000000 0.569994 0.773438 0.816406 1 0 1.000000 +0 7.918965 0.000000 23.414259 -0.273141 0.000000 0.961943 0.773438 0.835938 1 0 1.000000 +holygrail.tga +0 6.249387 2.274592 21.590519 -0.861690 -0.313608 0.398877 0.832031 0.855469 1 0 1.000000 +0 6.650457 0.000001 21.590519 -0.916990 0.000000 0.398877 0.773438 0.855469 1 0 1.000000 +0 7.918965 0.000000 23.414259 -0.273141 0.000000 0.961943 0.773438 0.835938 1 0 1.000000 +holygrail.tga +0 7.918965 0.000000 23.414259 -0.273141 0.000000 0.961943 0.773438 0.835938 1 0 1.000000 +0 7.441395 2.708446 23.414263 -0.256661 -0.093417 0.961974 0.832031 0.835938 1 0 1.000000 +0 6.249387 2.274592 21.590519 -0.861690 -0.313608 0.398877 0.832031 0.855469 1 0 1.000000 +holygrail.tga +0 5.094548 4.274832 21.590523 -0.702445 -0.589435 0.398877 0.886719 0.855469 1 0 1.000000 +0 6.249387 2.274592 21.590519 -0.861690 -0.313608 0.398877 0.832031 0.855469 1 0 1.000000 +0 7.441395 2.708446 23.414263 -0.256661 -0.093417 0.961974 0.832031 0.835938 1 0 1.000000 +holygrail.tga +0 7.441395 2.708446 23.414263 -0.256661 -0.093417 0.961974 0.832031 0.835938 1 0 1.000000 +0 6.066281 5.090213 23.414265 -0.209235 -0.175542 0.961943 0.886719 0.835938 1 0 1.000000 +0 5.094548 4.274832 21.590523 -0.702445 -0.589435 0.398877 0.886719 0.855469 1 0 1.000000 +holygrail.tga +0 3.325229 5.759467 21.590523 -0.458480 -0.794122 0.398877 0.941406 0.855469 1 0 1.000000 +0 5.094548 4.274832 21.590523 -0.702445 -0.589435 0.398877 0.886719 0.855469 1 0 1.000000 +0 6.066281 5.090213 23.414265 -0.209235 -0.175542 0.961943 0.886719 0.835938 1 0 1.000000 +holygrail.tga +0 6.066281 5.090213 23.414265 -0.209235 -0.175542 0.961943 0.886719 0.835938 1 0 1.000000 +0 3.959483 6.858027 23.414265 -0.136540 -0.236518 0.961974 0.941406 0.835938 1 0 1.000000 +0 3.325229 5.759467 21.590523 -0.458480 -0.794122 0.398877 0.941406 0.855469 1 0 1.000000 +holygrail.tga +0 1.154840 6.549425 21.590523 -0.159215 -0.903043 0.398877 1.000000 0.855469 1 0 1.000000 +0 3.325229 5.759467 21.590523 -0.458480 -0.794122 0.398877 0.941406 0.855469 1 0 1.000000 +0 3.959483 6.858027 23.414265 -0.136540 -0.236518 0.961974 0.941406 0.835938 1 0 1.000000 +holygrail.tga +0 3.959483 6.858027 23.414265 -0.136540 -0.236518 0.961974 0.941406 0.835938 1 0 1.000000 +0 1.375114 7.798662 23.414265 -0.047426 -0.268960 0.961974 1.000000 0.835938 1 0 1.000000 +0 1.154840 6.549425 21.590523 -0.159215 -0.903043 0.398877 1.000000 0.855469 1 0 1.000000 +holygrail.tga +0 -1.154840 6.549425 21.590523 0.159215 -0.903043 0.398877 0.058594 0.855469 1 0 1.000000 +0 1.154840 6.549425 21.590523 -0.159215 -0.903043 0.398877 0.000000 0.855469 1 0 1.000000 +0 1.375114 7.798662 23.414265 -0.047426 -0.268960 0.961974 0.000000 0.835938 1 0 1.000000 +holygrail.tga +0 1.375114 7.798662 23.414265 -0.047426 -0.268960 0.961974 0.000000 0.835938 1 0 1.000000 +0 -1.375114 7.798662 23.414265 0.047426 -0.268960 0.961974 0.058594 0.835938 1 0 1.000000 +0 -1.154840 6.549425 21.590523 0.159215 -0.903043 0.398877 0.058594 0.855469 1 0 1.000000 +holygrail.tga +0 -3.325229 5.759468 21.590523 0.458480 -0.794122 0.398877 0.117188 0.855469 1 0 1.000000 +0 -1.154840 6.549425 21.590523 0.159215 -0.903043 0.398877 0.058594 0.855469 1 0 1.000000 +0 -1.375114 7.798662 23.414265 0.047426 -0.268960 0.961974 0.058594 0.835938 1 0 1.000000 +holygrail.tga +0 -1.375114 7.798662 23.414265 0.047426 -0.268960 0.961974 0.058594 0.835938 1 0 1.000000 +0 -3.959483 6.858027 23.414265 0.136570 -0.236518 0.961974 0.117188 0.835938 1 0 1.000000 +0 -3.325229 5.759468 21.590523 0.458480 -0.794122 0.398877 0.117188 0.855469 1 0 1.000000 +holygrail.tga +0 -5.094546 4.274832 21.590523 0.702445 -0.589435 0.398877 0.171875 0.855469 1 0 1.000000 +0 -3.325229 5.759468 21.590523 0.458480 -0.794122 0.398877 0.117188 0.855469 1 0 1.000000 +0 -3.959483 6.858027 23.414265 0.136570 -0.236518 0.961974 0.117188 0.835938 1 0 1.000000 +holygrail.tga +0 -3.959483 6.858027 23.414265 0.136570 -0.236518 0.961974 0.117188 0.835938 1 0 1.000000 +0 -6.066280 5.090213 23.414265 0.209204 -0.175542 0.961974 0.171875 0.835938 1 0 1.000000 +0 -5.094546 4.274832 21.590523 0.702445 -0.589435 0.398877 0.171875 0.855469 1 0 1.000000 +holygrail.tga +0 -6.249386 2.274591 21.590519 0.861690 -0.313608 0.398877 0.226563 0.855469 1 0 1.000000 +0 -5.094546 4.274832 21.590523 0.702445 -0.589435 0.398877 0.171875 0.855469 1 0 1.000000 +0 -6.066280 5.090213 23.414265 0.209204 -0.175542 0.961974 0.171875 0.835938 1 0 1.000000 +holygrail.tga +0 -6.066280 5.090213 23.414265 0.209204 -0.175542 0.961974 0.171875 0.835938 1 0 1.000000 +0 -7.441395 2.708446 23.414263 0.256661 -0.093417 0.961974 0.226563 0.835938 1 0 1.000000 +0 -6.249386 2.274591 21.590519 0.861690 -0.313608 0.398877 0.226563 0.855469 1 0 1.000000 +holygrail.tga +0 -6.650458 0.000001 21.590519 0.916990 0.000000 0.398877 0.289063 0.855469 1 0 1.000000 +0 -6.249386 2.274591 21.590519 0.861690 -0.313608 0.398877 0.226563 0.855469 1 0 1.000000 +0 -7.441395 2.708446 23.414263 0.256661 -0.093417 0.961974 0.226563 0.835938 1 0 1.000000 +holygrail.tga +0 -7.441395 2.708446 23.414263 0.256661 -0.093417 0.961974 0.226563 0.835938 1 0 1.000000 +0 -7.918966 0.000001 23.414259 0.273141 0.000000 0.961943 0.289063 0.835938 1 0 1.000000 +0 -6.650458 0.000001 21.590519 0.916990 0.000000 0.398877 0.289063 0.855469 1 0 1.000000 +holygrail.tga +0 -6.249387 -2.274589 21.590519 0.861690 0.313608 0.398877 0.339844 0.855469 1 0 1.000000 +0 -6.650458 0.000001 21.590519 0.916990 0.000000 0.398877 0.289063 0.855469 1 0 1.000000 +0 -7.918966 0.000001 23.414259 0.273141 0.000000 0.961943 0.289063 0.835938 1 0 1.000000 +holygrail.tga +0 -7.918966 0.000001 23.414259 0.273141 0.000000 0.961943 0.289063 0.835938 1 0 1.000000 +0 -7.441395 -2.708445 23.414259 0.256661 0.093417 0.961943 0.339844 0.835938 1 0 1.000000 +0 -6.249387 -2.274589 21.590519 0.861690 0.313608 0.398877 0.339844 0.855469 1 0 1.000000 +holygrail.tga +0 -5.094548 -4.274831 21.590519 0.702445 0.589435 0.398877 0.394531 0.855469 1 0 1.000000 +0 -6.249387 -2.274589 21.590519 0.861690 0.313608 0.398877 0.339844 0.855469 1 0 1.000000 +0 -7.441395 -2.708445 23.414259 0.256661 0.093417 0.961943 0.339844 0.835938 1 0 1.000000 +holygrail.tga +0 -7.441395 -2.708445 23.414259 0.256661 0.093417 0.961943 0.339844 0.835938 1 0 1.000000 +0 -6.066282 -5.090212 23.414259 0.209235 0.175542 0.961943 0.394531 0.835938 1 0 1.000000 +0 -5.094548 -4.274831 21.590519 0.702445 0.589435 0.398877 0.394531 0.855469 1 0 1.000000 +holygrail.tga +0 -3.325232 -5.759462 21.590519 0.458480 0.794122 0.398877 0.449219 0.855469 1 0 1.000000 +0 -5.094548 -4.274831 21.590519 0.702445 0.589435 0.398877 0.394531 0.855469 1 0 1.000000 +0 -6.066282 -5.090212 23.414259 0.209235 0.175542 0.961943 0.394531 0.835938 1 0 1.000000 +holygrail.tga +0 -6.066282 -5.090212 23.414259 0.209235 0.175542 0.961943 0.394531 0.835938 1 0 1.000000 +0 -3.959486 -6.858022 23.414259 0.136570 0.236518 0.961943 0.449219 0.835938 1 0 1.000000 +0 -3.325232 -5.759462 21.590519 0.458480 0.794122 0.398877 0.449219 0.855469 1 0 1.000000 +holygrail.tga +0 -1.154842 -6.549421 21.590519 0.159215 0.903043 0.398877 0.503906 0.855469 1 0 1.000000 +0 -3.325232 -5.759462 21.590519 0.458480 0.794122 0.398877 0.449219 0.855469 1 0 1.000000 +0 -3.959486 -6.858022 23.414259 0.136570 0.236518 0.961943 0.449219 0.835938 1 0 1.000000 +holygrail.tga +0 -3.959486 -6.858022 23.414259 0.136570 0.236518 0.961943 0.449219 0.835938 1 0 1.000000 +0 -1.375116 -7.798658 23.414259 0.047426 0.268990 0.961974 0.503906 0.835938 1 0 1.000000 +0 -1.154842 -6.549421 21.590519 0.159215 0.903043 0.398877 0.503906 0.855469 1 0 1.000000 +holygrail.tga +0 1.154837 -6.549423 21.590519 -0.159215 0.903043 0.398877 0.554688 0.855469 1 0 1.000000 +0 -1.154842 -6.549421 21.590519 0.159215 0.903043 0.398877 0.503906 0.855469 1 0 1.000000 +0 -1.375116 -7.798658 23.414259 0.047426 0.268990 0.961974 0.503906 0.835938 1 0 1.000000 +holygrail.tga +0 -1.375116 -7.798658 23.414259 0.047426 0.268990 0.961974 0.503906 0.835938 1 0 1.000000 +0 1.375110 -7.798660 23.414259 -0.047426 0.268990 0.961943 0.554688 0.835938 1 0 1.000000 +0 1.154837 -6.549423 21.590519 -0.159215 0.903043 0.398877 0.554688 0.855469 1 0 1.000000 +holygrail.tga +0 3.325227 -5.759466 21.590519 -0.458480 0.794122 0.398877 0.613281 0.855469 1 0 1.000000 +0 1.154837 -6.549423 21.590519 -0.159215 0.903043 0.398877 0.554688 0.855469 1 0 1.000000 +0 1.375110 -7.798660 23.414259 -0.047426 0.268990 0.961943 0.554688 0.835938 1 0 1.000000 +holygrail.tga +0 1.375110 -7.798660 23.414259 -0.047426 0.268990 0.961943 0.554688 0.835938 1 0 1.000000 +0 3.959481 -6.858026 23.414259 -0.136570 0.236518 0.961943 0.613281 0.835938 1 0 1.000000 +0 3.325227 -5.759466 21.590519 -0.458480 0.794122 0.398877 0.613281 0.855469 1 0 1.000000 +holygrail.tga +0 5.094545 -4.274835 21.590519 -0.702445 0.589435 0.398877 0.664063 0.855469 1 0 1.000000 +0 3.325227 -5.759466 21.590519 -0.458480 0.794122 0.398877 0.613281 0.855469 1 0 1.000000 +0 3.959481 -6.858026 23.414259 -0.136570 0.236518 0.961943 0.613281 0.835938 1 0 1.000000 +holygrail.tga +0 3.959481 -6.858026 23.414259 -0.136570 0.236518 0.961943 0.613281 0.835938 1 0 1.000000 +0 6.066278 -5.090217 23.414259 -0.209235 0.175542 0.961943 0.664063 0.835938 1 0 1.000000 +0 5.094545 -4.274835 21.590519 -0.702445 0.589435 0.398877 0.664063 0.855469 1 0 1.000000 +holygrail.tga +0 6.249385 -2.274596 21.590519 -0.861690 0.313608 0.398877 0.726563 0.855469 1 0 1.000000 +0 5.094545 -4.274835 21.590519 -0.702445 0.589435 0.398877 0.664063 0.855469 1 0 1.000000 +0 6.066278 -5.090217 23.414259 -0.209235 0.175542 0.961943 0.664063 0.835938 1 0 1.000000 +holygrail.tga +0 6.066278 -5.090217 23.414259 -0.209235 0.175542 0.961943 0.664063 0.835938 1 0 1.000000 +0 7.441392 -2.708453 23.414259 -0.256661 0.093417 0.961974 0.726563 0.835938 1 0 1.000000 +0 6.249385 -2.274596 21.590519 -0.861690 0.313608 0.398877 0.726563 0.855469 1 0 1.000000 +holygrail.tga +0 6.650457 0.000001 21.590519 -0.916990 0.000000 0.398877 0.773438 0.855469 1 0 1.000000 +0 6.249385 -2.274596 21.590519 -0.861690 0.313608 0.398877 0.726563 0.855469 1 0 1.000000 +0 7.441392 -2.708453 23.414259 -0.256661 0.093417 0.961974 0.726563 0.835938 1 0 1.000000 +holygrail.tga +0 7.441392 -2.708453 23.414259 -0.256661 0.093417 0.961974 0.726563 0.835938 1 0 1.000000 +0 7.918965 0.000000 23.414259 -0.273141 0.000000 0.961943 0.773438 0.835938 1 0 1.000000 +0 6.650457 0.000001 21.590519 -0.916990 0.000000 0.398877 0.773438 0.855469 1 0 1.000000 +holygrail.tga +0 5.652801 2.057453 18.369108 -0.818079 -0.297739 0.491989 0.832031 0.898438 1 0 1.000000 +0 6.015584 0.000001 18.369108 -0.870571 0.000000 0.491989 0.773438 0.898438 1 0 1.000000 +0 6.650457 0.000001 21.590519 -0.916990 0.000000 0.398877 0.773438 0.855469 1 0 1.000000 +holygrail.tga +0 6.650457 0.000001 21.590519 -0.916990 0.000000 0.398877 0.773438 0.855469 1 0 1.000000 +0 6.249387 2.274592 21.590519 -0.861690 -0.313608 0.398877 0.832031 0.855469 1 0 1.000000 +0 5.652801 2.057453 18.369108 -0.818079 -0.297739 0.491989 0.832031 0.898438 1 0 1.000000 +holygrail.tga +0 4.608207 3.866745 18.369110 -0.666890 -0.559587 0.491989 0.886719 0.898438 1 0 1.000000 +0 5.652801 2.057453 18.369108 -0.818079 -0.297739 0.491989 0.832031 0.898438 1 0 1.000000 +0 6.249387 2.274592 21.590519 -0.861690 -0.313608 0.398877 0.832031 0.855469 1 0 1.000000 +holygrail.tga +0 6.249387 2.274592 21.590519 -0.861690 -0.313608 0.398877 0.832031 0.855469 1 0 1.000000 +0 5.094548 4.274832 21.590523 -0.702445 -0.589435 0.398877 0.886719 0.855469 1 0 1.000000 +0 4.608207 3.866745 18.369110 -0.666890 -0.559587 0.491989 0.886719 0.898438 1 0 1.000000 +holygrail.tga +0 3.007792 5.209651 18.369110 -0.435286 -0.753929 0.491989 0.941406 0.898438 1 0 1.000000 +0 4.608207 3.866745 18.369110 -0.666890 -0.559587 0.491989 0.886719 0.898438 1 0 1.000000 +0 5.094548 4.274832 21.590523 -0.702445 -0.589435 0.398877 0.886719 0.855469 1 0 1.000000 +holygrail.tga +0 5.094548 4.274832 21.590523 -0.702445 -0.589435 0.398877 0.886719 0.855469 1 0 1.000000 +0 3.325229 5.759467 21.590523 -0.458480 -0.794122 0.398877 0.941406 0.855469 1 0 1.000000 +0 3.007792 5.209651 18.369110 -0.435286 -0.753929 0.491989 0.941406 0.898438 1 0 1.000000 +holygrail.tga +0 1.044595 5.924198 18.369110 -0.151158 -0.857356 0.491989 1.000000 0.898438 1 0 1.000000 +0 3.007792 5.209651 18.369110 -0.435286 -0.753929 0.491989 0.941406 0.898438 1 0 1.000000 +0 3.325229 5.759467 21.590523 -0.458480 -0.794122 0.398877 0.941406 0.855469 1 0 1.000000 +holygrail.tga +0 3.325229 5.759467 21.590523 -0.458480 -0.794122 0.398877 0.941406 0.855469 1 0 1.000000 +0 1.154840 6.549425 21.590523 -0.159215 -0.903043 0.398877 1.000000 0.855469 1 0 1.000000 +0 1.044595 5.924198 18.369110 -0.151158 -0.857356 0.491989 1.000000 0.898438 1 0 1.000000 +holygrail.tga +0 -1.044596 5.924198 18.369110 0.151158 -0.857356 0.491989 0.058594 0.898438 1 0 1.000000 +0 1.044595 5.924198 18.369110 -0.151158 -0.857356 0.491989 0.000000 0.898438 1 0 1.000000 +0 1.154840 6.549425 21.590523 -0.159215 -0.903043 0.398877 0.000000 0.855469 1 0 1.000000 +holygrail.tga +0 1.154840 6.549425 21.590523 -0.159215 -0.903043 0.398877 0.000000 0.855469 1 0 1.000000 +0 -1.154840 6.549425 21.590523 0.159215 -0.903043 0.398877 0.058594 0.855469 1 0 1.000000 +0 -1.044596 5.924198 18.369110 0.151158 -0.857356 0.491989 0.058594 0.898438 1 0 1.000000 +holygrail.tga +0 -3.007792 5.209652 18.369110 0.435286 -0.753929 0.491989 0.117188 0.898438 1 0 1.000000 +0 -1.044596 5.924198 18.369110 0.151158 -0.857356 0.491989 0.058594 0.898438 1 0 1.000000 +0 -1.154840 6.549425 21.590523 0.159215 -0.903043 0.398877 0.058594 0.855469 1 0 1.000000 +holygrail.tga +0 -1.154840 6.549425 21.590523 0.159215 -0.903043 0.398877 0.058594 0.855469 1 0 1.000000 +0 -3.325229 5.759468 21.590523 0.458480 -0.794122 0.398877 0.117188 0.855469 1 0 1.000000 +0 -3.007792 5.209652 18.369110 0.435286 -0.753929 0.491989 0.117188 0.898438 1 0 1.000000 +holygrail.tga +0 -4.608205 3.866745 18.369110 0.666890 -0.559587 0.491989 0.171875 0.898438 1 0 1.000000 +0 -3.007792 5.209652 18.369110 0.435286 -0.753929 0.491989 0.117188 0.898438 1 0 1.000000 +0 -3.325229 5.759468 21.590523 0.458480 -0.794122 0.398877 0.117188 0.855469 1 0 1.000000 +holygrail.tga +0 -3.325229 5.759468 21.590523 0.458480 -0.794122 0.398877 0.117188 0.855469 1 0 1.000000 +0 -5.094546 4.274832 21.590523 0.702445 -0.589435 0.398877 0.171875 0.855469 1 0 1.000000 +0 -4.608205 3.866745 18.369110 0.666890 -0.559587 0.491989 0.171875 0.898438 1 0 1.000000 +holygrail.tga +0 -5.652801 2.057453 18.369108 0.818079 -0.297739 0.491989 0.226563 0.898438 1 0 1.000000 +0 -4.608205 3.866745 18.369110 0.666890 -0.559587 0.491989 0.171875 0.898438 1 0 1.000000 +0 -5.094546 4.274832 21.590523 0.702445 -0.589435 0.398877 0.171875 0.855469 1 0 1.000000 +holygrail.tga +0 -5.094546 4.274832 21.590523 0.702445 -0.589435 0.398877 0.171875 0.855469 1 0 1.000000 +0 -6.249386 2.274591 21.590519 0.861690 -0.313608 0.398877 0.226563 0.855469 1 0 1.000000 +0 -5.652801 2.057453 18.369108 0.818079 -0.297739 0.491989 0.226563 0.898438 1 0 1.000000 +holygrail.tga +0 -6.015585 0.000002 18.369108 0.870571 0.000000 0.491989 0.289063 0.898438 1 0 1.000000 +0 -5.652801 2.057453 18.369108 0.818079 -0.297739 0.491989 0.226563 0.898438 1 0 1.000000 +0 -6.249386 2.274591 21.590519 0.861690 -0.313608 0.398877 0.226563 0.855469 1 0 1.000000 +holygrail.tga +0 -6.249386 2.274591 21.590519 0.861690 -0.313608 0.398877 0.226563 0.855469 1 0 1.000000 +0 -6.650458 0.000001 21.590519 0.916990 0.000000 0.398877 0.289063 0.855469 1 0 1.000000 +0 -6.015585 0.000002 18.369108 0.870571 0.000000 0.491989 0.289063 0.898438 1 0 1.000000 +holygrail.tga +0 -5.652802 -2.057449 18.369108 0.818079 0.297739 0.491989 0.339844 0.898438 1 0 1.000000 +0 -6.015585 0.000002 18.369108 0.870571 0.000000 0.491989 0.289063 0.898438 1 0 1.000000 +0 -6.650458 0.000001 21.590519 0.916990 0.000000 0.398877 0.289063 0.855469 1 0 1.000000 +holygrail.tga +0 -6.650458 0.000001 21.590519 0.916990 0.000000 0.398877 0.289063 0.855469 1 0 1.000000 +0 -6.249387 -2.274589 21.590519 0.861690 0.313608 0.398877 0.339844 0.855469 1 0 1.000000 +0 -5.652802 -2.057449 18.369108 0.818079 0.297739 0.491989 0.339844 0.898438 1 0 1.000000 +holygrail.tga +0 -4.608207 -3.866742 18.369108 0.666890 0.559587 0.491989 0.394531 0.898438 1 0 1.000000 +0 -5.652802 -2.057449 18.369108 0.818079 0.297739 0.491989 0.339844 0.898438 1 0 1.000000 +0 -6.249387 -2.274589 21.590519 0.861690 0.313608 0.398877 0.339844 0.855469 1 0 1.000000 +holygrail.tga +0 -6.249387 -2.274589 21.590519 0.861690 0.313608 0.398877 0.339844 0.855469 1 0 1.000000 +0 -5.094548 -4.274831 21.590519 0.702445 0.589435 0.398877 0.394531 0.855469 1 0 1.000000 +0 -4.608207 -3.866742 18.369108 0.666890 0.559587 0.491989 0.394531 0.898438 1 0 1.000000 +holygrail.tga +0 -3.007795 -5.209646 18.369108 0.435286 0.753929 0.491989 0.449219 0.898438 1 0 1.000000 +0 -4.608207 -3.866742 18.369108 0.666890 0.559587 0.491989 0.394531 0.898438 1 0 1.000000 +0 -5.094548 -4.274831 21.590519 0.702445 0.589435 0.398877 0.394531 0.855469 1 0 1.000000 +holygrail.tga +0 -5.094548 -4.274831 21.590519 0.702445 0.589435 0.398877 0.394531 0.855469 1 0 1.000000 +0 -3.325232 -5.759462 21.590519 0.458480 0.794122 0.398877 0.449219 0.855469 1 0 1.000000 +0 -3.007795 -5.209646 18.369108 0.435286 0.753929 0.491989 0.449219 0.898438 1 0 1.000000 +holygrail.tga +0 -1.044597 -5.924192 18.369108 0.151158 0.857356 0.491989 0.503906 0.898438 1 0 1.000000 +0 -3.007795 -5.209646 18.369108 0.435286 0.753929 0.491989 0.449219 0.898438 1 0 1.000000 +0 -3.325232 -5.759462 21.590519 0.458480 0.794122 0.398877 0.449219 0.855469 1 0 1.000000 +holygrail.tga +0 -3.325232 -5.759462 21.590519 0.458480 0.794122 0.398877 0.449219 0.855469 1 0 1.000000 +0 -1.154842 -6.549421 21.590519 0.159215 0.903043 0.398877 0.503906 0.855469 1 0 1.000000 +0 -1.044597 -5.924192 18.369108 0.151158 0.857356 0.491989 0.503906 0.898438 1 0 1.000000 +holygrail.tga +0 1.044592 -5.924194 18.369108 -0.151158 0.857356 0.491989 0.554688 0.898438 1 0 1.000000 +0 -1.044597 -5.924192 18.369108 0.151158 0.857356 0.491989 0.503906 0.898438 1 0 1.000000 +0 -1.154842 -6.549421 21.590519 0.159215 0.903043 0.398877 0.503906 0.855469 1 0 1.000000 +holygrail.tga +0 -1.154842 -6.549421 21.590519 0.159215 0.903043 0.398877 0.503906 0.855469 1 0 1.000000 +0 1.154837 -6.549423 21.590519 -0.159215 0.903043 0.398877 0.554688 0.855469 1 0 1.000000 +0 1.044592 -5.924194 18.369108 -0.151158 0.857356 0.491989 0.554688 0.898438 1 0 1.000000 +holygrail.tga +0 3.007790 -5.209648 18.369108 -0.435286 0.753929 0.491989 0.613281 0.898438 1 0 1.000000 +0 1.044592 -5.924194 18.369108 -0.151158 0.857356 0.491989 0.554688 0.898438 1 0 1.000000 +0 1.154837 -6.549423 21.590519 -0.159215 0.903043 0.398877 0.554688 0.855469 1 0 1.000000 +holygrail.tga +0 1.154837 -6.549423 21.590519 -0.159215 0.903043 0.398877 0.554688 0.855469 1 0 1.000000 +0 3.325227 -5.759466 21.590519 -0.458480 0.794122 0.398877 0.613281 0.855469 1 0 1.000000 +0 3.007790 -5.209648 18.369108 -0.435286 0.753929 0.491989 0.613281 0.898438 1 0 1.000000 +holygrail.tga +0 4.608204 -3.866745 18.369108 -0.666890 0.559587 0.491989 0.664063 0.898438 1 0 1.000000 +0 3.007790 -5.209648 18.369108 -0.435286 0.753929 0.491989 0.613281 0.898438 1 0 1.000000 +0 3.325227 -5.759466 21.590519 -0.458480 0.794122 0.398877 0.613281 0.855469 1 0 1.000000 +holygrail.tga +0 3.325227 -5.759466 21.590519 -0.458480 0.794122 0.398877 0.613281 0.855469 1 0 1.000000 +0 5.094545 -4.274835 21.590519 -0.702445 0.589435 0.398877 0.664063 0.855469 1 0 1.000000 +0 4.608204 -3.866745 18.369108 -0.666890 0.559587 0.491989 0.664063 0.898438 1 0 1.000000 +holygrail.tga +0 5.652799 -2.057456 18.369108 -0.818079 0.297739 0.491989 0.726563 0.898438 1 0 1.000000 +0 4.608204 -3.866745 18.369108 -0.666890 0.559587 0.491989 0.664063 0.898438 1 0 1.000000 +0 5.094545 -4.274835 21.590519 -0.702445 0.589435 0.398877 0.664063 0.855469 1 0 1.000000 +holygrail.tga +0 5.094545 -4.274835 21.590519 -0.702445 0.589435 0.398877 0.664063 0.855469 1 0 1.000000 +0 6.249385 -2.274596 21.590519 -0.861690 0.313608 0.398877 0.726563 0.855469 1 0 1.000000 +0 5.652799 -2.057456 18.369108 -0.818079 0.297739 0.491989 0.726563 0.898438 1 0 1.000000 +holygrail.tga +0 6.015584 0.000001 18.369108 -0.870571 0.000000 0.491989 0.773438 0.898438 1 0 1.000000 +0 5.652799 -2.057456 18.369108 -0.818079 0.297739 0.491989 0.726563 0.898438 1 0 1.000000 +0 6.249385 -2.274596 21.590519 -0.861690 0.313608 0.398877 0.726563 0.855469 1 0 1.000000 +holygrail.tga +0 6.249385 -2.274596 21.590519 -0.861690 0.313608 0.398877 0.726563 0.855469 1 0 1.000000 +0 6.650457 0.000001 21.590519 -0.916990 0.000000 0.398877 0.773438 0.855469 1 0 1.000000 +0 6.015584 0.000001 18.369108 -0.870571 0.000000 0.491989 0.773438 0.898438 1 0 1.000000 +holygrail.tga +0 3.266459 1.188897 16.225468 -0.477004 -0.173589 0.861568 0.832031 0.953125 1 0 1.000000 +0 3.476092 0.000003 16.225468 -0.507614 0.000000 0.861568 0.773438 0.953125 1 0 1.000000 +0 6.015584 0.000001 18.369108 -0.870571 0.000000 0.491989 0.773438 0.898438 1 0 1.000000 +holygrail.tga +0 6.015584 0.000001 18.369108 -0.870571 0.000000 0.491989 0.773438 0.898438 1 0 1.000000 +0 5.652801 2.057453 18.369108 -0.818079 -0.297739 0.491989 0.832031 0.898438 1 0 1.000000 +0 3.266459 1.188897 16.225468 -0.477004 -0.173589 0.861568 0.832031 0.953125 1 0 1.000000 +holygrail.tga +0 2.662842 2.234391 16.225471 -0.388836 -0.326273 0.861568 0.886719 0.953125 1 0 1.000000 +0 3.266459 1.188897 16.225468 -0.477004 -0.173589 0.861568 0.832031 0.953125 1 0 1.000000 +0 5.652801 2.057453 18.369108 -0.818079 -0.297739 0.491989 0.832031 0.898438 1 0 1.000000 +holygrail.tga +0 5.652801 2.057453 18.369108 -0.818079 -0.297739 0.491989 0.832031 0.898438 1 0 1.000000 +0 4.608207 3.866745 18.369110 -0.666890 -0.559587 0.491989 0.886719 0.898438 1 0 1.000000 +0 2.662842 2.234391 16.225471 -0.388836 -0.326273 0.861568 0.886719 0.953125 1 0 1.000000 +holygrail.tga +0 1.738046 3.010388 16.225471 -0.253792 -0.439589 0.861568 0.941406 0.953125 1 0 1.000000 +0 2.662842 2.234391 16.225471 -0.388836 -0.326273 0.861568 0.886719 0.953125 1 0 1.000000 +0 4.608207 3.866745 18.369110 -0.666890 -0.559587 0.491989 0.886719 0.898438 1 0 1.000000 +holygrail.tga +0 4.608207 3.866745 18.369110 -0.666890 -0.559587 0.491989 0.886719 0.898438 1 0 1.000000 +0 3.007792 5.209651 18.369110 -0.435286 -0.753929 0.491989 0.941406 0.898438 1 0 1.000000 +0 1.738046 3.010388 16.225471 -0.253792 -0.439589 0.861568 0.941406 0.953125 1 0 1.000000 +holygrail.tga +0 0.603616 3.423287 16.225471 -0.088137 -0.499893 0.861568 1.000000 0.953125 1 0 1.000000 +0 1.738046 3.010388 16.225471 -0.253792 -0.439589 0.861568 0.941406 0.953125 1 0 1.000000 +0 3.007792 5.209651 18.369110 -0.435286 -0.753929 0.491989 0.941406 0.898438 1 0 1.000000 +holygrail.tga +0 3.007792 5.209651 18.369110 -0.435286 -0.753929 0.491989 0.941406 0.898438 1 0 1.000000 +0 1.044595 5.924198 18.369110 -0.151158 -0.857356 0.491989 1.000000 0.898438 1 0 1.000000 +0 0.603616 3.423287 16.225471 -0.088137 -0.499893 0.861568 1.000000 0.953125 1 0 1.000000 +holygrail.tga +0 -0.603617 3.423287 16.225471 0.088137 -0.499893 0.861568 0.058594 0.953125 1 0 1.000000 +0 0.603616 3.423287 16.225471 -0.088137 -0.499893 0.861568 0.000000 0.953125 1 0 1.000000 +0 1.044595 5.924198 18.369110 -0.151158 -0.857356 0.491989 0.000000 0.898438 1 0 1.000000 +holygrail.tga +0 1.044595 5.924198 18.369110 -0.151158 -0.857356 0.491989 0.000000 0.898438 1 0 1.000000 +0 -1.044596 5.924198 18.369110 0.151158 -0.857356 0.491989 0.058594 0.898438 1 0 1.000000 +0 -0.603617 3.423287 16.225471 0.088137 -0.499893 0.861568 0.058594 0.953125 1 0 1.000000 +holygrail.tga +0 -1.738045 3.010389 16.225471 0.253792 -0.439589 0.861568 0.117188 0.953125 1 0 1.000000 +0 -0.603617 3.423287 16.225471 0.088137 -0.499893 0.861568 0.058594 0.953125 1 0 1.000000 +0 -1.044596 5.924198 18.369110 0.151158 -0.857356 0.491989 0.058594 0.898438 1 0 1.000000 +holygrail.tga +0 -1.044596 5.924198 18.369110 0.151158 -0.857356 0.491989 0.058594 0.898438 1 0 1.000000 +0 -3.007792 5.209652 18.369110 0.435286 -0.753929 0.491989 0.117188 0.898438 1 0 1.000000 +0 -1.738045 3.010389 16.225471 0.253792 -0.439589 0.861568 0.117188 0.953125 1 0 1.000000 +holygrail.tga +0 -2.662841 2.234391 16.225471 0.388836 -0.326273 0.861568 0.171875 0.953125 1 0 1.000000 +0 -1.738045 3.010389 16.225471 0.253792 -0.439589 0.861568 0.117188 0.953125 1 0 1.000000 +0 -3.007792 5.209652 18.369110 0.435286 -0.753929 0.491989 0.117188 0.898438 1 0 1.000000 +holygrail.tga +0 -3.007792 5.209652 18.369110 0.435286 -0.753929 0.491989 0.117188 0.898438 1 0 1.000000 +0 -4.608205 3.866745 18.369110 0.666890 -0.559587 0.491989 0.171875 0.898438 1 0 1.000000 +0 -2.662841 2.234391 16.225471 0.388836 -0.326273 0.861568 0.171875 0.953125 1 0 1.000000 +holygrail.tga +0 -3.266459 1.188895 16.225468 0.477004 -0.173589 0.861568 0.226563 0.953125 1 0 1.000000 +0 -2.662841 2.234391 16.225471 0.388836 -0.326273 0.861568 0.171875 0.953125 1 0 1.000000 +0 -4.608205 3.866745 18.369110 0.666890 -0.559587 0.491989 0.171875 0.898438 1 0 1.000000 +holygrail.tga +0 -4.608205 3.866745 18.369110 0.666890 -0.559587 0.491989 0.171875 0.898438 1 0 1.000000 +0 -5.652801 2.057453 18.369108 0.818079 -0.297739 0.491989 0.226563 0.898438 1 0 1.000000 +0 -3.266459 1.188895 16.225468 0.477004 -0.173589 0.861568 0.226563 0.953125 1 0 1.000000 +holygrail.tga +0 -3.476093 0.000002 16.225468 0.507614 0.000000 0.861568 0.289063 0.953125 1 0 1.000000 +0 -3.266459 1.188895 16.225468 0.477004 -0.173589 0.861568 0.226563 0.953125 1 0 1.000000 +0 -5.652801 2.057453 18.369108 0.818079 -0.297739 0.491989 0.226563 0.898438 1 0 1.000000 +holygrail.tga +0 -5.652801 2.057453 18.369108 0.818079 -0.297739 0.491989 0.226563 0.898438 1 0 1.000000 +0 -6.015585 0.000002 18.369108 0.870571 0.000000 0.491989 0.289063 0.898438 1 0 1.000000 +0 -3.476093 0.000002 16.225468 0.507614 0.000000 0.861568 0.289063 0.953125 1 0 1.000000 +holygrail.tga +0 -3.266459 -1.188892 16.225468 0.477004 0.173589 0.861568 0.339844 0.953125 1 0 1.000000 +0 -3.476093 0.000002 16.225468 0.507614 0.000000 0.861568 0.289063 0.953125 1 0 1.000000 +0 -6.015585 0.000002 18.369108 0.870571 0.000000 0.491989 0.289063 0.898438 1 0 1.000000 +holygrail.tga +0 -6.015585 0.000002 18.369108 0.870571 0.000000 0.491989 0.289063 0.898438 1 0 1.000000 +0 -5.652802 -2.057449 18.369108 0.818079 0.297739 0.491989 0.339844 0.898438 1 0 1.000000 +0 -3.266459 -1.188892 16.225468 0.477004 0.173589 0.861568 0.339844 0.953125 1 0 1.000000 +holygrail.tga +0 -2.662843 -2.234386 16.225468 0.388836 0.326273 0.861568 0.394531 0.953125 1 0 1.000000 +0 -3.266459 -1.188892 16.225468 0.477004 0.173589 0.861568 0.339844 0.953125 1 0 1.000000 +0 -5.652802 -2.057449 18.369108 0.818079 0.297739 0.491989 0.339844 0.898438 1 0 1.000000 +holygrail.tga +0 -5.652802 -2.057449 18.369108 0.818079 0.297739 0.491989 0.339844 0.898438 1 0 1.000000 +0 -4.608207 -3.866742 18.369108 0.666890 0.559587 0.491989 0.394531 0.898438 1 0 1.000000 +0 -2.662843 -2.234386 16.225468 0.388836 0.326273 0.861568 0.394531 0.953125 1 0 1.000000 +holygrail.tga +0 -1.738049 -3.010380 16.225470 0.253792 0.439589 0.861568 0.449219 0.953125 1 0 1.000000 +0 -2.662843 -2.234386 16.225468 0.388836 0.326273 0.861568 0.394531 0.953125 1 0 1.000000 +0 -4.608207 -3.866742 18.369108 0.666890 0.559587 0.491989 0.394531 0.898438 1 0 1.000000 +holygrail.tga +0 -4.608207 -3.866742 18.369108 0.666890 0.559587 0.491989 0.394531 0.898438 1 0 1.000000 +0 -3.007795 -5.209646 18.369108 0.435286 0.753929 0.491989 0.449219 0.898438 1 0 1.000000 +0 -1.738049 -3.010380 16.225470 0.253792 0.439589 0.861568 0.449219 0.953125 1 0 1.000000 +holygrail.tga +0 -0.603617 -3.423280 16.225470 0.088137 0.499893 0.861568 0.503906 0.953125 1 0 1.000000 +0 -1.738049 -3.010380 16.225470 0.253792 0.439589 0.861568 0.449219 0.953125 1 0 1.000000 +0 -3.007795 -5.209646 18.369108 0.435286 0.753929 0.491989 0.449219 0.898438 1 0 1.000000 +holygrail.tga +0 -3.007795 -5.209646 18.369108 0.435286 0.753929 0.491989 0.449219 0.898438 1 0 1.000000 +0 -1.044597 -5.924192 18.369108 0.151158 0.857356 0.491989 0.503906 0.898438 1 0 1.000000 +0 -0.603617 -3.423280 16.225470 0.088137 0.499893 0.861568 0.503906 0.953125 1 0 1.000000 +holygrail.tga +0 0.603615 -3.423281 16.225470 -0.088137 0.499893 0.861568 0.554688 0.953125 1 0 1.000000 +0 -0.603617 -3.423280 16.225470 0.088137 0.499893 0.861568 0.503906 0.953125 1 0 1.000000 +0 -1.044597 -5.924192 18.369108 0.151158 0.857356 0.491989 0.503906 0.898438 1 0 1.000000 +holygrail.tga +0 -1.044597 -5.924192 18.369108 0.151158 0.857356 0.491989 0.503906 0.898438 1 0 1.000000 +0 1.044592 -5.924194 18.369108 -0.151158 0.857356 0.491989 0.554688 0.898438 1 0 1.000000 +0 0.603615 -3.423281 16.225470 -0.088137 0.499893 0.861568 0.554688 0.953125 1 0 1.000000 +holygrail.tga +0 1.738045 -3.010382 16.225470 -0.253792 0.439589 0.861568 0.613281 0.953125 1 0 1.000000 +0 0.603615 -3.423281 16.225470 -0.088137 0.499893 0.861568 0.554688 0.953125 1 0 1.000000 +0 1.044592 -5.924194 18.369108 -0.151158 0.857356 0.491989 0.554688 0.898438 1 0 1.000000 +holygrail.tga +0 1.044592 -5.924194 18.369108 -0.151158 0.857356 0.491989 0.554688 0.898438 1 0 1.000000 +0 3.007790 -5.209648 18.369108 -0.435286 0.753929 0.491989 0.613281 0.898438 1 0 1.000000 +0 1.738045 -3.010382 16.225470 -0.253792 0.439589 0.861568 0.613281 0.953125 1 0 1.000000 +holygrail.tga +0 2.662842 -2.234388 16.225468 -0.388836 0.326273 0.861568 0.664063 0.953125 1 0 1.000000 +0 1.738045 -3.010382 16.225470 -0.253792 0.439589 0.861568 0.613281 0.953125 1 0 1.000000 +0 3.007790 -5.209648 18.369108 -0.435286 0.753929 0.491989 0.613281 0.898438 1 0 1.000000 +holygrail.tga +0 3.007790 -5.209648 18.369108 -0.435286 0.753929 0.491989 0.613281 0.898438 1 0 1.000000 +0 4.608204 -3.866745 18.369108 -0.666890 0.559587 0.491989 0.664063 0.898438 1 0 1.000000 +0 2.662842 -2.234388 16.225468 -0.388836 0.326273 0.861568 0.664063 0.953125 1 0 1.000000 +holygrail.tga +0 3.266457 -1.188897 16.225468 -0.477004 0.173589 0.861568 0.726563 0.953125 1 0 1.000000 +0 2.662842 -2.234388 16.225468 -0.388836 0.326273 0.861568 0.664063 0.953125 1 0 1.000000 +0 4.608204 -3.866745 18.369108 -0.666890 0.559587 0.491989 0.664063 0.898438 1 0 1.000000 +holygrail.tga +0 4.608204 -3.866745 18.369108 -0.666890 0.559587 0.491989 0.664063 0.898438 1 0 1.000000 +0 5.652799 -2.057456 18.369108 -0.818079 0.297739 0.491989 0.726563 0.898438 1 0 1.000000 +0 3.266457 -1.188897 16.225468 -0.477004 0.173589 0.861568 0.726563 0.953125 1 0 1.000000 +holygrail.tga +0 3.476092 0.000003 16.225468 -0.507614 0.000000 0.861568 0.773438 0.953125 1 0 1.000000 +0 3.266457 -1.188897 16.225468 -0.477004 0.173589 0.861568 0.726563 0.953125 1 0 1.000000 +0 5.652799 -2.057456 18.369108 -0.818079 0.297739 0.491989 0.726563 0.898438 1 0 1.000000 +holygrail.tga +0 5.652799 -2.057456 18.369108 -0.818079 0.297739 0.491989 0.726563 0.898438 1 0 1.000000 +0 6.015584 0.000001 18.369108 -0.870571 0.000000 0.491989 0.773438 0.898438 1 0 1.000000 +0 3.476092 0.000003 16.225468 -0.507614 0.000000 0.861568 0.773438 0.953125 1 0 1.000000 +holygrail.tga +0 1.050568 0.382381 15.421604 -0.170171 -0.061922 0.983459 0.832031 1.000000 1 0 1.000000 +0 1.117992 0.000004 15.421604 -0.181097 0.000000 0.983459 0.773438 1.000000 1 0 1.000000 +0 3.476092 0.000003 16.225468 -0.507614 0.000000 0.861568 0.773438 0.953125 1 0 1.000000 +holygrail.tga +0 3.476092 0.000003 16.225468 -0.507614 0.000000 0.861568 0.773438 0.953125 1 0 1.000000 +0 3.266459 1.188897 16.225468 -0.477004 -0.173589 0.861568 0.832031 0.953125 1 0 1.000000 +0 1.050568 0.382381 15.421604 -0.170171 -0.061922 0.983459 0.832031 1.000000 1 0 1.000000 +holygrail.tga +0 0.856432 0.718634 15.421607 -0.138737 -0.116398 0.983459 0.886719 1.000000 1 0 1.000000 +0 1.050568 0.382381 15.421604 -0.170171 -0.061922 0.983459 0.832031 1.000000 1 0 1.000000 +0 3.266459 1.188897 16.225468 -0.477004 -0.173589 0.861568 0.832031 0.953125 1 0 1.000000 +holygrail.tga +0 3.266459 1.188897 16.225468 -0.477004 -0.173589 0.861568 0.832031 0.953125 1 0 1.000000 +0 2.662842 2.234391 16.225471 -0.388836 -0.326273 0.861568 0.886719 0.953125 1 0 1.000000 +0 0.856432 0.718634 15.421607 -0.138737 -0.116398 0.983459 0.886719 1.000000 1 0 1.000000 +holygrail.tga +0 0.558995 0.968213 15.421606 -0.090548 -0.156835 0.983459 0.941406 1.000000 1 0 1.000000 +0 0.856432 0.718634 15.421607 -0.138737 -0.116398 0.983459 0.886719 1.000000 1 0 1.000000 +0 2.662842 2.234391 16.225471 -0.388836 -0.326273 0.861568 0.886719 0.953125 1 0 1.000000 +holygrail.tga +0 2.662842 2.234391 16.225471 -0.388836 -0.326273 0.861568 0.886719 0.953125 1 0 1.000000 +0 1.738046 3.010388 16.225471 -0.253792 -0.439589 0.861568 0.941406 0.953125 1 0 1.000000 +0 0.558995 0.968213 15.421606 -0.090548 -0.156835 0.983459 0.941406 1.000000 1 0 1.000000 +holygrail.tga +0 0.194135 1.101012 15.421606 -0.031434 -0.178350 0.983459 1.000000 1.000000 1 0 1.000000 +0 0.558995 0.968213 15.421606 -0.090548 -0.156835 0.983459 0.941406 1.000000 1 0 1.000000 +0 1.738046 3.010388 16.225471 -0.253792 -0.439589 0.861568 0.941406 0.953125 1 0 1.000000 +holygrail.tga +0 1.738046 3.010388 16.225471 -0.253792 -0.439589 0.861568 0.941406 0.953125 1 0 1.000000 +0 0.603616 3.423287 16.225471 -0.088137 -0.499893 0.861568 1.000000 0.953125 1 0 1.000000 +0 0.194135 1.101012 15.421606 -0.031434 -0.178350 0.983459 1.000000 1.000000 1 0 1.000000 +holygrail.tga +0 -0.194137 1.101012 15.421606 0.031434 -0.178350 0.983459 0.058594 1.000000 1 0 1.000000 +0 0.194135 1.101012 15.421606 -0.031434 -0.178350 0.983459 0.000000 1.000000 1 0 1.000000 +0 0.603616 3.423287 16.225471 -0.088137 -0.499893 0.861568 0.000000 0.953125 1 0 1.000000 +holygrail.tga +0 0.603616 3.423287 16.225471 -0.088137 -0.499893 0.861568 0.000000 0.953125 1 0 1.000000 +0 -0.603617 3.423287 16.225471 0.088137 -0.499893 0.861568 0.058594 0.953125 1 0 1.000000 +0 -0.194137 1.101012 15.421606 0.031434 -0.178350 0.983459 0.058594 1.000000 1 0 1.000000 +holygrail.tga +0 -0.558994 0.968215 15.421606 0.090548 -0.156835 0.983459 0.117188 1.000000 1 0 1.000000 +0 -0.194137 1.101012 15.421606 0.031434 -0.178350 0.983459 0.058594 1.000000 1 0 1.000000 +0 -0.603617 3.423287 16.225471 0.088137 -0.499893 0.861568 0.058594 0.953125 1 0 1.000000 +holygrail.tga +0 -0.603617 3.423287 16.225471 0.088137 -0.499893 0.861568 0.058594 0.953125 1 0 1.000000 +0 -1.738045 3.010389 16.225471 0.253792 -0.439589 0.861568 0.117188 0.953125 1 0 1.000000 +0 -0.558994 0.968215 15.421606 0.090548 -0.156835 0.983459 0.117188 1.000000 1 0 1.000000 +holygrail.tga +0 -0.856431 0.718634 15.421607 0.138707 -0.116398 0.983459 0.171875 1.000000 1 0 1.000000 +0 -0.558994 0.968215 15.421606 0.090548 -0.156835 0.983459 0.117188 1.000000 1 0 1.000000 +0 -1.738045 3.010389 16.225471 0.253792 -0.439589 0.861568 0.117188 0.953125 1 0 1.000000 +holygrail.tga +0 -1.738045 3.010389 16.225471 0.253792 -0.439589 0.861568 0.117188 0.953125 1 0 1.000000 +0 -2.662841 2.234391 16.225471 0.388836 -0.326273 0.861568 0.171875 0.953125 1 0 1.000000 +0 -0.856431 0.718634 15.421607 0.138707 -0.116398 0.983459 0.171875 1.000000 1 0 1.000000 +holygrail.tga +0 -1.050570 0.382377 15.421604 0.170171 -0.061922 0.983459 0.226563 1.000000 1 0 1.000000 +0 -0.856431 0.718634 15.421607 0.138707 -0.116398 0.983459 0.171875 1.000000 1 0 1.000000 +0 -2.662841 2.234391 16.225471 0.388836 -0.326273 0.861568 0.171875 0.953125 1 0 1.000000 +holygrail.tga +0 -2.662841 2.234391 16.225471 0.388836 -0.326273 0.861568 0.171875 0.953125 1 0 1.000000 +0 -3.266459 1.188895 16.225468 0.477004 -0.173589 0.861568 0.226563 0.953125 1 0 1.000000 +0 -1.050570 0.382377 15.421604 0.170171 -0.061922 0.983459 0.226563 1.000000 1 0 1.000000 +holygrail.tga +0 -1.117993 0.000002 15.421604 0.181097 0.000000 0.983459 0.289063 1.000000 1 0 1.000000 +0 -1.050570 0.382377 15.421604 0.170171 -0.061922 0.983459 0.226563 1.000000 1 0 1.000000 +0 -3.266459 1.188895 16.225468 0.477004 -0.173589 0.861568 0.226563 0.953125 1 0 1.000000 +holygrail.tga +0 -3.266459 1.188895 16.225468 0.477004 -0.173589 0.861568 0.226563 0.953125 1 0 1.000000 +0 -3.476093 0.000002 16.225468 0.507614 0.000000 0.861568 0.289063 0.953125 1 0 1.000000 +0 -1.117993 0.000002 15.421604 0.181097 0.000000 0.983459 0.289063 1.000000 1 0 1.000000 +holygrail.tga +0 -1.050570 -0.382374 15.421605 0.170171 0.061922 0.983459 0.339844 1.000000 1 0 1.000000 +0 -1.117993 0.000002 15.421604 0.181097 0.000000 0.983459 0.289063 1.000000 1 0 1.000000 +0 -3.476093 0.000002 16.225468 0.507614 0.000000 0.861568 0.289063 0.953125 1 0 1.000000 +holygrail.tga +0 -3.476093 0.000002 16.225468 0.507614 0.000000 0.861568 0.289063 0.953125 1 0 1.000000 +0 -3.266459 -1.188892 16.225468 0.477004 0.173589 0.861568 0.339844 0.953125 1 0 1.000000 +0 -1.050570 -0.382374 15.421605 0.170171 0.061922 0.983459 0.339844 1.000000 1 0 1.000000 +holygrail.tga +0 -0.856433 -0.718628 15.421605 0.138707 0.116398 0.983459 0.394531 1.000000 1 0 1.000000 +0 -1.050570 -0.382374 15.421605 0.170171 0.061922 0.983459 0.339844 1.000000 1 0 1.000000 +0 -3.266459 -1.188892 16.225468 0.477004 0.173589 0.861568 0.339844 0.953125 1 0 1.000000 +holygrail.tga +0 -3.266459 -1.188892 16.225468 0.477004 0.173589 0.861568 0.339844 0.953125 1 0 1.000000 +0 -2.662843 -2.234386 16.225468 0.388836 0.326273 0.861568 0.394531 0.953125 1 0 1.000000 +0 -0.856433 -0.718628 15.421605 0.138707 0.116398 0.983459 0.394531 1.000000 1 0 1.000000 +holygrail.tga +0 -0.558999 -0.968206 15.421605 0.090548 0.156835 0.983459 0.449219 1.000000 1 0 1.000000 +0 -0.856433 -0.718628 15.421605 0.138707 0.116398 0.983459 0.394531 1.000000 1 0 1.000000 +0 -2.662843 -2.234386 16.225468 0.388836 0.326273 0.861568 0.394531 0.953125 1 0 1.000000 +holygrail.tga +0 -2.662843 -2.234386 16.225468 0.388836 0.326273 0.861568 0.394531 0.953125 1 0 1.000000 +0 -1.738049 -3.010380 16.225470 0.253792 0.439589 0.861568 0.449219 0.953125 1 0 1.000000 +0 -0.558999 -0.968206 15.421605 0.090548 0.156835 0.983459 0.449219 1.000000 1 0 1.000000 +holygrail.tga +0 -0.194136 -1.101005 15.421605 0.031434 0.178350 0.983459 0.503906 1.000000 1 0 1.000000 +0 -0.558999 -0.968206 15.421605 0.090548 0.156835 0.983459 0.449219 1.000000 1 0 1.000000 +0 -1.738049 -3.010380 16.225470 0.253792 0.439589 0.861568 0.449219 0.953125 1 0 1.000000 +holygrail.tga +0 -1.738049 -3.010380 16.225470 0.253792 0.439589 0.861568 0.449219 0.953125 1 0 1.000000 +0 -0.603617 -3.423280 16.225470 0.088137 0.499893 0.861568 0.503906 0.953125 1 0 1.000000 +0 -0.194136 -1.101005 15.421605 0.031434 0.178350 0.983459 0.503906 1.000000 1 0 1.000000 +holygrail.tga +0 0.194136 -1.101005 15.421605 -0.031434 0.178350 0.983459 0.554688 1.000000 1 0 1.000000 +0 -0.194136 -1.101005 15.421605 0.031434 0.178350 0.983459 0.503906 1.000000 1 0 1.000000 +0 -0.603617 -3.423280 16.225470 0.088137 0.499893 0.861568 0.503906 0.953125 1 0 1.000000 +holygrail.tga +0 -0.603617 -3.423280 16.225470 0.088137 0.499893 0.861568 0.503906 0.953125 1 0 1.000000 +0 0.603615 -3.423281 16.225470 -0.088137 0.499893 0.861568 0.554688 0.953125 1 0 1.000000 +0 0.194136 -1.101005 15.421605 -0.031434 0.178350 0.983459 0.554688 1.000000 1 0 1.000000 +holygrail.tga +0 0.558996 -0.968207 15.421605 -0.090548 0.156835 0.983459 0.613281 1.000000 1 0 1.000000 +0 0.194136 -1.101005 15.421605 -0.031434 0.178350 0.983459 0.554688 1.000000 1 0 1.000000 +0 0.603615 -3.423281 16.225470 -0.088137 0.499893 0.861568 0.554688 0.953125 1 0 1.000000 +holygrail.tga +0 0.603615 -3.423281 16.225470 -0.088137 0.499893 0.861568 0.554688 0.953125 1 0 1.000000 +0 1.738045 -3.010382 16.225470 -0.253792 0.439589 0.861568 0.613281 0.953125 1 0 1.000000 +0 0.558996 -0.968207 15.421605 -0.090548 0.156835 0.983459 0.613281 1.000000 1 0 1.000000 +holygrail.tga +0 0.856433 -0.718628 15.421605 -0.138707 0.116398 0.983459 0.664063 1.000000 1 0 1.000000 +0 0.558996 -0.968207 15.421605 -0.090548 0.156835 0.983459 0.613281 1.000000 1 0 1.000000 +0 1.738045 -3.010382 16.225470 -0.253792 0.439589 0.861568 0.613281 0.953125 1 0 1.000000 +holygrail.tga +0 1.738045 -3.010382 16.225470 -0.253792 0.439589 0.861568 0.613281 0.953125 1 0 1.000000 +0 2.662842 -2.234388 16.225468 -0.388836 0.326273 0.861568 0.664063 0.953125 1 0 1.000000 +0 0.856433 -0.718628 15.421605 -0.138707 0.116398 0.983459 0.664063 1.000000 1 0 1.000000 +holygrail.tga +0 1.050567 -0.382379 15.421605 -0.170171 0.061922 0.983459 0.726563 1.000000 1 0 1.000000 +0 0.856433 -0.718628 15.421605 -0.138707 0.116398 0.983459 0.664063 1.000000 1 0 1.000000 +0 2.662842 -2.234388 16.225468 -0.388836 0.326273 0.861568 0.664063 0.953125 1 0 1.000000 +holygrail.tga +0 2.662842 -2.234388 16.225468 -0.388836 0.326273 0.861568 0.664063 0.953125 1 0 1.000000 +0 3.266457 -1.188897 16.225468 -0.477004 0.173589 0.861568 0.726563 0.953125 1 0 1.000000 +0 1.050567 -0.382379 15.421605 -0.170171 0.061922 0.983459 0.726563 1.000000 1 0 1.000000 +holygrail.tga +0 1.117992 0.000004 15.421604 -0.181097 0.000000 0.983459 0.773438 1.000000 1 0 1.000000 +0 1.050567 -0.382379 15.421605 -0.170171 0.061922 0.983459 0.726563 1.000000 1 0 1.000000 +0 3.266457 -1.188897 16.225468 -0.477004 0.173589 0.861568 0.726563 0.953125 1 0 1.000000 +holygrail.tga +0 3.266457 -1.188897 16.225468 -0.477004 0.173589 0.861568 0.726563 0.953125 1 0 1.000000 +0 3.476092 0.000003 16.225468 -0.507614 0.000000 0.861568 0.773438 0.953125 1 0 1.000000 +0 1.117992 0.000004 15.421604 -0.181097 0.000000 0.983459 0.773438 1.000000 1 0 1.000000 +end diff --git a/test/models/SMD/holygrail.tga b/test/models/SMD/holygrail.tga new file mode 100644 index 000000000..99df7364f Binary files /dev/null and b/test/models/SMD/holygrail.tga differ diff --git a/test/models/STL/triangle_with_two_solids.stl b/test/models/STL/triangle_with_two_solids.stl new file mode 100644 index 000000000..9af3841ae --- /dev/null +++ b/test/models/STL/triangle_with_two_solids.stl @@ -0,0 +1,18 @@ +solid testTriangle_1 + facet normal 0.0 0.0 1.0 + outer loop + vertex 1.0 1.0 0.0 + vertex -1.0 1.0 0.0 + vertex 0.0 -1.0 0.0 + endloop + endfacet +endsolid +solid testTriangle_2 + facet normal 0.0 0.0 1.0 + outer loop + vertex 3.0 3.0 0.0 + vertex 2.0 3.0 0.0 + vertex 0.0 2.0 0.0 + endloop + endfacet +endsolid diff --git a/test/models/X3D/ComputerKeyboard.x3d b/test/models/X3D/ComputerKeyboard.x3d new file mode 100644 index 000000000..2d6c0707f --- /dev/null +++ b/test/models/X3D/ComputerKeyboard.x3d @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/models/glTF2/2CylinderEngine-glTF-Binary/2CylinderEngine.glb b/test/models/glTF2/2CylinderEngine-glTF-Binary/2CylinderEngine.glb new file mode 100644 index 000000000..0e9b10568 Binary files /dev/null and b/test/models/glTF2/2CylinderEngine-glTF-Binary/2CylinderEngine.glb differ diff --git a/test/models/glTF2/BoxTextured-glTF-Binary/BoxTextured.glb b/test/models/glTF2/BoxTextured-glTF-Binary/BoxTextured.glb new file mode 100644 index 000000000..03cd2acf9 Binary files /dev/null and b/test/models/glTF2/BoxTextured-glTF-Binary/BoxTextured.glb differ diff --git a/test/models/glTF2/BoxTextured-glTF-Embedded/BoxTextured.gltf b/test/models/glTF2/BoxTextured-glTF-Embedded/BoxTextured.gltf new file mode 100644 index 000000000..c9c461495 --- /dev/null +++ b/test/models/glTF2/BoxTextured-glTF-Embedded/BoxTextured.gltf @@ -0,0 +1,181 @@ +{ + "asset": { + "generator": "COLLADA2GLTF", + "version": "2.0" + }, + "scene": 0, + "scenes": [ + { + "nodes": [ + 0 + ] + } + ], + "nodes": [ + { + "children": [ + 1 + ], + "matrix": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ] + }, + { + "mesh": 0 + } + ], + "meshes": [ + { + "primitives": [ + { + "attributes": { + "NORMAL": 1, + "POSITION": 2, + "TEXCOORD_0": 3 + }, + "indices": 0, + "mode": 4, + "material": 0 + } + ], + "name": "Mesh" + } + ], + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5123, + "count": 36, + "max": [ + 23 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 1.0, + 1.0, + 1.0 + ], + "min": [ + -1.0, + -1.0, + -1.0 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 288, + "componentType": 5126, + "count": 24, + "max": [ + 0.5, + 0.5, + 0.5 + ], + "min": [ + -0.5, + -0.5, + -0.5 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 6.0, + 1.0 + ], + "min": [ + 0.0, + 0.0 + ], + "type": "VEC2" + } + ], + "materials": [ + { + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 0 + }, + "metallicFactor": 0.0 + }, + "name": "Texture" + } + ], + "textures": [ + { + "sampler": 0, + "source": 0 + } + ], + "images": [ + { + "uri": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANMAAADTCAMAAAAs2dbrAAAAsVBMVEXc3Nz8/f3+//9chyf///+VsHP4+/thiy3Z29dyl0R8nlH09vJeiCqzxZ6ft4GLqWatwZXw9vyEpFynvYxmjjTS3cNrkjvu8urn8vre7fjY6ffL08K6yqbEz7XT183K4vTQ5fW62fC/zq3J17fn7d/g6NbC3fLb5c/l5eVsrd+wzOF/t+OWw+WGu+TE099vr+CmyON5tOJ0seG50OHL1t7S2d7Z29yOv+Wdx+emzuyx1O6AHuoWAAAIi0lEQVR4XuzUS3LEIAxF0WznIYk/xun9LyxDRqnqGANq4rODW4L39d88Ho/H43HkZPzJVYgoxhiIpDJ7k2z5wJpizSkBv4vCJn1OWTZMeE9gY/Xfx3DE30Q2WfGBvOAa8lZnEKFH0JZ1GEE/MnpGw54R93Cs41ip4k6SjuWPjnC3YJZWtaJdqhJhlJDWLINgJJm/FoUxGpfJ0xAxnvMTv1UWzEF21pG8wzT+2OZIjeTxScZhLmdGz13FfHXoAGbCCmHgVCSHNVwaleSxjh8z4Yxmj09VBGtRGbAOq1G+OSlgvZC3SwLijVE2Qodot7lS4+xGSS1quyS4O/5UIegSSm/SUaENHZ1NDH1qX5SHRmdPUoJOqWPyInS6Pn6HoNlkJxh68T6fqTFXkkrERPL9en0L3ueufKkf6uxmt1EYiAN4sP7i0pNPABeItEIdeV0vJMTA+z/YaqWo3WSS1gn2lP4ewFHEfNqexLi5hAIAvTgKZZ+4myQxpsSZUtomiD75yPM5Pqg8uDK5cbORZzT+p3JDgfxma16LK3WaceLUkxQPJjj6hnGbo2sHpkkxzB4didFgcgp23OJQ5BS4Pn6TeiM5PThYCva2vQmCHDgYCmZXfCbJfMpc9PXQk6QGTE0PMNv7TDSBmaM/IXqSVeKKdsSsy6gjCfMZLijWSVaXvomkzbiwRF/jR0fS3JThXTbTw8aAVVCcbXFW2wRv8oa+hVmaumoWS88YTgKFXNpBYHrd1GXfaaCfyI0CK7u0g0DoSfMCoSduTBF6Zto3bV033ewdiel/L/9+te3G6HOR35d4p/JmcjI9rVI4e9nd0z9XSStc08tAidkmw4cs6khuK3BK6ZlS6huFC6/xZj23z3BHbSiZOceVIto2aCrcp1N1BteByXe3DfQgq/EZNVMKQwUui5ROPscXFoqvL3HLa5R0sjkg/6eGEjcVMQajXuNraqK4XA3ufoey9AhXIURmUzyDhCbUya0/nFN6SHIbyK0vERMCqZZW4ikcXCQOcQ7nlgT1gVPFjvuz+vCXX4UCl/mEd+tAXhSsSDxT9rq/tJjbasJAFEWJm2QwF6NJVNra0hptoFVsERrp/39YXwTrbDWZOcf1GrLDhrMyF45elUMAVTjlR5NvrctNIsniFDB5HVzstJWEB+MUR/I5PdVRahtQcF3hSNxEkoMGhw+SAidmU1bqLjIFI5wwS670IwhPYvzHNCRweweZBiHOeBH8yik8KnBOtWal9GUqcc4T38D6h49gM0zoNLXTlqmGBQ/fXhDOhKyUskyrChYZ78ol4cyCpn+jKlMUw6bkTpJwxjgqJZ93jHgbIQt3Ukou0zOYkDv5rUw1rpDmtE9685VpYn91ZXp1OjiFs0xMpqXUa795z7mTRnjH0jvxuh77pXkP0a/TRh7erdSDh1ItybTERQruJA5nNJTia4+16dvp4C4Th+srxfOeDKHVaccyUTiRNnan6FNNpm6fvhTCmVlil3JTqh3wvDt1ksvE5PTeu5ZM3evTh0o4MxZcY+4eO2QSdeobzpgpK6UjU/d+b68TzszmvqvUhmRa4Aal05mwdQhnClbKU6bG4AYZn91dwv94t+MepYEgCuDTzhSudIFSgKIHKtwlaIBEe5cTv/8XM8ZEIrPtGxzw9zd5TcO83SbbgjKhSsnJXyZtRZfeHOFAmKut7fgF2siFdMyd1qQ0/nB7pZbN9WUacrcPpOwd4bev1B6USeuTdnA0FZqCF67h6Rae95y0r45wTO9SR0+ZtFCR9uIIx2agUv55H5H26gnHqp7906395W/TXWBkGD/7xOGiw/2VwvNeLxhaU8Qeh6eFCrd7ugxLjsbTrWTM2IPtTbeNIdxu9myr1EnNe8lYThFvL65wLAyilcLzPg+MZRTz6gzHRoaTgWYZKxNWUlRzZbi/UpKc4MNlUrHFI0Udrg73Vyo5oKP10pZseCexeR8J9ztXKvrNfvNR/nHeK2px3jC+T2zh/kql6ebPxnhcCph3VCett/zx7dfYHT6lINxTKWWy2aurqnnHdYqrRdLJu2UiAsId+s8S0XJVmbJNTm0+iwLCPZXC0jkbZdQqkRYq3CETq3rGRltqVUhUqsI9wlYAdbqFzB4IDp8O99Ln19iIHaMHhi/N+KbCohaDFZutqUPhWB9864RnP1yQAoav5NurCrjk9dlsRJ16KnzK9zAAN/XUZ7tH6nQ56cWY7yPvWiiSku3CgAD5yy7newmrRFrUFV9jSEAhZ8Uo8P2EQfyvSoYzVtDmZFwlihJku4VM31Vvm/N1pgQVv6PnWZ//g2pby1m6my5+cls3ubHCQBCASypZbiPbIGDYAF7wXpScYO5/tCxZBgb8g78btKpdbZ6kA/708/Vah35kKrbxy+v7/9frX9dOPE/hb2KYi+V5dsYBjk+icIjhc+gZhyz1xQRp+BQ6ALUF5XFYz2eYBIfNmo/gcILnEzQ4QwzLZ2ecstVTELuWpTOCk8LEwq04batm83Zvz5I1gg+IeczftY7L2+FDHUul8DFVzWPaSc8SjTMuCIblsRt2lfSEw0WLZVmsx2Wu5Mqro9FbwR0GlqMX3OLtyztM16n6RgJ8PYu36+qph52zzEwJ7rZoZjUggnViPtohitAwl2lFLIp5NAHxdDZTO8S0GqY2OkQmqp69220T07EDkggtU2lmpOLSRKUHJCTeMro2IK25Z1xmRXqLYTxjJ8jh7QzjGAdBLhJlKu0DcpLO8F7TEJDd1lrexjhBCd7Bj7yDVivKIe56WL/t2jEKwCAMheEsYirEBgNdohl6CO9/tM6FgrRdFPJNWX/I+BIbTMao/MhKYjAlo/3LE8bCChND5RLfLXxPhNl1wMYhxXHOtktDWInWHMr2mHakkEkRVoXaaiUWyVmEqTY1hOX1+z3mnHPOXX/B0DoXjBYdAAAAAElFTkSuQmCC" + } + ], + "samplers": [ + { + "magFilter": 9729, + "minFilter": 9986, + "wrapS": 10497, + "wrapT": 10497 + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 768, + "byteLength": 72, + "target": 34963 + }, + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 576, + "byteStride": 12, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 576, + "byteLength": 192, + "byteStride": 8, + "target": 34962 + } + ], + "buffers": [ + { + "byteLength": 840, + "uri": "data:application/octet-stream;base64,AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAvwAAAL8AAAA/AAAAPwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAPwAAAL8AAAA/AAAAPwAAAD8AAAC/AAAAPwAAAL8AAAC/AAAAvwAAAD8AAAA/AAAAPwAAAD8AAAA/AAAAvwAAAD8AAAC/AAAAPwAAAD8AAAC/AAAAPwAAAL8AAAA/AAAAvwAAAL8AAAA/AAAAPwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAA/AAAAvwAAAD8AAAA/AAAAvwAAAL8AAAC/AAAAvwAAAD8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAD8AAAC/AAAAPwAAAL8AAAC/AAAAPwAAAD8AAAC/AADAQAAAAAAAAKBAAAAAAAAAwED+/38/AACgQP7/fz8AAIBAAAAAAAAAoEAAAAAAAACAQAAAgD8AAKBAAACAPwAAAEAAAAAAAACAPwAAAAAAAABAAACAPwAAgD8AAIA/AABAQAAAAAAAAIBAAAAAAAAAQEAAAIA/AACAQAAAgD8AAEBAAAAAAAAAAEAAAAAAAABAQAAAgD8AAABAAACAPwAAAAAAAAAAAAAAAP7/fz8AAIA/AAAAAAAAgD/+/38/AAABAAIAAwACAAEABAAFAAYABwAGAAUACAAJAAoACwAKAAkADAANAA4ADwAOAA0AEAARABIAEwASABEAFAAVABYAFwAWABUA" + } + ] +} diff --git a/test/models/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured.gltf b/test/models/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured.gltf new file mode 100644 index 000000000..b286239fa --- /dev/null +++ b/test/models/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured.gltf @@ -0,0 +1,197 @@ +{ + "asset": { + "generator": "COLLADA2GLTF", + "version": "2.0" + }, + "scene": 0, + "scenes": [ + { + "nodes": [ + 0 + ] + } + ], + "nodes": [ + { + "children": [ + 1 + ], + "matrix": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ] + }, + { + "mesh": 0 + } + ], + "meshes": [ + { + "primitives": [ + { + "attributes": { + "NORMAL": 1, + "POSITION": 2, + "TEXCOORD_0": 3 + }, + "indices": 0, + "mode": 4, + "material": 0 + } + ], + "name": "Mesh" + } + ], + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5123, + "count": 36, + "max": [ + 23 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 1.0, + 1.0, + 1.0 + ], + "min": [ + -1.0, + -1.0, + -1.0 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 288, + "componentType": 5126, + "count": 24, + "max": [ + 0.5, + 0.5, + 0.5 + ], + "min": [ + -0.5, + -0.5, + -0.5 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 6.0, + 1.0 + ], + "min": [ + 0.0, + 0.0 + ], + "type": "VEC2" + } + ], + "materials": [ + { + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 0 + }, + "metallicFactor": 0.0 + }, + "extensions": { + "KHR_materials_pbrSpecularGlossiness": { + "diffuseTexture": { + "index": 0 + }, + "specularFactor": [ + 0.20000000298023225, + 0.20000000298023225, + 0.20000000298023225 + ], + "glossinessFactor": 1.0 + } + }, + "name": "Texture" + } + ], + "textures": [ + { + "sampler": 0, + "source": 0 + } + ], + "images": [ + { + "uri": "CesiumLogoFlat.png" + } + ], + "samplers": [ + { + "magFilter": 9729, + "minFilter": 9986, + "wrapS": 10497, + "wrapT": 10497 + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 768, + "byteLength": 72, + "target": 34963 + }, + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 576, + "byteStride": 12, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 576, + "byteLength": 192, + "byteStride": 8, + "target": 34962 + } + ], + "buffers": [ + { + "byteLength": 840, + "uri": "BoxTextured0.bin" + } + ], + "extensionsUsed": [ + "KHR_materials_pbrSpecularGlossiness" + ] +} diff --git a/test/models/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured0.bin b/test/models/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured0.bin new file mode 100644 index 000000000..d2a73551f Binary files /dev/null and b/test/models/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/BoxTextured0.bin differ diff --git a/test/models/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/CesiumLogoFlat.png b/test/models/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/CesiumLogoFlat.png new file mode 100644 index 000000000..45d502ed2 Binary files /dev/null and b/test/models/glTF2/BoxTextured-glTF-pbrSpecularGlossiness/CesiumLogoFlat.png differ diff --git a/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured.gltf b/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured.gltf new file mode 100644 index 000000000..7401dced1 --- /dev/null +++ b/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured.gltf @@ -0,0 +1,282 @@ +{ + "asset": { + "generator": "COLLADA2GLTF", + "version": "2.0" + }, + "scene": 0, + "scenes": [ + { + "nodes": [ + 0 + ] + } + ], + "nodes": [ + { + "children": [ + 1 + ], + "matrix": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ] + }, + { + "mesh": 0 + } + ], + "meshes": [ + { + "primitives": [ + { + "attributes": { + "NORMAL": 1, + "POSITION": 2, + "TEXCOORD_0": 3 + }, + "indices": 0, + "mode": 4, + "material": 0 + } + ], + "name": "Mesh" + } + ], + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5123, + "count": 36, + "max": [ + 23 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 1.0, + 1.0, + 1.0 + ], + "min": [ + -1.0, + -1.0, + -1.0 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 288, + "componentType": 5126, + "count": 24, + "max": [ + 0.5, + 0.5, + 0.5 + ], + "min": [ + -0.5, + -0.5, + -0.5 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 6.0, + 1.0 + ], + "min": [ + 0.0, + 0.0 + ], + "type": "VEC2" + } + ], + "materials": [ + { + "values": { + "diffuse": [ + 0 + ], + "specular": [ + 0.20000000298023225, + 0.20000000298023225, + 0.20000000298023225, + 1.0 + ], + "shininess": [ + 256.0 + ], + "transparency": [ + 1.0 + ] + }, + "technique": 0 + } + ], + "textures": [ + { + "sampler": 0, + "source": 0 + } + ], + "images": [ + { + "uri": "CesiumLogoFlat.png" + } + ], + "samplers": [ + { + "magFilter": 9729, + "minFilter": 9986, + "wrapS": 10497, + "wrapT": 10497 + } + ], + "techniques": [ + { + "attributes": { + "a_normal": "normal", + "a_position": "position", + "a_texcoord0": "texcoord0" + }, + "parameters": { + "diffuse": { + "type": 35678 + }, + "modelViewMatrix": { + "semantic": "MODELVIEW", + "type": 35676 + }, + "normal": { + "semantic": "NORMAL", + "type": 35665 + }, + "normalMatrix": { + "semantic": "MODELVIEWINVERSETRANSPOSE", + "type": 35675 + }, + "position": { + "semantic": "POSITION", + "type": 35665 + }, + "projectionMatrix": { + "semantic": "PROJECTION", + "type": 35676 + }, + "shininess": { + "type": 5126 + }, + "specular": { + "type": 35666 + }, + "texcoord0": { + "semantic": "TEXCOORD_0", + "type": 35665 + }, + "transparency": { + "type": 5126 + } + }, + "program": 0, + "states": { + "enable": [ + 2884, + 2929 + ] + }, + "uniforms": { + "u_diffuse": "diffuse", + "u_modelViewMatrix": "modelViewMatrix", + "u_normalMatrix": "normalMatrix", + "u_projectionMatrix": "projectionMatrix", + "u_shininess": "shininess", + "u_specular": "specular", + "u_transparency": "transparency" + } + } + ], + "programs": [ + { + "attributes": [ + "a_normal", + "a_position", + "a_texcoord0" + ], + "fragmentShader": 1, + "vertexShader": 0 + } + ], + "shaders": [ + { + "type": 35633, + "uri": "BoxTextured0.vert" + }, + { + "type": 35632, + "uri": "BoxTextured1.frag" + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 768, + "byteLength": 72, + "target": 34963 + }, + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 576, + "byteStride": 12, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 576, + "byteLength": 192, + "byteStride": 8, + "target": 34962 + } + ], + "buffers": [ + { + "byteLength": 840, + "uri": "BoxTextured0.bin" + } + ], + "extensionsRequired": [ + "KHR_technique_webgl" + ], + "extensionsUsed": [ + "KHR_technique_webgl" + ] +} diff --git a/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured0.bin b/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured0.bin new file mode 100644 index 000000000..d2a73551f Binary files /dev/null and b/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured0.bin differ diff --git a/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured0.vert b/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured0.vert new file mode 100644 index 000000000..05d5e82c2 --- /dev/null +++ b/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured0.vert @@ -0,0 +1,17 @@ +precision highp float; +uniform mat4 u_modelViewMatrix; +uniform mat4 u_projectionMatrix; +uniform mat3 u_normalMatrix; +attribute vec3 a_position; +varying vec3 v_position; +attribute vec3 a_normal; +varying vec3 v_normal; +attribute vec2 a_texcoord0; +varying vec2 v_texcoord0; +void main(void) { + vec4 pos = u_modelViewMatrix * vec4(a_position,1.0); + v_position = pos.xyz; + gl_Position = u_projectionMatrix * pos; + v_normal = u_normalMatrix * a_normal; + v_texcoord0 = a_texcoord0; +} diff --git a/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured1.frag b/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured1.frag new file mode 100644 index 000000000..3850980a0 --- /dev/null +++ b/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/BoxTextured1.frag @@ -0,0 +1,29 @@ +precision highp float; +uniform sampler2D u_diffuse; +uniform vec4 u_specular; +uniform float u_shininess; +uniform float u_transparency; +varying vec3 v_position; +varying vec3 v_normal; +varying vec2 v_texcoord0; +void main(void) { + vec3 normal = normalize(v_normal); + vec4 diffuse = texture2D(u_diffuse, v_texcoord0); + vec3 diffuseLight = vec3(0.0, 0.0, 0.0); + vec3 specular = u_specular.rgb; + vec3 specularLight = vec3(0.0, 0.0, 0.0); + vec3 ambient = diffuse.rgb; + vec3 viewDir = -normalize(v_position); + vec3 ambientLight = vec3(0.0, 0.0, 0.0); + ambientLight += vec3(0.2, 0.2, 0.2); + vec3 l = vec3(0.0, 0.0, 1.0); + diffuseLight += vec3(1.0, 1.0, 1.0) * max(dot(normal, l), 0.); + vec3 reflectDir = reflect(-l, normal); + float specularIntensity = max(0., pow(max(dot(reflectDir, viewDir), 0.), u_shininess)); + specularLight += vec3(1.0, 1.0, 1.0) * specularIntensity; + vec3 color = vec3(0.0, 0.0, 0.0); + color += diffuse.rgb * diffuseLight; + color += specular * specularLight; + color += ambient * ambientLight; + gl_FragColor = vec4(color * diffuse.a * u_transparency, diffuse.a * u_transparency); +} diff --git a/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/CesiumLogoFlat.png b/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/CesiumLogoFlat.png new file mode 100644 index 000000000..45d502ed2 Binary files /dev/null and b/test/models/glTF2/BoxTextured-glTF-techniqueWebGL/CesiumLogoFlat.png differ diff --git a/test/models/glTF2/BoxTextured-glTF/BoxTextured.gltf b/test/models/glTF2/BoxTextured-glTF/BoxTextured.gltf new file mode 100644 index 000000000..eff658f02 --- /dev/null +++ b/test/models/glTF2/BoxTextured-glTF/BoxTextured.gltf @@ -0,0 +1,181 @@ +{ + "asset": { + "generator": "COLLADA2GLTF", + "version": "2.0" + }, + "scene": 0, + "scenes": [ + { + "nodes": [ + 0 + ] + } + ], + "nodes": [ + { + "children": [ + 1 + ], + "matrix": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + -1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0 + ] + }, + { + "mesh": 0 + } + ], + "meshes": [ + { + "primitives": [ + { + "attributes": { + "NORMAL": 1, + "POSITION": 2, + "TEXCOORD_0": 3 + }, + "indices": 0, + "mode": 4, + "material": 0 + } + ], + "name": "Mesh" + } + ], + "accessors": [ + { + "bufferView": 0, + "byteOffset": 0, + "componentType": 5123, + "count": 36, + "max": [ + 23 + ], + "min": [ + 0 + ], + "type": "SCALAR" + }, + { + "bufferView": 1, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 1.0, + 1.0, + 1.0 + ], + "min": [ + -1.0, + -1.0, + -1.0 + ], + "type": "VEC3" + }, + { + "bufferView": 1, + "byteOffset": 288, + "componentType": 5126, + "count": 24, + "max": [ + 0.5, + 0.5, + 0.5 + ], + "min": [ + -0.5, + -0.5, + -0.5 + ], + "type": "VEC3" + }, + { + "bufferView": 2, + "byteOffset": 0, + "componentType": 5126, + "count": 24, + "max": [ + 6.0, + 1.0 + ], + "min": [ + 0.0, + 0.0 + ], + "type": "VEC2" + } + ], + "materials": [ + { + "pbrMetallicRoughness": { + "baseColorTexture": { + "index": 0 + }, + "metallicFactor": 0.0 + }, + "name": "Texture" + } + ], + "textures": [ + { + "sampler": 0, + "source": 0 + } + ], + "images": [ + { + "uri": "CesiumLogoFlat.png" + } + ], + "samplers": [ + { + "magFilter": 9729, + "minFilter": 9986, + "wrapS": 10497, + "wrapT": 10497 + } + ], + "bufferViews": [ + { + "buffer": 0, + "byteOffset": 768, + "byteLength": 72, + "target": 34963 + }, + { + "buffer": 0, + "byteOffset": 0, + "byteLength": 576, + "byteStride": 12, + "target": 34962 + }, + { + "buffer": 0, + "byteOffset": 576, + "byteLength": 192, + "byteStride": 8, + "target": 34962 + } + ], + "buffers": [ + { + "byteLength": 840, + "uri": "BoxTextured0.bin" + } + ] +} diff --git a/test/models/glTF2/BoxTextured-glTF/BoxTextured0.bin b/test/models/glTF2/BoxTextured-glTF/BoxTextured0.bin new file mode 100644 index 000000000..d2a73551f Binary files /dev/null and b/test/models/glTF2/BoxTextured-glTF/BoxTextured0.bin differ diff --git a/test/models/glTF2/BoxTextured-glTF/CesiumLogoFlat.png b/test/models/glTF2/BoxTextured-glTF/CesiumLogoFlat.png new file mode 100644 index 000000000..45d502ed2 Binary files /dev/null and b/test/models/glTF2/BoxTextured-glTF/CesiumLogoFlat.png differ diff --git a/test/unit/AbstractImportExportBase.cpp b/test/unit/AbstractImportExportBase.cpp index 27748301f..f3d49b85d 100644 --- a/test/unit/AbstractImportExportBase.cpp +++ b/test/unit/AbstractImportExportBase.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/AbstractImportExportBase.h b/test/unit/AbstractImportExportBase.h index 32c52d9ab..529b9cf7d 100644 --- a/test/unit/AbstractImportExportBase.h +++ b/test/unit/AbstractImportExportBase.h @@ -46,4 +46,10 @@ class AbstractImportExportBase : public ::testing::Test { public: virtual ~AbstractImportExportBase(); virtual bool importerTest() = 0; + virtual bool exporterTest(); }; + +inline +bool AbstractImportExportBase::exporterTest() { + return true; +} diff --git a/test/unit/AssimpAPITest.cpp b/test/unit/AssimpAPITest.cpp index fa78e76a0..a284d385e 100644 --- a/test/unit/AssimpAPITest.cpp +++ b/test/unit/AssimpAPITest.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/SceneDiffer.cpp b/test/unit/SceneDiffer.cpp index a874bd28c..401a655cc 100644 --- a/test/unit/SceneDiffer.cpp +++ b/test/unit/SceneDiffer.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -145,11 +146,11 @@ static std::string dumpVector3( const aiVector3D &toDump ) { return stream.str(); } -static std::string dumpColor4D( const aiColor4D &toDump ) { +/*static std::string dumpColor4D( const aiColor4D &toDump ) { std::stringstream stream; stream << "( " << toDump.r << ", " << toDump.g << ", " << toDump.b << ", " << toDump.a << ")"; return stream.str(); -} +}*/ static std::string dumpFace( const aiFace &face ) { std::stringstream stream; @@ -218,8 +219,8 @@ bool SceneDiffer::compareMesh( aiMesh *expected, aiMesh *toCompare ) { // return true; //ToDo! - bool normalEqual( true ); - /* for ( unsigned int i = 0; i < expected->mNumVertices; i++ ) { + /*bool normalEqual( true ); + for ( unsigned int i = 0; i < expected->mNumVertices; i++ ) { aiVector3D &expNormal( expected->mNormals[ i ] ); aiVector3D &toCompNormal( toCompare->mNormals[ i ] ); if ( expNormal.Equal( toCompNormal ) ) { @@ -370,4 +371,4 @@ bool SceneDiffer::compareMaterial( aiMaterial *expected, aiMaterial *toCompare ) return true; } -} \ No newline at end of file +} diff --git a/test/unit/SceneDiffer.h b/test/unit/SceneDiffer.h index f0cc45907..90f0d367c 100644 --- a/test/unit/SceneDiffer.h +++ b/test/unit/SceneDiffer.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/TestIOStream.h b/test/unit/TestIOStream.h index a979caec8..3dbfc45e3 100644 --- a/test/unit/TestIOStream.h +++ b/test/unit/TestIOStream.h @@ -39,7 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once -#include "DefaultIOStream.h" +#include using namespace ::Assimp; diff --git a/test/unit/TestIOSystem.h b/test/unit/TestIOSystem.h index e7ed193b8..40d894a21 100644 --- a/test/unit/TestIOSystem.h +++ b/test/unit/TestIOSystem.h @@ -3,7 +3,7 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team All rights reserved. @@ -45,25 +45,39 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include using namespace std; -using namespace Assimp; + +namespace Assimp { static const string Sep = "/"; + class TestIOSystem : public IOSystem { public: - TestIOSystem() : IOSystem() {} - virtual ~TestIOSystem() {} + TestIOSystem() + : IOSystem() { + // empty + } + + virtual ~TestIOSystem() { + // empty + } + virtual bool Exists( const char* ) const { return true; } + virtual char getOsSeparator() const { return Sep[ 0 ]; } virtual IOStream* Open( const char* pFile, const char* pMode = "rb" ) { + EXPECT_NE( nullptr, pFile ); + EXPECT_NE( nullptr, pMode ); return NULL; } virtual void Close( IOStream* pFile ) { - // empty + EXPECT_NE( nullptr, pFile ); } }; + +} // Namespace Assimp diff --git a/test/unit/TestModelFactory.h b/test/unit/TestModelFactory.h index 94dd97036..950374112 100644 --- a/test/unit/TestModelFactory.h +++ b/test/unit/TestModelFactory.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -42,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "UnitTestPCH.h" #include +#include #include namespace Assimp { @@ -56,10 +58,10 @@ public: // empty } - static aiScene *createDefaultTestModel( float &opacity ) { + static aiScene *createDefaultTestModel( float &opacity ) { aiScene *scene( new aiScene ); scene->mNumMaterials = 1; - scene->mMaterials = new aiMaterial*; + scene->mMaterials = new aiMaterial*[scene->mNumMaterials]; scene->mMaterials[ 0 ] = new aiMaterial; aiColor3D color( 1, 0, 0 ); EXPECT_EQ( AI_SUCCESS, scene->mMaterials[ 0 ]->AddProperty( &color, 1, AI_MATKEY_COLOR_DIFFUSE ) ); @@ -69,7 +71,7 @@ public: EXPECT_EQ( AI_SUCCESS, scene->mMaterials[ 0 ]->AddProperty( &opacity, 1, AI_MATKEY_OPACITY ) ); scene->mNumMeshes = 1; - scene->mMeshes = new aiMesh*; + scene->mMeshes = new aiMesh*[scene->mNumMeshes]; scene->mMeshes[ 0 ] = new aiMesh; scene->mMeshes[ 0 ]->mMaterialIndex = 0; scene->mMeshes[ 0 ]->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; @@ -79,7 +81,7 @@ public: scene->mMeshes[ 0 ]->mVertices[ 1 ] = aiVector3D( 0, 1, 0 ); scene->mMeshes[ 0 ]->mVertices[ 2 ] = aiVector3D( 0, 0, 1 ); scene->mMeshes[ 0 ]->mNumFaces = 1; - scene->mMeshes[ 0 ]->mFaces = new aiFace; + scene->mMeshes[ 0 ]->mFaces = new aiFace[scene->mMeshes[ 0 ]->mNumFaces]; scene->mMeshes[ 0 ]->mFaces[ 0 ].mNumIndices = 3; scene->mMeshes[ 0 ]->mFaces[ 0 ].mIndices = new unsigned int[ 3 ]; scene->mMeshes[ 0 ]->mFaces[ 0 ].mIndices[ 0 ] = 0; @@ -88,10 +90,15 @@ public: scene->mRootNode = new aiNode; scene->mRootNode->mNumMeshes = 1; - scene->mRootNode->mMeshes = new unsigned int( 0 ); + scene->mRootNode->mMeshes = new unsigned int[1]{ 0 }; return scene; } + + static void releaseDefaultTestModel( aiScene **scene ) { + delete *scene; + *scene = nullptr; + } }; } diff --git a/test/unit/UTLogStream.h b/test/unit/UTLogStream.h new file mode 100644 index 000000000..87ebea91d --- /dev/null +++ b/test/unit/UTLogStream.h @@ -0,0 +1,63 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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. +--------------------------------------------------------------------------- +*/ +#pragma once + +#include + +class UTLogStream : public Assimp::LogStream { +public: + UTLogStream() + : LogStream() { + // empty + } + + virtual ~UTLogStream() { + // empty + } + + virtual void write(const char* message) { + if ( nullptr != message ) { + m_messages.push_back( std::string( message ) ); + } + } + + std::vector m_messages; +}; diff --git a/test/unit/UnitTestFileGenerator.h b/test/unit/UnitTestFileGenerator.h new file mode 100644 index 000000000..2e4aede0f --- /dev/null +++ b/test/unit/UnitTestFileGenerator.h @@ -0,0 +1,76 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, 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. +--------------------------------------------------------------------------- +*/ +#pragma once + +#include +#include +#include + +#if defined(__GNUC__) || defined(__clang__) +#define TMP_PATH "/tmp/" +inline FILE* MakeTmpFile(char* tmplate) +{ + auto fd = mkstemp(tmplate); + EXPECT_NE(-1, fd); + if(fd == -1) + { + return nullptr; + } + auto fs = fdopen(fd, "w+"); + EXPECT_NE(nullptr, fs); + return fs; +} +#elif defined(_MSC_VER) +#include +#define TMP_PATH "./" +inline FILE* MakeTmpFile(char* tmplate) +{ + auto pathtemplate = _mktemp(tmplate); + EXPECT_NE(pathtemplate, nullptr); + if(pathtemplate == nullptr) + { + return nullptr; + } + auto* fs = std::fopen(pathtemplate, "w+"); + EXPECT_NE(fs, nullptr); + return fs; +} +#endif diff --git a/test/unit/UnitTestPCH.h b/test/unit/UnitTestPCH.h index 890bedd0c..0d5f08992 100644 --- a/test/unit/UnitTestPCH.h +++ b/test/unit/UnitTestPCH.h @@ -1,8 +1,44 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- +Copyright (c) 2006-2017, assimp team -// #ifndef ASSIMP_BUILD_SINGLETHREADED -// # include -// #endif +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. +--------------------------------------------------------------------------- +*/ +#pragma once // We need to be sure to have the same STL settings as Assimp @@ -10,6 +46,7 @@ #include #include #include +#include "UTLogStream.h" #undef min #undef max diff --git a/test/unit/ut3DImportExport.cpp b/test/unit/ut3DImportExport.cpp new file mode 100644 index 000000000..6becbd866 --- /dev/null +++ b/test/unit/ut3DImportExport.cpp @@ -0,0 +1,63 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#include "UnitTestPCH.h" +#include "SceneDiffer.h" +#include "AbstractImportExportBase.h" + +#include +#include + +using namespace Assimp; + +class ut3DImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/3D/box_a.3d", aiProcess_ValidateDataStructure ); + return nullptr != scene; + } +}; + +TEST_F( ut3DImportExport, import3DFromFileTest ) { + EXPECT_TRUE( importerTest() ); +} diff --git a/test/unit/ut3DSImportExport.cpp b/test/unit/ut3DSImportExport.cpp new file mode 100644 index 000000000..69e889ae6 --- /dev/null +++ b/test/unit/ut3DSImportExport.cpp @@ -0,0 +1,67 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#include "UnitTestPCH.h" +#include "SceneDiffer.h" +#include "AbstractImportExportBase.h" + +#include +#include + +using namespace Assimp; + +class ut3DSImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/3DS/fels.3ds", aiProcess_ValidateDataStructure ); +#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER + return nullptr != scene; +#else + return nullptr == scene; +#endif // ASSIMP_BUILD_NO_3DS_IMPORTER + } +}; + +TEST_F( ut3DSImportExport, import3DSFromFileTest ) { + EXPECT_TRUE( importerTest() ); +} diff --git a/test/unit/utACImportExport.cpp b/test/unit/utACImportExport.cpp new file mode 100644 index 000000000..178816532 --- /dev/null +++ b/test/unit/utACImportExport.cpp @@ -0,0 +1,63 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#include "UnitTestPCH.h" +#include "SceneDiffer.h" +#include "AbstractImportExportBase.h" + +#include +#include + +using namespace Assimp; + +class utACImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/AC/Wuson.ac", aiProcess_ValidateDataStructure ); + return nullptr != scene; + } +}; + +TEST_F( utACImportExport, importACFromFileTest ) { + EXPECT_TRUE( importerTest() ); +} diff --git a/test/unit/utAMFImportExport.cpp b/test/unit/utAMFImportExport.cpp new file mode 100644 index 000000000..35afd375c --- /dev/null +++ b/test/unit/utAMFImportExport.cpp @@ -0,0 +1,63 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#include "UnitTestPCH.h" +#include "SceneDiffer.h" +#include "AbstractImportExportBase.h" + +#include +#include + +using namespace Assimp; + +class utAMFImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/AMF/test1.amf", aiProcess_ValidateDataStructure ); + return nullptr != scene; + } +}; + +TEST_F( utAMFImportExport, importACFromFileTest ) { + EXPECT_TRUE( importerTest() ); +} diff --git a/test/unit/utASEImportExport.cpp b/test/unit/utASEImportExport.cpp new file mode 100644 index 000000000..1f62d3385 --- /dev/null +++ b/test/unit/utASEImportExport.cpp @@ -0,0 +1,67 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#include "UnitTestPCH.h" +#include "SceneDiffer.h" +#include "AbstractImportExportBase.h" + +#include +#include + +using namespace Assimp; + +class utASEImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/ASE/ThreeCubesGreen.ASE", aiProcess_ValidateDataStructure ); +#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER + return nullptr != scene; +#else + return nullptr == scene; +#endif // ASSIMP_BUILD_NO_3DS_IMPORTER + } +}; + +TEST_F( utASEImportExport, importACFromFileTest ) { + EXPECT_TRUE( importerTest() ); +} diff --git a/test/unit/utAnim.cpp b/test/unit/utAnim.cpp index 90d6d36b3..643730f1b 100644 --- a/test/unit/utAnim.cpp +++ b/test/unit/utAnim.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utB3DImportExport.cpp b/test/unit/utB3DImportExport.cpp new file mode 100644 index 000000000..eaa56beed --- /dev/null +++ b/test/unit/utB3DImportExport.cpp @@ -0,0 +1,63 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#include "UnitTestPCH.h" +#include "SceneDiffer.h" +#include "AbstractImportExportBase.h" + +#include +#include + +using namespace Assimp; + +class utB3DImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/B3D/WusonBlitz.b3d", aiProcess_ValidateDataStructure ); + return nullptr != scene; + } +}; + +TEST_F( utB3DImportExport, importACFromFileTest ) { + EXPECT_TRUE( importerTest() ); +} diff --git a/test/unit/utBVHImportExport.cpp b/test/unit/utBVHImportExport.cpp new file mode 100644 index 000000000..a080ca3a4 --- /dev/null +++ b/test/unit/utBVHImportExport.cpp @@ -0,0 +1,61 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" +#include "AbstractImportExportBase.h" + +#include +#include + +using namespace Assimp; + +class utBVHImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/BVH/01_01.bvh", aiProcess_ValidateDataStructure ); + return nullptr != scene; + } +}; + +TEST_F( utBVHImportExport, importBlenFromFileTest ) { + EXPECT_TRUE( importerTest() ); +} diff --git a/test/unit/utBatchLoader.cpp b/test/unit/utBatchLoader.cpp index b3d74a0aa..56862f912 100644 --- a/test/unit/utBatchLoader.cpp +++ b/test/unit/utBatchLoader.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -65,6 +66,7 @@ TEST_F( BatchLoaderTest, createTest ) { } catch ( ... ) { ok = false; } + EXPECT_TRUE( ok ); } TEST_F( BatchLoaderTest, validateAccessTest ) { diff --git a/test/unit/utBlendImportAreaLight.cpp b/test/unit/utBlendImportAreaLight.cpp index 603a5e513..55a68b040 100644 --- a/test/unit/utBlendImportAreaLight.cpp +++ b/test/unit/utBlendImportAreaLight.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -44,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include class BlendImportAreaLight : public ::testing::Test { public: @@ -66,7 +68,7 @@ protected: // ------------------------------------------------------------------------------------------------ TEST_F(BlendImportAreaLight, testImportLight) { - const aiScene* pTest = im->ReadFile(ASSIMP_TEST_MODELS_DIR "/BLEND/AreaLight_269.blend",0); + const aiScene* pTest = im->ReadFile(ASSIMP_TEST_MODELS_DIR "/BLEND/AreaLight_269.blend", aiProcess_ValidateDataStructure); ASSERT_TRUE(pTest != NULL); ASSERT_TRUE(pTest->HasLights()); diff --git a/test/unit/utBlendImportMaterials.cpp b/test/unit/utBlendImportMaterials.cpp index f45c2a219..4387243c4 100644 --- a/test/unit/utBlendImportMaterials.cpp +++ b/test/unit/utBlendImportMaterials.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -43,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include class BlendImportMaterials : public ::testing::Test { public: @@ -65,11 +67,11 @@ protected: // ------------------------------------------------------------------------------------------------ TEST_F(BlendImportMaterials, testImportMaterial) { - const aiScene* pTest = im->ReadFile(ASSIMP_TEST_MODELS_DIR "/BLEND/BlenderMaterial_269.blend", 0); + const aiScene* pTest = im->ReadFile(ASSIMP_TEST_MODELS_DIR "/BLEND/BlenderMaterial_269.blend", aiProcess_ValidateDataStructure); ASSERT_TRUE(pTest != NULL); ASSERT_TRUE(pTest->HasMaterials()); - ASSERT_EQ(1, pTest->mNumMaterials); + ASSERT_EQ(1U, pTest->mNumMaterials); auto alpha = pTest->mMaterials[0]; diff --git a/test/unit/utBlenderImportExport.cpp b/test/unit/utBlenderImportExport.cpp new file mode 100644 index 000000000..6d7ca8dd7 --- /dev/null +++ b/test/unit/utBlenderImportExport.cpp @@ -0,0 +1,61 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" +#include "AbstractImportExportBase.h" + +#include +#include + +using namespace Assimp; + +class utBlenderImporterExporter : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/BLEND/box.blend", aiProcess_ValidateDataStructure ); + return nullptr != scene; + } +}; + +TEST_F( utBlenderImporterExporter, importBlenFromFileTest ) { + EXPECT_TRUE( importerTest() ); +} diff --git a/test/unit/utBlenderIntermediate.cpp b/test/unit/utBlenderIntermediate.cpp index 89b324324..9c9436574 100644 --- a/test/unit/utBlenderIntermediate.cpp +++ b/test/unit/utBlenderIntermediate.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utCSMImportExport.cpp b/test/unit/utCSMImportExport.cpp new file mode 100644 index 000000000..74cdfcf94 --- /dev/null +++ b/test/unit/utCSMImportExport.cpp @@ -0,0 +1,61 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" +#include "AbstractImportExportBase.h" + +#include +#include + +using namespace Assimp; + +class utCSMImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/CSM/ThomasFechten.csm", aiProcess_ValidateDataStructure ); + return nullptr != scene; + } +}; + +TEST_F( utCSMImportExport, importBlenFromFileTest ) { + EXPECT_TRUE( importerTest() ); +} diff --git a/test/unit/utColladaExportCamera.cpp b/test/unit/utColladaExportCamera.cpp index 1d03b62a1..cbb491204 100644 --- a/test/unit/utColladaExportCamera.cpp +++ b/test/unit/utColladaExportCamera.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -44,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #ifndef ASSIMP_BUILD_NO_EXPORT @@ -72,7 +74,7 @@ TEST_F(ColladaExportCamera, testExportCamera) { const char* file = "cameraExp.dae"; - const aiScene* pTest = im->ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/cameras.dae",0); + const aiScene* pTest = im->ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/cameras.dae", aiProcess_ValidateDataStructure); ASSERT_TRUE(pTest!=NULL); ASSERT_TRUE(pTest->HasCameras()); @@ -94,7 +96,7 @@ TEST_F(ColladaExportCamera, testExportCamera) names[ i ] = orig->mName; pos[ i ] = orig->mPosition; } - const aiScene* imported = im->ReadFile(file,0); + const aiScene* imported = im->ReadFile(file, aiProcess_ValidateDataStructure); ASSERT_TRUE(imported!=NULL); diff --git a/test/unit/utColladaExportLight.cpp b/test/unit/utColladaExportLight.cpp index 2c502b987..5c4801d32 100644 --- a/test/unit/utColladaExportLight.cpp +++ b/test/unit/utColladaExportLight.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -44,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #ifndef ASSIMP_BUILD_NO_EXPORT @@ -71,7 +73,7 @@ TEST_F(ColladaExportLight, testExportLight) { const char* file = "lightsExp.dae"; - const aiScene* pTest = im->ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/lights.dae",0); + const aiScene* pTest = im->ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/lights.dae", aiProcess_ValidateDataStructure); ASSERT_TRUE(pTest!=NULL); ASSERT_TRUE(pTest->HasLights()); @@ -85,7 +87,7 @@ TEST_F(ColladaExportLight, testExportLight) EXPECT_EQ(AI_SUCCESS,ex->Export(pTest,"collada",file)); - const aiScene* imported = im->ReadFile(file,0); + const aiScene* imported = im->ReadFile(file, aiProcess_ValidateDataStructure); ASSERT_TRUE(imported!=NULL); diff --git a/test/unit/utColladaImportExport.cpp b/test/unit/utColladaImportExport.cpp new file mode 100644 index 000000000..97cb5c2ca --- /dev/null +++ b/test/unit/utColladaImportExport.cpp @@ -0,0 +1,61 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" +#include "AbstractImportExportBase.h" + +#include +#include + +using namespace Assimp; + +class utColladaImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/Collada/duck.dae", aiProcess_ValidateDataStructure ); + return nullptr != scene; + } +}; + +TEST_F( utColladaImportExport, importBlenFromFileTest ) { + EXPECT_TRUE( importerTest() ); +} diff --git a/test/unit/utD3MFImportExport.cpp b/test/unit/utD3MFImportExport.cpp new file mode 100644 index 000000000..d344f0a3f --- /dev/null +++ b/test/unit/utD3MFImportExport.cpp @@ -0,0 +1,88 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" +#include "AbstractImportExportBase.h" + +#include +#include +#include +#include + +#include "D3MFExporter.h" + +class utD3MFImporterExporter : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/3MF/box.3mf", aiProcess_ValidateDataStructure); + EXPECT_EQ( 1u, scene->mNumMeshes ); + aiMesh *mesh = scene->mMeshes[ 0 ]; + EXPECT_NE( nullptr, mesh ); + EXPECT_EQ( 12u, mesh->mNumFaces ); + EXPECT_EQ( 8u, mesh->mNumVertices ); + + return ( nullptr != scene ); + } + +#ifndef ASSIMP_BUILD_NO_EXPORT + + virtual bool exporterTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/3MF/box.3mf", 0 ); + + Assimp::Exporter exporter; + return AI_SUCCESS == exporter.Export( scene, "3mf", "test.3mf" ); + } +#endif // ASSIMP_BUILD_NO_EXPORT +}; + +TEST_F(utD3MFImporterExporter, import3MFFromFileTest) { + EXPECT_TRUE(importerTest()); +} + +#ifndef ASSIMP_BUILD_NO_EXPORT + +TEST_F( utD3MFImporterExporter, export3MFtoMemTest ) { + EXPECT_TRUE( exporterTest() ); +} + +#endif // ASSIMP_BUILD_NO_EXPORT diff --git a/test/unit/utDXFImporterExporter.cpp b/test/unit/utDXFImporterExporter.cpp index 74912212c..b75db3ec4 100644 --- a/test/unit/utDXFImporterExporter.cpp +++ b/test/unit/utDXFImporterExporter.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -44,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AbstractImportExportBase.h" #include +#include using namespace Assimp; @@ -51,7 +53,7 @@ class utDXFImporterExporter : public AbstractImportExportBase { public: virtual bool importerTest() { Assimp::Importer importer; - const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/DXF/PinkEggFromLW.dxf", 0 ); + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/DXF/PinkEggFromLW.dxf", aiProcess_ValidateDataStructure ); return nullptr != scene; } }; diff --git a/test/unit/utDefaultIOStream.cpp b/test/unit/utDefaultIOStream.cpp index 3f570665f..128e4e6ef 100644 --- a/test/unit/utDefaultIOStream.cpp +++ b/test/unit/utDefaultIOStream.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -38,6 +39,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------*/ #include #include "TestIOStream.h" +#include "UnitTestFileGenerator.h" +#include +#include +#include using namespace ::Assimp; @@ -45,16 +50,33 @@ class utDefaultIOStream : public ::testing::Test { // empty }; -TEST_F( utDefaultIOStream, FileSizeTest ) { - char buffer[ L_tmpnam ]; - tmpnam( buffer ); - std::FILE *fs( std::fopen( buffer, "w+" ) ); - size_t written( std::fwrite( buffer, 1, sizeof( char ) * L_tmpnam, fs ) ); - EXPECT_NE( 0U, written ); - std::fflush( fs ); +const char data[]{"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Qui\ +sque luctus sem diam, ut eleifend arcu auctor eu. Vestibulum id est vel nulla l\ +obortis malesuada ut sed turpis. Nulla a volutpat tortor. Nunc vestibulum portt\ +itor sapien ornare sagittis volutpat."}; - TestDefaultIOStream myStream( fs, buffer ); - size_t size = myStream.FileSize(); - EXPECT_EQ( size, sizeof( char ) * L_tmpnam ); - remove( buffer ); +TEST_F( utDefaultIOStream, FileSizeTest ) { + const auto dataSize = sizeof(data); + const auto dataCount = dataSize / sizeof(*data); + + char fpath[] = { TMP_PATH"rndfp.XXXXXX" }; + auto* fs = MakeTmpFile(fpath); + ASSERT_NE(nullptr, fs); + { + auto written = std::fwrite(data, sizeof(*data), dataCount, fs ); + EXPECT_NE( 0U, written ); + + auto vflush = std::fflush( fs ); + ASSERT_EQ(vflush, 0); + + std::fclose(fs); + fs = std::fopen(fpath, "r"); + + ASSERT_NE(nullptr, fs); + + TestDefaultIOStream myStream( fs, fpath); + size_t size = myStream.FileSize(); + EXPECT_EQ( size, dataSize); + } + remove(fpath); } diff --git a/test/unit/utExport.cpp b/test/unit/utExport.cpp index f34429338..b3ab5e372 100644 --- a/test/unit/utExport.cpp +++ b/test/unit/utExport.cpp @@ -14,7 +14,7 @@ public: ex = new Assimp::Exporter(); im = new Assimp::Importer(); - pTest = im->ReadFile(ASSIMP_TEST_MODELS_DIR "/X/test.x",0); + pTest = im->ReadFile(ASSIMP_TEST_MODELS_DIR "/X/test.x", aiProcess_ValidateDataStructure); } virtual void TearDown() @@ -37,7 +37,7 @@ TEST_F(ExporterTest, testExportToFile) EXPECT_EQ(AI_SUCCESS,ex->Export(pTest,"collada",file)); // check if we can read it again - EXPECT_TRUE(im->ReadFile(file,0)); + EXPECT_TRUE(im->ReadFile(file, aiProcess_ValidateDataStructure)); } // ------------------------------------------------------------------------------------------------ @@ -77,7 +77,7 @@ TEST_F(ExporterTest, testCExportInterface) for(size_t i = 0; i < aiGetExportFormatCount(); ++i) { const aiExportFormatDesc* const desc = aiGetExportFormatDescription(i); EXPECT_TRUE(desc); - // rest has aleady been validated by testCppExportInterface + // rest has already been validated by testCppExportInterface } } diff --git a/test/unit/utFBXImporterExporter.cpp b/test/unit/utFBXImporterExporter.cpp index d02d06def..2807f801c 100644 --- a/test/unit/utFBXImporterExporter.cpp +++ b/test/unit/utFBXImporterExporter.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -44,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AbstractImportExportBase.h" #include +#include using namespace Assimp; @@ -51,7 +53,7 @@ class utFBXImporterExporter : public AbstractImportExportBase { public: virtual bool importerTest() { Assimp::Importer importer; - const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/FBX/spider.fbx", 0 ); + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/FBX/spider.fbx", aiProcess_ValidateDataStructure ); return nullptr != scene; } }; diff --git a/test/unit/utFastAtof.cpp b/test/unit/utFastAtof.cpp index 2b58f6bd7..a9d6fdbd0 100644 --- a/test/unit/utFastAtof.cpp +++ b/test/unit/utFastAtof.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utFindDegenerates.cpp b/test/unit/utFindDegenerates.cpp index 8df160107..dce42732c 100644 --- a/test/unit/utFindDegenerates.cpp +++ b/test/unit/utFindDegenerates.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -57,8 +58,7 @@ protected: }; // ------------------------------------------------------------------------------------------------ -void FindDegeneratesProcessTest::SetUp() -{ +void FindDegeneratesProcessTest::SetUp() { mesh = new aiMesh(); process = new FindDegeneratesProcess(); @@ -106,16 +106,12 @@ void FindDegeneratesProcessTest::SetUp() mesh->mNumUVComponents[1] = numFaces; } -// ------------------------------------------------------------------------------------------------ -void FindDegeneratesProcessTest::TearDown() -{ +void FindDegeneratesProcessTest::TearDown() { delete mesh; delete process; } -// ------------------------------------------------------------------------------------------------ -TEST_F(FindDegeneratesProcessTest, testDegeneratesDetection) -{ +TEST_F(FindDegeneratesProcessTest, testDegeneratesDetection) { process->EnableInstantRemoval(false); process->ExecuteOnMesh(mesh); @@ -134,12 +130,18 @@ TEST_F(FindDegeneratesProcessTest, testDegeneratesDetection) mesh->mPrimitiveTypes); } -// ------------------------------------------------------------------------------------------------ -TEST_F(FindDegeneratesProcessTest, testDegeneratesRemoval) -{ +TEST_F(FindDegeneratesProcessTest, testDegeneratesRemoval) { + process->EnableAreaCheck(false); process->EnableInstantRemoval(true); process->ExecuteOnMesh(mesh); EXPECT_EQ(mesh->mNumUVComponents[1], mesh->mNumFaces); } +TEST_F(FindDegeneratesProcessTest, testDegeneratesRemovalWithAreaCheck) { + process->EnableAreaCheck(true); + process->EnableInstantRemoval(true); + process->ExecuteOnMesh(mesh); + + EXPECT_EQ(mesh->mNumUVComponents[1]-100, mesh->mNumFaces); +} diff --git a/test/unit/utFindInvalidData.cpp b/test/unit/utFindInvalidData.cpp index 0fe291c80..adba32256 100644 --- a/test/unit/utFindInvalidData.cpp +++ b/test/unit/utFindInvalidData.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utFixInfacingNormals.cpp b/test/unit/utFixInfacingNormals.cpp index e55958cd5..66be19807 100644 --- a/test/unit/utFixInfacingNormals.cpp +++ b/test/unit/utFixInfacingNormals.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utGenNormals.cpp b/test/unit/utGenNormals.cpp index b108242da..ec3469f14 100644 --- a/test/unit/utGenNormals.cpp +++ b/test/unit/utGenNormals.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utHMPImportExport.cpp b/test/unit/utHMPImportExport.cpp new file mode 100644 index 000000000..35bc0bb01 --- /dev/null +++ b/test/unit/utHMPImportExport.cpp @@ -0,0 +1,63 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" +#include "AbstractImportExportBase.h" + +#include +#include + +using namespace Assimp; + +class utHMPImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/HMP/terrain.hmp", aiProcess_ValidateDataStructure ); + return nullptr != scene; + + return true; + } +}; + +TEST_F( utHMPImportExport, importHMPFromFileTest ) { + EXPECT_TRUE( importerTest() ); +} diff --git a/test/unit/utIFCImportExport.cpp b/test/unit/utIFCImportExport.cpp new file mode 100644 index 000000000..20a11ca57 --- /dev/null +++ b/test/unit/utIFCImportExport.cpp @@ -0,0 +1,63 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" +#include "AbstractImportExportBase.h" + +#include +#include + +using namespace Assimp; + +class utIFCImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/IFC/AC14-FZK-Haus.ifc", aiProcess_ValidateDataStructure ); + return nullptr != scene; + + return true; + } +}; + +TEST_F( utIFCImportExport, importIFCFromFileTest ) { + EXPECT_TRUE( importerTest() ); +} diff --git a/test/unit/utIOStreamBuffer.cpp b/test/unit/utIOStreamBuffer.cpp index ded6c0eb7..f53a9c9d5 100644 --- a/test/unit/utIOStreamBuffer.cpp +++ b/test/unit/utIOStreamBuffer.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -42,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "UnitTestPCH.h" #include "IOStreamBuffer.h" #include "TestIOStream.h" +#include "UnitTestFileGenerator.h" class IOStreamBufferTest : public ::testing::Test { // empty @@ -61,44 +63,74 @@ TEST_F( IOStreamBufferTest, creationTest ) { TEST_F( IOStreamBufferTest, accessCacheSizeTest ) { IOStreamBuffer myBuffer1; - EXPECT_NE( 0, myBuffer1.cacheSize() ); + EXPECT_NE( 0U, myBuffer1.cacheSize() ); IOStreamBuffer myBuffer2( 100 ); - EXPECT_EQ( 100, myBuffer2.cacheSize() ); + EXPECT_EQ( 100U, myBuffer2.cacheSize() ); } +const char data[]{"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Qui\ +sque luctus sem diam, ut eleifend arcu auctor eu. Vestibulum id est vel nulla l\ +obortis malesuada ut sed turpis. Nulla a volutpat tortor. Nunc vestibulum portt\ +itor sapien ornare sagittis volutpat."}; + + TEST_F( IOStreamBufferTest, open_close_Test ) { IOStreamBuffer myBuffer; EXPECT_FALSE( myBuffer.open( nullptr ) ); EXPECT_FALSE( myBuffer.close() ); + + const auto dataSize = sizeof(data); + const auto dataCount = dataSize / sizeof(*data); - char buffer[ L_tmpnam ]; - tmpnam( buffer ); - std::FILE *fs( std::fopen( buffer, "w+" ) ); - size_t written( std::fwrite( buffer, 1, sizeof( char ) * L_tmpnam, fs ) ); - std::fflush( fs ); + char fname[]={ "octest.XXXXXX" }; + auto* fs = MakeTmpFile(fname); + ASSERT_NE(nullptr, fs); + + auto written = std::fwrite( data, sizeof(*data), dataCount, fs ); + EXPECT_NE( 0U, written ); + auto flushResult = std::fflush( fs ); + ASSERT_EQ(0, flushResult); + std::fclose( fs ); + fs = std::fopen(fname, "r"); + ASSERT_NE(nullptr, fs); + { + TestDefaultIOStream myStream( fs, fname ); - TestDefaultIOStream myStream( fs, buffer ); - - EXPECT_TRUE( myBuffer.open( &myStream ) ); - EXPECT_FALSE( myBuffer.open( &myStream ) ); - EXPECT_TRUE( myBuffer.close() ); + EXPECT_TRUE( myBuffer.open( &myStream ) ); + EXPECT_FALSE( myBuffer.open( &myStream ) ); + EXPECT_TRUE( myBuffer.close() ); + } + remove(fname); } TEST_F( IOStreamBufferTest, readlineTest ) { - char buffer[ L_tmpnam ]; - tmpnam( buffer ); - std::FILE *fs( std::fopen( buffer, "w+" ) ); - size_t written( std::fwrite( buffer, 1, sizeof( char ) * L_tmpnam, fs ) ); - std::fflush( fs ); + + const auto dataSize = sizeof(data); + const auto dataCount = dataSize / sizeof(*data); - IOStreamBuffer myBuffer( 26 ); - EXPECT_EQ( 26, myBuffer.cacheSize() ); + char fname[]={ "readlinetest.XXXXXX" }; + auto* fs = MakeTmpFile(fname); + ASSERT_NE(nullptr, fs); - TestDefaultIOStream myStream( fs, buffer ); - size_t size( myStream.FileSize() ); - size_t numBlocks( size / myBuffer.cacheSize() ); + auto written = std::fwrite( data, sizeof(*data), dataCount, fs ); + EXPECT_NE( 0U, written ); + + auto flushResult = std::fflush(fs); + ASSERT_EQ(0, flushResult); + std::fclose(fs); + fs = std::fopen(fname, "r"); + ASSERT_NE(nullptr, fs); + + const auto tCacheSize = 26u; + + IOStreamBuffer myBuffer( tCacheSize ); + EXPECT_EQ(tCacheSize, myBuffer.cacheSize() ); + + TestDefaultIOStream myStream( fs, fname ); + auto size = myStream.FileSize(); + auto numBlocks = size / myBuffer.cacheSize(); if ( size % myBuffer.cacheSize() > 0 ) { numBlocks++; } @@ -110,3 +142,4 @@ TEST_F( IOStreamBufferTest, readlineTest ) { TEST_F( IOStreamBufferTest, accessBlockIndexTest ) { } + diff --git a/test/unit/utIOSystem.cpp b/test/unit/utIOSystem.cpp index a2b333ab0..5e3e98031 100644 --- a/test/unit/utIOSystem.cpp +++ b/test/unit/utIOSystem.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -62,12 +63,16 @@ protected: TEST_F( IOSystemTest, accessDirectoryStackTest ) { EXPECT_FALSE( pImp->PopDirectory() ); - EXPECT_EQ( 0, pImp->StackSize() ); + EXPECT_EQ( 0U, pImp->StackSize() ); EXPECT_FALSE( pImp->PushDirectory( "" ) ); std::string path = "test/"; EXPECT_TRUE( pImp->PushDirectory( path ) ); - EXPECT_EQ( 1, pImp->StackSize() ); + EXPECT_EQ( 1U, pImp->StackSize() ); EXPECT_EQ( path, pImp->CurrentDirectory() ); EXPECT_TRUE( pImp->PopDirectory() ); - EXPECT_EQ( 0, pImp->StackSize() ); + EXPECT_EQ( 0U, pImp->StackSize() ); +} + +TEST_F( IOSystemTest, delFileTest ) { + EXPECT_FALSE( pImp->DeleteFile( "none" ) ); } diff --git a/test/unit/utImporter.cpp b/test/unit/utImporter.cpp index ac1f0194f..aaf0bd4ec 100644 --- a/test/unit/utImporter.cpp +++ b/test/unit/utImporter.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -45,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include "TestIOSystem.h" -#include "DefaultIOSystem.h" +#include using namespace ::std; using namespace ::Assimp; @@ -53,12 +54,12 @@ using namespace ::Assimp; class ImporterTest : public ::testing::Test { public: - virtual void SetUp() { - pImp = new Importer(); + virtual void SetUp() { + pImp = new Importer(); } - - virtual void TearDown() { - delete pImp; + + virtual void TearDown() { + delete pImp; } protected: @@ -275,4 +276,4 @@ TEST_F(ImporterTest, testMultipleReads) TEST_F( ImporterTest, SearchFileHeaderForTokenTest ) { //DefaultIOSystem ioSystem; // BaseImporter::SearchFileHeaderForToken( &ioSystem, assetPath, Token, 2 ) -} \ No newline at end of file +} diff --git a/test/unit/utImproveCacheLocality.cpp b/test/unit/utImproveCacheLocality.cpp index 630526754..0f08d462c 100644 --- a/test/unit/utImproveCacheLocality.cpp +++ b/test/unit/utImproveCacheLocality.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utIssues.cpp b/test/unit/utIssues.cpp index cae5ee8cc..a05adc856 100644 --- a/test/unit/utIssues.cpp +++ b/test/unit/utIssues.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -43,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include "TestModelFactory.h" @@ -65,7 +67,7 @@ TEST_F( utIssues, OpacityBugWhenExporting_727 ) { EXPECT_NE( desc, nullptr ); path.append( desc->fileExtension ); EXPECT_EQ( AI_SUCCESS, exporter.Export( scene, desc->id, path ) ); - const aiScene *newScene( importer.ReadFile( path, 0 ) ); + const aiScene *newScene( importer.ReadFile( path, aiProcess_ValidateDataStructure ) ); EXPECT_TRUE( NULL != newScene ); float newOpacity; if ( newScene->mNumMaterials > 0 ) { @@ -73,6 +75,7 @@ TEST_F( utIssues, OpacityBugWhenExporting_727 ) { EXPECT_EQ( AI_SUCCESS, newScene->mMaterials[ 0 ]->Get( AI_MATKEY_OPACITY, newOpacity ) ); EXPECT_EQ( opacity, newOpacity ); } + delete scene; } #endif // ASSIMP_BUILD_NO_EXPORT diff --git a/test/unit/utJoinVertices.cpp b/test/unit/utJoinVertices.cpp index f9ad2cc98..d2add2b90 100644 --- a/test/unit/utJoinVertices.cpp +++ b/test/unit/utJoinVertices.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utLWSImportExport.cpp b/test/unit/utLWSImportExport.cpp new file mode 100644 index 000000000..f0252e211 --- /dev/null +++ b/test/unit/utLWSImportExport.cpp @@ -0,0 +1,63 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" +#include "AbstractImportExportBase.h" + +#include + +using namespace Assimp; + + +class utLWSImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/LWS/move_x.lws", 0 ); + return nullptr != scene; + + return true; + } +}; + +TEST_F( utLWSImportExport, importLWSFromFileTest ) { + EXPECT_TRUE( importerTest() ); +} diff --git a/test/unit/utLimitBoneWeights.cpp b/test/unit/utLimitBoneWeights.cpp index 9b38a2fa5..022e4bda1 100644 --- a/test/unit/utLimitBoneWeights.cpp +++ b/test/unit/utLimitBoneWeights.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utMaterialSystem.cpp b/test/unit/utMaterialSystem.cpp index af31d19c8..80408db00 100644 --- a/test/unit/utMaterialSystem.cpp +++ b/test/unit/utMaterialSystem.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -72,7 +73,7 @@ TEST_F(MaterialSystemTest, testFloatArrayProperty) { float pf[] = {0.0f,1.0f,2.0f,3.0f}; unsigned int pMax = sizeof(pf) / sizeof(float); - this->pcMat->AddProperty(&pf,pMax,"testKey2"); + this->pcMat->AddProperty(pf,pMax,"testKey2"); pf[0] = pf[1] = pf[2] = pf[3] = 12.0f; EXPECT_EQ(AI_SUCCESS, pcMat->Get("testKey2",0,0,pf,&pMax)); @@ -96,7 +97,7 @@ TEST_F(MaterialSystemTest, testIntArrayProperty) { int pf[] = {0,1,2,3}; unsigned int pMax = sizeof(pf) / sizeof(int); - this->pcMat->AddProperty(&pf,pMax,"testKey4"); + this->pcMat->AddProperty(pf,pMax,"testKey4"); pf[0] = pf[1] = pf[2] = pf[3] = 12; EXPECT_EQ(AI_SUCCESS, pcMat->Get("testKey4",0,0,pf,&pMax)); diff --git a/test/unit/utMatrix3x3.cpp b/test/unit/utMatrix3x3.cpp index d013980d0..47c20acf6 100644 --- a/test/unit/utMatrix3x3.cpp +++ b/test/unit/utMatrix3x3.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -45,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace ::Assimp; class utMatrix3x3Test : public ::testing::Test { - + // empty }; TEST_F( utMatrix3x3Test, FromToMatrixTest ) { diff --git a/test/unit/utMatrix4x4.cpp b/test/unit/utMatrix4x4.cpp index 64ab2e499..92d430c0f 100644 --- a/test/unit/utMatrix4x4.cpp +++ b/test/unit/utMatrix4x4.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utMetadata.cpp b/test/unit/utMetadata.cpp index 61bff3897..4109b068c 100644 --- a/test/unit/utMetadata.cpp +++ b/test/unit/utMetadata.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -54,7 +55,7 @@ protected: } virtual void TearDown() { - delete m_data; + aiMetadata::Dealloc( m_data ); } }; @@ -75,9 +76,10 @@ TEST_F( utMetadata, allocTest ) { data = aiMetadata::Alloc( 1 ); EXPECT_NE( nullptr, data ); - EXPECT_EQ( 1, data->mNumProperties ); + EXPECT_EQ( 1U, data->mNumProperties ); EXPECT_NE( nullptr, data->mKeys ); EXPECT_NE( nullptr, data->mValues ); + aiMetadata::Dealloc( data ); } TEST_F( utMetadata, get_set_pod_Test ) { @@ -177,3 +179,4 @@ TEST_F( utMetadata, get_set_aiVector3D_Test ) { EXPECT_EQ( vec, result ); EXPECT_TRUE( success ); } + diff --git a/test/unit/utObjImportExport.cpp b/test/unit/utObjImportExport.cpp index 0bfcf7cc5..dd8adcd80 100644 --- a/test/unit/utObjImportExport.cpp +++ b/test/unit/utObjImportExport.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -42,9 +43,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "UnitTestPCH.h" #include "SceneDiffer.h" #include "AbstractImportExportBase.h" - -#include #include +#include +#include +#include using namespace Assimp; @@ -91,6 +93,7 @@ static const std::string ObjModel = "\n" "# Point / Line / Face list\n" "\n" + "g Box01\n" "usemtl Default\n" "f 4 3 2 1\n" "f 2 6 5 1\n" @@ -101,6 +104,20 @@ static const std::string ObjModel = "\n" "# End of file\n"; +static const std::string ObjModel_Issue1111 = + "o 1\n" + "\n" + "# Vertex list\n" + "\n" + "v -0.5 -0.5 0.5\n" + "v -0.5 -0.5 -0.5\n" + "v -0.5 0.5 -0.5\n" + "\n" + "usemtl\n" + "f 1 2 3\n" + "\n" + "# End of file\n"; + class utObjImportExport : public AbstractImportExportBase { protected: virtual void SetUp() { @@ -175,14 +192,28 @@ protected: } virtual bool importerTest() { - Assimp::Importer importer; - const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", 0 ); + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure ); return nullptr != scene; } +#ifndef ASSIMP_BUILD_NO_EXPORT + + virtual bool exporterTest() { + ::Assimp::Importer importer; + ::Assimp::Exporter exporter; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure ); + EXPECT_NE( nullptr, scene ); + EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "obj", ASSIMP_TEST_MODELS_DIR "/OBJ/spider_test.obj" ) ); + EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "objnomtl", ASSIMP_TEST_MODELS_DIR "/OBJ/spider_nomtl_test.obj" ) ); + + return true; + } + +#endif // ASSIMP_BUILD_NO_EXPORT protected: - Assimp::Importer *m_im; + ::Assimp::Importer *m_im; aiScene *m_expectedScene; }; @@ -190,6 +221,14 @@ TEST_F( utObjImportExport, importObjFromFileTest ) { EXPECT_TRUE( importerTest() ); } +#ifndef ASSIMP_BUILD_NO_EXPORT + +TEST_F( utObjImportExport, exportObjFromFileTest ) { + EXPECT_TRUE( exporterTest() ); +} + +#endif // ASSIMP_BUILD_NO_EXPORT + TEST_F( utObjImportExport, obj_import_test ) { const aiScene *scene = m_im->ReadFileFromMemory( (void*) ObjModel.c_str(), ObjModel.size(), 0 ); aiScene *expected = createScene(); @@ -200,4 +239,105 @@ TEST_F( utObjImportExport, obj_import_test ) { differ.showReport(); m_im->FreeScene(); + for(unsigned int i = 0; i < expected->mNumMeshes; ++i) + { + delete expected->mMeshes[i]; + } + delete[] expected->mMeshes; + expected->mMeshes = nullptr; + delete[] expected->mMaterials; + expected->mMaterials = nullptr; + delete expected; +} + +TEST_F( utObjImportExport, issue1111_no_mat_name_Test ) { + const aiScene *scene = m_im->ReadFileFromMemory( ( void* ) ObjModel_Issue1111.c_str(), ObjModel_Issue1111.size(), 0 ); + EXPECT_NE( nullptr, scene ); +} + +TEST_F( utObjImportExport, issue809_vertex_color_Test ) { + ::Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OBJ/cube_with_vertexcolors.obj", aiProcess_ValidateDataStructure ); + EXPECT_NE( nullptr, scene ); + +#ifndef ASSIMP_BUILD_NO_EXPORT + ::Assimp::Exporter exporter; + EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "obj", ASSIMP_TEST_MODELS_DIR "/OBJ/test.obj" ) ); +#endif // ASSIMP_BUILD_NO_EXPORT +} + +TEST_F( utObjImportExport, issue1453_segfault ) { + static const std::string ObjModel = + "v 0.0 0.0 0.0\n" + "v 0.0 0.0 1.0\n" + "v 0.0 1.0 0.0\n" + "v 0.0 1.0 1.0\n" + "v 1.0 0.0 0.0\n" + "v 1.0 0.0 1.0\n" + "v 1.0 1.0 0.0\n" + "v 1.0 1.0 1.0\nB"; + + Assimp::Importer myimporter; + const aiScene *scene = myimporter.ReadFileFromMemory( ObjModel.c_str(), ObjModel.size(), aiProcess_ValidateDataStructure ); + EXPECT_EQ( nullptr, scene ); +} + +TEST_F(utObjImportExport, relative_indices_Test) { + static const std::string ObjModel = + "v -0.500000 0.000000 0.400000\n" + "v -0.500000 0.000000 -0.800000\n" + "v -0.500000 1.000000 -0.800000\n" + "v -0.500000 1.000000 0.400000\n" + "f -4 -3 -2 -1\nB"; + + Assimp::Importer myimporter; + const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel.c_str(), ObjModel.size(), aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); + + EXPECT_EQ(scene->mNumMeshes, 1U); + const aiMesh *mesh = scene->mMeshes[0]; + EXPECT_EQ(mesh->mNumVertices, 4U); + EXPECT_EQ(mesh->mNumFaces, 1U); + const aiFace face = mesh->mFaces[0]; + EXPECT_EQ(face.mNumIndices, 4U); + for (unsigned int i = 0; i < face.mNumIndices; ++i) + { + EXPECT_EQ(face.mIndices[i], i); + } + +} + +TEST_F(utObjImportExport, homogeneous_coordinates_Test) { + static const std::string ObjModel = + "v -0.500000 0.000000 0.400000 0.50000\n" + "v -0.500000 0.000000 -0.800000 1.00000\n" + "v 0.500000 1.000000 -0.800000 0.5000\n" + "f 1 2 3\nB"; + + Assimp::Importer myimporter; + const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel.c_str(), ObjModel.size(), aiProcess_ValidateDataStructure); + EXPECT_NE(nullptr, scene); + + EXPECT_EQ(scene->mNumMeshes, 1U); + const aiMesh *mesh = scene->mMeshes[0]; + EXPECT_EQ(mesh->mNumVertices, 3U); + EXPECT_EQ(mesh->mNumFaces, 1U); + const aiFace face = mesh->mFaces[0]; + EXPECT_EQ(face.mNumIndices, 3U); + const aiVector3D vertice = mesh->mVertices[0]; + EXPECT_EQ(vertice.x, -1.0f); + EXPECT_EQ(vertice.y, 0.0f); + EXPECT_EQ(vertice.z, 0.8f); +} + +TEST_F(utObjImportExport, 0based_array_Test) { + static const std::string ObjModel = + "v -0.500000 0.000000 0.400000\n" + "v -0.500000 0.000000 -0.800000\n" + "v -0.500000 1.000000 -0.800000\n" + "f 0 1 2\nB"; + + Assimp::Importer myimporter; + const aiScene *scene = myimporter.ReadFileFromMemory(ObjModel.c_str(), ObjModel.size(), 0); + EXPECT_EQ(nullptr, scene); } diff --git a/test/unit/utObjTools.cpp b/test/unit/utObjTools.cpp new file mode 100644 index 000000000..2d9e2779f --- /dev/null +++ b/test/unit/utObjTools.cpp @@ -0,0 +1,117 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" +#include "ObjTools.h" +#include "ObjFileParser.h" + +using namespace ::Assimp; + +class utObjTools : public ::testing::Test { + // empty +}; + +class TestObjFileParser : public ObjFileParser { +public: + TestObjFileParser() : ObjFileParser(){ + // empty + } + + ~TestObjFileParser() { + // empty + } + + void testCopyNextWord( char *pBuffer, size_t length ) { + copyNextWord( pBuffer, length ); + } + + size_t testGetNumComponentsInDataDefinition() { + return getNumComponentsInDataDefinition(); + } +}; + +TEST_F( utObjTools, skipDataLine_OneLine_Success ) { + std::vector buffer; + std::string data( "v -0.5 -0.5 0.5\nend" ); + buffer.resize( data.size() ); + ::memcpy( &buffer[ 0 ], &data[ 0 ], data.size() ); + std::vector::iterator itBegin( buffer.begin() ), itEnd( buffer.end() ); + unsigned int line = 0; + std::vector::iterator current = skipLine::iterator>( itBegin, itEnd, line ); + EXPECT_EQ( 'e', *current ); +} + +TEST_F( utObjTools, skipDataLine_TwoLines_Success ) { + TestObjFileParser test_parser; + std::string data( "vn -2.061493116917992e-15 -0.9009688496589661 \\\n-0.4338837265968323" ); + std::vector buffer; + buffer.resize( data.size() ); + ::memcpy( &buffer[ 0 ], &data[ 0 ], data.size() ); + test_parser.setBuffer( buffer ); + static const size_t Size = 4096UL; + char data_buffer[ Size ]; + + test_parser.testCopyNextWord( data_buffer, Size ); + EXPECT_EQ( 0, strncmp( data_buffer, "vn", 2 ) ); + + test_parser.testCopyNextWord( data_buffer, Size ); + EXPECT_EQ( data_buffer[0], '-' ); + + test_parser.testCopyNextWord( data_buffer, Size ); + EXPECT_EQ( data_buffer[0], '-' ); + + test_parser.testCopyNextWord( data_buffer, Size ); + EXPECT_EQ( data_buffer[ 0 ], '-' ); +} + +TEST_F( utObjTools, countComponents_TwoLines_Success ) { + TestObjFileParser test_parser; + std::string data( "-2.061493116917992e-15 -0.9009688496589661 \\\n-0.4338837265968323" ); + std::vector buffer; + buffer.resize( data.size() + 1 ); + ::memcpy( &buffer[ 0 ], &data[ 0 ], data.size() ); + buffer[ buffer.size() - 1 ] = '\0'; + test_parser.setBuffer( buffer ); + + size_t numComps = test_parser.testGetNumComponentsInDataDefinition(); + EXPECT_EQ( 3U, numComps ); +} + diff --git a/test/unit/utOpenGEXImportExport.cpp b/test/unit/utOpenGEXImportExport.cpp new file mode 100644 index 000000000..021a7bf81 --- /dev/null +++ b/test/unit/utOpenGEXImportExport.cpp @@ -0,0 +1,69 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#include "UnitTestPCH.h" +#include "AbstractImportExportBase.h" + +#include + +using namespace Assimp; + + +class utOpenGEXImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OpenGEX/Example.ogex", 0 ); + return nullptr != scene; + } +}; + +TEST_F( utOpenGEXImportExport, importLWSFromFileTest ) { + EXPECT_TRUE( importerTest() ); +} + +TEST_F( utOpenGEXImportExport, Importissue1262_NoCrash ) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/OpenGEX/light_issue1262.ogex", 0 ); + EXPECT_NE( nullptr, scene ); + +} diff --git a/test/unit/utPLYImportExport.cpp b/test/unit/utPLYImportExport.cpp new file mode 100644 index 000000000..82cc54bdb --- /dev/null +++ b/test/unit/utPLYImportExport.cpp @@ -0,0 +1,92 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" + +#include +#include +#include +#include "AbstractImportExportBase.h" + +using namespace ::Assimp; + +class utPLYImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", 0 ); + EXPECT_EQ( 1u, scene->mNumMeshes ); + EXPECT_NE( nullptr, scene->mMeshes[0] ); + EXPECT_EQ( 8u, scene->mMeshes[0]->mNumVertices ); + EXPECT_EQ( 6u, scene->mMeshes[0]->mNumFaces ); + + return (nullptr != scene); + } + +#ifndef ASSIMP_BUILD_NO_EXPORT + virtual bool exporterTest() { + Importer importer; + Exporter exporter; + const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", 0); + EXPECT_NE(nullptr, scene); + EXPECT_EQ(aiReturn_SUCCESS, exporter.Export(scene, "ply", ASSIMP_TEST_MODELS_DIR "/PLY/cube_test.ply")); + + return true; + } +#endif // ASSIMP_BUILD_NO_EXPORT +}; + +TEST_F( utPLYImportExport, importTest_Success ) { + EXPECT_TRUE( importerTest() ); +} + +#ifndef ASSIMP_BUILD_NO_EXPORT + +TEST_F(utPLYImportExport, exportTest_Success ) { + EXPECT_TRUE(exporterTest()); +} + +#endif // ASSIMP_BUILD_NO_EXPORT + +TEST_F( utPLYImportExport, vertexColorTest ) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/PLY/float-color.ply", 0 ); + EXPECT_NE( nullptr, scene ); +} diff --git a/test/unit/utPMXImporter.cpp b/test/unit/utPMXImporter.cpp new file mode 100644 index 000000000..3a1ce1f6a --- /dev/null +++ b/test/unit/utPMXImporter.cpp @@ -0,0 +1,63 @@ +/* +--------------------------------------------------------------------------- +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. +--------------------------------------------------------------------------- +*/ + +#include "UnitTestPCH.h" +#include "SceneDiffer.h" +#include "AbstractImportExportBase.h" +#include "MMDImporter.h" + +#include + +using namespace ::Assimp; + +class utPMXImporter : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + /*const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/../models-nonbsd/MMD/Alicia_blade.pmx", aiProcess_ValidateDataStructure ); + return nullptr != scene;*/ + return true; + } +}; + +TEST_F( utPMXImporter, importTest ) { + EXPECT_TRUE( importerTest() ); +} diff --git a/test/unit/utPretransformVertices.cpp b/test/unit/utPretransformVertices.cpp index dd1062ad4..437cbdba5 100644 --- a/test/unit/utPretransformVertices.cpp +++ b/test/unit/utPretransformVertices.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -89,28 +90,36 @@ void PretransformVerticesTest::SetUp() // add 5 empty materials scene->mMaterials = new aiMaterial*[scene->mNumMaterials = 5]; - for (unsigned int i = 0; i < 5;++i) + for (unsigned int i = 0; i < 5;++i) { scene->mMaterials[i] = new aiMaterial(); + } // add 25 test meshes scene->mMeshes = new aiMesh*[scene->mNumMeshes = 25]; - for (unsigned int i = 0; i < 25;++i) { - aiMesh* mesh = scene->mMeshes[i] = new aiMesh(); + for ( unsigned int i = 0; i < 25; ++i) { + aiMesh* mesh = scene->mMeshes[ i ] = new aiMesh(); mesh->mPrimitiveTypes = aiPrimitiveType_POINT; mesh->mFaces = new aiFace[ mesh->mNumFaces = 10+i ]; mesh->mVertices = new aiVector3D[mesh->mNumVertices = mesh->mNumFaces]; for (unsigned int a = 0; a < mesh->mNumFaces; ++a ) { - aiFace& f = mesh->mFaces[a]; - f.mIndices = new unsigned int [f.mNumIndices = 1]; + aiFace& f = mesh->mFaces[ a ]; + f.mIndices = new unsigned int [ f.mNumIndices = 1 ]; f.mIndices[0] = a*3; mesh->mVertices[a] = aiVector3D((float)i,(float)a,0.f); } mesh->mMaterialIndex = i%5; - if (i % 2) + if (i % 2) { mesh->mNormals = new aiVector3D[mesh->mNumVertices]; + for ( unsigned int normalIdx=0; normalIdxmNumVertices; ++normalIdx ) { + mesh->mNormals[ normalIdx ].x = 1.0f; + mesh->mNormals[ normalIdx ].y = 1.0f; + mesh->mNormals[ normalIdx ].z = 1.0f; + mesh->mNormals[ normalIdx ].Normalize(); + } + } } // construct some nodes (1+25) diff --git a/test/unit/utProfiler.cpp b/test/unit/utProfiler.cpp new file mode 100644 index 000000000..ea71dd688 --- /dev/null +++ b/test/unit/utProfiler.cpp @@ -0,0 +1,76 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" +#include "UTLogStream.h" +#include "code/Profiler.h" +#include + +using namespace ::Assimp; +using namespace ::Assimp::Profiling; + +class utProfiler : public ::testing::Test { +public: + LogStream *m_stream; + + /*virtual void SetUp() { + m_stream = new UTLogStream; + DefaultLogger::create(); + DefaultLogger::get()->attachStream( m_stream ); + } + + virtual void TearDown() { + DefaultLogger::get()->detatchStream( m_stream ); + m_stream = nullptr; + }*/ +}; + +TEST_F( utProfiler, addRegion_success ) { + Profiler myProfiler; + myProfiler.BeginRegion( "t1" ); + for ( int i=0; i<10; i++ ) { + volatile int j=0; + j++; + } + myProfiler.EndRegion( "t1" ); + //UTLogStream *stream( (UTLogStream*) m_stream ); + //EXPECT_FALSE( stream->m_messages.empty() ); +} diff --git a/test/unit/utQ3DImportExport.cpp b/test/unit/utQ3DImportExport.cpp new file mode 100644 index 000000000..e656bc53c --- /dev/null +++ b/test/unit/utQ3DImportExport.cpp @@ -0,0 +1,62 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" + +#include "AbstractImportExportBase.h" + +#include +#include + +using namespace Assimp; + +class utQ3DImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/Q3D/earth.q3o", aiProcess_ValidateDataStructure ); + return nullptr != scene; + } +}; + +TEST_F(utQ3DImportExport, importTest) { + EXPECT_TRUE( importerTest() ); +} diff --git a/test/unit/utRemoveComments.cpp b/test/unit/utRemoveComments.cpp index 12ff158aa..5bce51126 100644 --- a/test/unit/utRemoveComments.cpp +++ b/test/unit/utRemoveComments.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utRemoveComponent.cpp b/test/unit/utRemoveComponent.cpp index fc3bbbd49..31e47b77c 100644 --- a/test/unit/utRemoveComponent.cpp +++ b/test/unit/utRemoveComponent.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utRemoveRedundantMaterials.cpp b/test/unit/utRemoveRedundantMaterials.cpp index c683d4643..072ca6060 100644 --- a/test/unit/utRemoveRedundantMaterials.cpp +++ b/test/unit/utRemoveRedundantMaterials.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utRemoveVCProcess.cpp b/test/unit/utRemoveVCProcess.cpp new file mode 100644 index 000000000..6caa72c11 --- /dev/null +++ b/test/unit/utRemoveVCProcess.cpp @@ -0,0 +1,76 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" +#include "code/RemoveVCProcess.h" +#include +#include + +using namespace ::Assimp; + +class utRevmoveVCProcess : public ::testing::Test { + // empty +}; + +TEST_F( utRevmoveVCProcess, createTest ) { + bool ok = true; + try { + RemoveVCProcess *process = new RemoveVCProcess; + delete process; + } catch ( ... ) { + ok = false; + } + EXPECT_TRUE( ok ); +} + +TEST_F( utRevmoveVCProcess, issue1266_ProcessMeshTest_NoCrash ) { + aiScene *scene = new aiScene; + scene->mNumMeshes = 1; + scene->mMeshes = new aiMesh*[ 1 ]; + + aiMesh *mesh = new aiMesh; + mesh->mNumVertices = 1; + mesh->mColors[ 0 ] = new aiColor4D[ 2 ]; + scene->mMeshes[ 0 ] = mesh; + std::unique_ptr process(new RemoveVCProcess); + process->Execute( scene ); + delete scene; +} diff --git a/test/unit/utSIBImporter.cpp b/test/unit/utSIBImporter.cpp index b201537ce..affa3c9ad 100644 --- a/test/unit/utSIBImporter.cpp +++ b/test/unit/utSIBImporter.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -42,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "SIBImporter.h" #include +#include #include "AbstractImportExportBase.h" using namespace ::Assimp; @@ -50,7 +52,7 @@ class utSIBImporter : public AbstractImportExportBase { public: virtual bool importerTest() { Assimp::Importer importer; - const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/SIB/heffalump.sib", 0 ); + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/SIB/heffalump.sib", aiProcess_ValidateDataStructure ); return nullptr != scene; } }; diff --git a/test/unit/utSMDImportExport.cpp b/test/unit/utSMDImportExport.cpp new file mode 100644 index 000000000..610d0c5d4 --- /dev/null +++ b/test/unit/utSMDImportExport.cpp @@ -0,0 +1,79 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" + +#include "SMDLoader.h" +#include +#include +#include "AbstractImportExportBase.h" + +using namespace ::Assimp; + +class utSMDImporter : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/SMD/triangle.smd", aiProcess_ValidateDataStructure ); + return nullptr != scene; + } +}; + +TEST_F( utSMDImporter, createTest ) { + bool ok( true ); + try { + SMDImporter myImporter; + } + catch ( ... ) { + ok = false; + } + EXPECT_TRUE( ok ); +} + +TEST_F( utSMDImporter, importTest ) { + EXPECT_TRUE( importerTest() ); +} + +TEST_F( utSMDImporter, issue_899_Texture_garbage_at_end_of_string_Test ) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/SMD/holy_grailref.smd", aiProcess_ValidateDataStructure ); + EXPECT_NE( nullptr, scene ); +} diff --git a/test/unit/utSTLImportExport.cpp b/test/unit/utSTLImportExport.cpp new file mode 100644 index 000000000..2a3cceaf0 --- /dev/null +++ b/test/unit/utSTLImportExport.cpp @@ -0,0 +1,69 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#include "UnitTestPCH.h" +#include "SceneDiffer.h" +#include "AbstractImportExportBase.h" + +#include +#include + +using namespace Assimp; + +class utSTLImporterExporter : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/STL/Spider_ascii.stl", aiProcess_ValidateDataStructure ); + return nullptr != scene; + } +}; + +TEST_F( utSTLImporterExporter, importXFromFileTest ) { + EXPECT_TRUE( importerTest() ); +} + +TEST_F( utSTLImporterExporter, test_with_two_solids ) { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/STL/triangle_with_two_solids.stl", aiProcess_ValidateDataStructure ); + EXPECT_NE( nullptr, scene ); +} diff --git a/test/unit/utScaleProcess.cpp b/test/unit/utScaleProcess.cpp new file mode 100644 index 000000000..7ab44dd15 --- /dev/null +++ b/test/unit/utScaleProcess.cpp @@ -0,0 +1,85 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" +#include "ScaleProcess.h" +#include "TestModelFactory.h" + +namespace Assimp { +namespace UnitTest { + +class utScaleProcess : public ::testing::Test { + // empty +}; + +TEST_F( utScaleProcess, createTest ) { + bool ok = true; + try { + ScaleProcess process; + } catch ( ... ) { + ok = false; + } + EXPECT_TRUE( ok ); +} + +TEST_F( utScaleProcess, accessScaleTest ) { + ScaleProcess process; + EXPECT_FLOAT_EQ( AI_CONFIG_GLOBAL_SCALE_FACTOR_DEFAULT, process.getScale() ); + + process.setScale( 2.0f ); + EXPECT_FLOAT_EQ( 2.0f, process.getScale() ); +} + +TEST_F( utScaleProcess, rescaleModelTest ) { + float opacity; + aiScene *testScene = TestModelFacttory::createDefaultTestModel( opacity ); + ai_real v1 = testScene->mRootNode->mTransformation.a1; + ScaleProcess process; + process.setScale( 10.0f ); + process.Execute( testScene ); + ai_real v2 = testScene->mRootNode->mTransformation.a1; + const ai_real scale = v2 / v1; + EXPECT_FLOAT_EQ( scale, 10.0f ); + TestModelFacttory::releaseDefaultTestModel( &testScene ); +} + +} // Namespace UnitTest +} // Namespace Assimp diff --git a/test/unit/utScene.cpp b/test/unit/utScene.cpp new file mode 100644 index 000000000..8d630ce35 --- /dev/null +++ b/test/unit/utScene.cpp @@ -0,0 +1,64 @@ +/* +--------------------------------------------------------------------------- +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. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" +#include + +using namespace ::Assimp; + +class utScene : public ::testing::Test { + // empty +}; + +TEST_F( utScene, aiNode_addChildrenTest ) { + aiNode myNode; + + static const size_t NumChildren = 10; + aiNode **childrenPtr = new aiNode*[ NumChildren ]; + for ( unsigned int i = 0; i < NumChildren; i++ ) { + childrenPtr[ i ] = new aiNode; + } + myNode.addChildren( NumChildren, childrenPtr ); + EXPECT_EQ( NumChildren, myNode.mNumChildren ); + for ( unsigned int i = 0; i < NumChildren; i++ ) { + EXPECT_EQ( childrenPtr[ i ], myNode.mChildren[ i ] ); + } +} + diff --git a/test/unit/utSceneCombiner.cpp b/test/unit/utSceneCombiner.cpp new file mode 100644 index 000000000..99d483769 --- /dev/null +++ b/test/unit/utSceneCombiner.cpp @@ -0,0 +1,78 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" +#include +#include +#include + +using namespace ::Assimp; + +class utSceneCombiner : public ::testing::Test { + // empty +}; + +TEST_F( utSceneCombiner, MergeMeshes_ValidNames_Test ) { + std::vector merge_list; + aiMesh *mesh1 = new aiMesh; + mesh1->mName.Set( "mesh_1" ); + merge_list.push_back( mesh1 ); + + aiMesh *mesh2 = new aiMesh; + mesh2->mName.Set( "mesh_2" ); + merge_list.push_back( mesh2 ); + + aiMesh *mesh3 = new aiMesh; + mesh3->mName.Set( "mesh_3" ); + merge_list.push_back( mesh3 ); + + std::unique_ptr out; + aiMesh* ptr = nullptr; + SceneCombiner::MergeMeshes( &ptr, 0, merge_list.begin(), merge_list.end() ); + out.reset(ptr); + std::string outName = out->mName.C_Str(); + EXPECT_EQ( "mesh_1.mesh_2.mesh_3", outName ); +} + +TEST_F( utSceneCombiner, CopySceneWithNullptr_NoException ) { + EXPECT_NO_THROW( SceneCombiner::CopyScene( nullptr, nullptr ) ); + EXPECT_NO_THROW( SceneCombiner::CopySceneFlat( nullptr, nullptr ) ); +} diff --git a/test/unit/utScenePreprocessor.cpp b/test/unit/utScenePreprocessor.cpp index 732990f9a..ce3716baf 100644 --- a/test/unit/utScenePreprocessor.cpp +++ b/test/unit/utScenePreprocessor.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utSharedPPData.cpp b/test/unit/utSharedPPData.cpp index fe7841b3d..495faa7ac 100644 --- a/test/unit/utSharedPPData.cpp +++ b/test/unit/utSharedPPData.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -91,7 +92,7 @@ TEST_F(SharedPPDataTest, testPODProperty) // ------------------------------------------------------------------------------------------------ TEST_F(SharedPPDataTest, testPropertyPointer) { - int *i = new int[35]; + int *i = new int; shared->AddProperty("test16",i); int* o; EXPECT_TRUE(shared->GetProperty("test16",o)); diff --git a/test/unit/utSortByPType.cpp b/test/unit/utSortByPType.cpp index 4dd26f983..13c46bd42 100644 --- a/test/unit/utSortByPType.cpp +++ b/test/unit/utSortByPType.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utSplitLargeMeshes.cpp b/test/unit/utSplitLargeMeshes.cpp index 47876caea..af6ed14ef 100644 --- a/test/unit/utSplitLargeMeshes.cpp +++ b/test/unit/utSplitLargeMeshes.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utStringUtils.cpp b/test/unit/utStringUtils.cpp index e75ff8d4b..3b45075eb 100644 --- a/test/unit/utStringUtils.cpp +++ b/test/unit/utStringUtils.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utTargetAnimation.cpp b/test/unit/utTargetAnimation.cpp index 1c039aa90..6742543a6 100644 --- a/test/unit/utTargetAnimation.cpp +++ b/test/unit/utTargetAnimation.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utTextureTransform.cpp b/test/unit/utTextureTransform.cpp index 1c039aa90..6742543a6 100644 --- a/test/unit/utTextureTransform.cpp +++ b/test/unit/utTextureTransform.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utTriangulate.cpp b/test/unit/utTriangulate.cpp index e9677d3e4..8908b9703 100644 --- a/test/unit/utTriangulate.cpp +++ b/test/unit/utTriangulate.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utTypes.cpp b/test/unit/utTypes.cpp index 875f66240..70a734082 100644 --- a/test/unit/utTypes.cpp +++ b/test/unit/utTypes.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utVector3.cpp b/test/unit/utVector3.cpp new file mode 100644 index 000000000..1492281a1 --- /dev/null +++ b/test/unit/utVector3.cpp @@ -0,0 +1,69 @@ +/*------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------*/ +#include "UnitTestPCH.h" +#include + +using namespace ::Assimp; + +class utVector3 : public ::testing::Test { + // empty +}; + +TEST_F(utVector3, CreationTest) { + aiVector3D v0; + aiVector3D v1( 1.0f, 2.0f, 3.0f ); + EXPECT_FLOAT_EQ (1.0f, v1[ 0 ] ); + EXPECT_FLOAT_EQ( 2.0f, v1[ 1 ] ); + EXPECT_FLOAT_EQ( 3.0f, v1[ 2 ] ); + aiVector3D v2( 1 ); + EXPECT_FLOAT_EQ( 1.0f, v2[ 0 ] ); + EXPECT_FLOAT_EQ( 1.0f, v2[ 1 ] ); + EXPECT_FLOAT_EQ( 1.0f, v2[ 2 ] ); + aiVector3D v3( v1 ); + EXPECT_FLOAT_EQ( v1[ 0 ], v3[ 0 ] ); + EXPECT_FLOAT_EQ( v1[ 1 ], v3[ 1 ] ); + EXPECT_FLOAT_EQ( v1[ 2 ], v3[ 2 ] ); +} + +TEST_F( utVector3, BracketOpTest ) { + aiVector3D v(1.0f, 2.0f, 3.0f); + EXPECT_FLOAT_EQ( 1.0f, v[ 0 ] ); + EXPECT_FLOAT_EQ( 2.0f, v[ 1 ] ); + EXPECT_FLOAT_EQ( 3.0f, v[ 2 ] ); +} diff --git a/test/unit/utVersion.cpp b/test/unit/utVersion.cpp index d8953f866..a424a27cf 100644 --- a/test/unit/utVersion.cpp +++ b/test/unit/utVersion.cpp @@ -2,7 +2,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -48,22 +49,23 @@ TEST_F( utVersion, aiGetLegalStringTest ) { EXPECT_NE( lv, nullptr ); std::string text( lv ); - size_t pos( text.find( std::string( "2016" ) ) ); + size_t pos( text.find( std::string( "2017" ) ) ); EXPECT_NE( pos, std::string::npos ); } TEST_F( utVersion, aiGetVersionMinorTest ) { - EXPECT_EQ( aiGetVersionMinor(), 3 ); + EXPECT_EQ( aiGetVersionMinor(), 1U ); } TEST_F( utVersion, aiGetVersionMajorTest ) { - EXPECT_EQ( aiGetVersionMajor(), 3 ); + EXPECT_EQ( aiGetVersionMajor(), 4U ); } TEST_F( utVersion, aiGetCompileFlagsTest ) { - EXPECT_NE( aiGetCompileFlags(), 0 ); + EXPECT_NE( aiGetCompileFlags(), 0U ); } TEST_F( utVersion, aiGetVersionRevisionTest ) { - EXPECT_NE( aiGetVersionRevision(), 0 ); + EXPECT_NE( aiGetVersionRevision(), 0U ); } + diff --git a/test/unit/utVertexTriangleAdjacency.cpp b/test/unit/utVertexTriangleAdjacency.cpp index ec729bac5..29067fead 100644 --- a/test/unit/utVertexTriangleAdjacency.cpp +++ b/test/unit/utVertexTriangleAdjacency.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/test/unit/utX3DImportExport.cpp b/test/unit/utX3DImportExport.cpp new file mode 100644 index 000000000..cb53b3292 --- /dev/null +++ b/test/unit/utX3DImportExport.cpp @@ -0,0 +1,63 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +#include "UnitTestPCH.h" +#include "SceneDiffer.h" +#include "AbstractImportExportBase.h" + +#include +#include + +using namespace Assimp; + +class utX3DImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/X3D/ComputerKeyboard.x3d", aiProcess_ValidateDataStructure ); + return nullptr != scene; + } +}; + +TEST_F( utX3DImportExport, importX3DFromFileTest ) { + EXPECT_TRUE( importerTest() ); +} diff --git a/test/unit/utXImporterExporter.cpp b/test/unit/utXImporterExporter.cpp index 9293e042e..4a6300d19 100644 --- a/test/unit/utXImporterExporter.cpp +++ b/test/unit/utXImporterExporter.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -44,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AbstractImportExportBase.h" #include +#include using namespace Assimp; @@ -51,7 +53,7 @@ class utXImporterExporter : public AbstractImportExportBase { public: virtual bool importerTest() { Assimp::Importer importer; - const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/X/test.x", 0 ); + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/X/test.x", aiProcess_ValidateDataStructure ); return nullptr != scene; } }; diff --git a/test/unit/utglTF2ImportExport.cpp b/test/unit/utglTF2ImportExport.cpp new file mode 100644 index 000000000..865159d0d --- /dev/null +++ b/test/unit/utglTF2ImportExport.cpp @@ -0,0 +1,91 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" +#include "AbstractImportExportBase.h" + +#include +#include +#include + +using namespace Assimp; + +class utglTF2ImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", aiProcess_ValidateDataStructure); + return nullptr != scene; + } + + virtual bool binaryImporterTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/2CylinderEngine-glTF-Binary/2CylinderEngine.glb", aiProcess_ValidateDataStructure); + return nullptr != scene; + } + +#ifndef ASSIMP_BUILD_NO_EXPORT + virtual bool exporterTest() { + Assimp::Importer importer; + Assimp::Exporter exporter; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured.gltf", aiProcess_ValidateDataStructure ); + EXPECT_NE( nullptr, scene ); + EXPECT_EQ( aiReturn_SUCCESS, exporter.Export( scene, "gltf2", ASSIMP_TEST_MODELS_DIR "/glTF2/BoxTextured-glTF/BoxTextured_out.gltf" ) ); + + return true; + } +#endif // ASSIMP_BUILD_NO_EXPORT + +}; + +TEST_F( utglTF2ImportExport, importglTF2FromFileTest ) { + EXPECT_TRUE( importerTest() ); +} + +TEST_F( utglTF2ImportExport, importBinaryglTF2FromFileTest ) { + EXPECT_TRUE( binaryImporterTest() ); +} + +#ifndef ASSIMP_BUILD_NO_EXPORT +TEST_F( utglTF2ImportExport, exportglTF2FromFileTest ) { + EXPECT_TRUE( exporterTest() ); +} +#endif // ASSIMP_BUILD_NO_EXPORT diff --git a/test/unit/utglTFImportExport.cpp b/test/unit/utglTFImportExport.cpp new file mode 100644 index 000000000..4e1f765a1 --- /dev/null +++ b/test/unit/utglTFImportExport.cpp @@ -0,0 +1,61 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2017, assimp team + + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" +#include "AbstractImportExportBase.h" + +#include +#include + +using namespace Assimp; + +class utglTFImportExport : public AbstractImportExportBase { +public: + virtual bool importerTest() { + Assimp::Importer importer; + const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/glTF/TwoBoxes/TwoBoxes.gltf", aiProcess_ValidateDataStructure ); + return nullptr != scene; + } +}; + +TEST_F( utglTFImportExport, importglTFFromFileTest ) { + EXPECT_TRUE( importerTest() ); +} diff --git a/tools/assimp_cmd/CMakeLists.txt b/tools/assimp_cmd/CMakeLists.txt index f8af93a10..cb78942d7 100644 --- a/tools/assimp_cmd/CMakeLists.txt +++ b/tools/assimp_cmd/CMakeLists.txt @@ -1,7 +1,8 @@ # Open Asset Import Library (assimp) # ---------------------------------------------------------------------- # -# Copyright (c) 2006-2016, assimp team +# Copyright (c) 2006-2017, assimp team + # All rights reserved. # # Redistribution and use of this software in source and binary forms, diff --git a/tools/assimp_cmd/CompareDump.cpp b/tools/assimp_cmd/CompareDump.cpp index 1821ff6ec..2db11ef25 100644 --- a/tools/assimp_cmd/CompareDump.cpp +++ b/tools/assimp_cmd/CompareDump.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/tools/assimp_cmd/Export.cpp b/tools/assimp_cmd/Export.cpp index d83f5272a..3752db5e5 100644 --- a/tools/assimp_cmd/Export.cpp +++ b/tools/assimp_cmd/Export.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/tools/assimp_cmd/ImageExtractor.cpp b/tools/assimp_cmd/ImageExtractor.cpp index 7e7b9b439..691f62929 100644 --- a/tools/assimp_cmd/ImageExtractor.cpp +++ b/tools/assimp_cmd/ImageExtractor.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/tools/assimp_cmd/Info.cpp b/tools/assimp_cmd/Info.cpp index 3eb0e9d10..d116f04d2 100644 --- a/tools/assimp_cmd/Info.cpp +++ b/tools/assimp_cmd/Info.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/tools/assimp_cmd/Main.cpp b/tools/assimp_cmd/Main.cpp index 9c5368bf5..587e111d5 100644 --- a/tools/assimp_cmd/Main.cpp +++ b/tools/assimp_cmd/Main.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -47,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. const char* AICMD_MSG_ABOUT = "------------------------------------------------------ \n" -"Open Asset Import Library (\"Assimp\", http://assimp.sourceforge.net) \n" +"Open Asset Import Library (\"Assimp\", https://github.com/assimp/assimp) \n" " -- Commandline toolchain --\n" "------------------------------------------------------ \n\n" diff --git a/tools/assimp_cmd/WriteDumb.cpp b/tools/assimp_cmd/WriteDumb.cpp index 44b0c6926..e1b104d40 100644 --- a/tools/assimp_cmd/WriteDumb.cpp +++ b/tools/assimp_cmd/WriteDumb.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -176,6 +177,17 @@ inline uint32_t Write(const aiVector3D& v) return t; } +// ----------------------------------------------------------------------------------- +// Serialize a color value +template <> +inline uint32_t Write(const aiColor3D& v) +{ + uint32_t t = Write(v.r); + t += Write(v.g); + t += Write(v.b); + return t; +} + // ----------------------------------------------------------------------------------- // Serialize a color value template <> @@ -197,6 +209,7 @@ inline uint32_t Write(const aiQuaternion& v) t += Write(v.x); t += Write(v.y); t += Write(v.z); + ai_assert(t == 16); return 16; } @@ -564,9 +577,9 @@ uint32_t WriteBinaryLight(const aiLight* l) len += Write(l->mAttenuationQuadratic); } - len += Write((const aiVector3D&)l->mColorDiffuse); - len += Write((const aiVector3D&)l->mColorSpecular); - len += Write((const aiVector3D&)l->mColorAmbient); + len += Write(l->mColorDiffuse); + len += Write(l->mColorSpecular); + len += Write(l->mColorAmbient); if (l->mType == aiLightSource_SPOT) { len += Write(l->mAngleInnerCone); diff --git a/tools/assimp_qt_viewer/CMakeLists.txt b/tools/assimp_qt_viewer/CMakeLists.txt index 2985d6e30..42ef0fb34 100644 --- a/tools/assimp_qt_viewer/CMakeLists.txt +++ b/tools/assimp_qt_viewer/CMakeLists.txt @@ -1,5 +1,5 @@ -project(assimp_qt_viewer) set(PROJECT_VERSION "") +project(assimp_qt_viewer) cmake_minimum_required(VERSION 2.6) diff --git a/tools/assimp_qt_viewer/glview.cpp b/tools/assimp_qt_viewer/glview.cpp index 2d1e07a98..5b755d456 100644 --- a/tools/assimp_qt_viewer/glview.cpp +++ b/tools/assimp_qt_viewer/glview.cpp @@ -6,7 +6,11 @@ #include "glview.hpp" // Header files, OpenGL. -#include +#if defined(__APPLE__) +# include +#else +# include +#endif // Header files, DevIL. #include @@ -142,8 +146,8 @@ void CGLView::Material_Apply(const aiMaterial* pMaterial) void CGLView::Matrix_NodeToRoot(const aiNode* pNode, aiMatrix4x4& pOutMatrix) { -const aiNode* node_cur; -std::list mat_list; + const aiNode* node_cur; + std::list mat_list; pOutMatrix = aiMatrix4x4(); // starting walk from current element to root @@ -557,7 +561,7 @@ void CGLView::Enable_Textures(const bool pEnable) } /********************************************************************/ -/*********************** Overrided functions ************************/ +/*********************** Override functions ************************/ /********************************************************************/ void CGLView::initializeGL() @@ -715,7 +719,7 @@ void CGLView::SetScene(const aiScene *pScene, const QString& pScenePath) mHelper_Mesh_Quantity = mScene->mNumMeshes; mHelper_Mesh = new SHelper_Mesh*[mScene->mNumMeshes]; - // Walk thru the meshes and extract needed data and, also calculate BBox. + // Walk through the meshes and extract needed data and, also calculate BBox. for(size_t idx_mesh = 0; idx_mesh < mScene->mNumMeshes; idx_mesh++) { aiMesh& mesh_cur = *mScene->mMeshes[idx_mesh]; @@ -793,7 +797,7 @@ void CGLView::SetScene(const aiScene *pScene, const QString& pScenePath) // // Scene BBox // - // For calculating right BBox we must walk thru all nodes and apply transformation to meshes BBoxes + // For calculating right BBox we must walk through all nodes and apply transformation to meshes BBoxes if(mHelper_Mesh_Quantity > 0) { bool first_assign = true; diff --git a/tools/assimp_qt_viewer/glview.hpp b/tools/assimp_qt_viewer/glview.hpp index 49207a7ed..ecd7c6b0f 100644 --- a/tools/assimp_qt_viewer/glview.hpp +++ b/tools/assimp_qt_viewer/glview.hpp @@ -249,13 +249,13 @@ private: void Draw_BBox(const SBBox& pBBox); /********************************************************************/ - /*********************** Overrided functions ************************/ + /*********************** Override functions ************************/ /********************************************************************/ protected: void drawCoordSystem(); /// \fn void initializeGL() override - /// Overrided function for initialise OpenGL. + /// Override function to initialise OpenGL. void initializeGL() override; /// \fn void resizeGL(int pWidth, int pHeight) override @@ -264,7 +264,7 @@ protected: void resizeGL(int pWidth, int pHeight) override; /// \fn void paintGL() override - /// Overrided function for rendering. + /// Override function for rendering. void paintGL() override; public: diff --git a/tools/assimp_qt_viewer/mainwindow.cpp b/tools/assimp_qt_viewer/mainwindow.cpp index cb4c4a67e..82ddc7092 100644 --- a/tools/assimp_qt_viewer/mainwindow.cpp +++ b/tools/assimp_qt_viewer/mainwindow.cpp @@ -107,7 +107,7 @@ void MainWindow::LogError(const QString& pMessage) } /********************************************************************/ -/*********************** Overrided functions ************************/ +/*********************** Override functions ************************/ /********************************************************************/ void MainWindow::mousePressEvent(QMouseEvent* pEvent) @@ -295,7 +295,7 @@ aiReturn rv; // begin export time_begin = QTime::currentTime(); - rv = exporter.Export(mScene, format_id.toLocal8Bit(), filename.toLocal8Bit()); + rv = exporter.Export(mScene, format_id.toLocal8Bit(), filename.toLocal8Bit(), aiProcess_FlipUVs); ui->lblExportTime->setText(QString("%1").arg(time_begin.secsTo(QTime::currentTime()))); if(rv == aiReturn_SUCCESS) LogInfo("Export done: " + filename); diff --git a/tools/assimp_qt_viewer/mainwindow.hpp b/tools/assimp_qt_viewer/mainwindow.hpp index 940840aee..b20acb884 100644 --- a/tools/assimp_qt_viewer/mainwindow.hpp +++ b/tools/assimp_qt_viewer/mainwindow.hpp @@ -65,23 +65,23 @@ private: void LogError(const QString& pMessage); /********************************************************************/ - /*********************** Overrided functions ************************/ + /*********************** Override functions ************************/ /********************************************************************/ protected: /// \fn void mousePressEvent(QMouseEvent* pEvent) override - /// Overrided function which handle mouse event "button pressed". + /// Override function which handles mouse event "button pressed". /// \param [in] pEvent - pointer to event data. void mousePressEvent(QMouseEvent* pEvent) override; /// \fn void mouseMoveEvent(QMouseEvent* pEvent) override - /// Overrided function which handle mouse event "move". + /// Override function which handles mouse event "move". /// \param [in] pEvent - pointer to event data. void mouseMoveEvent(QMouseEvent* pEvent) override; /// \fn void keyPressEvent(QKeyEvent* pEvent) override - /// Overrided function which handle key event "key pressed". + /// Override function which handles key event "key pressed". /// \param [in] pEvent - pointer to event data. void keyPressEvent(QKeyEvent* pEvent) override; diff --git a/tools/assimp_view/CMakeLists.txt b/tools/assimp_view/CMakeLists.txt index 23e648b5b..adf2ae877 100644 --- a/tools/assimp_view/CMakeLists.txt +++ b/tools/assimp_view/CMakeLists.txt @@ -1,7 +1,8 @@ # Open Asset Import Library (assimp) # ---------------------------------------------------------------------- # -# Copyright (c) 2006-2016, assimp team +# Copyright (c) 2006-2017, assimp team + # All rights reserved. # # Redistribution and use of this software in source and binary forms, diff --git a/tools/assimp_view/Display.cpp b/tools/assimp_view/Display.cpp index 91ea9573b..21c0c022a 100644 --- a/tools/assimp_view/Display.cpp +++ b/tools/assimp_view/Display.cpp @@ -43,6 +43,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "SceneAnimator.h" #include "StringUtils.h" +#include + namespace AssimpView { using namespace Assimp; diff --git a/tools/assimp_view/LogWindow.cpp b/tools/assimp_view/LogWindow.cpp index c21c2802e..dba70ee71 100644 --- a/tools/assimp_view/LogWindow.cpp +++ b/tools/assimp_view/LogWindow.cpp @@ -41,6 +41,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "assimp_view.h" #include "richedit.h" +#include +#include namespace AssimpView { diff --git a/tools/assimp_view/MaterialManager.h b/tools/assimp_view/MaterialManager.h index d1c9eb507..17e133821 100644 --- a/tools/assimp_view/MaterialManager.h +++ b/tools/assimp_view/MaterialManager.h @@ -178,7 +178,7 @@ namespace AssimpView // Convert a height map to a normal map if necessary // // The function tries to detect the type of a texture automatically. - // However, this wont work in every case. + // However, this won't work in every case. void HMtoNMIfNecessary( IDirect3DTexture9* piTexture, IDirect3DTexture9** piTextureOut, bool bWasOriginallyHM = true ); diff --git a/tools/assimp_view/MessageProc.cpp b/tools/assimp_view/MessageProc.cpp index 4595c58cd..b8c56503b 100644 --- a/tools/assimp_view/MessageProc.cpp +++ b/tools/assimp_view/MessageProc.cpp @@ -44,6 +44,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include +#include namespace AssimpView { diff --git a/tools/assimp_view/SceneAnimator.h b/tools/assimp_view/SceneAnimator.h index ba79b4faa..afcbac925 100644 --- a/tools/assimp_view/SceneAnimator.h +++ b/tools/assimp_view/SceneAnimator.h @@ -72,20 +72,26 @@ struct SceneAnimNode size_t mChannelIndex; //! Default construction - SceneAnimNode() { - mChannelIndex = -1; mParent = NULL; + SceneAnimNode() + : mName() + , mParent(NULL) + , mChannelIndex(-1) { + // empty } //! Construction from a given name SceneAnimNode( const std::string& pName) - : mName( pName) { - mChannelIndex = -1; mParent = NULL; + : mName( pName) + , mParent(NULL) + , mChannelIndex( -1 ) { + // empty } //! Destruct all children recursively ~SceneAnimNode() { - for( std::vector::iterator it = mChildren.begin(); it != mChildren.end(); ++it) + for (std::vector::iterator it = mChildren.begin(); it != mChildren.end(); ++it) { delete *it; + } } }; diff --git a/tools/assimp_view/assimp_view.cpp b/tools/assimp_view/assimp_view.cpp index 811fe47e7..283761e88 100644 --- a/tools/assimp_view/assimp_view.cpp +++ b/tools/assimp_view/assimp_view.cpp @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. @@ -41,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "assimp_view.h" +#include #include "StringUtils.h" #include diff --git a/tools/assimp_view/assimp_view.h b/tools/assimp_view/assimp_view.h index 6300c1a87..73c7d7947 100644 --- a/tools/assimp_view/assimp_view.h +++ b/tools/assimp_view/assimp_view.h @@ -3,7 +3,8 @@ Open Asset Import Library (assimp) --------------------------------------------------------------------------- -Copyright (c) 2006-2016, assimp team +Copyright (c) 2006-2017, assimp team + All rights reserved. diff --git a/tools/assimp_view/assimp_view.rc b/tools/assimp_view/assimp_view.rc index 13b05b18c..aebb1e2d9 100644 --- a/tools/assimp_view/assimp_view.rc +++ b/tools/assimp_view/assimp_view.rc @@ -189,7 +189,7 @@ BEGIN LTEXT "Angle limit (in degrees):",IDC_STATIC,13,10,76,8 LTEXT "The angle limit defines the maximum angle that may be between two adjacent face normals that they're smoothed together.",IDC_STATIC,13,31,253,19 CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,113,278,1 - LTEXT "This setting is also used during import, but it can be overriden by single model importers to match the original look of a model as closely as possible. Examples include 3DS, ASE and LWO, all of them relying on smoothing groups and their own angle limits. ",IDC_STATIC,13,51,254,33 + LTEXT "This setting is also used during import, but it can be overridden by single model importers to match the original look of a model as closely as possible. Examples include 3DS, ASE and LWO, all of them relying on smoothing groups and their own angle limits. ",IDC_STATIC,13,51,254,33 LTEXT "NOTE: New settings don't take effect immediately, use 'Smooth Normals' or 'Reload' to update the model.",IDC_STATIC,14,118,254,22 CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,90,277,1 END diff --git a/tools/assimp_view/stdafx.h b/tools/assimp_view/stdafx.h index 3c78d385c..35104d4b0 100644 --- a/tools/assimp_view/stdafx.h +++ b/tools/assimp_view/stdafx.h @@ -23,7 +23,6 @@ #define _WIN32_IE 0x0600 // Ändern Sie dies in den geeigneten Wert für andere Versionen von IE. #endif -#define WIN32_LEAN_AND_MEAN // Selten verwendete Teile der Windows-Header nicht einbinden. // Windows-Headerdateien: #include diff --git a/workspaces/Android-NDK/jni/Android.mk b/workspaces/Android-NDK/jni/Android.mk deleted file mode 100755 index b4d1da7ef..000000000 --- a/workspaces/Android-NDK/jni/Android.mk +++ /dev/null @@ -1,124 +0,0 @@ -LOCAL_PATH := $(call my-dir)/../../../ - -include $(CLEAR_VARS) -LOCAL_MODULE := assimp_static -ASSIMP_SRC_DIR = code - -FILE_LIST := $(wildcard $(LOCAL_PATH)/$(ASSIMP_SRC_DIR)/*.cpp) -FILE_LIST += $(wildcard $(LOCAL_PATH)/contrib/openddlparser/code/*.cpp) -FILE_LIST += $(wildcard $(LOCAL_PATH)/contrib/unzip/*.c) -FILE_LIST += $(wildcard $(LOCAL_PATH)/contrib/poly2tri/poly2tri/*/*.cc) - -LOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)/%=%) - -LOCAL_SRC_FILES += contrib/clipper/clipper.cpp \ - contrib/ConvertUTF/ConvertUTF.c \ - contrib/irrXML/irrXML.cpp - -# enables -frtti and -fexceptions -LOCAL_CPP_FEATURES := exceptions -# identifier 'nullptr' will become a keyword in C++0x [-Wc++0x-compat] -# but next breaks blender and other importer -# LOCAL_CFLAGS += -std=c++11 - -# can't be disabled? rudamentary function? -# -DASSIMP_BUILD_NO_FLIPWINDING_PROCESS \ -# -DontBuildProcess = \ - -DASSIMP_BUILD_NO_FLIPUVS_PROCESS \ - -DASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS \ - -DASSIMP_BUILD_NO_CALCTANGENTS_PROCESS \ - -DASSIMP_BUILD_NO_DEBONE_PROCESS \ - -DASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS \ - -DASSIMP_BUILD_NO_FINDINSTANCES_PROCESS \ - -DASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS \ - -DASSIMP_BUILD_NO_FIXINFACINGNORMALS_PROCESS \ - -DASSIMP_BUILD_NO_GENFACENORMALS_PROCESS \ - -DASSIMP_BUILD_NO_GENUVCOORDS_PROCESS \ - -DASSIMP_BUILD_NO_GENVERTEXNORMALS_PROCESS \ - -DASSIMP_BUILD_NO_IMPROVECACHELOCALITY_PROCESS \ - -DASSIMP_BUILD_NO_JOINVERTICES_PROCESS \ - -DASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS \ - -DASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS \ - -DASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS \ - -DASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS \ - -DASSIMP_BUILD_NO_REMOVEVC_PROCESS \ - -DASSIMP_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS \ - -DASSIMP_BUILD_NO_SORTBYPTYPE_PROCESS \ - -DASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS \ - -DASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS \ - -DASSIMP_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS \ - -DASSIMP_BUILD_NO_TRIANGULATE_PROCESS \ - -DASSIMP_BUILD_NO_VALIDATEDS_PROCESS - -DontBuildImporters = \ - -DASSIMP_BUILD_NO_X_IMPORTER \ - -DASSIMP_BUILD_NO_3DS_IMPORTER \ - -DASSIMP_BUILD_NO_MD3_IMPORTER \ - -DASSIMP_BUILD_NO_MDL_IMPORTER \ - -DASSIMP_BUILD_NO_MD2_IMPORTER \ - -DASSIMP_BUILD_NO_PLY_IMPORTER \ - -DASSIMP_BUILD_NO_ASE_IMPORTER \ - -DASSIMP_BUILD_NO_HMP_IMPORTER \ - -DASSIMP_BUILD_NO_SMD_IMPORTER \ - -DASSIMP_BUILD_NO_MDC_IMPORTER \ - -DASSIMP_BUILD_NO_MD5_IMPORTER \ - -DASSIMP_BUILD_NO_STL_IMPORTER \ - -DASSIMP_BUILD_NO_LWO_IMPORTER \ - -DASSIMP_BUILD_NO_DXF_IMPORTER \ - -DASSIMP_BUILD_NO_NFF_IMPORTER \ - -DASSIMP_BUILD_NO_RAW_IMPORTER \ - -DASSIMP_BUILD_NO_OFF_IMPORTER \ - -DASSIMP_BUILD_NO_AC_IMPORTER \ - -DASSIMP_BUILD_NO_BVH_IMPORTER \ - -DASSIMP_BUILD_NO_IRRMESH_IMPORTER \ - -DASSIMP_BUILD_NO_IRR_IMPORTER \ - -DASSIMP_BUILD_NO_Q3D_IMPORTER \ - -DASSIMP_BUILD_NO_B3D_IMPORTER \ - -DASSIMP_BUILD_NO_COLLADA_IMPORTER \ - -DASSIMP_BUILD_NO_TERRAGEN_IMPORTER \ - -DASSIMP_BUILD_NO_CSM_IMPORTER \ - -DASSIMP_BUILD_NO_3D_IMPORTER \ - -DASSIMP_BUILD_NO_LWS_IMPORTER \ - -DASSIMP_BUILD_NO_OGRE_IMPORTER \ - -DASSIMP_BUILD_NO_MS3D_IMPORTER \ - -DASSIMP_BUILD_NO_COB_IMPORTER \ - -DASSIMP_BUILD_NO_Q3BSP_IMPORTER \ - -DASSIMP_BUILD_NO_NDO_IMPORTER \ - -DASSIMP_BUILD_NO_IFC_IMPORTER \ - -DASSIMP_BUILD_NO_XGL_IMPORTER \ - -DASSIMP_BUILD_NO_FBX_IMPORTER \ - -DASSIMP_BUILD_NO_C4D_IMPORTER \ - -DASSIMP_BUILD_NO_OPENGEX_IMPORTER \ - -DASSIMP_BUILD_NO_ASSBIN_IMPORTER -# -DASSIMP_BUILD_NO_BLEND_IMPORTER \ -# -DASSIMP_BUILD_NO_GEO_IMPORTER -# -DASSIMP_BUILD_NO_OBJ_IMPORTER \ -# -DontBuildImporters := -DASSIMP_BUILD_NO_IFC_IMPORTER -DASSIMP_BUILD_NO_IRRMESH_IMPORTER -DASSIMP_BUILD_NO_IRR_IMPORTER -DASSIMP_BUILD_NO_C4D_IMPORTER - -ASSIMP_FLAGS_3_0 = -DASSIMP_BUILD_DLL_EXPORT -DASSIMP_BUILD_NO_OWN_ZLIB -DASSIMP_BUILD_BOOST_WORKAROUND -Dassimp_EXPORTS -fPIC -fvisibility=hidden -Wall -ASSIMP_FLAGS_3_1 = $(ASSIMP_FLAGS_3_0) # -DASSIMP_BUILD_BLENDER_DEBUG - -LOCAL_CFLAGS += $(ASSIMP_FLAGS_3_1) -DASSIMP_BUILD_NO_EXPORT -DOPENDDL_NO_USE_CPP11 $(DontBuildImporters) # $(DontBuildProcess) - -LOCAL_C_INCLUDES += $(LOCAL_PATH)/include $(LOCAL_PATH)/$(ASSIMP_SRC_DIR)/BoostWorkaround $(LOCAL_PATH)/contrib/openddlparser/include ./ -LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/$(ASSIMP_SRC_DIR)/BoostWorkaround - -include $(BUILD_STATIC_LIBRARY) - -include $(CLEAR_VARS) -LOCAL_MODULE := assimp - -LOCAL_CFLAGS += -UASSIMP_BUILD_DLL_EXPORT -LOCAL_WHOLE_STATIC_LIBRARIES = assimp_static - -LOCAL_LDLIBS := -lz - -LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/$(ASSIMP_SRC_DIR)/BoostWorkaround -include $(BUILD_SHARED_LIBRARY) - --include $(LOCAL_PATH)/assimp_cmd.mk - -# let it on original place -include $(LOCAL_PATH)/port/jassimp/jassimp-native/Android.mk diff --git a/workspaces/Android-NDK/jni/Application.mk b/workspaces/Android-NDK/jni/Application.mk deleted file mode 100755 index 3d264db1b..000000000 --- a/workspaces/Android-NDK/jni/Application.mk +++ /dev/null @@ -1,8 +0,0 @@ -ifeq ($(CC),clang) - NDK_TOOLCHAIN_VERSION := $(CC) - $(info "Use llvm Compiler") -endif - -APP_ABI := armeabi-v7a - -APP_STL := stlport_static diff --git a/workspaces/xcode3/assimp.xcodeproj/project.pbxproj b/workspaces/xcode3/assimp.xcodeproj/project.pbxproj deleted file mode 100644 index 1ae088b13..000000000 --- a/workspaces/xcode3/assimp.xcodeproj/project.pbxproj +++ /dev/null @@ -1,5912 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 2B7F46DD1708365200A106A9 /* assbin_chunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F456D1708365100A106A9 /* assbin_chunks.h */; }; - 2B7F46DE1708365200A106A9 /* assbin_chunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F456D1708365100A106A9 /* assbin_chunks.h */; }; - 2B7F46DF1708365200A106A9 /* assbin_chunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F456D1708365100A106A9 /* assbin_chunks.h */; }; - 2B7F46E01708365200A106A9 /* assbin_chunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F456D1708365100A106A9 /* assbin_chunks.h */; }; - 2B7F46E11708365200A106A9 /* assbin_chunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F456D1708365100A106A9 /* assbin_chunks.h */; }; - 2B7F46E21708365200A106A9 /* Assimp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F456E1708365100A106A9 /* Assimp.cpp */; }; - 2B7F46E31708365200A106A9 /* Assimp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F456E1708365100A106A9 /* Assimp.cpp */; }; - 2B7F46E41708365200A106A9 /* Assimp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F456E1708365100A106A9 /* Assimp.cpp */; }; - 2B7F46E51708365200A106A9 /* Assimp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F456E1708365100A106A9 /* Assimp.cpp */; }; - 2B7F46E61708365200A106A9 /* Assimp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F456E1708365100A106A9 /* Assimp.cpp */; }; - 2B7F46E71708365200A106A9 /* AssimpCExport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F456F1708365100A106A9 /* AssimpCExport.cpp */; }; - 2B7F46E81708365200A106A9 /* AssimpCExport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F456F1708365100A106A9 /* AssimpCExport.cpp */; }; - 2B7F46E91708365200A106A9 /* AssimpCExport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F456F1708365100A106A9 /* AssimpCExport.cpp */; }; - 2B7F46EA1708365200A106A9 /* AssimpCExport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F456F1708365100A106A9 /* AssimpCExport.cpp */; }; - 2B7F46EB1708365200A106A9 /* AssimpCExport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F456F1708365100A106A9 /* AssimpCExport.cpp */; }; - 2B7F47001708365200A106A9 /* BaseImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45741708365100A106A9 /* BaseImporter.cpp */; }; - 2B7F47011708365200A106A9 /* BaseImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45741708365100A106A9 /* BaseImporter.cpp */; }; - 2B7F47021708365200A106A9 /* BaseImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45741708365100A106A9 /* BaseImporter.cpp */; }; - 2B7F47031708365200A106A9 /* BaseImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45741708365100A106A9 /* BaseImporter.cpp */; }; - 2B7F47041708365200A106A9 /* BaseImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45741708365100A106A9 /* BaseImporter.cpp */; }; - 2B7F47051708365200A106A9 /* BaseImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45751708365100A106A9 /* BaseImporter.h */; }; - 2B7F47061708365200A106A9 /* BaseImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45751708365100A106A9 /* BaseImporter.h */; }; - 2B7F47071708365200A106A9 /* BaseImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45751708365100A106A9 /* BaseImporter.h */; }; - 2B7F47081708365200A106A9 /* BaseImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45751708365100A106A9 /* BaseImporter.h */; }; - 2B7F47091708365200A106A9 /* BaseImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45751708365100A106A9 /* BaseImporter.h */; }; - 2B7F470A1708365200A106A9 /* BaseProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45761708365100A106A9 /* BaseProcess.cpp */; }; - 2B7F470B1708365200A106A9 /* BaseProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45761708365100A106A9 /* BaseProcess.cpp */; }; - 2B7F470C1708365200A106A9 /* BaseProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45761708365100A106A9 /* BaseProcess.cpp */; }; - 2B7F470D1708365200A106A9 /* BaseProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45761708365100A106A9 /* BaseProcess.cpp */; }; - 2B7F470E1708365200A106A9 /* BaseProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45761708365100A106A9 /* BaseProcess.cpp */; }; - 2B7F470F1708365200A106A9 /* BaseProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45771708365100A106A9 /* BaseProcess.h */; }; - 2B7F47101708365200A106A9 /* BaseProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45771708365100A106A9 /* BaseProcess.h */; }; - 2B7F47111708365200A106A9 /* BaseProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45771708365100A106A9 /* BaseProcess.h */; }; - 2B7F47121708365200A106A9 /* BaseProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45771708365100A106A9 /* BaseProcess.h */; }; - 2B7F47131708365200A106A9 /* BaseProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45771708365100A106A9 /* BaseProcess.h */; }; - 2B7F47461708365200A106A9 /* BlobIOSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45831708365100A106A9 /* BlobIOSystem.h */; }; - 2B7F47471708365200A106A9 /* BlobIOSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45831708365100A106A9 /* BlobIOSystem.h */; }; - 2B7F47481708365200A106A9 /* BlobIOSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45831708365100A106A9 /* BlobIOSystem.h */; }; - 2B7F47491708365200A106A9 /* BlobIOSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45831708365100A106A9 /* BlobIOSystem.h */; }; - 2B7F474A1708365200A106A9 /* BlobIOSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45831708365100A106A9 /* BlobIOSystem.h */; }; - 2B7F474B1708365200A106A9 /* foreach.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45861708365100A106A9 /* foreach.hpp */; }; - 2B7F474C1708365200A106A9 /* foreach.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45861708365100A106A9 /* foreach.hpp */; }; - 2B7F474D1708365200A106A9 /* foreach.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45861708365100A106A9 /* foreach.hpp */; }; - 2B7F474E1708365200A106A9 /* foreach.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45861708365100A106A9 /* foreach.hpp */; }; - 2B7F474F1708365200A106A9 /* foreach.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45861708365100A106A9 /* foreach.hpp */; }; - 2B7F47501708365200A106A9 /* format.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45871708365100A106A9 /* format.hpp */; }; - 2B7F47511708365200A106A9 /* format.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45871708365100A106A9 /* format.hpp */; }; - 2B7F47521708365200A106A9 /* format.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45871708365100A106A9 /* format.hpp */; }; - 2B7F47531708365200A106A9 /* format.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45871708365100A106A9 /* format.hpp */; }; - 2B7F47541708365200A106A9 /* format.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45871708365100A106A9 /* format.hpp */; }; - 2B7F47551708365200A106A9 /* lexical_cast.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45881708365100A106A9 /* lexical_cast.hpp */; }; - 2B7F47561708365200A106A9 /* lexical_cast.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45881708365100A106A9 /* lexical_cast.hpp */; }; - 2B7F47571708365200A106A9 /* lexical_cast.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45881708365100A106A9 /* lexical_cast.hpp */; }; - 2B7F47581708365200A106A9 /* lexical_cast.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45881708365100A106A9 /* lexical_cast.hpp */; }; - 2B7F47591708365200A106A9 /* lexical_cast.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45881708365100A106A9 /* lexical_cast.hpp */; }; - 2B7F475A1708365200A106A9 /* make_shared.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458A1708365100A106A9 /* make_shared.hpp */; }; - 2B7F475B1708365200A106A9 /* make_shared.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458A1708365100A106A9 /* make_shared.hpp */; }; - 2B7F475C1708365200A106A9 /* make_shared.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458A1708365100A106A9 /* make_shared.hpp */; }; - 2B7F475D1708365200A106A9 /* make_shared.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458A1708365100A106A9 /* make_shared.hpp */; }; - 2B7F475E1708365200A106A9 /* make_shared.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458A1708365100A106A9 /* make_shared.hpp */; }; - 2B7F475F1708365200A106A9 /* common_factor_rt.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458C1708365100A106A9 /* common_factor_rt.hpp */; }; - 2B7F47601708365200A106A9 /* common_factor_rt.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458C1708365100A106A9 /* common_factor_rt.hpp */; }; - 2B7F47611708365200A106A9 /* common_factor_rt.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458C1708365100A106A9 /* common_factor_rt.hpp */; }; - 2B7F47621708365200A106A9 /* common_factor_rt.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458C1708365100A106A9 /* common_factor_rt.hpp */; }; - 2B7F47631708365200A106A9 /* common_factor_rt.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458C1708365100A106A9 /* common_factor_rt.hpp */; }; - 2B7F47641708365200A106A9 /* noncopyable.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458D1708365100A106A9 /* noncopyable.hpp */; }; - 2B7F47651708365200A106A9 /* noncopyable.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458D1708365100A106A9 /* noncopyable.hpp */; }; - 2B7F47661708365200A106A9 /* noncopyable.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458D1708365100A106A9 /* noncopyable.hpp */; }; - 2B7F47671708365200A106A9 /* noncopyable.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458D1708365100A106A9 /* noncopyable.hpp */; }; - 2B7F47681708365200A106A9 /* noncopyable.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458D1708365100A106A9 /* noncopyable.hpp */; }; - 2B7F47691708365200A106A9 /* pointer_cast.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458E1708365100A106A9 /* pointer_cast.hpp */; }; - 2B7F476A1708365200A106A9 /* pointer_cast.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458E1708365100A106A9 /* pointer_cast.hpp */; }; - 2B7F476B1708365200A106A9 /* pointer_cast.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458E1708365100A106A9 /* pointer_cast.hpp */; }; - 2B7F476C1708365200A106A9 /* pointer_cast.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458E1708365100A106A9 /* pointer_cast.hpp */; }; - 2B7F476D1708365200A106A9 /* pointer_cast.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458E1708365100A106A9 /* pointer_cast.hpp */; }; - 2B7F476E1708365200A106A9 /* scoped_array.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458F1708365100A106A9 /* scoped_array.hpp */; }; - 2B7F476F1708365200A106A9 /* scoped_array.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458F1708365100A106A9 /* scoped_array.hpp */; }; - 2B7F47701708365200A106A9 /* scoped_array.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458F1708365100A106A9 /* scoped_array.hpp */; }; - 2B7F47711708365200A106A9 /* scoped_array.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458F1708365100A106A9 /* scoped_array.hpp */; }; - 2B7F47721708365200A106A9 /* scoped_array.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F458F1708365100A106A9 /* scoped_array.hpp */; }; - 2B7F47731708365200A106A9 /* scoped_ptr.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45901708365100A106A9 /* scoped_ptr.hpp */; }; - 2B7F47741708365200A106A9 /* scoped_ptr.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45901708365100A106A9 /* scoped_ptr.hpp */; }; - 2B7F47751708365200A106A9 /* scoped_ptr.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45901708365100A106A9 /* scoped_ptr.hpp */; }; - 2B7F47761708365200A106A9 /* scoped_ptr.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45901708365100A106A9 /* scoped_ptr.hpp */; }; - 2B7F47771708365200A106A9 /* scoped_ptr.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45901708365100A106A9 /* scoped_ptr.hpp */; }; - 2B7F47781708365200A106A9 /* shared_array.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45911708365100A106A9 /* shared_array.hpp */; }; - 2B7F47791708365200A106A9 /* shared_array.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45911708365100A106A9 /* shared_array.hpp */; }; - 2B7F477A1708365200A106A9 /* shared_array.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45911708365100A106A9 /* shared_array.hpp */; }; - 2B7F477B1708365200A106A9 /* shared_array.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45911708365100A106A9 /* shared_array.hpp */; }; - 2B7F477C1708365200A106A9 /* shared_array.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45911708365100A106A9 /* shared_array.hpp */; }; - 2B7F477D1708365200A106A9 /* shared_ptr.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45921708365100A106A9 /* shared_ptr.hpp */; }; - 2B7F477E1708365200A106A9 /* shared_ptr.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45921708365100A106A9 /* shared_ptr.hpp */; }; - 2B7F477F1708365200A106A9 /* shared_ptr.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45921708365100A106A9 /* shared_ptr.hpp */; }; - 2B7F47801708365200A106A9 /* shared_ptr.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45921708365100A106A9 /* shared_ptr.hpp */; }; - 2B7F47811708365200A106A9 /* shared_ptr.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45921708365100A106A9 /* shared_ptr.hpp */; }; - 2B7F47821708365200A106A9 /* static_assert.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45931708365100A106A9 /* static_assert.hpp */; }; - 2B7F47831708365200A106A9 /* static_assert.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45931708365100A106A9 /* static_assert.hpp */; }; - 2B7F47841708365200A106A9 /* static_assert.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45931708365100A106A9 /* static_assert.hpp */; }; - 2B7F47851708365200A106A9 /* static_assert.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45931708365100A106A9 /* static_assert.hpp */; }; - 2B7F47861708365200A106A9 /* static_assert.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45931708365100A106A9 /* static_assert.hpp */; }; - 2B7F47871708365200A106A9 /* timer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45941708365100A106A9 /* timer.hpp */; }; - 2B7F47881708365200A106A9 /* timer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45941708365100A106A9 /* timer.hpp */; }; - 2B7F47891708365200A106A9 /* timer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45941708365100A106A9 /* timer.hpp */; }; - 2B7F478A1708365200A106A9 /* timer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45941708365100A106A9 /* timer.hpp */; }; - 2B7F478B1708365200A106A9 /* timer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45941708365100A106A9 /* timer.hpp */; }; - 2B7F478C1708365200A106A9 /* tuple.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45961708365100A106A9 /* tuple.hpp */; }; - 2B7F478D1708365200A106A9 /* tuple.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45961708365100A106A9 /* tuple.hpp */; }; - 2B7F478E1708365200A106A9 /* tuple.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45961708365100A106A9 /* tuple.hpp */; }; - 2B7F478F1708365200A106A9 /* tuple.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45961708365100A106A9 /* tuple.hpp */; }; - 2B7F47901708365200A106A9 /* tuple.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45961708365100A106A9 /* tuple.hpp */; }; - 2B7F479B1708365200A106A9 /* ByteSwapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45991708365100A106A9 /* ByteSwapper.h */; }; - 2B7F479C1708365200A106A9 /* ByteSwapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45991708365100A106A9 /* ByteSwapper.h */; }; - 2B7F479D1708365200A106A9 /* ByteSwapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45991708365100A106A9 /* ByteSwapper.h */; }; - 2B7F479E1708365200A106A9 /* ByteSwapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45991708365100A106A9 /* ByteSwapper.h */; }; - 2B7F479F1708365200A106A9 /* ByteSwapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45991708365100A106A9 /* ByteSwapper.h */; }; - 2B7F47A01708365200A106A9 /* CalcTangentsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F459A1708365100A106A9 /* CalcTangentsProcess.cpp */; }; - 2B7F47A11708365200A106A9 /* CalcTangentsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F459A1708365100A106A9 /* CalcTangentsProcess.cpp */; }; - 2B7F47A21708365200A106A9 /* CalcTangentsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F459A1708365100A106A9 /* CalcTangentsProcess.cpp */; }; - 2B7F47A31708365200A106A9 /* CalcTangentsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F459A1708365100A106A9 /* CalcTangentsProcess.cpp */; }; - 2B7F47A41708365200A106A9 /* CalcTangentsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F459A1708365100A106A9 /* CalcTangentsProcess.cpp */; }; - 2B7F47A51708365200A106A9 /* CalcTangentsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F459B1708365100A106A9 /* CalcTangentsProcess.h */; }; - 2B7F47A61708365200A106A9 /* CalcTangentsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F459B1708365100A106A9 /* CalcTangentsProcess.h */; }; - 2B7F47A71708365200A106A9 /* CalcTangentsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F459B1708365100A106A9 /* CalcTangentsProcess.h */; }; - 2B7F47A81708365200A106A9 /* CalcTangentsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F459B1708365100A106A9 /* CalcTangentsProcess.h */; }; - 2B7F47A91708365200A106A9 /* CalcTangentsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F459B1708365100A106A9 /* CalcTangentsProcess.h */; }; - 2B7F47AA1708365200A106A9 /* CInterfaceIOWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F459C1708365100A106A9 /* CInterfaceIOWrapper.h */; }; - 2B7F47AB1708365200A106A9 /* CInterfaceIOWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F459C1708365100A106A9 /* CInterfaceIOWrapper.h */; }; - 2B7F47AC1708365200A106A9 /* CInterfaceIOWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F459C1708365100A106A9 /* CInterfaceIOWrapper.h */; }; - 2B7F47AD1708365200A106A9 /* CInterfaceIOWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F459C1708365100A106A9 /* CInterfaceIOWrapper.h */; }; - 2B7F47AE1708365200A106A9 /* CInterfaceIOWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F459C1708365100A106A9 /* CInterfaceIOWrapper.h */; }; - 2B7F47BE1708365200A106A9 /* ColladaExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A11708365100A106A9 /* ColladaExporter.cpp */; }; - 2B7F47BF1708365200A106A9 /* ColladaExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A11708365100A106A9 /* ColladaExporter.cpp */; }; - 2B7F47C01708365200A106A9 /* ColladaExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A11708365100A106A9 /* ColladaExporter.cpp */; }; - 2B7F47C11708365200A106A9 /* ColladaExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A11708365100A106A9 /* ColladaExporter.cpp */; }; - 2B7F47C21708365200A106A9 /* ColladaExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A11708365100A106A9 /* ColladaExporter.cpp */; }; - 2B7F47C31708365200A106A9 /* ColladaExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A21708365100A106A9 /* ColladaExporter.h */; }; - 2B7F47C41708365200A106A9 /* ColladaExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A21708365100A106A9 /* ColladaExporter.h */; }; - 2B7F47C51708365200A106A9 /* ColladaExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A21708365100A106A9 /* ColladaExporter.h */; }; - 2B7F47C61708365200A106A9 /* ColladaExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A21708365100A106A9 /* ColladaExporter.h */; }; - 2B7F47C71708365200A106A9 /* ColladaExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A21708365100A106A9 /* ColladaExporter.h */; }; - 2B7F47C81708365200A106A9 /* ColladaHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A31708365100A106A9 /* ColladaHelper.h */; }; - 2B7F47C91708365200A106A9 /* ColladaHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A31708365100A106A9 /* ColladaHelper.h */; }; - 2B7F47CA1708365200A106A9 /* ColladaHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A31708365100A106A9 /* ColladaHelper.h */; }; - 2B7F47CB1708365200A106A9 /* ColladaHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A31708365100A106A9 /* ColladaHelper.h */; }; - 2B7F47CC1708365200A106A9 /* ColladaHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A31708365100A106A9 /* ColladaHelper.h */; }; - 2B7F47CD1708365200A106A9 /* ColladaLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A41708365100A106A9 /* ColladaLoader.cpp */; }; - 2B7F47CE1708365200A106A9 /* ColladaLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A41708365100A106A9 /* ColladaLoader.cpp */; }; - 2B7F47CF1708365200A106A9 /* ColladaLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A41708365100A106A9 /* ColladaLoader.cpp */; }; - 2B7F47D01708365200A106A9 /* ColladaLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A41708365100A106A9 /* ColladaLoader.cpp */; }; - 2B7F47D11708365200A106A9 /* ColladaLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A41708365100A106A9 /* ColladaLoader.cpp */; }; - 2B7F47D21708365200A106A9 /* ColladaLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A51708365100A106A9 /* ColladaLoader.h */; }; - 2B7F47D31708365200A106A9 /* ColladaLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A51708365100A106A9 /* ColladaLoader.h */; }; - 2B7F47D41708365200A106A9 /* ColladaLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A51708365100A106A9 /* ColladaLoader.h */; }; - 2B7F47D51708365200A106A9 /* ColladaLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A51708365100A106A9 /* ColladaLoader.h */; }; - 2B7F47D61708365200A106A9 /* ColladaLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A51708365100A106A9 /* ColladaLoader.h */; }; - 2B7F47D71708365200A106A9 /* ColladaParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A61708365100A106A9 /* ColladaParser.cpp */; }; - 2B7F47D81708365200A106A9 /* ColladaParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A61708365100A106A9 /* ColladaParser.cpp */; }; - 2B7F47D91708365200A106A9 /* ColladaParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A61708365100A106A9 /* ColladaParser.cpp */; }; - 2B7F47DA1708365200A106A9 /* ColladaParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A61708365100A106A9 /* ColladaParser.cpp */; }; - 2B7F47DB1708365200A106A9 /* ColladaParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A61708365100A106A9 /* ColladaParser.cpp */; }; - 2B7F47DC1708365200A106A9 /* ColladaParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A71708365100A106A9 /* ColladaParser.h */; }; - 2B7F47DD1708365200A106A9 /* ColladaParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A71708365100A106A9 /* ColladaParser.h */; }; - 2B7F47DE1708365200A106A9 /* ColladaParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A71708365100A106A9 /* ColladaParser.h */; }; - 2B7F47DF1708365200A106A9 /* ColladaParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A71708365100A106A9 /* ColladaParser.h */; }; - 2B7F47E01708365200A106A9 /* ColladaParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A71708365100A106A9 /* ColladaParser.h */; }; - 2B7F47E11708365200A106A9 /* ComputeUVMappingProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A81708365100A106A9 /* ComputeUVMappingProcess.cpp */; }; - 2B7F47E21708365200A106A9 /* ComputeUVMappingProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A81708365100A106A9 /* ComputeUVMappingProcess.cpp */; }; - 2B7F47E31708365200A106A9 /* ComputeUVMappingProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A81708365100A106A9 /* ComputeUVMappingProcess.cpp */; }; - 2B7F47E41708365200A106A9 /* ComputeUVMappingProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A81708365100A106A9 /* ComputeUVMappingProcess.cpp */; }; - 2B7F47E51708365200A106A9 /* ComputeUVMappingProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45A81708365100A106A9 /* ComputeUVMappingProcess.cpp */; }; - 2B7F47E61708365200A106A9 /* ComputeUVMappingProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A91708365100A106A9 /* ComputeUVMappingProcess.h */; }; - 2B7F47E71708365200A106A9 /* ComputeUVMappingProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A91708365100A106A9 /* ComputeUVMappingProcess.h */; }; - 2B7F47E81708365200A106A9 /* ComputeUVMappingProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A91708365100A106A9 /* ComputeUVMappingProcess.h */; }; - 2B7F47E91708365200A106A9 /* ComputeUVMappingProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A91708365100A106A9 /* ComputeUVMappingProcess.h */; }; - 2B7F47EA1708365200A106A9 /* ComputeUVMappingProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45A91708365100A106A9 /* ComputeUVMappingProcess.h */; }; - 2B7F47EB1708365200A106A9 /* ConvertToLHProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45AA1708365100A106A9 /* ConvertToLHProcess.cpp */; }; - 2B7F47EC1708365200A106A9 /* ConvertToLHProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45AA1708365100A106A9 /* ConvertToLHProcess.cpp */; }; - 2B7F47ED1708365200A106A9 /* ConvertToLHProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45AA1708365100A106A9 /* ConvertToLHProcess.cpp */; }; - 2B7F47EE1708365200A106A9 /* ConvertToLHProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45AA1708365100A106A9 /* ConvertToLHProcess.cpp */; }; - 2B7F47EF1708365200A106A9 /* ConvertToLHProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45AA1708365100A106A9 /* ConvertToLHProcess.cpp */; }; - 2B7F47F01708365200A106A9 /* ConvertToLHProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45AB1708365100A106A9 /* ConvertToLHProcess.h */; }; - 2B7F47F11708365200A106A9 /* ConvertToLHProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45AB1708365100A106A9 /* ConvertToLHProcess.h */; }; - 2B7F47F21708365200A106A9 /* ConvertToLHProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45AB1708365100A106A9 /* ConvertToLHProcess.h */; }; - 2B7F47F31708365200A106A9 /* ConvertToLHProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45AB1708365100A106A9 /* ConvertToLHProcess.h */; }; - 2B7F47F41708365200A106A9 /* ConvertToLHProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45AB1708365100A106A9 /* ConvertToLHProcess.h */; }; - 2B7F47FF1708365200A106A9 /* DeboneProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45AE1708365100A106A9 /* DeboneProcess.cpp */; }; - 2B7F48001708365200A106A9 /* DeboneProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45AE1708365100A106A9 /* DeboneProcess.cpp */; }; - 2B7F48011708365200A106A9 /* DeboneProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45AE1708365100A106A9 /* DeboneProcess.cpp */; }; - 2B7F48021708365200A106A9 /* DeboneProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45AE1708365100A106A9 /* DeboneProcess.cpp */; }; - 2B7F48031708365200A106A9 /* DeboneProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45AE1708365100A106A9 /* DeboneProcess.cpp */; }; - 2B7F48041708365200A106A9 /* DeboneProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45AF1708365100A106A9 /* DeboneProcess.h */; }; - 2B7F48051708365200A106A9 /* DeboneProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45AF1708365100A106A9 /* DeboneProcess.h */; }; - 2B7F48061708365200A106A9 /* DeboneProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45AF1708365100A106A9 /* DeboneProcess.h */; }; - 2B7F48071708365200A106A9 /* DeboneProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45AF1708365100A106A9 /* DeboneProcess.h */; }; - 2B7F48081708365200A106A9 /* DeboneProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45AF1708365100A106A9 /* DeboneProcess.h */; }; - 2B7F48091708365200A106A9 /* DefaultIOStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45B01708365100A106A9 /* DefaultIOStream.cpp */; }; - 2B7F480A1708365200A106A9 /* DefaultIOStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45B01708365100A106A9 /* DefaultIOStream.cpp */; }; - 2B7F480B1708365200A106A9 /* DefaultIOStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45B01708365100A106A9 /* DefaultIOStream.cpp */; }; - 2B7F480C1708365200A106A9 /* DefaultIOStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45B01708365100A106A9 /* DefaultIOStream.cpp */; }; - 2B7F480D1708365200A106A9 /* DefaultIOStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45B01708365100A106A9 /* DefaultIOStream.cpp */; }; - 2B7F480E1708365200A106A9 /* DefaultIOStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B11708365100A106A9 /* DefaultIOStream.h */; }; - 2B7F480F1708365200A106A9 /* DefaultIOStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B11708365100A106A9 /* DefaultIOStream.h */; }; - 2B7F48101708365200A106A9 /* DefaultIOStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B11708365100A106A9 /* DefaultIOStream.h */; }; - 2B7F48111708365200A106A9 /* DefaultIOStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B11708365100A106A9 /* DefaultIOStream.h */; }; - 2B7F48121708365200A106A9 /* DefaultIOStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B11708365100A106A9 /* DefaultIOStream.h */; }; - 2B7F48131708365200A106A9 /* DefaultIOSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45B21708365100A106A9 /* DefaultIOSystem.cpp */; }; - 2B7F48141708365200A106A9 /* DefaultIOSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45B21708365100A106A9 /* DefaultIOSystem.cpp */; }; - 2B7F48151708365200A106A9 /* DefaultIOSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45B21708365100A106A9 /* DefaultIOSystem.cpp */; }; - 2B7F48161708365200A106A9 /* DefaultIOSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45B21708365100A106A9 /* DefaultIOSystem.cpp */; }; - 2B7F48171708365200A106A9 /* DefaultIOSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45B21708365100A106A9 /* DefaultIOSystem.cpp */; }; - 2B7F48181708365200A106A9 /* DefaultIOSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B31708365100A106A9 /* DefaultIOSystem.h */; }; - 2B7F48191708365200A106A9 /* DefaultIOSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B31708365100A106A9 /* DefaultIOSystem.h */; }; - 2B7F481A1708365200A106A9 /* DefaultIOSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B31708365100A106A9 /* DefaultIOSystem.h */; }; - 2B7F481B1708365200A106A9 /* DefaultIOSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B31708365100A106A9 /* DefaultIOSystem.h */; }; - 2B7F481C1708365200A106A9 /* DefaultIOSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B31708365100A106A9 /* DefaultIOSystem.h */; }; - 2B7F481D1708365200A106A9 /* DefaultLogger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45B41708365100A106A9 /* DefaultLogger.cpp */; }; - 2B7F481E1708365200A106A9 /* DefaultLogger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45B41708365100A106A9 /* DefaultLogger.cpp */; }; - 2B7F481F1708365200A106A9 /* DefaultLogger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45B41708365100A106A9 /* DefaultLogger.cpp */; }; - 2B7F48201708365200A106A9 /* DefaultLogger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45B41708365100A106A9 /* DefaultLogger.cpp */; }; - 2B7F48211708365200A106A9 /* DefaultLogger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45B41708365100A106A9 /* DefaultLogger.cpp */; }; - 2B7F48221708365200A106A9 /* DefaultProgressHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B51708365100A106A9 /* DefaultProgressHandler.h */; }; - 2B7F48231708365200A106A9 /* DefaultProgressHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B51708365100A106A9 /* DefaultProgressHandler.h */; }; - 2B7F48241708365200A106A9 /* DefaultProgressHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B51708365100A106A9 /* DefaultProgressHandler.h */; }; - 2B7F48251708365200A106A9 /* DefaultProgressHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B51708365100A106A9 /* DefaultProgressHandler.h */; }; - 2B7F48261708365200A106A9 /* DefaultProgressHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B51708365100A106A9 /* DefaultProgressHandler.h */; }; - 2B7F48361708365200A106A9 /* Exceptional.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B91708365100A106A9 /* Exceptional.h */; }; - 2B7F48371708365200A106A9 /* Exceptional.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B91708365100A106A9 /* Exceptional.h */; }; - 2B7F48381708365200A106A9 /* Exceptional.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B91708365100A106A9 /* Exceptional.h */; }; - 2B7F48391708365200A106A9 /* Exceptional.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B91708365100A106A9 /* Exceptional.h */; }; - 2B7F483A1708365200A106A9 /* Exceptional.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45B91708365100A106A9 /* Exceptional.h */; }; - 2B7F483B1708365200A106A9 /* Exporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BA1708365100A106A9 /* Exporter.cpp */; }; - 2B7F483C1708365200A106A9 /* Exporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BA1708365100A106A9 /* Exporter.cpp */; }; - 2B7F483D1708365200A106A9 /* Exporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BA1708365100A106A9 /* Exporter.cpp */; }; - 2B7F483E1708365200A106A9 /* Exporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BA1708365100A106A9 /* Exporter.cpp */; }; - 2B7F483F1708365200A106A9 /* Exporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BA1708365100A106A9 /* Exporter.cpp */; }; - 2B7F48401708365200A106A9 /* fast_atof.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45BB1708365100A106A9 /* fast_atof.h */; }; - 2B7F48411708365200A106A9 /* fast_atof.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45BB1708365100A106A9 /* fast_atof.h */; }; - 2B7F48421708365200A106A9 /* fast_atof.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45BB1708365100A106A9 /* fast_atof.h */; }; - 2B7F48431708365200A106A9 /* fast_atof.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45BB1708365100A106A9 /* fast_atof.h */; }; - 2B7F48441708365200A106A9 /* fast_atof.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45BB1708365100A106A9 /* fast_atof.h */; }; - 2B7F48451708365200A106A9 /* FBXAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BC1708365100A106A9 /* FBXAnimation.cpp */; }; - 2B7F48461708365200A106A9 /* FBXAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BC1708365100A106A9 /* FBXAnimation.cpp */; }; - 2B7F48471708365200A106A9 /* FBXAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BC1708365100A106A9 /* FBXAnimation.cpp */; }; - 2B7F48481708365200A106A9 /* FBXAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BC1708365100A106A9 /* FBXAnimation.cpp */; }; - 2B7F48491708365200A106A9 /* FBXAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BC1708365100A106A9 /* FBXAnimation.cpp */; }; - 2B7F484A1708365200A106A9 /* FBXBinaryTokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BD1708365100A106A9 /* FBXBinaryTokenizer.cpp */; }; - 2B7F484B1708365200A106A9 /* FBXBinaryTokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BD1708365100A106A9 /* FBXBinaryTokenizer.cpp */; }; - 2B7F484C1708365200A106A9 /* FBXBinaryTokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BD1708365100A106A9 /* FBXBinaryTokenizer.cpp */; }; - 2B7F484D1708365200A106A9 /* FBXBinaryTokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BD1708365100A106A9 /* FBXBinaryTokenizer.cpp */; }; - 2B7F484E1708365200A106A9 /* FBXBinaryTokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BD1708365100A106A9 /* FBXBinaryTokenizer.cpp */; }; - 2B7F484F1708365200A106A9 /* FBXCompileConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45BE1708365100A106A9 /* FBXCompileConfig.h */; }; - 2B7F48501708365200A106A9 /* FBXCompileConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45BE1708365100A106A9 /* FBXCompileConfig.h */; }; - 2B7F48511708365200A106A9 /* FBXCompileConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45BE1708365100A106A9 /* FBXCompileConfig.h */; }; - 2B7F48521708365200A106A9 /* FBXCompileConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45BE1708365100A106A9 /* FBXCompileConfig.h */; }; - 2B7F48531708365200A106A9 /* FBXCompileConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45BE1708365100A106A9 /* FBXCompileConfig.h */; }; - 2B7F48541708365200A106A9 /* FBXConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BF1708365100A106A9 /* FBXConverter.cpp */; }; - 2B7F48551708365200A106A9 /* FBXConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BF1708365100A106A9 /* FBXConverter.cpp */; }; - 2B7F48561708365200A106A9 /* FBXConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BF1708365100A106A9 /* FBXConverter.cpp */; }; - 2B7F48571708365200A106A9 /* FBXConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BF1708365100A106A9 /* FBXConverter.cpp */; }; - 2B7F48581708365200A106A9 /* FBXConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45BF1708365100A106A9 /* FBXConverter.cpp */; }; - 2B7F48591708365200A106A9 /* FBXConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C01708365100A106A9 /* FBXConverter.h */; }; - 2B7F485A1708365200A106A9 /* FBXConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C01708365100A106A9 /* FBXConverter.h */; }; - 2B7F485B1708365200A106A9 /* FBXConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C01708365100A106A9 /* FBXConverter.h */; }; - 2B7F485C1708365200A106A9 /* FBXConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C01708365100A106A9 /* FBXConverter.h */; }; - 2B7F485D1708365200A106A9 /* FBXConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C01708365100A106A9 /* FBXConverter.h */; }; - 2B7F485E1708365200A106A9 /* FBXDeformer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C11708365100A106A9 /* FBXDeformer.cpp */; }; - 2B7F485F1708365200A106A9 /* FBXDeformer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C11708365100A106A9 /* FBXDeformer.cpp */; }; - 2B7F48601708365200A106A9 /* FBXDeformer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C11708365100A106A9 /* FBXDeformer.cpp */; }; - 2B7F48611708365200A106A9 /* FBXDeformer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C11708365100A106A9 /* FBXDeformer.cpp */; }; - 2B7F48621708365200A106A9 /* FBXDeformer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C11708365100A106A9 /* FBXDeformer.cpp */; }; - 2B7F48631708365200A106A9 /* FBXDocument.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C21708365100A106A9 /* FBXDocument.cpp */; }; - 2B7F48641708365200A106A9 /* FBXDocument.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C21708365100A106A9 /* FBXDocument.cpp */; }; - 2B7F48651708365200A106A9 /* FBXDocument.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C21708365100A106A9 /* FBXDocument.cpp */; }; - 2B7F48661708365200A106A9 /* FBXDocument.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C21708365100A106A9 /* FBXDocument.cpp */; }; - 2B7F48671708365200A106A9 /* FBXDocument.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C21708365100A106A9 /* FBXDocument.cpp */; }; - 2B7F48681708365200A106A9 /* FBXDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C31708365100A106A9 /* FBXDocument.h */; }; - 2B7F48691708365200A106A9 /* FBXDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C31708365100A106A9 /* FBXDocument.h */; }; - 2B7F486A1708365200A106A9 /* FBXDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C31708365100A106A9 /* FBXDocument.h */; }; - 2B7F486B1708365200A106A9 /* FBXDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C31708365100A106A9 /* FBXDocument.h */; }; - 2B7F486C1708365200A106A9 /* FBXDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C31708365100A106A9 /* FBXDocument.h */; }; - 2B7F486D1708365200A106A9 /* FBXDocumentUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C41708365100A106A9 /* FBXDocumentUtil.cpp */; }; - 2B7F486E1708365200A106A9 /* FBXDocumentUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C41708365100A106A9 /* FBXDocumentUtil.cpp */; }; - 2B7F486F1708365200A106A9 /* FBXDocumentUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C41708365100A106A9 /* FBXDocumentUtil.cpp */; }; - 2B7F48701708365200A106A9 /* FBXDocumentUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C41708365100A106A9 /* FBXDocumentUtil.cpp */; }; - 2B7F48711708365200A106A9 /* FBXDocumentUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C41708365100A106A9 /* FBXDocumentUtil.cpp */; }; - 2B7F48721708365200A106A9 /* FBXDocumentUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C51708365100A106A9 /* FBXDocumentUtil.h */; }; - 2B7F48731708365200A106A9 /* FBXDocumentUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C51708365100A106A9 /* FBXDocumentUtil.h */; }; - 2B7F48741708365200A106A9 /* FBXDocumentUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C51708365100A106A9 /* FBXDocumentUtil.h */; }; - 2B7F48751708365200A106A9 /* FBXDocumentUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C51708365100A106A9 /* FBXDocumentUtil.h */; }; - 2B7F48761708365200A106A9 /* FBXDocumentUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C51708365100A106A9 /* FBXDocumentUtil.h */; }; - 2B7F48771708365200A106A9 /* FBXImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C61708365100A106A9 /* FBXImporter.cpp */; }; - 2B7F48781708365200A106A9 /* FBXImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C61708365100A106A9 /* FBXImporter.cpp */; }; - 2B7F48791708365200A106A9 /* FBXImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C61708365100A106A9 /* FBXImporter.cpp */; }; - 2B7F487A1708365200A106A9 /* FBXImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C61708365100A106A9 /* FBXImporter.cpp */; }; - 2B7F487B1708365200A106A9 /* FBXImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C61708365100A106A9 /* FBXImporter.cpp */; }; - 2B7F487C1708365200A106A9 /* FBXImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C71708365100A106A9 /* FBXImporter.h */; }; - 2B7F487D1708365200A106A9 /* FBXImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C71708365100A106A9 /* FBXImporter.h */; }; - 2B7F487E1708365200A106A9 /* FBXImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C71708365100A106A9 /* FBXImporter.h */; }; - 2B7F487F1708365200A106A9 /* FBXImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C71708365100A106A9 /* FBXImporter.h */; }; - 2B7F48801708365200A106A9 /* FBXImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C71708365100A106A9 /* FBXImporter.h */; }; - 2B7F48811708365200A106A9 /* FBXImportSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C81708365100A106A9 /* FBXImportSettings.h */; }; - 2B7F48821708365200A106A9 /* FBXImportSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C81708365100A106A9 /* FBXImportSettings.h */; }; - 2B7F48831708365200A106A9 /* FBXImportSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C81708365100A106A9 /* FBXImportSettings.h */; }; - 2B7F48841708365200A106A9 /* FBXImportSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C81708365100A106A9 /* FBXImportSettings.h */; }; - 2B7F48851708365200A106A9 /* FBXImportSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45C81708365100A106A9 /* FBXImportSettings.h */; }; - 2B7F48861708365200A106A9 /* FBXMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C91708365100A106A9 /* FBXMaterial.cpp */; }; - 2B7F48871708365200A106A9 /* FBXMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C91708365100A106A9 /* FBXMaterial.cpp */; }; - 2B7F48881708365200A106A9 /* FBXMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C91708365100A106A9 /* FBXMaterial.cpp */; }; - 2B7F48891708365200A106A9 /* FBXMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C91708365100A106A9 /* FBXMaterial.cpp */; }; - 2B7F488A1708365200A106A9 /* FBXMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45C91708365100A106A9 /* FBXMaterial.cpp */; }; - 2B7F488B1708365200A106A9 /* FBXMeshGeometry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CA1708365100A106A9 /* FBXMeshGeometry.cpp */; }; - 2B7F488C1708365200A106A9 /* FBXMeshGeometry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CA1708365100A106A9 /* FBXMeshGeometry.cpp */; }; - 2B7F488D1708365200A106A9 /* FBXMeshGeometry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CA1708365100A106A9 /* FBXMeshGeometry.cpp */; }; - 2B7F488E1708365200A106A9 /* FBXMeshGeometry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CA1708365100A106A9 /* FBXMeshGeometry.cpp */; }; - 2B7F488F1708365200A106A9 /* FBXMeshGeometry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CA1708365100A106A9 /* FBXMeshGeometry.cpp */; }; - 2B7F48901708365200A106A9 /* FBXModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CB1708365100A106A9 /* FBXModel.cpp */; }; - 2B7F48911708365200A106A9 /* FBXModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CB1708365100A106A9 /* FBXModel.cpp */; }; - 2B7F48921708365200A106A9 /* FBXModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CB1708365100A106A9 /* FBXModel.cpp */; }; - 2B7F48931708365200A106A9 /* FBXModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CB1708365100A106A9 /* FBXModel.cpp */; }; - 2B7F48941708365200A106A9 /* FBXModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CB1708365100A106A9 /* FBXModel.cpp */; }; - 2B7F48951708365200A106A9 /* FBXNodeAttribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CC1708365100A106A9 /* FBXNodeAttribute.cpp */; }; - 2B7F48961708365200A106A9 /* FBXNodeAttribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CC1708365100A106A9 /* FBXNodeAttribute.cpp */; }; - 2B7F48971708365200A106A9 /* FBXNodeAttribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CC1708365100A106A9 /* FBXNodeAttribute.cpp */; }; - 2B7F48981708365200A106A9 /* FBXNodeAttribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CC1708365100A106A9 /* FBXNodeAttribute.cpp */; }; - 2B7F48991708365200A106A9 /* FBXNodeAttribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CC1708365100A106A9 /* FBXNodeAttribute.cpp */; }; - 2B7F489A1708365200A106A9 /* FBXParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CD1708365100A106A9 /* FBXParser.cpp */; }; - 2B7F489B1708365200A106A9 /* FBXParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CD1708365100A106A9 /* FBXParser.cpp */; }; - 2B7F489C1708365200A106A9 /* FBXParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CD1708365100A106A9 /* FBXParser.cpp */; }; - 2B7F489D1708365200A106A9 /* FBXParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CD1708365100A106A9 /* FBXParser.cpp */; }; - 2B7F489E1708365200A106A9 /* FBXParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CD1708365100A106A9 /* FBXParser.cpp */; }; - 2B7F489F1708365200A106A9 /* FBXParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45CE1708365100A106A9 /* FBXParser.h */; }; - 2B7F48A01708365200A106A9 /* FBXParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45CE1708365100A106A9 /* FBXParser.h */; }; - 2B7F48A11708365200A106A9 /* FBXParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45CE1708365100A106A9 /* FBXParser.h */; }; - 2B7F48A21708365200A106A9 /* FBXParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45CE1708365100A106A9 /* FBXParser.h */; }; - 2B7F48A31708365200A106A9 /* FBXParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45CE1708365100A106A9 /* FBXParser.h */; }; - 2B7F48A41708365200A106A9 /* FBXProperties.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CF1708365100A106A9 /* FBXProperties.cpp */; }; - 2B7F48A51708365200A106A9 /* FBXProperties.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CF1708365100A106A9 /* FBXProperties.cpp */; }; - 2B7F48A61708365200A106A9 /* FBXProperties.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CF1708365100A106A9 /* FBXProperties.cpp */; }; - 2B7F48A71708365200A106A9 /* FBXProperties.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CF1708365100A106A9 /* FBXProperties.cpp */; }; - 2B7F48A81708365200A106A9 /* FBXProperties.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45CF1708365100A106A9 /* FBXProperties.cpp */; }; - 2B7F48A91708365200A106A9 /* FBXProperties.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D01708365100A106A9 /* FBXProperties.h */; }; - 2B7F48AA1708365200A106A9 /* FBXProperties.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D01708365100A106A9 /* FBXProperties.h */; }; - 2B7F48AB1708365200A106A9 /* FBXProperties.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D01708365100A106A9 /* FBXProperties.h */; }; - 2B7F48AC1708365200A106A9 /* FBXProperties.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D01708365100A106A9 /* FBXProperties.h */; }; - 2B7F48AD1708365200A106A9 /* FBXProperties.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D01708365100A106A9 /* FBXProperties.h */; }; - 2B7F48AE1708365200A106A9 /* FBXTokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D11708365100A106A9 /* FBXTokenizer.cpp */; }; - 2B7F48AF1708365200A106A9 /* FBXTokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D11708365100A106A9 /* FBXTokenizer.cpp */; }; - 2B7F48B01708365200A106A9 /* FBXTokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D11708365100A106A9 /* FBXTokenizer.cpp */; }; - 2B7F48B11708365200A106A9 /* FBXTokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D11708365100A106A9 /* FBXTokenizer.cpp */; }; - 2B7F48B21708365200A106A9 /* FBXTokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D11708365100A106A9 /* FBXTokenizer.cpp */; }; - 2B7F48B31708365200A106A9 /* FBXTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D21708365100A106A9 /* FBXTokenizer.h */; }; - 2B7F48B41708365200A106A9 /* FBXTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D21708365100A106A9 /* FBXTokenizer.h */; }; - 2B7F48B51708365200A106A9 /* FBXTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D21708365100A106A9 /* FBXTokenizer.h */; }; - 2B7F48B61708365200A106A9 /* FBXTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D21708365100A106A9 /* FBXTokenizer.h */; }; - 2B7F48B71708365200A106A9 /* FBXTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D21708365100A106A9 /* FBXTokenizer.h */; }; - 2B7F48B81708365200A106A9 /* FBXUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D31708365100A106A9 /* FBXUtil.cpp */; }; - 2B7F48B91708365200A106A9 /* FBXUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D31708365100A106A9 /* FBXUtil.cpp */; }; - 2B7F48BA1708365200A106A9 /* FBXUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D31708365100A106A9 /* FBXUtil.cpp */; }; - 2B7F48BB1708365200A106A9 /* FBXUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D31708365100A106A9 /* FBXUtil.cpp */; }; - 2B7F48BC1708365200A106A9 /* FBXUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D31708365100A106A9 /* FBXUtil.cpp */; }; - 2B7F48BD1708365200A106A9 /* FBXUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D41708365100A106A9 /* FBXUtil.h */; }; - 2B7F48BE1708365200A106A9 /* FBXUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D41708365100A106A9 /* FBXUtil.h */; }; - 2B7F48BF1708365200A106A9 /* FBXUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D41708365100A106A9 /* FBXUtil.h */; }; - 2B7F48C01708365200A106A9 /* FBXUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D41708365100A106A9 /* FBXUtil.h */; }; - 2B7F48C11708365200A106A9 /* FBXUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D41708365100A106A9 /* FBXUtil.h */; }; - 2B7F48C21708365200A106A9 /* FileLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D51708365100A106A9 /* FileLogStream.h */; }; - 2B7F48C31708365200A106A9 /* FileLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D51708365100A106A9 /* FileLogStream.h */; }; - 2B7F48C41708365200A106A9 /* FileLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D51708365100A106A9 /* FileLogStream.h */; }; - 2B7F48C51708365200A106A9 /* FileLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D51708365100A106A9 /* FileLogStream.h */; }; - 2B7F48C61708365200A106A9 /* FileLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D51708365100A106A9 /* FileLogStream.h */; }; - 2B7F48C71708365200A106A9 /* FileSystemFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D61708365100A106A9 /* FileSystemFilter.h */; }; - 2B7F48C81708365200A106A9 /* FileSystemFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D61708365100A106A9 /* FileSystemFilter.h */; }; - 2B7F48C91708365200A106A9 /* FileSystemFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D61708365100A106A9 /* FileSystemFilter.h */; }; - 2B7F48CA1708365200A106A9 /* FileSystemFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D61708365100A106A9 /* FileSystemFilter.h */; }; - 2B7F48CB1708365200A106A9 /* FileSystemFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D61708365100A106A9 /* FileSystemFilter.h */; }; - 2B7F48CC1708365200A106A9 /* FindDegenerates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D71708365100A106A9 /* FindDegenerates.cpp */; }; - 2B7F48CD1708365200A106A9 /* FindDegenerates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D71708365100A106A9 /* FindDegenerates.cpp */; }; - 2B7F48CE1708365200A106A9 /* FindDegenerates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D71708365100A106A9 /* FindDegenerates.cpp */; }; - 2B7F48CF1708365200A106A9 /* FindDegenerates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D71708365100A106A9 /* FindDegenerates.cpp */; }; - 2B7F48D01708365200A106A9 /* FindDegenerates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D71708365100A106A9 /* FindDegenerates.cpp */; }; - 2B7F48D11708365200A106A9 /* FindDegenerates.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D81708365100A106A9 /* FindDegenerates.h */; }; - 2B7F48D21708365200A106A9 /* FindDegenerates.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D81708365100A106A9 /* FindDegenerates.h */; }; - 2B7F48D31708365200A106A9 /* FindDegenerates.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D81708365100A106A9 /* FindDegenerates.h */; }; - 2B7F48D41708365200A106A9 /* FindDegenerates.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D81708365100A106A9 /* FindDegenerates.h */; }; - 2B7F48D51708365200A106A9 /* FindDegenerates.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45D81708365100A106A9 /* FindDegenerates.h */; }; - 2B7F48D61708365200A106A9 /* FindInstancesProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D91708365100A106A9 /* FindInstancesProcess.cpp */; }; - 2B7F48D71708365200A106A9 /* FindInstancesProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D91708365100A106A9 /* FindInstancesProcess.cpp */; }; - 2B7F48D81708365200A106A9 /* FindInstancesProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D91708365100A106A9 /* FindInstancesProcess.cpp */; }; - 2B7F48D91708365200A106A9 /* FindInstancesProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D91708365100A106A9 /* FindInstancesProcess.cpp */; }; - 2B7F48DA1708365200A106A9 /* FindInstancesProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45D91708365100A106A9 /* FindInstancesProcess.cpp */; }; - 2B7F48DB1708365200A106A9 /* FindInstancesProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DA1708365100A106A9 /* FindInstancesProcess.h */; }; - 2B7F48DC1708365200A106A9 /* FindInstancesProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DA1708365100A106A9 /* FindInstancesProcess.h */; }; - 2B7F48DD1708365200A106A9 /* FindInstancesProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DA1708365100A106A9 /* FindInstancesProcess.h */; }; - 2B7F48DE1708365200A106A9 /* FindInstancesProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DA1708365100A106A9 /* FindInstancesProcess.h */; }; - 2B7F48DF1708365200A106A9 /* FindInstancesProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DA1708365100A106A9 /* FindInstancesProcess.h */; }; - 2B7F48E01708365200A106A9 /* FindInvalidDataProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45DB1708365100A106A9 /* FindInvalidDataProcess.cpp */; }; - 2B7F48E11708365200A106A9 /* FindInvalidDataProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45DB1708365100A106A9 /* FindInvalidDataProcess.cpp */; }; - 2B7F48E21708365200A106A9 /* FindInvalidDataProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45DB1708365100A106A9 /* FindInvalidDataProcess.cpp */; }; - 2B7F48E31708365200A106A9 /* FindInvalidDataProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45DB1708365100A106A9 /* FindInvalidDataProcess.cpp */; }; - 2B7F48E41708365200A106A9 /* FindInvalidDataProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45DB1708365100A106A9 /* FindInvalidDataProcess.cpp */; }; - 2B7F48E51708365200A106A9 /* FindInvalidDataProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DC1708365100A106A9 /* FindInvalidDataProcess.h */; }; - 2B7F48E61708365200A106A9 /* FindInvalidDataProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DC1708365100A106A9 /* FindInvalidDataProcess.h */; }; - 2B7F48E71708365200A106A9 /* FindInvalidDataProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DC1708365100A106A9 /* FindInvalidDataProcess.h */; }; - 2B7F48E81708365200A106A9 /* FindInvalidDataProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DC1708365100A106A9 /* FindInvalidDataProcess.h */; }; - 2B7F48E91708365200A106A9 /* FindInvalidDataProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DC1708365100A106A9 /* FindInvalidDataProcess.h */; }; - 2B7F48EA1708365200A106A9 /* FixNormalsStep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45DD1708365100A106A9 /* FixNormalsStep.cpp */; }; - 2B7F48EB1708365200A106A9 /* FixNormalsStep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45DD1708365100A106A9 /* FixNormalsStep.cpp */; }; - 2B7F48EC1708365200A106A9 /* FixNormalsStep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45DD1708365100A106A9 /* FixNormalsStep.cpp */; }; - 2B7F48ED1708365200A106A9 /* FixNormalsStep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45DD1708365100A106A9 /* FixNormalsStep.cpp */; }; - 2B7F48EE1708365200A106A9 /* FixNormalsStep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45DD1708365100A106A9 /* FixNormalsStep.cpp */; }; - 2B7F48EF1708365200A106A9 /* FixNormalsStep.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DE1708365100A106A9 /* FixNormalsStep.h */; }; - 2B7F48F01708365200A106A9 /* FixNormalsStep.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DE1708365100A106A9 /* FixNormalsStep.h */; }; - 2B7F48F11708365200A106A9 /* FixNormalsStep.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DE1708365100A106A9 /* FixNormalsStep.h */; }; - 2B7F48F21708365200A106A9 /* FixNormalsStep.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DE1708365100A106A9 /* FixNormalsStep.h */; }; - 2B7F48F31708365200A106A9 /* FixNormalsStep.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DE1708365100A106A9 /* FixNormalsStep.h */; }; - 2B7F48F41708365200A106A9 /* GenericProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DF1708365100A106A9 /* GenericProperty.h */; }; - 2B7F48F51708365200A106A9 /* GenericProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DF1708365100A106A9 /* GenericProperty.h */; }; - 2B7F48F61708365200A106A9 /* GenericProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DF1708365100A106A9 /* GenericProperty.h */; }; - 2B7F48F71708365200A106A9 /* GenericProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DF1708365100A106A9 /* GenericProperty.h */; }; - 2B7F48F81708365200A106A9 /* GenericProperty.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45DF1708365100A106A9 /* GenericProperty.h */; }; - 2B7F48F91708365200A106A9 /* GenFaceNormalsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45E01708365100A106A9 /* GenFaceNormalsProcess.cpp */; }; - 2B7F48FA1708365200A106A9 /* GenFaceNormalsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45E01708365100A106A9 /* GenFaceNormalsProcess.cpp */; }; - 2B7F48FB1708365200A106A9 /* GenFaceNormalsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45E01708365100A106A9 /* GenFaceNormalsProcess.cpp */; }; - 2B7F48FC1708365200A106A9 /* GenFaceNormalsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45E01708365100A106A9 /* GenFaceNormalsProcess.cpp */; }; - 2B7F48FD1708365200A106A9 /* GenFaceNormalsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45E01708365100A106A9 /* GenFaceNormalsProcess.cpp */; }; - 2B7F48FE1708365200A106A9 /* GenFaceNormalsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45E11708365100A106A9 /* GenFaceNormalsProcess.h */; }; - 2B7F48FF1708365200A106A9 /* GenFaceNormalsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45E11708365100A106A9 /* GenFaceNormalsProcess.h */; }; - 2B7F49001708365200A106A9 /* GenFaceNormalsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45E11708365100A106A9 /* GenFaceNormalsProcess.h */; }; - 2B7F49011708365200A106A9 /* GenFaceNormalsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45E11708365100A106A9 /* GenFaceNormalsProcess.h */; }; - 2B7F49021708365200A106A9 /* GenFaceNormalsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45E11708365100A106A9 /* GenFaceNormalsProcess.h */; }; - 2B7F49031708365200A106A9 /* GenVertexNormalsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45E21708365100A106A9 /* GenVertexNormalsProcess.cpp */; }; - 2B7F49041708365200A106A9 /* GenVertexNormalsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45E21708365100A106A9 /* GenVertexNormalsProcess.cpp */; }; - 2B7F49051708365200A106A9 /* GenVertexNormalsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45E21708365100A106A9 /* GenVertexNormalsProcess.cpp */; }; - 2B7F49061708365200A106A9 /* GenVertexNormalsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45E21708365100A106A9 /* GenVertexNormalsProcess.cpp */; }; - 2B7F49071708365200A106A9 /* GenVertexNormalsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45E21708365100A106A9 /* GenVertexNormalsProcess.cpp */; }; - 2B7F49081708365200A106A9 /* GenVertexNormalsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45E31708365100A106A9 /* GenVertexNormalsProcess.h */; }; - 2B7F49091708365200A106A9 /* GenVertexNormalsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45E31708365100A106A9 /* GenVertexNormalsProcess.h */; }; - 2B7F490A1708365200A106A9 /* GenVertexNormalsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45E31708365100A106A9 /* GenVertexNormalsProcess.h */; }; - 2B7F490B1708365200A106A9 /* GenVertexNormalsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45E31708365100A106A9 /* GenVertexNormalsProcess.h */; }; - 2B7F490C1708365200A106A9 /* GenVertexNormalsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45E31708365100A106A9 /* GenVertexNormalsProcess.h */; }; - 2B7F49121708365200A106A9 /* Hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45E51708365100A106A9 /* Hash.h */; }; - 2B7F49131708365200A106A9 /* Hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45E51708365100A106A9 /* Hash.h */; }; - 2B7F49141708365200A106A9 /* Hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45E51708365100A106A9 /* Hash.h */; }; - 2B7F49151708365200A106A9 /* Hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45E51708365100A106A9 /* Hash.h */; }; - 2B7F49161708365200A106A9 /* Hash.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45E51708365100A106A9 /* Hash.h */; }; - 2B7F49261708365200A106A9 /* IFCBoolean.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45E91708365100A106A9 /* IFCBoolean.cpp */; }; - 2B7F49271708365200A106A9 /* IFCBoolean.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45E91708365100A106A9 /* IFCBoolean.cpp */; }; - 2B7F49281708365200A106A9 /* IFCBoolean.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45E91708365100A106A9 /* IFCBoolean.cpp */; }; - 2B7F49291708365200A106A9 /* IFCBoolean.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45E91708365100A106A9 /* IFCBoolean.cpp */; }; - 2B7F492A1708365200A106A9 /* IFCBoolean.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45E91708365100A106A9 /* IFCBoolean.cpp */; }; - 2B7F492B1708365200A106A9 /* IFCCurve.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EA1708365100A106A9 /* IFCCurve.cpp */; }; - 2B7F492C1708365200A106A9 /* IFCCurve.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EA1708365100A106A9 /* IFCCurve.cpp */; }; - 2B7F492D1708365200A106A9 /* IFCCurve.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EA1708365100A106A9 /* IFCCurve.cpp */; }; - 2B7F492E1708365200A106A9 /* IFCCurve.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EA1708365100A106A9 /* IFCCurve.cpp */; }; - 2B7F492F1708365200A106A9 /* IFCCurve.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EA1708365100A106A9 /* IFCCurve.cpp */; }; - 2B7F49301708365200A106A9 /* IFCGeometry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EB1708365100A106A9 /* IFCGeometry.cpp */; }; - 2B7F49311708365200A106A9 /* IFCGeometry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EB1708365100A106A9 /* IFCGeometry.cpp */; }; - 2B7F49321708365200A106A9 /* IFCGeometry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EB1708365100A106A9 /* IFCGeometry.cpp */; }; - 2B7F49331708365200A106A9 /* IFCGeometry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EB1708365100A106A9 /* IFCGeometry.cpp */; }; - 2B7F49341708365200A106A9 /* IFCGeometry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EB1708365100A106A9 /* IFCGeometry.cpp */; }; - 2B7F49351708365200A106A9 /* IFCLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EC1708365100A106A9 /* IFCLoader.cpp */; }; - 2B7F49361708365200A106A9 /* IFCLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EC1708365100A106A9 /* IFCLoader.cpp */; }; - 2B7F49371708365200A106A9 /* IFCLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EC1708365100A106A9 /* IFCLoader.cpp */; }; - 2B7F49381708365200A106A9 /* IFCLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EC1708365100A106A9 /* IFCLoader.cpp */; }; - 2B7F49391708365200A106A9 /* IFCLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EC1708365100A106A9 /* IFCLoader.cpp */; }; - 2B7F493A1708365200A106A9 /* IFCLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45ED1708365100A106A9 /* IFCLoader.h */; }; - 2B7F493B1708365200A106A9 /* IFCLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45ED1708365100A106A9 /* IFCLoader.h */; }; - 2B7F493C1708365200A106A9 /* IFCLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45ED1708365100A106A9 /* IFCLoader.h */; }; - 2B7F493D1708365200A106A9 /* IFCLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45ED1708365100A106A9 /* IFCLoader.h */; }; - 2B7F493E1708365200A106A9 /* IFCLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45ED1708365100A106A9 /* IFCLoader.h */; }; - 2B7F493F1708365200A106A9 /* IFCMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EE1708365100A106A9 /* IFCMaterial.cpp */; }; - 2B7F49401708365200A106A9 /* IFCMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EE1708365100A106A9 /* IFCMaterial.cpp */; }; - 2B7F49411708365200A106A9 /* IFCMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EE1708365100A106A9 /* IFCMaterial.cpp */; }; - 2B7F49421708365200A106A9 /* IFCMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EE1708365100A106A9 /* IFCMaterial.cpp */; }; - 2B7F49431708365200A106A9 /* IFCMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EE1708365100A106A9 /* IFCMaterial.cpp */; }; - 2B7F49441708365200A106A9 /* IFCOpenings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EF1708365100A106A9 /* IFCOpenings.cpp */; }; - 2B7F49451708365200A106A9 /* IFCOpenings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EF1708365100A106A9 /* IFCOpenings.cpp */; }; - 2B7F49461708365200A106A9 /* IFCOpenings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EF1708365100A106A9 /* IFCOpenings.cpp */; }; - 2B7F49471708365200A106A9 /* IFCOpenings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EF1708365100A106A9 /* IFCOpenings.cpp */; }; - 2B7F49481708365200A106A9 /* IFCOpenings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45EF1708365100A106A9 /* IFCOpenings.cpp */; }; - 2B7F49491708365200A106A9 /* IFCProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F01708365100A106A9 /* IFCProfile.cpp */; }; - 2B7F494A1708365200A106A9 /* IFCProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F01708365100A106A9 /* IFCProfile.cpp */; }; - 2B7F494B1708365200A106A9 /* IFCProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F01708365100A106A9 /* IFCProfile.cpp */; }; - 2B7F494C1708365200A106A9 /* IFCProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F01708365100A106A9 /* IFCProfile.cpp */; }; - 2B7F494D1708365200A106A9 /* IFCProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F01708365100A106A9 /* IFCProfile.cpp */; }; - 2B7F494E1708365200A106A9 /* IFCReaderGen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F11708365100A106A9 /* IFCReaderGen.cpp */; }; - 2B7F494F1708365200A106A9 /* IFCReaderGen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F11708365100A106A9 /* IFCReaderGen.cpp */; }; - 2B7F49501708365200A106A9 /* IFCReaderGen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F11708365100A106A9 /* IFCReaderGen.cpp */; }; - 2B7F49511708365200A106A9 /* IFCReaderGen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F11708365100A106A9 /* IFCReaderGen.cpp */; }; - 2B7F49521708365200A106A9 /* IFCReaderGen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F11708365100A106A9 /* IFCReaderGen.cpp */; }; - 2B7F49531708365200A106A9 /* IFCReaderGen.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F21708365100A106A9 /* IFCReaderGen.h */; }; - 2B7F49541708365200A106A9 /* IFCReaderGen.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F21708365100A106A9 /* IFCReaderGen.h */; }; - 2B7F49551708365200A106A9 /* IFCReaderGen.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F21708365100A106A9 /* IFCReaderGen.h */; }; - 2B7F49561708365200A106A9 /* IFCReaderGen.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F21708365100A106A9 /* IFCReaderGen.h */; }; - 2B7F49571708365200A106A9 /* IFCReaderGen.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F21708365100A106A9 /* IFCReaderGen.h */; }; - 2B7F49581708365200A106A9 /* IFCUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F31708365100A106A9 /* IFCUtil.cpp */; }; - 2B7F49591708365200A106A9 /* IFCUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F31708365100A106A9 /* IFCUtil.cpp */; }; - 2B7F495A1708365200A106A9 /* IFCUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F31708365100A106A9 /* IFCUtil.cpp */; }; - 2B7F495B1708365200A106A9 /* IFCUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F31708365100A106A9 /* IFCUtil.cpp */; }; - 2B7F495C1708365200A106A9 /* IFCUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F31708365100A106A9 /* IFCUtil.cpp */; }; - 2B7F495D1708365200A106A9 /* IFCUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F41708365100A106A9 /* IFCUtil.h */; }; - 2B7F495E1708365200A106A9 /* IFCUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F41708365100A106A9 /* IFCUtil.h */; }; - 2B7F495F1708365200A106A9 /* IFCUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F41708365100A106A9 /* IFCUtil.h */; }; - 2B7F49601708365200A106A9 /* IFCUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F41708365100A106A9 /* IFCUtil.h */; }; - 2B7F49611708365200A106A9 /* IFCUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F41708365100A106A9 /* IFCUtil.h */; }; - 2B7F49621708365200A106A9 /* IFF.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F51708365100A106A9 /* IFF.h */; }; - 2B7F49631708365200A106A9 /* IFF.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F51708365100A106A9 /* IFF.h */; }; - 2B7F49641708365200A106A9 /* IFF.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F51708365100A106A9 /* IFF.h */; }; - 2B7F49651708365200A106A9 /* IFF.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F51708365100A106A9 /* IFF.h */; }; - 2B7F49661708365200A106A9 /* IFF.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F51708365100A106A9 /* IFF.h */; }; - 2B7F49671708365200A106A9 /* Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F61708365100A106A9 /* Importer.cpp */; }; - 2B7F49681708365200A106A9 /* Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F61708365100A106A9 /* Importer.cpp */; }; - 2B7F49691708365200A106A9 /* Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F61708365100A106A9 /* Importer.cpp */; }; - 2B7F496A1708365200A106A9 /* Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F61708365100A106A9 /* Importer.cpp */; }; - 2B7F496B1708365200A106A9 /* Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F61708365100A106A9 /* Importer.cpp */; }; - 2B7F496C1708365200A106A9 /* Importer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F71708365100A106A9 /* Importer.h */; }; - 2B7F496D1708365200A106A9 /* Importer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F71708365100A106A9 /* Importer.h */; }; - 2B7F496E1708365200A106A9 /* Importer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F71708365100A106A9 /* Importer.h */; }; - 2B7F496F1708365200A106A9 /* Importer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F71708365100A106A9 /* Importer.h */; }; - 2B7F49701708365200A106A9 /* Importer.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45F71708365100A106A9 /* Importer.h */; }; - 2B7F49711708365200A106A9 /* ImporterRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F81708365100A106A9 /* ImporterRegistry.cpp */; }; - 2B7F49721708365200A106A9 /* ImporterRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F81708365100A106A9 /* ImporterRegistry.cpp */; }; - 2B7F49731708365200A106A9 /* ImporterRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F81708365100A106A9 /* ImporterRegistry.cpp */; }; - 2B7F49741708365200A106A9 /* ImporterRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F81708365100A106A9 /* ImporterRegistry.cpp */; }; - 2B7F49751708365200A106A9 /* ImporterRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F81708365100A106A9 /* ImporterRegistry.cpp */; }; - 2B7F49761708365200A106A9 /* ImproveCacheLocality.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F91708365100A106A9 /* ImproveCacheLocality.cpp */; }; - 2B7F49771708365200A106A9 /* ImproveCacheLocality.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F91708365100A106A9 /* ImproveCacheLocality.cpp */; }; - 2B7F49781708365200A106A9 /* ImproveCacheLocality.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F91708365100A106A9 /* ImproveCacheLocality.cpp */; }; - 2B7F49791708365200A106A9 /* ImproveCacheLocality.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F91708365100A106A9 /* ImproveCacheLocality.cpp */; }; - 2B7F497A1708365200A106A9 /* ImproveCacheLocality.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F45F91708365100A106A9 /* ImproveCacheLocality.cpp */; }; - 2B7F497B1708365200A106A9 /* ImproveCacheLocality.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45FA1708365100A106A9 /* ImproveCacheLocality.h */; }; - 2B7F497C1708365200A106A9 /* ImproveCacheLocality.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45FA1708365100A106A9 /* ImproveCacheLocality.h */; }; - 2B7F497D1708365200A106A9 /* ImproveCacheLocality.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45FA1708365100A106A9 /* ImproveCacheLocality.h */; }; - 2B7F497E1708365200A106A9 /* ImproveCacheLocality.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45FA1708365100A106A9 /* ImproveCacheLocality.h */; }; - 2B7F497F1708365200A106A9 /* ImproveCacheLocality.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F45FA1708365100A106A9 /* ImproveCacheLocality.h */; }; - 2B7F49A31708365200A106A9 /* JoinVerticesProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46021708365100A106A9 /* JoinVerticesProcess.cpp */; }; - 2B7F49A41708365200A106A9 /* JoinVerticesProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46021708365100A106A9 /* JoinVerticesProcess.cpp */; }; - 2B7F49A51708365200A106A9 /* JoinVerticesProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46021708365100A106A9 /* JoinVerticesProcess.cpp */; }; - 2B7F49A61708365200A106A9 /* JoinVerticesProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46021708365100A106A9 /* JoinVerticesProcess.cpp */; }; - 2B7F49A71708365200A106A9 /* JoinVerticesProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46021708365100A106A9 /* JoinVerticesProcess.cpp */; }; - 2B7F49A81708365200A106A9 /* JoinVerticesProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46031708365100A106A9 /* JoinVerticesProcess.h */; }; - 2B7F49A91708365200A106A9 /* JoinVerticesProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46031708365100A106A9 /* JoinVerticesProcess.h */; }; - 2B7F49AA1708365200A106A9 /* JoinVerticesProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46031708365100A106A9 /* JoinVerticesProcess.h */; }; - 2B7F49AB1708365200A106A9 /* JoinVerticesProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46031708365100A106A9 /* JoinVerticesProcess.h */; }; - 2B7F49AC1708365200A106A9 /* JoinVerticesProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46031708365100A106A9 /* JoinVerticesProcess.h */; }; - 2B7F49AD1708365200A106A9 /* LimitBoneWeightsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46041708365100A106A9 /* LimitBoneWeightsProcess.cpp */; }; - 2B7F49AE1708365200A106A9 /* LimitBoneWeightsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46041708365100A106A9 /* LimitBoneWeightsProcess.cpp */; }; - 2B7F49AF1708365200A106A9 /* LimitBoneWeightsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46041708365100A106A9 /* LimitBoneWeightsProcess.cpp */; }; - 2B7F49B01708365200A106A9 /* LimitBoneWeightsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46041708365100A106A9 /* LimitBoneWeightsProcess.cpp */; }; - 2B7F49B11708365200A106A9 /* LimitBoneWeightsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46041708365100A106A9 /* LimitBoneWeightsProcess.cpp */; }; - 2B7F49B21708365200A106A9 /* LimitBoneWeightsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46051708365100A106A9 /* LimitBoneWeightsProcess.h */; }; - 2B7F49B31708365200A106A9 /* LimitBoneWeightsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46051708365100A106A9 /* LimitBoneWeightsProcess.h */; }; - 2B7F49B41708365200A106A9 /* LimitBoneWeightsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46051708365100A106A9 /* LimitBoneWeightsProcess.h */; }; - 2B7F49B51708365200A106A9 /* LimitBoneWeightsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46051708365100A106A9 /* LimitBoneWeightsProcess.h */; }; - 2B7F49B61708365200A106A9 /* LimitBoneWeightsProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46051708365100A106A9 /* LimitBoneWeightsProcess.h */; }; - 2B7F49B71708365200A106A9 /* LineSplitter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46061708365100A106A9 /* LineSplitter.h */; }; - 2B7F49B81708365200A106A9 /* LineSplitter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46061708365100A106A9 /* LineSplitter.h */; }; - 2B7F49B91708365200A106A9 /* LineSplitter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46061708365100A106A9 /* LineSplitter.h */; }; - 2B7F49BA1708365200A106A9 /* LineSplitter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46061708365100A106A9 /* LineSplitter.h */; }; - 2B7F49BB1708365200A106A9 /* LineSplitter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46061708365100A106A9 /* LineSplitter.h */; }; - 2B7F49BC1708365200A106A9 /* LogAux.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46071708365100A106A9 /* LogAux.h */; }; - 2B7F49BD1708365200A106A9 /* LogAux.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46071708365100A106A9 /* LogAux.h */; }; - 2B7F49BE1708365200A106A9 /* LogAux.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46071708365100A106A9 /* LogAux.h */; }; - 2B7F49BF1708365200A106A9 /* LogAux.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46071708365100A106A9 /* LogAux.h */; }; - 2B7F49C01708365200A106A9 /* LogAux.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46071708365100A106A9 /* LogAux.h */; }; - 2B7F49F81708365200A106A9 /* MakeVerboseFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46141708365200A106A9 /* MakeVerboseFormat.cpp */; }; - 2B7F49F91708365200A106A9 /* MakeVerboseFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46141708365200A106A9 /* MakeVerboseFormat.cpp */; }; - 2B7F49FA1708365200A106A9 /* MakeVerboseFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46141708365200A106A9 /* MakeVerboseFormat.cpp */; }; - 2B7F49FB1708365200A106A9 /* MakeVerboseFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46141708365200A106A9 /* MakeVerboseFormat.cpp */; }; - 2B7F49FC1708365200A106A9 /* MakeVerboseFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46141708365200A106A9 /* MakeVerboseFormat.cpp */; }; - 2B7F49FD1708365200A106A9 /* MakeVerboseFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46151708365200A106A9 /* MakeVerboseFormat.h */; }; - 2B7F49FE1708365200A106A9 /* MakeVerboseFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46151708365200A106A9 /* MakeVerboseFormat.h */; }; - 2B7F49FF1708365200A106A9 /* MakeVerboseFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46151708365200A106A9 /* MakeVerboseFormat.h */; }; - 2B7F4A001708365200A106A9 /* MakeVerboseFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46151708365200A106A9 /* MakeVerboseFormat.h */; }; - 2B7F4A011708365200A106A9 /* MakeVerboseFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46151708365200A106A9 /* MakeVerboseFormat.h */; }; - 2B7F4A021708365200A106A9 /* MaterialSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46161708365200A106A9 /* MaterialSystem.cpp */; }; - 2B7F4A031708365200A106A9 /* MaterialSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46161708365200A106A9 /* MaterialSystem.cpp */; }; - 2B7F4A041708365200A106A9 /* MaterialSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46161708365200A106A9 /* MaterialSystem.cpp */; }; - 2B7F4A051708365200A106A9 /* MaterialSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46161708365200A106A9 /* MaterialSystem.cpp */; }; - 2B7F4A061708365200A106A9 /* MaterialSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46161708365200A106A9 /* MaterialSystem.cpp */; }; - 2B7F4A071708365200A106A9 /* MaterialSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46171708365200A106A9 /* MaterialSystem.h */; }; - 2B7F4A081708365200A106A9 /* MaterialSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46171708365200A106A9 /* MaterialSystem.h */; }; - 2B7F4A091708365200A106A9 /* MaterialSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46171708365200A106A9 /* MaterialSystem.h */; }; - 2B7F4A0A1708365200A106A9 /* MaterialSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46171708365200A106A9 /* MaterialSystem.h */; }; - 2B7F4A0B1708365200A106A9 /* MaterialSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46171708365200A106A9 /* MaterialSystem.h */; }; - 2B7F4A2F1708365200A106A9 /* MD4FileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F461F1708365200A106A9 /* MD4FileData.h */; }; - 2B7F4A301708365200A106A9 /* MD4FileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F461F1708365200A106A9 /* MD4FileData.h */; }; - 2B7F4A311708365200A106A9 /* MD4FileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F461F1708365200A106A9 /* MD4FileData.h */; }; - 2B7F4A321708365200A106A9 /* MD4FileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F461F1708365200A106A9 /* MD4FileData.h */; }; - 2B7F4A331708365200A106A9 /* MD4FileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F461F1708365200A106A9 /* MD4FileData.h */; }; - 2B7F4A751708365200A106A9 /* MemoryIOWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F462D1708365200A106A9 /* MemoryIOWrapper.h */; }; - 2B7F4A761708365200A106A9 /* MemoryIOWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F462D1708365200A106A9 /* MemoryIOWrapper.h */; }; - 2B7F4A771708365200A106A9 /* MemoryIOWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F462D1708365200A106A9 /* MemoryIOWrapper.h */; }; - 2B7F4A781708365200A106A9 /* MemoryIOWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F462D1708365200A106A9 /* MemoryIOWrapper.h */; }; - 2B7F4A791708365200A106A9 /* MemoryIOWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F462D1708365200A106A9 /* MemoryIOWrapper.h */; }; - 2B7F4A981708365200A106A9 /* ObjExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46341708365200A106A9 /* ObjExporter.cpp */; }; - 2B7F4A991708365200A106A9 /* ObjExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46341708365200A106A9 /* ObjExporter.cpp */; }; - 2B7F4A9A1708365200A106A9 /* ObjExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46341708365200A106A9 /* ObjExporter.cpp */; }; - 2B7F4A9B1708365200A106A9 /* ObjExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46341708365200A106A9 /* ObjExporter.cpp */; }; - 2B7F4A9C1708365200A106A9 /* ObjExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46341708365200A106A9 /* ObjExporter.cpp */; }; - 2B7F4A9D1708365200A106A9 /* ObjExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46351708365200A106A9 /* ObjExporter.h */; }; - 2B7F4A9E1708365200A106A9 /* ObjExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46351708365200A106A9 /* ObjExporter.h */; }; - 2B7F4A9F1708365200A106A9 /* ObjExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46351708365200A106A9 /* ObjExporter.h */; }; - 2B7F4AA01708365200A106A9 /* ObjExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46351708365200A106A9 /* ObjExporter.h */; }; - 2B7F4AA11708365200A106A9 /* ObjExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46351708365200A106A9 /* ObjExporter.h */; }; - 2B7F4AA21708365200A106A9 /* ObjFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46361708365200A106A9 /* ObjFileData.h */; }; - 2B7F4AA31708365200A106A9 /* ObjFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46361708365200A106A9 /* ObjFileData.h */; }; - 2B7F4AA41708365200A106A9 /* ObjFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46361708365200A106A9 /* ObjFileData.h */; }; - 2B7F4AA51708365200A106A9 /* ObjFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46361708365200A106A9 /* ObjFileData.h */; }; - 2B7F4AA61708365200A106A9 /* ObjFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46361708365200A106A9 /* ObjFileData.h */; }; - 2B7F4AA71708365200A106A9 /* ObjFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46371708365200A106A9 /* ObjFileImporter.cpp */; }; - 2B7F4AA81708365200A106A9 /* ObjFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46371708365200A106A9 /* ObjFileImporter.cpp */; }; - 2B7F4AA91708365200A106A9 /* ObjFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46371708365200A106A9 /* ObjFileImporter.cpp */; }; - 2B7F4AAA1708365200A106A9 /* ObjFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46371708365200A106A9 /* ObjFileImporter.cpp */; }; - 2B7F4AAB1708365200A106A9 /* ObjFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46371708365200A106A9 /* ObjFileImporter.cpp */; }; - 2B7F4AAC1708365200A106A9 /* ObjFileImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46381708365200A106A9 /* ObjFileImporter.h */; }; - 2B7F4AAD1708365200A106A9 /* ObjFileImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46381708365200A106A9 /* ObjFileImporter.h */; }; - 2B7F4AAE1708365200A106A9 /* ObjFileImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46381708365200A106A9 /* ObjFileImporter.h */; }; - 2B7F4AAF1708365200A106A9 /* ObjFileImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46381708365200A106A9 /* ObjFileImporter.h */; }; - 2B7F4AB01708365200A106A9 /* ObjFileImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46381708365200A106A9 /* ObjFileImporter.h */; }; - 2B7F4AB11708365200A106A9 /* ObjFileMtlImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46391708365200A106A9 /* ObjFileMtlImporter.cpp */; }; - 2B7F4AB21708365200A106A9 /* ObjFileMtlImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46391708365200A106A9 /* ObjFileMtlImporter.cpp */; }; - 2B7F4AB31708365200A106A9 /* ObjFileMtlImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46391708365200A106A9 /* ObjFileMtlImporter.cpp */; }; - 2B7F4AB41708365200A106A9 /* ObjFileMtlImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46391708365200A106A9 /* ObjFileMtlImporter.cpp */; }; - 2B7F4AB51708365200A106A9 /* ObjFileMtlImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46391708365200A106A9 /* ObjFileMtlImporter.cpp */; }; - 2B7F4AB61708365200A106A9 /* ObjFileMtlImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F463A1708365200A106A9 /* ObjFileMtlImporter.h */; }; - 2B7F4AB71708365200A106A9 /* ObjFileMtlImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F463A1708365200A106A9 /* ObjFileMtlImporter.h */; }; - 2B7F4AB81708365200A106A9 /* ObjFileMtlImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F463A1708365200A106A9 /* ObjFileMtlImporter.h */; }; - 2B7F4AB91708365200A106A9 /* ObjFileMtlImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F463A1708365200A106A9 /* ObjFileMtlImporter.h */; }; - 2B7F4ABA1708365200A106A9 /* ObjFileMtlImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F463A1708365200A106A9 /* ObjFileMtlImporter.h */; }; - 2B7F4ABB1708365200A106A9 /* ObjFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F463B1708365200A106A9 /* ObjFileParser.cpp */; }; - 2B7F4ABC1708365200A106A9 /* ObjFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F463B1708365200A106A9 /* ObjFileParser.cpp */; }; - 2B7F4ABD1708365200A106A9 /* ObjFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F463B1708365200A106A9 /* ObjFileParser.cpp */; }; - 2B7F4ABE1708365200A106A9 /* ObjFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F463B1708365200A106A9 /* ObjFileParser.cpp */; }; - 2B7F4ABF1708365200A106A9 /* ObjFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F463B1708365200A106A9 /* ObjFileParser.cpp */; }; - 2B7F4AC01708365200A106A9 /* ObjFileParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F463C1708365200A106A9 /* ObjFileParser.h */; }; - 2B7F4AC11708365200A106A9 /* ObjFileParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F463C1708365200A106A9 /* ObjFileParser.h */; }; - 2B7F4AC21708365200A106A9 /* ObjFileParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F463C1708365200A106A9 /* ObjFileParser.h */; }; - 2B7F4AC31708365200A106A9 /* ObjFileParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F463C1708365200A106A9 /* ObjFileParser.h */; }; - 2B7F4AC41708365200A106A9 /* ObjFileParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F463C1708365200A106A9 /* ObjFileParser.h */; }; - 2B7F4AC51708365200A106A9 /* ObjTools.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F463D1708365200A106A9 /* ObjTools.h */; }; - 2B7F4AC61708365200A106A9 /* ObjTools.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F463D1708365200A106A9 /* ObjTools.h */; }; - 2B7F4AC71708365200A106A9 /* ObjTools.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F463D1708365200A106A9 /* ObjTools.h */; }; - 2B7F4AC81708365200A106A9 /* ObjTools.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F463D1708365200A106A9 /* ObjTools.h */; }; - 2B7F4AC91708365200A106A9 /* ObjTools.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F463D1708365200A106A9 /* ObjTools.h */; }; - 2B7F4AF21708365200A106A9 /* OptimizeGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46461708365200A106A9 /* OptimizeGraph.cpp */; }; - 2B7F4AF31708365200A106A9 /* OptimizeGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46461708365200A106A9 /* OptimizeGraph.cpp */; }; - 2B7F4AF41708365200A106A9 /* OptimizeGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46461708365200A106A9 /* OptimizeGraph.cpp */; }; - 2B7F4AF51708365200A106A9 /* OptimizeGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46461708365200A106A9 /* OptimizeGraph.cpp */; }; - 2B7F4AF61708365200A106A9 /* OptimizeGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46461708365200A106A9 /* OptimizeGraph.cpp */; }; - 2B7F4AF71708365200A106A9 /* OptimizeGraph.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46471708365200A106A9 /* OptimizeGraph.h */; }; - 2B7F4AF81708365200A106A9 /* OptimizeGraph.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46471708365200A106A9 /* OptimizeGraph.h */; }; - 2B7F4AF91708365200A106A9 /* OptimizeGraph.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46471708365200A106A9 /* OptimizeGraph.h */; }; - 2B7F4AFA1708365200A106A9 /* OptimizeGraph.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46471708365200A106A9 /* OptimizeGraph.h */; }; - 2B7F4AFB1708365200A106A9 /* OptimizeGraph.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46471708365200A106A9 /* OptimizeGraph.h */; }; - 2B7F4AFC1708365200A106A9 /* OptimizeMeshes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46481708365200A106A9 /* OptimizeMeshes.cpp */; }; - 2B7F4AFD1708365200A106A9 /* OptimizeMeshes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46481708365200A106A9 /* OptimizeMeshes.cpp */; }; - 2B7F4AFE1708365200A106A9 /* OptimizeMeshes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46481708365200A106A9 /* OptimizeMeshes.cpp */; }; - 2B7F4AFF1708365200A106A9 /* OptimizeMeshes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46481708365200A106A9 /* OptimizeMeshes.cpp */; }; - 2B7F4B001708365200A106A9 /* OptimizeMeshes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46481708365200A106A9 /* OptimizeMeshes.cpp */; }; - 2B7F4B011708365200A106A9 /* OptimizeMeshes.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46491708365200A106A9 /* OptimizeMeshes.h */; }; - 2B7F4B021708365200A106A9 /* OptimizeMeshes.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46491708365200A106A9 /* OptimizeMeshes.h */; }; - 2B7F4B031708365200A106A9 /* OptimizeMeshes.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46491708365200A106A9 /* OptimizeMeshes.h */; }; - 2B7F4B041708365200A106A9 /* OptimizeMeshes.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46491708365200A106A9 /* OptimizeMeshes.h */; }; - 2B7F4B051708365200A106A9 /* OptimizeMeshes.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46491708365200A106A9 /* OptimizeMeshes.h */; }; - 2B7F4B061708365200A106A9 /* ParsingUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F464A1708365200A106A9 /* ParsingUtils.h */; }; - 2B7F4B071708365200A106A9 /* ParsingUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F464A1708365200A106A9 /* ParsingUtils.h */; }; - 2B7F4B081708365200A106A9 /* ParsingUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F464A1708365200A106A9 /* ParsingUtils.h */; }; - 2B7F4B091708365200A106A9 /* ParsingUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F464A1708365200A106A9 /* ParsingUtils.h */; }; - 2B7F4B0A1708365200A106A9 /* ParsingUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F464A1708365200A106A9 /* ParsingUtils.h */; }; - 2B7F4B291708365200A106A9 /* PolyTools.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46511708365200A106A9 /* PolyTools.h */; }; - 2B7F4B2A1708365200A106A9 /* PolyTools.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46511708365200A106A9 /* PolyTools.h */; }; - 2B7F4B2B1708365200A106A9 /* PolyTools.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46511708365200A106A9 /* PolyTools.h */; }; - 2B7F4B2C1708365200A106A9 /* PolyTools.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46511708365200A106A9 /* PolyTools.h */; }; - 2B7F4B2D1708365200A106A9 /* PolyTools.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46511708365200A106A9 /* PolyTools.h */; }; - 2B7F4B2E1708365200A106A9 /* PostStepRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46521708365200A106A9 /* PostStepRegistry.cpp */; }; - 2B7F4B2F1708365200A106A9 /* PostStepRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46521708365200A106A9 /* PostStepRegistry.cpp */; }; - 2B7F4B301708365200A106A9 /* PostStepRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46521708365200A106A9 /* PostStepRegistry.cpp */; }; - 2B7F4B311708365200A106A9 /* PostStepRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46521708365200A106A9 /* PostStepRegistry.cpp */; }; - 2B7F4B321708365200A106A9 /* PostStepRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46521708365200A106A9 /* PostStepRegistry.cpp */; }; - 2B7F4B331708365200A106A9 /* PretransformVertices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46531708365200A106A9 /* PretransformVertices.cpp */; }; - 2B7F4B341708365200A106A9 /* PretransformVertices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46531708365200A106A9 /* PretransformVertices.cpp */; }; - 2B7F4B351708365200A106A9 /* PretransformVertices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46531708365200A106A9 /* PretransformVertices.cpp */; }; - 2B7F4B361708365200A106A9 /* PretransformVertices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46531708365200A106A9 /* PretransformVertices.cpp */; }; - 2B7F4B371708365200A106A9 /* PretransformVertices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46531708365200A106A9 /* PretransformVertices.cpp */; }; - 2B7F4B381708365200A106A9 /* PretransformVertices.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46541708365200A106A9 /* PretransformVertices.h */; }; - 2B7F4B391708365200A106A9 /* PretransformVertices.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46541708365200A106A9 /* PretransformVertices.h */; }; - 2B7F4B3A1708365200A106A9 /* PretransformVertices.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46541708365200A106A9 /* PretransformVertices.h */; }; - 2B7F4B3B1708365200A106A9 /* PretransformVertices.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46541708365200A106A9 /* PretransformVertices.h */; }; - 2B7F4B3C1708365200A106A9 /* PretransformVertices.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46541708365200A106A9 /* PretransformVertices.h */; }; - 2B7F4B3D1708365200A106A9 /* ProcessHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46551708365200A106A9 /* ProcessHelper.cpp */; }; - 2B7F4B3E1708365200A106A9 /* ProcessHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46551708365200A106A9 /* ProcessHelper.cpp */; }; - 2B7F4B3F1708365200A106A9 /* ProcessHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46551708365200A106A9 /* ProcessHelper.cpp */; }; - 2B7F4B401708365200A106A9 /* ProcessHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46551708365200A106A9 /* ProcessHelper.cpp */; }; - 2B7F4B411708365200A106A9 /* ProcessHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46551708365200A106A9 /* ProcessHelper.cpp */; }; - 2B7F4B421708365200A106A9 /* ProcessHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46561708365200A106A9 /* ProcessHelper.h */; }; - 2B7F4B431708365200A106A9 /* ProcessHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46561708365200A106A9 /* ProcessHelper.h */; }; - 2B7F4B441708365200A106A9 /* ProcessHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46561708365200A106A9 /* ProcessHelper.h */; }; - 2B7F4B451708365200A106A9 /* ProcessHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46561708365200A106A9 /* ProcessHelper.h */; }; - 2B7F4B461708365200A106A9 /* ProcessHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46561708365200A106A9 /* ProcessHelper.h */; }; - 2B7F4B471708365200A106A9 /* Profiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46571708365200A106A9 /* Profiler.h */; }; - 2B7F4B481708365200A106A9 /* Profiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46571708365200A106A9 /* Profiler.h */; }; - 2B7F4B491708365200A106A9 /* Profiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46571708365200A106A9 /* Profiler.h */; }; - 2B7F4B4A1708365200A106A9 /* Profiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46571708365200A106A9 /* Profiler.h */; }; - 2B7F4B4B1708365200A106A9 /* Profiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46571708365200A106A9 /* Profiler.h */; }; - 2B7F4B4C1708365200A106A9 /* pstdint.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46581708365200A106A9 /* pstdint.h */; }; - 2B7F4B4D1708365200A106A9 /* pstdint.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46581708365200A106A9 /* pstdint.h */; }; - 2B7F4B4E1708365200A106A9 /* pstdint.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46581708365200A106A9 /* pstdint.h */; }; - 2B7F4B4F1708365200A106A9 /* pstdint.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46581708365200A106A9 /* pstdint.h */; }; - 2B7F4B501708365200A106A9 /* pstdint.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46581708365200A106A9 /* pstdint.h */; }; - 2B7F4B7E1708365200A106A9 /* qnan.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46621708365200A106A9 /* qnan.h */; }; - 2B7F4B7F1708365200A106A9 /* qnan.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46621708365200A106A9 /* qnan.h */; }; - 2B7F4B801708365200A106A9 /* qnan.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46621708365200A106A9 /* qnan.h */; }; - 2B7F4B811708365200A106A9 /* qnan.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46621708365200A106A9 /* qnan.h */; }; - 2B7F4B821708365200A106A9 /* qnan.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46621708365200A106A9 /* qnan.h */; }; - 2B7F4B8D1708365200A106A9 /* RemoveComments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46651708365200A106A9 /* RemoveComments.cpp */; }; - 2B7F4B8E1708365200A106A9 /* RemoveComments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46651708365200A106A9 /* RemoveComments.cpp */; }; - 2B7F4B8F1708365200A106A9 /* RemoveComments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46651708365200A106A9 /* RemoveComments.cpp */; }; - 2B7F4B901708365200A106A9 /* RemoveComments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46651708365200A106A9 /* RemoveComments.cpp */; }; - 2B7F4B911708365200A106A9 /* RemoveComments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46651708365200A106A9 /* RemoveComments.cpp */; }; - 2B7F4B921708365200A106A9 /* RemoveComments.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46661708365200A106A9 /* RemoveComments.h */; }; - 2B7F4B931708365200A106A9 /* RemoveComments.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46661708365200A106A9 /* RemoveComments.h */; }; - 2B7F4B941708365200A106A9 /* RemoveComments.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46661708365200A106A9 /* RemoveComments.h */; }; - 2B7F4B951708365200A106A9 /* RemoveComments.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46661708365200A106A9 /* RemoveComments.h */; }; - 2B7F4B961708365200A106A9 /* RemoveComments.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46661708365200A106A9 /* RemoveComments.h */; }; - 2B7F4B971708365200A106A9 /* RemoveRedundantMaterials.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46671708365200A106A9 /* RemoveRedundantMaterials.cpp */; }; - 2B7F4B981708365200A106A9 /* RemoveRedundantMaterials.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46671708365200A106A9 /* RemoveRedundantMaterials.cpp */; }; - 2B7F4B991708365200A106A9 /* RemoveRedundantMaterials.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46671708365200A106A9 /* RemoveRedundantMaterials.cpp */; }; - 2B7F4B9A1708365200A106A9 /* RemoveRedundantMaterials.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46671708365200A106A9 /* RemoveRedundantMaterials.cpp */; }; - 2B7F4B9B1708365200A106A9 /* RemoveRedundantMaterials.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46671708365200A106A9 /* RemoveRedundantMaterials.cpp */; }; - 2B7F4B9C1708365200A106A9 /* RemoveRedundantMaterials.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46681708365200A106A9 /* RemoveRedundantMaterials.h */; }; - 2B7F4B9D1708365200A106A9 /* RemoveRedundantMaterials.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46681708365200A106A9 /* RemoveRedundantMaterials.h */; }; - 2B7F4B9E1708365200A106A9 /* RemoveRedundantMaterials.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46681708365200A106A9 /* RemoveRedundantMaterials.h */; }; - 2B7F4B9F1708365200A106A9 /* RemoveRedundantMaterials.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46681708365200A106A9 /* RemoveRedundantMaterials.h */; }; - 2B7F4BA01708365200A106A9 /* RemoveRedundantMaterials.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46681708365200A106A9 /* RemoveRedundantMaterials.h */; }; - 2B7F4BA11708365200A106A9 /* RemoveVCProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46691708365200A106A9 /* RemoveVCProcess.cpp */; }; - 2B7F4BA21708365200A106A9 /* RemoveVCProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46691708365200A106A9 /* RemoveVCProcess.cpp */; }; - 2B7F4BA31708365200A106A9 /* RemoveVCProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46691708365200A106A9 /* RemoveVCProcess.cpp */; }; - 2B7F4BA41708365200A106A9 /* RemoveVCProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46691708365200A106A9 /* RemoveVCProcess.cpp */; }; - 2B7F4BA51708365200A106A9 /* RemoveVCProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46691708365200A106A9 /* RemoveVCProcess.cpp */; }; - 2B7F4BA61708365200A106A9 /* RemoveVCProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F466A1708365200A106A9 /* RemoveVCProcess.h */; }; - 2B7F4BA71708365200A106A9 /* RemoveVCProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F466A1708365200A106A9 /* RemoveVCProcess.h */; }; - 2B7F4BA81708365200A106A9 /* RemoveVCProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F466A1708365200A106A9 /* RemoveVCProcess.h */; }; - 2B7F4BA91708365200A106A9 /* RemoveVCProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F466A1708365200A106A9 /* RemoveVCProcess.h */; }; - 2B7F4BAA1708365200A106A9 /* RemoveVCProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F466A1708365200A106A9 /* RemoveVCProcess.h */; }; - 2B7F4BB01708365200A106A9 /* SceneCombiner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F466E1708365200A106A9 /* SceneCombiner.cpp */; }; - 2B7F4BB11708365200A106A9 /* SceneCombiner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F466E1708365200A106A9 /* SceneCombiner.cpp */; }; - 2B7F4BB21708365200A106A9 /* SceneCombiner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F466E1708365200A106A9 /* SceneCombiner.cpp */; }; - 2B7F4BB31708365200A106A9 /* SceneCombiner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F466E1708365200A106A9 /* SceneCombiner.cpp */; }; - 2B7F4BB41708365200A106A9 /* SceneCombiner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F466E1708365200A106A9 /* SceneCombiner.cpp */; }; - 2B7F4BB51708365200A106A9 /* SceneCombiner.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F466F1708365200A106A9 /* SceneCombiner.h */; }; - 2B7F4BB61708365200A106A9 /* SceneCombiner.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F466F1708365200A106A9 /* SceneCombiner.h */; }; - 2B7F4BB71708365200A106A9 /* SceneCombiner.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F466F1708365200A106A9 /* SceneCombiner.h */; }; - 2B7F4BB81708365200A106A9 /* SceneCombiner.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F466F1708365200A106A9 /* SceneCombiner.h */; }; - 2B7F4BB91708365200A106A9 /* SceneCombiner.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F466F1708365200A106A9 /* SceneCombiner.h */; }; - 2B7F4BBA1708365200A106A9 /* ScenePreprocessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46701708365200A106A9 /* ScenePreprocessor.cpp */; }; - 2B7F4BBB1708365200A106A9 /* ScenePreprocessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46701708365200A106A9 /* ScenePreprocessor.cpp */; }; - 2B7F4BBC1708365200A106A9 /* ScenePreprocessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46701708365200A106A9 /* ScenePreprocessor.cpp */; }; - 2B7F4BBD1708365200A106A9 /* ScenePreprocessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46701708365200A106A9 /* ScenePreprocessor.cpp */; }; - 2B7F4BBE1708365200A106A9 /* ScenePreprocessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46701708365200A106A9 /* ScenePreprocessor.cpp */; }; - 2B7F4BBF1708365200A106A9 /* ScenePreprocessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46711708365200A106A9 /* ScenePreprocessor.h */; }; - 2B7F4BC01708365200A106A9 /* ScenePreprocessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46711708365200A106A9 /* ScenePreprocessor.h */; }; - 2B7F4BC11708365200A106A9 /* ScenePreprocessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46711708365200A106A9 /* ScenePreprocessor.h */; }; - 2B7F4BC21708365200A106A9 /* ScenePreprocessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46711708365200A106A9 /* ScenePreprocessor.h */; }; - 2B7F4BC31708365200A106A9 /* ScenePreprocessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46711708365200A106A9 /* ScenePreprocessor.h */; }; - 2B7F4BC41708365200A106A9 /* ScenePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46721708365200A106A9 /* ScenePrivate.h */; }; - 2B7F4BC51708365200A106A9 /* ScenePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46721708365200A106A9 /* ScenePrivate.h */; }; - 2B7F4BC61708365200A106A9 /* ScenePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46721708365200A106A9 /* ScenePrivate.h */; }; - 2B7F4BC71708365200A106A9 /* ScenePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46721708365200A106A9 /* ScenePrivate.h */; }; - 2B7F4BC81708365200A106A9 /* ScenePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46721708365200A106A9 /* ScenePrivate.h */; }; - 2B7F4BC91708365200A106A9 /* SGSpatialSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46731708365200A106A9 /* SGSpatialSort.cpp */; }; - 2B7F4BCA1708365200A106A9 /* SGSpatialSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46731708365200A106A9 /* SGSpatialSort.cpp */; }; - 2B7F4BCB1708365200A106A9 /* SGSpatialSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46731708365200A106A9 /* SGSpatialSort.cpp */; }; - 2B7F4BCC1708365200A106A9 /* SGSpatialSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46731708365200A106A9 /* SGSpatialSort.cpp */; }; - 2B7F4BCD1708365200A106A9 /* SGSpatialSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46731708365200A106A9 /* SGSpatialSort.cpp */; }; - 2B7F4BCE1708365200A106A9 /* SGSpatialSort.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46741708365200A106A9 /* SGSpatialSort.h */; }; - 2B7F4BCF1708365200A106A9 /* SGSpatialSort.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46741708365200A106A9 /* SGSpatialSort.h */; }; - 2B7F4BD01708365200A106A9 /* SGSpatialSort.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46741708365200A106A9 /* SGSpatialSort.h */; }; - 2B7F4BD11708365200A106A9 /* SGSpatialSort.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46741708365200A106A9 /* SGSpatialSort.h */; }; - 2B7F4BD21708365200A106A9 /* SGSpatialSort.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46741708365200A106A9 /* SGSpatialSort.h */; }; - 2B7F4BD31708365200A106A9 /* SkeletonMeshBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46751708365200A106A9 /* SkeletonMeshBuilder.cpp */; }; - 2B7F4BD41708365200A106A9 /* SkeletonMeshBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46751708365200A106A9 /* SkeletonMeshBuilder.cpp */; }; - 2B7F4BD51708365200A106A9 /* SkeletonMeshBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46751708365200A106A9 /* SkeletonMeshBuilder.cpp */; }; - 2B7F4BD61708365200A106A9 /* SkeletonMeshBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46751708365200A106A9 /* SkeletonMeshBuilder.cpp */; }; - 2B7F4BD71708365200A106A9 /* SkeletonMeshBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46751708365200A106A9 /* SkeletonMeshBuilder.cpp */; }; - 2B7F4BD81708365200A106A9 /* SkeletonMeshBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46761708365200A106A9 /* SkeletonMeshBuilder.h */; }; - 2B7F4BD91708365200A106A9 /* SkeletonMeshBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46761708365200A106A9 /* SkeletonMeshBuilder.h */; }; - 2B7F4BDA1708365200A106A9 /* SkeletonMeshBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46761708365200A106A9 /* SkeletonMeshBuilder.h */; }; - 2B7F4BDB1708365200A106A9 /* SkeletonMeshBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46761708365200A106A9 /* SkeletonMeshBuilder.h */; }; - 2B7F4BDC1708365200A106A9 /* SkeletonMeshBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46761708365200A106A9 /* SkeletonMeshBuilder.h */; }; - 2B7F4BE71708365200A106A9 /* SmoothingGroups.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46791708365200A106A9 /* SmoothingGroups.h */; }; - 2B7F4BE81708365200A106A9 /* SmoothingGroups.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46791708365200A106A9 /* SmoothingGroups.h */; }; - 2B7F4BE91708365200A106A9 /* SmoothingGroups.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46791708365200A106A9 /* SmoothingGroups.h */; }; - 2B7F4BEA1708365200A106A9 /* SmoothingGroups.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46791708365200A106A9 /* SmoothingGroups.h */; }; - 2B7F4BEB1708365200A106A9 /* SmoothingGroups.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46791708365200A106A9 /* SmoothingGroups.h */; }; - 2B7F4BEC1708365200A106A9 /* SortByPTypeProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F467B1708365200A106A9 /* SortByPTypeProcess.cpp */; }; - 2B7F4BED1708365200A106A9 /* SortByPTypeProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F467B1708365200A106A9 /* SortByPTypeProcess.cpp */; }; - 2B7F4BEE1708365200A106A9 /* SortByPTypeProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F467B1708365200A106A9 /* SortByPTypeProcess.cpp */; }; - 2B7F4BEF1708365200A106A9 /* SortByPTypeProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F467B1708365200A106A9 /* SortByPTypeProcess.cpp */; }; - 2B7F4BF01708365200A106A9 /* SortByPTypeProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F467B1708365200A106A9 /* SortByPTypeProcess.cpp */; }; - 2B7F4BF11708365200A106A9 /* SortByPTypeProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F467C1708365200A106A9 /* SortByPTypeProcess.h */; }; - 2B7F4BF21708365200A106A9 /* SortByPTypeProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F467C1708365200A106A9 /* SortByPTypeProcess.h */; }; - 2B7F4BF31708365200A106A9 /* SortByPTypeProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F467C1708365200A106A9 /* SortByPTypeProcess.h */; }; - 2B7F4BF41708365200A106A9 /* SortByPTypeProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F467C1708365200A106A9 /* SortByPTypeProcess.h */; }; - 2B7F4BF51708365200A106A9 /* SortByPTypeProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F467C1708365200A106A9 /* SortByPTypeProcess.h */; }; - 2B7F4BF61708365200A106A9 /* SpatialSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F467D1708365200A106A9 /* SpatialSort.cpp */; }; - 2B7F4BF71708365200A106A9 /* SpatialSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F467D1708365200A106A9 /* SpatialSort.cpp */; }; - 2B7F4BF81708365200A106A9 /* SpatialSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F467D1708365200A106A9 /* SpatialSort.cpp */; }; - 2B7F4BF91708365200A106A9 /* SpatialSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F467D1708365200A106A9 /* SpatialSort.cpp */; }; - 2B7F4BFA1708365200A106A9 /* SpatialSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F467D1708365200A106A9 /* SpatialSort.cpp */; }; - 2B7F4BFB1708365200A106A9 /* SpatialSort.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F467E1708365200A106A9 /* SpatialSort.h */; }; - 2B7F4BFC1708365200A106A9 /* SpatialSort.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F467E1708365200A106A9 /* SpatialSort.h */; }; - 2B7F4BFD1708365200A106A9 /* SpatialSort.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F467E1708365200A106A9 /* SpatialSort.h */; }; - 2B7F4BFE1708365200A106A9 /* SpatialSort.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F467E1708365200A106A9 /* SpatialSort.h */; }; - 2B7F4BFF1708365200A106A9 /* SpatialSort.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F467E1708365200A106A9 /* SpatialSort.h */; }; - 2B7F4C001708365200A106A9 /* SplitByBoneCountProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F467F1708365200A106A9 /* SplitByBoneCountProcess.cpp */; }; - 2B7F4C011708365200A106A9 /* SplitByBoneCountProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F467F1708365200A106A9 /* SplitByBoneCountProcess.cpp */; }; - 2B7F4C021708365200A106A9 /* SplitByBoneCountProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F467F1708365200A106A9 /* SplitByBoneCountProcess.cpp */; }; - 2B7F4C031708365200A106A9 /* SplitByBoneCountProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F467F1708365200A106A9 /* SplitByBoneCountProcess.cpp */; }; - 2B7F4C041708365200A106A9 /* SplitByBoneCountProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F467F1708365200A106A9 /* SplitByBoneCountProcess.cpp */; }; - 2B7F4C051708365200A106A9 /* SplitByBoneCountProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46801708365200A106A9 /* SplitByBoneCountProcess.h */; }; - 2B7F4C061708365200A106A9 /* SplitByBoneCountProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46801708365200A106A9 /* SplitByBoneCountProcess.h */; }; - 2B7F4C071708365200A106A9 /* SplitByBoneCountProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46801708365200A106A9 /* SplitByBoneCountProcess.h */; }; - 2B7F4C081708365200A106A9 /* SplitByBoneCountProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46801708365200A106A9 /* SplitByBoneCountProcess.h */; }; - 2B7F4C091708365200A106A9 /* SplitByBoneCountProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46801708365200A106A9 /* SplitByBoneCountProcess.h */; }; - 2B7F4C0A1708365200A106A9 /* SplitLargeMeshes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46811708365200A106A9 /* SplitLargeMeshes.cpp */; }; - 2B7F4C0B1708365200A106A9 /* SplitLargeMeshes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46811708365200A106A9 /* SplitLargeMeshes.cpp */; }; - 2B7F4C0C1708365200A106A9 /* SplitLargeMeshes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46811708365200A106A9 /* SplitLargeMeshes.cpp */; }; - 2B7F4C0D1708365200A106A9 /* SplitLargeMeshes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46811708365200A106A9 /* SplitLargeMeshes.cpp */; }; - 2B7F4C0E1708365200A106A9 /* SplitLargeMeshes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46811708365200A106A9 /* SplitLargeMeshes.cpp */; }; - 2B7F4C0F1708365200A106A9 /* SplitLargeMeshes.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46821708365200A106A9 /* SplitLargeMeshes.h */; }; - 2B7F4C101708365200A106A9 /* SplitLargeMeshes.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46821708365200A106A9 /* SplitLargeMeshes.h */; }; - 2B7F4C111708365200A106A9 /* SplitLargeMeshes.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46821708365200A106A9 /* SplitLargeMeshes.h */; }; - 2B7F4C121708365200A106A9 /* SplitLargeMeshes.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46821708365200A106A9 /* SplitLargeMeshes.h */; }; - 2B7F4C131708365200A106A9 /* SplitLargeMeshes.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46821708365200A106A9 /* SplitLargeMeshes.h */; }; - 2B7F4C141708365200A106A9 /* StandardShapes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46831708365200A106A9 /* StandardShapes.cpp */; }; - 2B7F4C151708365200A106A9 /* StandardShapes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46831708365200A106A9 /* StandardShapes.cpp */; }; - 2B7F4C161708365200A106A9 /* StandardShapes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46831708365200A106A9 /* StandardShapes.cpp */; }; - 2B7F4C171708365200A106A9 /* StandardShapes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46831708365200A106A9 /* StandardShapes.cpp */; }; - 2B7F4C181708365200A106A9 /* StandardShapes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46831708365200A106A9 /* StandardShapes.cpp */; }; - 2B7F4C191708365200A106A9 /* StandardShapes.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46841708365200A106A9 /* StandardShapes.h */; }; - 2B7F4C1A1708365200A106A9 /* StandardShapes.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46841708365200A106A9 /* StandardShapes.h */; }; - 2B7F4C1B1708365200A106A9 /* StandardShapes.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46841708365200A106A9 /* StandardShapes.h */; }; - 2B7F4C1C1708365200A106A9 /* StandardShapes.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46841708365200A106A9 /* StandardShapes.h */; }; - 2B7F4C1D1708365200A106A9 /* StandardShapes.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46841708365200A106A9 /* StandardShapes.h */; }; - 2B7F4C1E1708365200A106A9 /* StdOStreamLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46851708365200A106A9 /* StdOStreamLogStream.h */; }; - 2B7F4C1F1708365200A106A9 /* StdOStreamLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46851708365200A106A9 /* StdOStreamLogStream.h */; }; - 2B7F4C201708365200A106A9 /* StdOStreamLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46851708365200A106A9 /* StdOStreamLogStream.h */; }; - 2B7F4C211708365200A106A9 /* StdOStreamLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46851708365200A106A9 /* StdOStreamLogStream.h */; }; - 2B7F4C221708365200A106A9 /* StdOStreamLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46851708365200A106A9 /* StdOStreamLogStream.h */; }; - 2B7F4C231708365200A106A9 /* STEPFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46861708365200A106A9 /* STEPFile.h */; }; - 2B7F4C241708365200A106A9 /* STEPFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46861708365200A106A9 /* STEPFile.h */; }; - 2B7F4C251708365200A106A9 /* STEPFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46861708365200A106A9 /* STEPFile.h */; }; - 2B7F4C261708365200A106A9 /* STEPFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46861708365200A106A9 /* STEPFile.h */; }; - 2B7F4C271708365200A106A9 /* STEPFile.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46861708365200A106A9 /* STEPFile.h */; }; - 2B7F4C281708365200A106A9 /* STEPFileEncoding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46871708365200A106A9 /* STEPFileEncoding.cpp */; }; - 2B7F4C291708365200A106A9 /* STEPFileEncoding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46871708365200A106A9 /* STEPFileEncoding.cpp */; }; - 2B7F4C2A1708365200A106A9 /* STEPFileEncoding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46871708365200A106A9 /* STEPFileEncoding.cpp */; }; - 2B7F4C2B1708365200A106A9 /* STEPFileEncoding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46871708365200A106A9 /* STEPFileEncoding.cpp */; }; - 2B7F4C2C1708365200A106A9 /* STEPFileEncoding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46871708365200A106A9 /* STEPFileEncoding.cpp */; }; - 2B7F4C2D1708365200A106A9 /* STEPFileEncoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46881708365200A106A9 /* STEPFileEncoding.h */; }; - 2B7F4C2E1708365200A106A9 /* STEPFileEncoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46881708365200A106A9 /* STEPFileEncoding.h */; }; - 2B7F4C2F1708365200A106A9 /* STEPFileEncoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46881708365200A106A9 /* STEPFileEncoding.h */; }; - 2B7F4C301708365200A106A9 /* STEPFileEncoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46881708365200A106A9 /* STEPFileEncoding.h */; }; - 2B7F4C311708365200A106A9 /* STEPFileEncoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46881708365200A106A9 /* STEPFileEncoding.h */; }; - 2B7F4C321708365200A106A9 /* STEPFileReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46891708365200A106A9 /* STEPFileReader.cpp */; }; - 2B7F4C331708365200A106A9 /* STEPFileReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46891708365200A106A9 /* STEPFileReader.cpp */; }; - 2B7F4C341708365200A106A9 /* STEPFileReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46891708365200A106A9 /* STEPFileReader.cpp */; }; - 2B7F4C351708365200A106A9 /* STEPFileReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46891708365200A106A9 /* STEPFileReader.cpp */; }; - 2B7F4C361708365200A106A9 /* STEPFileReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46891708365200A106A9 /* STEPFileReader.cpp */; }; - 2B7F4C371708365200A106A9 /* STEPFileReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468A1708365200A106A9 /* STEPFileReader.h */; }; - 2B7F4C381708365200A106A9 /* STEPFileReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468A1708365200A106A9 /* STEPFileReader.h */; }; - 2B7F4C391708365200A106A9 /* STEPFileReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468A1708365200A106A9 /* STEPFileReader.h */; }; - 2B7F4C3A1708365200A106A9 /* STEPFileReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468A1708365200A106A9 /* STEPFileReader.h */; }; - 2B7F4C3B1708365200A106A9 /* STEPFileReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468A1708365200A106A9 /* STEPFileReader.h */; }; - 2B7F4C3C1708365200A106A9 /* STLExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F468B1708365200A106A9 /* STLExporter.cpp */; }; - 2B7F4C3D1708365200A106A9 /* STLExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F468B1708365200A106A9 /* STLExporter.cpp */; }; - 2B7F4C3E1708365200A106A9 /* STLExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F468B1708365200A106A9 /* STLExporter.cpp */; }; - 2B7F4C3F1708365200A106A9 /* STLExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F468B1708365200A106A9 /* STLExporter.cpp */; }; - 2B7F4C401708365200A106A9 /* STLExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F468B1708365200A106A9 /* STLExporter.cpp */; }; - 2B7F4C411708365200A106A9 /* STLExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468C1708365200A106A9 /* STLExporter.h */; }; - 2B7F4C421708365200A106A9 /* STLExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468C1708365200A106A9 /* STLExporter.h */; }; - 2B7F4C431708365200A106A9 /* STLExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468C1708365200A106A9 /* STLExporter.h */; }; - 2B7F4C441708365200A106A9 /* STLExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468C1708365200A106A9 /* STLExporter.h */; }; - 2B7F4C451708365200A106A9 /* STLExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468C1708365200A106A9 /* STLExporter.h */; }; - 2B7F4C461708365200A106A9 /* STLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F468D1708365200A106A9 /* STLLoader.cpp */; }; - 2B7F4C471708365200A106A9 /* STLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F468D1708365200A106A9 /* STLLoader.cpp */; }; - 2B7F4C481708365200A106A9 /* STLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F468D1708365200A106A9 /* STLLoader.cpp */; }; - 2B7F4C491708365200A106A9 /* STLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F468D1708365200A106A9 /* STLLoader.cpp */; }; - 2B7F4C4A1708365200A106A9 /* STLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F468D1708365200A106A9 /* STLLoader.cpp */; }; - 2B7F4C4B1708365200A106A9 /* STLLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468E1708365200A106A9 /* STLLoader.h */; }; - 2B7F4C4C1708365200A106A9 /* STLLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468E1708365200A106A9 /* STLLoader.h */; }; - 2B7F4C4D1708365200A106A9 /* STLLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468E1708365200A106A9 /* STLLoader.h */; }; - 2B7F4C4E1708365200A106A9 /* STLLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468E1708365200A106A9 /* STLLoader.h */; }; - 2B7F4C4F1708365200A106A9 /* STLLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468E1708365200A106A9 /* STLLoader.h */; }; - 2B7F4C501708365200A106A9 /* StreamReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468F1708365200A106A9 /* StreamReader.h */; }; - 2B7F4C511708365200A106A9 /* StreamReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468F1708365200A106A9 /* StreamReader.h */; }; - 2B7F4C521708365200A106A9 /* StreamReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468F1708365200A106A9 /* StreamReader.h */; }; - 2B7F4C531708365200A106A9 /* StreamReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468F1708365200A106A9 /* StreamReader.h */; }; - 2B7F4C541708365200A106A9 /* StreamReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F468F1708365200A106A9 /* StreamReader.h */; }; - 2B7F4C551708365200A106A9 /* StringComparison.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46901708365200A106A9 /* StringComparison.h */; }; - 2B7F4C561708365200A106A9 /* StringComparison.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46901708365200A106A9 /* StringComparison.h */; }; - 2B7F4C571708365200A106A9 /* StringComparison.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46901708365200A106A9 /* StringComparison.h */; }; - 2B7F4C581708365200A106A9 /* StringComparison.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46901708365200A106A9 /* StringComparison.h */; }; - 2B7F4C591708365200A106A9 /* StringComparison.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46901708365200A106A9 /* StringComparison.h */; }; - 2B7F4C5A1708365200A106A9 /* Subdivision.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46911708365200A106A9 /* Subdivision.cpp */; }; - 2B7F4C5B1708365200A106A9 /* Subdivision.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46911708365200A106A9 /* Subdivision.cpp */; }; - 2B7F4C5C1708365200A106A9 /* Subdivision.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46911708365200A106A9 /* Subdivision.cpp */; }; - 2B7F4C5D1708365200A106A9 /* Subdivision.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46911708365200A106A9 /* Subdivision.cpp */; }; - 2B7F4C5E1708365200A106A9 /* Subdivision.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46911708365200A106A9 /* Subdivision.cpp */; }; - 2B7F4C5F1708365200A106A9 /* Subdivision.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46921708365200A106A9 /* Subdivision.h */; }; - 2B7F4C601708365200A106A9 /* Subdivision.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46921708365200A106A9 /* Subdivision.h */; }; - 2B7F4C611708365200A106A9 /* Subdivision.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46921708365200A106A9 /* Subdivision.h */; }; - 2B7F4C621708365200A106A9 /* Subdivision.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46921708365200A106A9 /* Subdivision.h */; }; - 2B7F4C631708365200A106A9 /* Subdivision.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46921708365200A106A9 /* Subdivision.h */; }; - 2B7F4C641708365200A106A9 /* TargetAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46931708365200A106A9 /* TargetAnimation.cpp */; }; - 2B7F4C651708365200A106A9 /* TargetAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46931708365200A106A9 /* TargetAnimation.cpp */; }; - 2B7F4C661708365200A106A9 /* TargetAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46931708365200A106A9 /* TargetAnimation.cpp */; }; - 2B7F4C671708365200A106A9 /* TargetAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46931708365200A106A9 /* TargetAnimation.cpp */; }; - 2B7F4C681708365200A106A9 /* TargetAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46931708365200A106A9 /* TargetAnimation.cpp */; }; - 2B7F4C691708365200A106A9 /* TargetAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46941708365200A106A9 /* TargetAnimation.h */; }; - 2B7F4C6A1708365200A106A9 /* TargetAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46941708365200A106A9 /* TargetAnimation.h */; }; - 2B7F4C6B1708365200A106A9 /* TargetAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46941708365200A106A9 /* TargetAnimation.h */; }; - 2B7F4C6C1708365200A106A9 /* TargetAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46941708365200A106A9 /* TargetAnimation.h */; }; - 2B7F4C6D1708365200A106A9 /* TargetAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46941708365200A106A9 /* TargetAnimation.h */; }; - 2B7F4C781708365200A106A9 /* TextureTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46971708365200A106A9 /* TextureTransform.cpp */; }; - 2B7F4C791708365200A106A9 /* TextureTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46971708365200A106A9 /* TextureTransform.cpp */; }; - 2B7F4C7A1708365200A106A9 /* TextureTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46971708365200A106A9 /* TextureTransform.cpp */; }; - 2B7F4C7B1708365200A106A9 /* TextureTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46971708365200A106A9 /* TextureTransform.cpp */; }; - 2B7F4C7C1708365200A106A9 /* TextureTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46971708365200A106A9 /* TextureTransform.cpp */; }; - 2B7F4C7D1708365200A106A9 /* TextureTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46981708365200A106A9 /* TextureTransform.h */; }; - 2B7F4C7E1708365200A106A9 /* TextureTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46981708365200A106A9 /* TextureTransform.h */; }; - 2B7F4C7F1708365200A106A9 /* TextureTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46981708365200A106A9 /* TextureTransform.h */; }; - 2B7F4C801708365200A106A9 /* TextureTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46981708365200A106A9 /* TextureTransform.h */; }; - 2B7F4C811708365200A106A9 /* TextureTransform.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46981708365200A106A9 /* TextureTransform.h */; }; - 2B7F4C821708365200A106A9 /* TinyFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46991708365200A106A9 /* TinyFormatter.h */; }; - 2B7F4C831708365200A106A9 /* TinyFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46991708365200A106A9 /* TinyFormatter.h */; }; - 2B7F4C841708365200A106A9 /* TinyFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46991708365200A106A9 /* TinyFormatter.h */; }; - 2B7F4C851708365200A106A9 /* TinyFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46991708365200A106A9 /* TinyFormatter.h */; }; - 2B7F4C861708365200A106A9 /* TinyFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46991708365200A106A9 /* TinyFormatter.h */; }; - 2B7F4C871708365200A106A9 /* TriangulateProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F469A1708365200A106A9 /* TriangulateProcess.cpp */; }; - 2B7F4C881708365200A106A9 /* TriangulateProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F469A1708365200A106A9 /* TriangulateProcess.cpp */; }; - 2B7F4C891708365200A106A9 /* TriangulateProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F469A1708365200A106A9 /* TriangulateProcess.cpp */; }; - 2B7F4C8A1708365200A106A9 /* TriangulateProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F469A1708365200A106A9 /* TriangulateProcess.cpp */; }; - 2B7F4C8B1708365200A106A9 /* TriangulateProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F469A1708365200A106A9 /* TriangulateProcess.cpp */; }; - 2B7F4C8C1708365200A106A9 /* TriangulateProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F469B1708365200A106A9 /* TriangulateProcess.h */; }; - 2B7F4C8D1708365200A106A9 /* TriangulateProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F469B1708365200A106A9 /* TriangulateProcess.h */; }; - 2B7F4C8E1708365200A106A9 /* TriangulateProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F469B1708365200A106A9 /* TriangulateProcess.h */; }; - 2B7F4C8F1708365200A106A9 /* TriangulateProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F469B1708365200A106A9 /* TriangulateProcess.h */; }; - 2B7F4C901708365200A106A9 /* TriangulateProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F469B1708365200A106A9 /* TriangulateProcess.h */; }; - 2B7F4C9B1708365200A106A9 /* ValidateDataStructure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F469E1708365200A106A9 /* ValidateDataStructure.cpp */; }; - 2B7F4C9C1708365200A106A9 /* ValidateDataStructure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F469E1708365200A106A9 /* ValidateDataStructure.cpp */; }; - 2B7F4C9D1708365200A106A9 /* ValidateDataStructure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F469E1708365200A106A9 /* ValidateDataStructure.cpp */; }; - 2B7F4C9E1708365200A106A9 /* ValidateDataStructure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F469E1708365200A106A9 /* ValidateDataStructure.cpp */; }; - 2B7F4C9F1708365200A106A9 /* ValidateDataStructure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F469E1708365200A106A9 /* ValidateDataStructure.cpp */; }; - 2B7F4CA01708365200A106A9 /* ValidateDataStructure.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F469F1708365200A106A9 /* ValidateDataStructure.h */; }; - 2B7F4CA11708365200A106A9 /* ValidateDataStructure.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F469F1708365200A106A9 /* ValidateDataStructure.h */; }; - 2B7F4CA21708365200A106A9 /* ValidateDataStructure.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F469F1708365200A106A9 /* ValidateDataStructure.h */; }; - 2B7F4CA31708365200A106A9 /* ValidateDataStructure.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F469F1708365200A106A9 /* ValidateDataStructure.h */; }; - 2B7F4CA41708365200A106A9 /* ValidateDataStructure.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F469F1708365200A106A9 /* ValidateDataStructure.h */; }; - 2B7F4CA51708365200A106A9 /* Vertex.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46A01708365200A106A9 /* Vertex.h */; }; - 2B7F4CA61708365200A106A9 /* Vertex.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46A01708365200A106A9 /* Vertex.h */; }; - 2B7F4CA71708365200A106A9 /* Vertex.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46A01708365200A106A9 /* Vertex.h */; }; - 2B7F4CA81708365200A106A9 /* Vertex.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46A01708365200A106A9 /* Vertex.h */; }; - 2B7F4CA91708365200A106A9 /* Vertex.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46A01708365200A106A9 /* Vertex.h */; }; - 2B7F4CAA1708365200A106A9 /* VertexTriangleAdjacency.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46A11708365200A106A9 /* VertexTriangleAdjacency.cpp */; }; - 2B7F4CAB1708365200A106A9 /* VertexTriangleAdjacency.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46A11708365200A106A9 /* VertexTriangleAdjacency.cpp */; }; - 2B7F4CAC1708365200A106A9 /* VertexTriangleAdjacency.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46A11708365200A106A9 /* VertexTriangleAdjacency.cpp */; }; - 2B7F4CAD1708365200A106A9 /* VertexTriangleAdjacency.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46A11708365200A106A9 /* VertexTriangleAdjacency.cpp */; }; - 2B7F4CAE1708365200A106A9 /* VertexTriangleAdjacency.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2B7F46A11708365200A106A9 /* VertexTriangleAdjacency.cpp */; }; - 2B7F4CAF1708365200A106A9 /* VertexTriangleAdjacency.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46A21708365200A106A9 /* VertexTriangleAdjacency.h */; }; - 2B7F4CB01708365200A106A9 /* VertexTriangleAdjacency.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46A21708365200A106A9 /* VertexTriangleAdjacency.h */; }; - 2B7F4CB11708365200A106A9 /* VertexTriangleAdjacency.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46A21708365200A106A9 /* VertexTriangleAdjacency.h */; }; - 2B7F4CB21708365200A106A9 /* VertexTriangleAdjacency.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46A21708365200A106A9 /* VertexTriangleAdjacency.h */; }; - 2B7F4CB31708365200A106A9 /* VertexTriangleAdjacency.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46A21708365200A106A9 /* VertexTriangleAdjacency.h */; }; - 2B7F4CB41708365200A106A9 /* Win32DebugLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46A31708365200A106A9 /* Win32DebugLogStream.h */; }; - 2B7F4CB51708365200A106A9 /* Win32DebugLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46A31708365200A106A9 /* Win32DebugLogStream.h */; }; - 2B7F4CB61708365200A106A9 /* Win32DebugLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46A31708365200A106A9 /* Win32DebugLogStream.h */; }; - 2B7F4CB71708365200A106A9 /* Win32DebugLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46A31708365200A106A9 /* Win32DebugLogStream.h */; }; - 2B7F4CB81708365200A106A9 /* Win32DebugLogStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B7F46A31708365200A106A9 /* Win32DebugLogStream.h */; }; - 2BA44E11170862D800C78A66 /* libstdc++.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BA44E10170862D800C78A66 /* libstdc++.dylib */; }; - 2BA44E12170862DE00C78A66 /* libstdc++.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BA44E10170862D800C78A66 /* libstdc++.dylib */; }; - 2BA44E13170862E400C78A66 /* libstdc++.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BA44E10170862D800C78A66 /* libstdc++.dylib */; }; - 2BA44E14170862EA00C78A66 /* libstdc++.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BA44E10170862D800C78A66 /* libstdc++.dylib */; }; - 2BA44E1A1708680600C78A66 /* libstdc++.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BA44E10170862D800C78A66 /* libstdc++.dylib */; }; - 3AB8A3AF0E50D67A00606590 /* MDCFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3AB0E50D67A00606590 /* MDCFileData.h */; }; - 3AB8A3B00E50D67A00606590 /* MDCLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AB8A3AC0E50D67A00606590 /* MDCLoader.cpp */; }; - 3AB8A3B10E50D67A00606590 /* MDCLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3AD0E50D67A00606590 /* MDCLoader.h */; }; - 3AB8A3B20E50D67A00606590 /* MDCNormalTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3AE0E50D67A00606590 /* MDCNormalTable.h */; }; - 3AB8A3BA0E50D6DB00606590 /* LWOFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3B70E50D6DB00606590 /* LWOFileData.h */; }; - 3AB8A3BB0E50D6DB00606590 /* LWOLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AB8A3B80E50D6DB00606590 /* LWOLoader.cpp */; }; - 3AB8A3BC0E50D6DB00606590 /* LWOLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3B90E50D6DB00606590 /* LWOLoader.h */; }; - 3AB8A3C60E50D77900606590 /* HMPFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3C50E50D77900606590 /* HMPFileData.h */; }; - 3AB8A7DD0E53715F00606590 /* LWOMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AB8A7DC0E53715F00606590 /* LWOMaterial.cpp */; }; - 3AF45AF90E4B716800207D74 /* 3DSConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A860E4B716800207D74 /* 3DSConverter.cpp */; }; - 3AF45AFB0E4B716800207D74 /* 3DSHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A880E4B716800207D74 /* 3DSHelper.h */; }; - 3AF45AFC0E4B716800207D74 /* 3DSLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A890E4B716800207D74 /* 3DSLoader.cpp */; }; - 3AF45AFD0E4B716800207D74 /* 3DSLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A8A0E4B716800207D74 /* 3DSLoader.h */; }; - 3AF45B010E4B716800207D74 /* ASELoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A8E0E4B716800207D74 /* ASELoader.cpp */; }; - 3AF45B020E4B716800207D74 /* ASELoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A8F0E4B716800207D74 /* ASELoader.h */; }; - 3AF45B030E4B716800207D74 /* ASEParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A900E4B716800207D74 /* ASEParser.cpp */; }; - 3AF45B040E4B716800207D74 /* ASEParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A910E4B716800207D74 /* ASEParser.h */; }; - 3AF45B1B0E4B716800207D74 /* HalfLifeFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AA90E4B716800207D74 /* HalfLifeFileData.h */; }; - 3AF45B1D0E4B716800207D74 /* HMPLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AAB0E4B716800207D74 /* HMPLoader.cpp */; }; - 3AF45B1E0E4B716800207D74 /* HMPLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AAC0E4B716800207D74 /* HMPLoader.h */; }; - 3AF45B2A0E4B716800207D74 /* MD2FileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AB80E4B716800207D74 /* MD2FileData.h */; }; - 3AF45B2B0E4B716800207D74 /* MD2Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AB90E4B716800207D74 /* MD2Loader.cpp */; }; - 3AF45B2C0E4B716800207D74 /* MD2Loader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABA0E4B716800207D74 /* MD2Loader.h */; }; - 3AF45B2D0E4B716800207D74 /* MD2NormalTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABB0E4B716800207D74 /* MD2NormalTable.h */; }; - 3AF45B2E0E4B716800207D74 /* MD3FileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABC0E4B716800207D74 /* MD3FileData.h */; }; - 3AF45B2F0E4B716800207D74 /* MD3Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45ABD0E4B716800207D74 /* MD3Loader.cpp */; }; - 3AF45B300E4B716800207D74 /* MD3Loader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABE0E4B716800207D74 /* MD3Loader.h */; }; - 3AF45B340E4B716800207D74 /* MD5Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AC20E4B716800207D74 /* MD5Loader.cpp */; }; - 3AF45B350E4B716800207D74 /* MD5Loader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC30E4B716800207D74 /* MD5Loader.h */; }; - 3AF45B360E4B716800207D74 /* MD5Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AC40E4B716800207D74 /* MD5Parser.cpp */; }; - 3AF45B370E4B716800207D74 /* MD5Parser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC50E4B716800207D74 /* MD5Parser.h */; }; - 3AF45B380E4B716800207D74 /* MDLDefaultColorMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC60E4B716800207D74 /* MDLDefaultColorMap.h */; }; - 3AF45B390E4B716800207D74 /* MDLFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC70E4B716800207D74 /* MDLFileData.h */; }; - 3AF45B3A0E4B716800207D74 /* MDLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AC80E4B716800207D74 /* MDLLoader.cpp */; }; - 3AF45B3B0E4B716800207D74 /* MDLLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC90E4B716800207D74 /* MDLLoader.h */; }; - 3AF45B3C0E4B716800207D74 /* MDLMaterialLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45ACA0E4B716800207D74 /* MDLMaterialLoader.cpp */; }; - 3AF45B460E4B716800207D74 /* PlyLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AD40E4B716800207D74 /* PlyLoader.cpp */; }; - 3AF45B470E4B716800207D74 /* PlyLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AD50E4B716800207D74 /* PlyLoader.h */; }; - 3AF45B480E4B716800207D74 /* PlyParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AD60E4B716800207D74 /* PlyParser.cpp */; }; - 3AF45B490E4B716800207D74 /* PlyParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AD70E4B716800207D74 /* PlyParser.h */; }; - 3AF45B520E4B716800207D74 /* SMDLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AE20E4B716800207D74 /* SMDLoader.cpp */; }; - 3AF45B530E4B716800207D74 /* SMDLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AE30E4B716800207D74 /* SMDLoader.h */; }; - 3AF45B640E4B716800207D74 /* XFileHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AF40E4B716800207D74 /* XFileHelper.h */; }; - 3AF45B650E4B716800207D74 /* XFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AF50E4B716800207D74 /* XFileImporter.cpp */; }; - 3AF45B660E4B716800207D74 /* XFileImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AF60E4B716800207D74 /* XFileImporter.h */; }; - 3AF45B670E4B716800207D74 /* XFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AF70E4B716800207D74 /* XFileParser.cpp */; }; - 3AF45B680E4B716800207D74 /* XFileParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AF80E4B716800207D74 /* XFileParser.h */; }; - 7411B15011416D5E00BCD793 /* CSMLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B14E11416D5E00BCD793 /* CSMLoader.cpp */; }; - 7411B15111416D5E00BCD793 /* CSMLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B14F11416D5E00BCD793 /* CSMLoader.h */; }; - 7411B15211416D5E00BCD793 /* CSMLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B14E11416D5E00BCD793 /* CSMLoader.cpp */; }; - 7411B15311416D5E00BCD793 /* CSMLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B14F11416D5E00BCD793 /* CSMLoader.h */; }; - 7411B15411416D5E00BCD793 /* CSMLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B14E11416D5E00BCD793 /* CSMLoader.cpp */; }; - 7411B15511416D5E00BCD793 /* CSMLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B14F11416D5E00BCD793 /* CSMLoader.h */; }; - 7411B15611416D5E00BCD793 /* CSMLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B14E11416D5E00BCD793 /* CSMLoader.cpp */; }; - 7411B15711416D5E00BCD793 /* CSMLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B14F11416D5E00BCD793 /* CSMLoader.h */; }; - 7411B15B11416DDD00BCD793 /* LWSLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B15911416DDD00BCD793 /* LWSLoader.cpp */; }; - 7411B15C11416DDD00BCD793 /* LWSLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B15A11416DDD00BCD793 /* LWSLoader.h */; }; - 7411B15D11416DDD00BCD793 /* LWSLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B15911416DDD00BCD793 /* LWSLoader.cpp */; }; - 7411B15E11416DDD00BCD793 /* LWSLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B15A11416DDD00BCD793 /* LWSLoader.h */; }; - 7411B15F11416DDD00BCD793 /* LWSLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B15911416DDD00BCD793 /* LWSLoader.cpp */; }; - 7411B16011416DDD00BCD793 /* LWSLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B15A11416DDD00BCD793 /* LWSLoader.h */; }; - 7411B16111416DDD00BCD793 /* LWSLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B15911416DDD00BCD793 /* LWSLoader.cpp */; }; - 7411B16211416DDD00BCD793 /* LWSLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B15A11416DDD00BCD793 /* LWSLoader.h */; }; - 7411B16511416DF400BCD793 /* LWOAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B16311416DF400BCD793 /* LWOAnimation.cpp */; }; - 7411B16611416DF400BCD793 /* LWOAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B16411416DF400BCD793 /* LWOAnimation.h */; }; - 7411B16711416DF400BCD793 /* LWOAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B16311416DF400BCD793 /* LWOAnimation.cpp */; }; - 7411B16811416DF400BCD793 /* LWOAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B16411416DF400BCD793 /* LWOAnimation.h */; }; - 7411B16911416DF400BCD793 /* LWOAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B16311416DF400BCD793 /* LWOAnimation.cpp */; }; - 7411B16A11416DF400BCD793 /* LWOAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B16411416DF400BCD793 /* LWOAnimation.h */; }; - 7411B16B11416DF400BCD793 /* LWOAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B16311416DF400BCD793 /* LWOAnimation.cpp */; }; - 7411B16C11416DF400BCD793 /* LWOAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B16411416DF400BCD793 /* LWOAnimation.h */; }; - 7411B17211416E2500BCD793 /* MS3DLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B17011416E2500BCD793 /* MS3DLoader.cpp */; }; - 7411B17311416E2500BCD793 /* MS3DLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B17111416E2500BCD793 /* MS3DLoader.h */; }; - 7411B17411416E2500BCD793 /* MS3DLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B17011416E2500BCD793 /* MS3DLoader.cpp */; }; - 7411B17511416E2500BCD793 /* MS3DLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B17111416E2500BCD793 /* MS3DLoader.h */; }; - 7411B17611416E2500BCD793 /* MS3DLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B17011416E2500BCD793 /* MS3DLoader.cpp */; }; - 7411B17711416E2500BCD793 /* MS3DLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B17111416E2500BCD793 /* MS3DLoader.h */; }; - 7411B17811416E2500BCD793 /* MS3DLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B17011416E2500BCD793 /* MS3DLoader.cpp */; }; - 7411B17911416E2500BCD793 /* MS3DLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B17111416E2500BCD793 /* MS3DLoader.h */; }; - 7411B18D11416EBC00BCD793 /* UnrealLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B18B11416EBC00BCD793 /* UnrealLoader.cpp */; }; - 7411B18E11416EBC00BCD793 /* UnrealLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B18C11416EBC00BCD793 /* UnrealLoader.h */; }; - 7411B18F11416EBC00BCD793 /* UnrealLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B18B11416EBC00BCD793 /* UnrealLoader.cpp */; }; - 7411B19011416EBC00BCD793 /* UnrealLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B18C11416EBC00BCD793 /* UnrealLoader.h */; }; - 7411B19111416EBC00BCD793 /* UnrealLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B18B11416EBC00BCD793 /* UnrealLoader.cpp */; }; - 7411B19211416EBC00BCD793 /* UnrealLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B18C11416EBC00BCD793 /* UnrealLoader.h */; }; - 7411B19311416EBC00BCD793 /* UnrealLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B18B11416EBC00BCD793 /* UnrealLoader.cpp */; }; - 7411B19411416EBC00BCD793 /* UnrealLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B18C11416EBC00BCD793 /* UnrealLoader.h */; }; - 745FF840113ECB080020C31B /* 3DSHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A880E4B716800207D74 /* 3DSHelper.h */; }; - 745FF841113ECB080020C31B /* 3DSLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A8A0E4B716800207D74 /* 3DSLoader.h */; }; - 745FF842113ECB080020C31B /* ASELoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A8F0E4B716800207D74 /* ASELoader.h */; }; - 745FF843113ECB080020C31B /* ASEParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A910E4B716800207D74 /* ASEParser.h */; }; - 745FF850113ECB080020C31B /* HalfLifeFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AA90E4B716800207D74 /* HalfLifeFileData.h */; }; - 745FF851113ECB080020C31B /* HMPLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AAC0E4B716800207D74 /* HMPLoader.h */; }; - 745FF856113ECB080020C31B /* MD2FileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AB80E4B716800207D74 /* MD2FileData.h */; }; - 745FF857113ECB080020C31B /* MD2Loader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABA0E4B716800207D74 /* MD2Loader.h */; }; - 745FF858113ECB080020C31B /* MD2NormalTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABB0E4B716800207D74 /* MD2NormalTable.h */; }; - 745FF859113ECB080020C31B /* MD3FileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABC0E4B716800207D74 /* MD3FileData.h */; }; - 745FF85A113ECB080020C31B /* MD3Loader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABE0E4B716800207D74 /* MD3Loader.h */; }; - 745FF85B113ECB080020C31B /* MD5Loader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC30E4B716800207D74 /* MD5Loader.h */; }; - 745FF85C113ECB080020C31B /* MD5Parser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC50E4B716800207D74 /* MD5Parser.h */; }; - 745FF85D113ECB080020C31B /* MDLDefaultColorMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC60E4B716800207D74 /* MDLDefaultColorMap.h */; }; - 745FF85E113ECB080020C31B /* MDLFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC70E4B716800207D74 /* MDLFileData.h */; }; - 745FF85F113ECB080020C31B /* MDLLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC90E4B716800207D74 /* MDLLoader.h */; }; - 745FF866113ECB080020C31B /* PlyLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AD50E4B716800207D74 /* PlyLoader.h */; }; - 745FF867113ECB080020C31B /* PlyParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AD70E4B716800207D74 /* PlyParser.h */; }; - 745FF86C113ECB080020C31B /* SMDLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AE30E4B716800207D74 /* SMDLoader.h */; }; - 745FF876113ECB080020C31B /* XFileHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AF40E4B716800207D74 /* XFileHelper.h */; }; - 745FF877113ECB080020C31B /* XFileImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AF60E4B716800207D74 /* XFileImporter.h */; }; - 745FF878113ECB080020C31B /* XFileParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AF80E4B716800207D74 /* XFileParser.h */; }; - 745FF87B113ECB080020C31B /* MDCFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3AB0E50D67A00606590 /* MDCFileData.h */; }; - 745FF87C113ECB080020C31B /* MDCLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3AD0E50D67A00606590 /* MDCLoader.h */; }; - 745FF87D113ECB080020C31B /* MDCNormalTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3AE0E50D67A00606590 /* MDCNormalTable.h */; }; - 745FF87F113ECB080020C31B /* LWOFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3B70E50D6DB00606590 /* LWOFileData.h */; }; - 745FF880113ECB080020C31B /* LWOLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3B90E50D6DB00606590 /* LWOLoader.h */; }; - 745FF881113ECB080020C31B /* HMPFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3C50E50D77900606590 /* HMPFileData.h */; }; - 745FF889113ECB080020C31B /* ACLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFD10F5DD87000124155 /* ACLoader.h */; }; - 745FF88A113ECB080020C31B /* IRRLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFDA0F5DD90800124155 /* IRRLoader.h */; }; - 745FF88B113ECB080020C31B /* IRRMeshLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFDC0F5DD90800124155 /* IRRMeshLoader.h */; }; - 745FF88C113ECB080020C31B /* IRRShared.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFDE0F5DD90800124155 /* IRRShared.h */; }; - 745FF890113ECB080020C31B /* NFFLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFF50F5DD96100124155 /* NFFLoader.h */; }; - 745FF892113ECB080020C31B /* Q3DLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0070F5DD9DD00124155 /* Q3DLoader.h */; }; - 745FF893113ECB080020C31B /* BVHLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB00C0F5DD9F400124155 /* BVHLoader.h */; }; - 745FF894113ECB080020C31B /* OFFLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0130F5DDA1400124155 /* OFFLoader.h */; }; - 745FF895113ECB080020C31B /* RawLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB01B0F5DDA4400124155 /* RawLoader.h */; }; - 745FF896113ECB080020C31B /* DXFLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0210F5DDA5700124155 /* DXFLoader.h */; }; - 745FF897113ECB080020C31B /* TerragenLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB02F0F5DDAB500124155 /* TerragenLoader.h */; }; - 745FF898113ECB080020C31B /* irrXMLWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0360F5DDB1B00124155 /* irrXMLWrapper.h */; }; - 745FF8AA113ECB080020C31B /* B3DImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0870F5DDE0700124155 /* B3DImporter.h */; }; - 745FF8B0113ECB080020C31B /* 3DSConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A860E4B716800207D74 /* 3DSConverter.cpp */; }; - 745FF8B1113ECB080020C31B /* 3DSLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A890E4B716800207D74 /* 3DSLoader.cpp */; }; - 745FF8B3113ECB080020C31B /* ASELoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A8E0E4B716800207D74 /* ASELoader.cpp */; }; - 745FF8B4113ECB080020C31B /* ASEParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A900E4B716800207D74 /* ASEParser.cpp */; }; - 745FF8BF113ECB080020C31B /* HMPLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AAB0E4B716800207D74 /* HMPLoader.cpp */; }; - 745FF8C5113ECB080020C31B /* MD2Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AB90E4B716800207D74 /* MD2Loader.cpp */; }; - 745FF8C6113ECB080020C31B /* MD3Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45ABD0E4B716800207D74 /* MD3Loader.cpp */; }; - 745FF8C7113ECB080020C31B /* MD5Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AC20E4B716800207D74 /* MD5Loader.cpp */; }; - 745FF8C8113ECB080020C31B /* MD5Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AC40E4B716800207D74 /* MD5Parser.cpp */; }; - 745FF8C9113ECB080020C31B /* MDLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AC80E4B716800207D74 /* MDLLoader.cpp */; }; - 745FF8CA113ECB080020C31B /* MDLMaterialLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45ACA0E4B716800207D74 /* MDLMaterialLoader.cpp */; }; - 745FF8CE113ECB080020C31B /* PlyLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AD40E4B716800207D74 /* PlyLoader.cpp */; }; - 745FF8CF113ECB080020C31B /* PlyParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AD60E4B716800207D74 /* PlyParser.cpp */; }; - 745FF8D3113ECB080020C31B /* SMDLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AE20E4B716800207D74 /* SMDLoader.cpp */; }; - 745FF8DB113ECB080020C31B /* XFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AF50E4B716800207D74 /* XFileImporter.cpp */; }; - 745FF8DC113ECB080020C31B /* XFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AF70E4B716800207D74 /* XFileParser.cpp */; }; - 745FF8DD113ECB080020C31B /* MDCLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AB8A3AC0E50D67A00606590 /* MDCLoader.cpp */; }; - 745FF8DF113ECB080020C31B /* LWOLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AB8A3B80E50D6DB00606590 /* LWOLoader.cpp */; }; - 745FF8E1113ECB080020C31B /* LWOMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AB8A7DC0E53715F00606590 /* LWOMaterial.cpp */; }; - 745FF8E2113ECB080020C31B /* ACLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFD00F5DD87000124155 /* ACLoader.cpp */; }; - 745FF8E3113ECB080020C31B /* IRRLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFD90F5DD90800124155 /* IRRLoader.cpp */; }; - 745FF8E4113ECB080020C31B /* IRRMeshLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFDB0F5DD90800124155 /* IRRMeshLoader.cpp */; }; - 745FF8E5113ECB080020C31B /* IRRShared.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFDD0F5DD90800124155 /* IRRShared.cpp */; }; - 745FF8E8113ECB080020C31B /* NFFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFF60F5DD96100124155 /* NFFLoader.cpp */; }; - 745FF8EA113ECB080020C31B /* Q3DLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0060F5DD9DD00124155 /* Q3DLoader.cpp */; }; - 745FF8EB113ECB080020C31B /* BVHLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB00D0F5DD9F400124155 /* BVHLoader.cpp */; }; - 745FF8EC113ECB080020C31B /* OFFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0140F5DDA1400124155 /* OFFLoader.cpp */; }; - 745FF8ED113ECB080020C31B /* RawLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB01C0F5DDA4400124155 /* RawLoader.cpp */; }; - 745FF8EE113ECB080020C31B /* DXFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0220F5DDA5700124155 /* DXFLoader.cpp */; }; - 745FF8EF113ECB080020C31B /* LWOBLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0270F5DDA9200124155 /* LWOBLoader.cpp */; }; - 745FF8F0113ECB080020C31B /* TerragenLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0300F5DDAB500124155 /* TerragenLoader.cpp */; }; - 745FF8FC113ECB080020C31B /* B3DImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0880F5DDE0700124155 /* B3DImporter.cpp */; }; - 745FF923113ECC660020C31B /* 3DSHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A880E4B716800207D74 /* 3DSHelper.h */; }; - 745FF924113ECC660020C31B /* 3DSLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A8A0E4B716800207D74 /* 3DSLoader.h */; }; - 745FF925113ECC660020C31B /* ASELoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A8F0E4B716800207D74 /* ASELoader.h */; }; - 745FF926113ECC660020C31B /* ASEParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A910E4B716800207D74 /* ASEParser.h */; }; - 745FF933113ECC660020C31B /* HalfLifeFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AA90E4B716800207D74 /* HalfLifeFileData.h */; }; - 745FF934113ECC660020C31B /* HMPLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AAC0E4B716800207D74 /* HMPLoader.h */; }; - 745FF939113ECC660020C31B /* MD2FileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AB80E4B716800207D74 /* MD2FileData.h */; }; - 745FF93A113ECC660020C31B /* MD2Loader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABA0E4B716800207D74 /* MD2Loader.h */; }; - 745FF93B113ECC660020C31B /* MD2NormalTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABB0E4B716800207D74 /* MD2NormalTable.h */; }; - 745FF93C113ECC660020C31B /* MD3FileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABC0E4B716800207D74 /* MD3FileData.h */; }; - 745FF93D113ECC660020C31B /* MD3Loader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABE0E4B716800207D74 /* MD3Loader.h */; }; - 745FF93E113ECC660020C31B /* MD5Loader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC30E4B716800207D74 /* MD5Loader.h */; }; - 745FF93F113ECC660020C31B /* MD5Parser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC50E4B716800207D74 /* MD5Parser.h */; }; - 745FF940113ECC660020C31B /* MDLDefaultColorMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC60E4B716800207D74 /* MDLDefaultColorMap.h */; }; - 745FF941113ECC660020C31B /* MDLFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC70E4B716800207D74 /* MDLFileData.h */; }; - 745FF942113ECC660020C31B /* MDLLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC90E4B716800207D74 /* MDLLoader.h */; }; - 745FF949113ECC660020C31B /* PlyLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AD50E4B716800207D74 /* PlyLoader.h */; }; - 745FF94A113ECC660020C31B /* PlyParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AD70E4B716800207D74 /* PlyParser.h */; }; - 745FF94F113ECC660020C31B /* SMDLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AE30E4B716800207D74 /* SMDLoader.h */; }; - 745FF959113ECC660020C31B /* XFileHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AF40E4B716800207D74 /* XFileHelper.h */; }; - 745FF95A113ECC660020C31B /* XFileImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AF60E4B716800207D74 /* XFileImporter.h */; }; - 745FF95B113ECC660020C31B /* XFileParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AF80E4B716800207D74 /* XFileParser.h */; }; - 745FF95E113ECC660020C31B /* MDCFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3AB0E50D67A00606590 /* MDCFileData.h */; }; - 745FF95F113ECC660020C31B /* MDCLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3AD0E50D67A00606590 /* MDCLoader.h */; }; - 745FF960113ECC660020C31B /* MDCNormalTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3AE0E50D67A00606590 /* MDCNormalTable.h */; }; - 745FF962113ECC660020C31B /* LWOFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3B70E50D6DB00606590 /* LWOFileData.h */; }; - 745FF963113ECC660020C31B /* LWOLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3B90E50D6DB00606590 /* LWOLoader.h */; }; - 745FF964113ECC660020C31B /* HMPFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3C50E50D77900606590 /* HMPFileData.h */; }; - 745FF96C113ECC660020C31B /* ACLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFD10F5DD87000124155 /* ACLoader.h */; }; - 745FF96D113ECC660020C31B /* IRRLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFDA0F5DD90800124155 /* IRRLoader.h */; }; - 745FF96E113ECC660020C31B /* IRRMeshLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFDC0F5DD90800124155 /* IRRMeshLoader.h */; }; - 745FF96F113ECC660020C31B /* IRRShared.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFDE0F5DD90800124155 /* IRRShared.h */; }; - 745FF973113ECC660020C31B /* NFFLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFF50F5DD96100124155 /* NFFLoader.h */; }; - 745FF975113ECC660020C31B /* Q3DLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0070F5DD9DD00124155 /* Q3DLoader.h */; }; - 745FF976113ECC660020C31B /* BVHLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB00C0F5DD9F400124155 /* BVHLoader.h */; }; - 745FF977113ECC660020C31B /* OFFLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0130F5DDA1400124155 /* OFFLoader.h */; }; - 745FF978113ECC660020C31B /* RawLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB01B0F5DDA4400124155 /* RawLoader.h */; }; - 745FF979113ECC660020C31B /* DXFLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0210F5DDA5700124155 /* DXFLoader.h */; }; - 745FF97A113ECC660020C31B /* TerragenLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB02F0F5DDAB500124155 /* TerragenLoader.h */; }; - 745FF97B113ECC660020C31B /* irrXMLWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0360F5DDB1B00124155 /* irrXMLWrapper.h */; }; - 745FF98D113ECC660020C31B /* B3DImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0870F5DDE0700124155 /* B3DImporter.h */; }; - 745FF993113ECC660020C31B /* 3DSConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A860E4B716800207D74 /* 3DSConverter.cpp */; }; - 745FF994113ECC660020C31B /* 3DSLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A890E4B716800207D74 /* 3DSLoader.cpp */; }; - 745FF996113ECC660020C31B /* ASELoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A8E0E4B716800207D74 /* ASELoader.cpp */; }; - 745FF997113ECC660020C31B /* ASEParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A900E4B716800207D74 /* ASEParser.cpp */; }; - 745FF9A2113ECC660020C31B /* HMPLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AAB0E4B716800207D74 /* HMPLoader.cpp */; }; - 745FF9A8113ECC660020C31B /* MD2Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AB90E4B716800207D74 /* MD2Loader.cpp */; }; - 745FF9A9113ECC660020C31B /* MD3Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45ABD0E4B716800207D74 /* MD3Loader.cpp */; }; - 745FF9AA113ECC660020C31B /* MD5Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AC20E4B716800207D74 /* MD5Loader.cpp */; }; - 745FF9AB113ECC660020C31B /* MD5Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AC40E4B716800207D74 /* MD5Parser.cpp */; }; - 745FF9AC113ECC660020C31B /* MDLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AC80E4B716800207D74 /* MDLLoader.cpp */; }; - 745FF9AD113ECC660020C31B /* MDLMaterialLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45ACA0E4B716800207D74 /* MDLMaterialLoader.cpp */; }; - 745FF9B1113ECC660020C31B /* PlyLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AD40E4B716800207D74 /* PlyLoader.cpp */; }; - 745FF9B2113ECC660020C31B /* PlyParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AD60E4B716800207D74 /* PlyParser.cpp */; }; - 745FF9B6113ECC660020C31B /* SMDLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AE20E4B716800207D74 /* SMDLoader.cpp */; }; - 745FF9BE113ECC660020C31B /* XFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AF50E4B716800207D74 /* XFileImporter.cpp */; }; - 745FF9BF113ECC660020C31B /* XFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AF70E4B716800207D74 /* XFileParser.cpp */; }; - 745FF9C0113ECC660020C31B /* MDCLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AB8A3AC0E50D67A00606590 /* MDCLoader.cpp */; }; - 745FF9C2113ECC660020C31B /* LWOLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AB8A3B80E50D6DB00606590 /* LWOLoader.cpp */; }; - 745FF9C4113ECC660020C31B /* LWOMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AB8A7DC0E53715F00606590 /* LWOMaterial.cpp */; }; - 745FF9C5113ECC660020C31B /* ACLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFD00F5DD87000124155 /* ACLoader.cpp */; }; - 745FF9C6113ECC660020C31B /* IRRLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFD90F5DD90800124155 /* IRRLoader.cpp */; }; - 745FF9C7113ECC660020C31B /* IRRMeshLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFDB0F5DD90800124155 /* IRRMeshLoader.cpp */; }; - 745FF9C8113ECC660020C31B /* IRRShared.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFDD0F5DD90800124155 /* IRRShared.cpp */; }; - 745FF9CB113ECC660020C31B /* NFFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFF60F5DD96100124155 /* NFFLoader.cpp */; }; - 745FF9CD113ECC660020C31B /* Q3DLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0060F5DD9DD00124155 /* Q3DLoader.cpp */; }; - 745FF9CE113ECC660020C31B /* BVHLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB00D0F5DD9F400124155 /* BVHLoader.cpp */; }; - 745FF9CF113ECC660020C31B /* OFFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0140F5DDA1400124155 /* OFFLoader.cpp */; }; - 745FF9D0113ECC660020C31B /* RawLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB01C0F5DDA4400124155 /* RawLoader.cpp */; }; - 745FF9D1113ECC660020C31B /* DXFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0220F5DDA5700124155 /* DXFLoader.cpp */; }; - 745FF9D2113ECC660020C31B /* LWOBLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0270F5DDA9200124155 /* LWOBLoader.cpp */; }; - 745FF9D3113ECC660020C31B /* TerragenLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0300F5DDAB500124155 /* TerragenLoader.cpp */; }; - 745FF9DF113ECC660020C31B /* B3DImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0880F5DDE0700124155 /* B3DImporter.cpp */; }; - 74C9BB5111ACBB1000AF885C /* BlenderDNA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB4911ACBB1000AF885C /* BlenderDNA.cpp */; }; - 74C9BB5211ACBB1000AF885C /* BlenderDNA.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB4A11ACBB1000AF885C /* BlenderDNA.h */; }; - 74C9BB5311ACBB1000AF885C /* BlenderLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB4C11ACBB1000AF885C /* BlenderLoader.cpp */; }; - 74C9BB5411ACBB1000AF885C /* BlenderLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB4D11ACBB1000AF885C /* BlenderLoader.h */; }; - 74C9BB5511ACBB1000AF885C /* BlenderScene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB4E11ACBB1000AF885C /* BlenderScene.cpp */; }; - 74C9BB5611ACBB1000AF885C /* BlenderScene.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB4F11ACBB1000AF885C /* BlenderScene.h */; }; - 74C9BB5711ACBB1000AF885C /* BlenderSceneGen.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB5011ACBB1000AF885C /* BlenderSceneGen.h */; }; - 74C9BB5811ACBB1000AF885C /* BlenderDNA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB4911ACBB1000AF885C /* BlenderDNA.cpp */; }; - 74C9BB5911ACBB1000AF885C /* BlenderDNA.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB4A11ACBB1000AF885C /* BlenderDNA.h */; }; - 74C9BB5A11ACBB1000AF885C /* BlenderLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB4C11ACBB1000AF885C /* BlenderLoader.cpp */; }; - 74C9BB5B11ACBB1000AF885C /* BlenderLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB4D11ACBB1000AF885C /* BlenderLoader.h */; }; - 74C9BB5C11ACBB1000AF885C /* BlenderScene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB4E11ACBB1000AF885C /* BlenderScene.cpp */; }; - 74C9BB5D11ACBB1000AF885C /* BlenderScene.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB4F11ACBB1000AF885C /* BlenderScene.h */; }; - 74C9BB5E11ACBB1000AF885C /* BlenderSceneGen.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB5011ACBB1000AF885C /* BlenderSceneGen.h */; }; - 74C9BB5F11ACBB1000AF885C /* BlenderDNA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB4911ACBB1000AF885C /* BlenderDNA.cpp */; }; - 74C9BB6011ACBB1000AF885C /* BlenderDNA.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB4A11ACBB1000AF885C /* BlenderDNA.h */; }; - 74C9BB6111ACBB1000AF885C /* BlenderLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB4C11ACBB1000AF885C /* BlenderLoader.cpp */; }; - 74C9BB6211ACBB1000AF885C /* BlenderLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB4D11ACBB1000AF885C /* BlenderLoader.h */; }; - 74C9BB6311ACBB1000AF885C /* BlenderScene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB4E11ACBB1000AF885C /* BlenderScene.cpp */; }; - 74C9BB6411ACBB1000AF885C /* BlenderScene.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB4F11ACBB1000AF885C /* BlenderScene.h */; }; - 74C9BB6511ACBB1000AF885C /* BlenderSceneGen.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB5011ACBB1000AF885C /* BlenderSceneGen.h */; }; - 74C9BB6611ACBB1000AF885C /* BlenderDNA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB4911ACBB1000AF885C /* BlenderDNA.cpp */; }; - 74C9BB6711ACBB1000AF885C /* BlenderDNA.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB4A11ACBB1000AF885C /* BlenderDNA.h */; }; - 74C9BB6811ACBB1000AF885C /* BlenderLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB4C11ACBB1000AF885C /* BlenderLoader.cpp */; }; - 74C9BB6911ACBB1000AF885C /* BlenderLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB4D11ACBB1000AF885C /* BlenderLoader.h */; }; - 74C9BB6A11ACBB1000AF885C /* BlenderScene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB4E11ACBB1000AF885C /* BlenderScene.cpp */; }; - 74C9BB6B11ACBB1000AF885C /* BlenderScene.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB4F11ACBB1000AF885C /* BlenderScene.h */; }; - 74C9BB6C11ACBB1000AF885C /* BlenderSceneGen.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB5011ACBB1000AF885C /* BlenderSceneGen.h */; }; - 74C9BB8811ACBB9900AF885C /* AssimpPCH.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB8611ACBB9900AF885C /* AssimpPCH.cpp */; }; - 74C9BB8911ACBB9900AF885C /* AssimpPCH.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB8711ACBB9900AF885C /* AssimpPCH.h */; }; - 74C9BB8A11ACBB9900AF885C /* AssimpPCH.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB8611ACBB9900AF885C /* AssimpPCH.cpp */; }; - 74C9BB8B11ACBB9900AF885C /* AssimpPCH.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB8711ACBB9900AF885C /* AssimpPCH.h */; }; - 74C9BB8C11ACBB9900AF885C /* AssimpPCH.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB8611ACBB9900AF885C /* AssimpPCH.cpp */; }; - 74C9BB8D11ACBB9900AF885C /* AssimpPCH.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB8711ACBB9900AF885C /* AssimpPCH.h */; }; - 74C9BB8E11ACBB9900AF885C /* AssimpPCH.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB8611ACBB9900AF885C /* AssimpPCH.cpp */; }; - 74C9BB8F11ACBB9900AF885C /* AssimpPCH.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB8711ACBB9900AF885C /* AssimpPCH.h */; }; - 74C9BB9611ACBBBC00AF885C /* COBLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB9311ACBBBC00AF885C /* COBLoader.cpp */; }; - 74C9BB9711ACBBBC00AF885C /* COBLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB9411ACBBBC00AF885C /* COBLoader.h */; }; - 74C9BB9811ACBBBC00AF885C /* COBScene.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB9511ACBBBC00AF885C /* COBScene.h */; }; - 74C9BB9911ACBBBC00AF885C /* COBLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB9311ACBBBC00AF885C /* COBLoader.cpp */; }; - 74C9BB9A11ACBBBC00AF885C /* COBLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB9411ACBBBC00AF885C /* COBLoader.h */; }; - 74C9BB9B11ACBBBC00AF885C /* COBScene.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB9511ACBBBC00AF885C /* COBScene.h */; }; - 74C9BB9C11ACBBBC00AF885C /* COBLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB9311ACBBBC00AF885C /* COBLoader.cpp */; }; - 74C9BB9D11ACBBBC00AF885C /* COBLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB9411ACBBBC00AF885C /* COBLoader.h */; }; - 74C9BB9E11ACBBBC00AF885C /* COBScene.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB9511ACBBBC00AF885C /* COBScene.h */; }; - 74C9BB9F11ACBBBC00AF885C /* COBLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB9311ACBBBC00AF885C /* COBLoader.cpp */; }; - 74C9BBA011ACBBBC00AF885C /* COBLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB9411ACBBBC00AF885C /* COBLoader.h */; }; - 74C9BBA111ACBBBC00AF885C /* COBScene.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB9511ACBBBC00AF885C /* COBScene.h */; }; - 74C9BBB411ACBC2600AF885C /* revision.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BBB311ACBC2600AF885C /* revision.h */; }; - 74C9BBB511ACBC2600AF885C /* revision.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BBB311ACBC2600AF885C /* revision.h */; }; - 74C9BBB611ACBC2600AF885C /* revision.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BBB311ACBC2600AF885C /* revision.h */; }; - 74C9BBB711ACBC2600AF885C /* revision.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BBB311ACBC2600AF885C /* revision.h */; }; - 8E7ABBA8127E0F1A00512ED1 /* Q3BSPFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA1127E0F1A00512ED1 /* Q3BSPFileData.h */; }; - 8E7ABBA9127E0F1A00512ED1 /* Q3BSPFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBA2127E0F1A00512ED1 /* Q3BSPFileImporter.cpp */; }; - 8E7ABBAA127E0F1A00512ED1 /* Q3BSPFileImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA3127E0F1A00512ED1 /* Q3BSPFileImporter.h */; }; - 8E7ABBAB127E0F1A00512ED1 /* Q3BSPFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBA4127E0F1A00512ED1 /* Q3BSPFileParser.cpp */; }; - 8E7ABBAC127E0F1A00512ED1 /* Q3BSPFileParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA5127E0F1A00512ED1 /* Q3BSPFileParser.h */; }; - 8E7ABBAD127E0F1A00512ED1 /* Q3BSPZipArchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBA6127E0F1A00512ED1 /* Q3BSPZipArchive.cpp */; }; - 8E7ABBAE127E0F1A00512ED1 /* Q3BSPZipArchive.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA7127E0F1A00512ED1 /* Q3BSPZipArchive.h */; }; - 8E7ABBAF127E0F1A00512ED1 /* Q3BSPFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA1127E0F1A00512ED1 /* Q3BSPFileData.h */; }; - 8E7ABBB0127E0F1A00512ED1 /* Q3BSPFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBA2127E0F1A00512ED1 /* Q3BSPFileImporter.cpp */; }; - 8E7ABBB1127E0F1A00512ED1 /* Q3BSPFileImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA3127E0F1A00512ED1 /* Q3BSPFileImporter.h */; }; - 8E7ABBB2127E0F1A00512ED1 /* Q3BSPFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBA4127E0F1A00512ED1 /* Q3BSPFileParser.cpp */; }; - 8E7ABBB3127E0F1A00512ED1 /* Q3BSPFileParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA5127E0F1A00512ED1 /* Q3BSPFileParser.h */; }; - 8E7ABBB4127E0F1A00512ED1 /* Q3BSPZipArchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBA6127E0F1A00512ED1 /* Q3BSPZipArchive.cpp */; }; - 8E7ABBB5127E0F1A00512ED1 /* Q3BSPZipArchive.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA7127E0F1A00512ED1 /* Q3BSPZipArchive.h */; }; - 8E7ABBB6127E0F1A00512ED1 /* Q3BSPFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA1127E0F1A00512ED1 /* Q3BSPFileData.h */; }; - 8E7ABBB7127E0F1A00512ED1 /* Q3BSPFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBA2127E0F1A00512ED1 /* Q3BSPFileImporter.cpp */; }; - 8E7ABBB8127E0F1A00512ED1 /* Q3BSPFileImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA3127E0F1A00512ED1 /* Q3BSPFileImporter.h */; }; - 8E7ABBB9127E0F1A00512ED1 /* Q3BSPFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBA4127E0F1A00512ED1 /* Q3BSPFileParser.cpp */; }; - 8E7ABBBA127E0F1A00512ED1 /* Q3BSPFileParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA5127E0F1A00512ED1 /* Q3BSPFileParser.h */; }; - 8E7ABBBB127E0F1A00512ED1 /* Q3BSPZipArchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBA6127E0F1A00512ED1 /* Q3BSPZipArchive.cpp */; }; - 8E7ABBBC127E0F1A00512ED1 /* Q3BSPZipArchive.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA7127E0F1A00512ED1 /* Q3BSPZipArchive.h */; }; - 8E7ABBBD127E0F1A00512ED1 /* Q3BSPFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA1127E0F1A00512ED1 /* Q3BSPFileData.h */; }; - 8E7ABBBE127E0F1A00512ED1 /* Q3BSPFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBA2127E0F1A00512ED1 /* Q3BSPFileImporter.cpp */; }; - 8E7ABBBF127E0F1A00512ED1 /* Q3BSPFileImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA3127E0F1A00512ED1 /* Q3BSPFileImporter.h */; }; - 8E7ABBC0127E0F1A00512ED1 /* Q3BSPFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBA4127E0F1A00512ED1 /* Q3BSPFileParser.cpp */; }; - 8E7ABBC1127E0F1A00512ED1 /* Q3BSPFileParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA5127E0F1A00512ED1 /* Q3BSPFileParser.h */; }; - 8E7ABBC2127E0F1A00512ED1 /* Q3BSPZipArchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBA6127E0F1A00512ED1 /* Q3BSPZipArchive.cpp */; }; - 8E7ABBC3127E0F1A00512ED1 /* Q3BSPZipArchive.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA7127E0F1A00512ED1 /* Q3BSPZipArchive.h */; }; - 8E7ABBC6127E0F2A00512ED1 /* NDOLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBC4127E0F2A00512ED1 /* NDOLoader.cpp */; }; - 8E7ABBC7127E0F2A00512ED1 /* NDOLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBC5127E0F2A00512ED1 /* NDOLoader.h */; }; - 8E7ABBC8127E0F2A00512ED1 /* NDOLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBC4127E0F2A00512ED1 /* NDOLoader.cpp */; }; - 8E7ABBC9127E0F2A00512ED1 /* NDOLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBC5127E0F2A00512ED1 /* NDOLoader.h */; }; - 8E7ABBCA127E0F2A00512ED1 /* NDOLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBC4127E0F2A00512ED1 /* NDOLoader.cpp */; }; - 8E7ABBCB127E0F2A00512ED1 /* NDOLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBC5127E0F2A00512ED1 /* NDOLoader.h */; }; - 8E7ABBCC127E0F2A00512ED1 /* NDOLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBC4127E0F2A00512ED1 /* NDOLoader.cpp */; }; - 8E7ABBCD127E0F2A00512ED1 /* NDOLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBC5127E0F2A00512ED1 /* NDOLoader.h */; }; - 8E7ABBD1127E0F3800512ED1 /* BlenderIntermediate.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBCE127E0F3800512ED1 /* BlenderIntermediate.h */; }; - 8E7ABBD2127E0F3800512ED1 /* BlenderModifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBCF127E0F3800512ED1 /* BlenderModifier.cpp */; }; - 8E7ABBD3127E0F3800512ED1 /* BlenderModifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBD0127E0F3800512ED1 /* BlenderModifier.h */; }; - 8E7ABBD4127E0F3800512ED1 /* BlenderIntermediate.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBCE127E0F3800512ED1 /* BlenderIntermediate.h */; }; - 8E7ABBD5127E0F3800512ED1 /* BlenderModifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBCF127E0F3800512ED1 /* BlenderModifier.cpp */; }; - 8E7ABBD6127E0F3800512ED1 /* BlenderModifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBD0127E0F3800512ED1 /* BlenderModifier.h */; }; - 8E7ABBD7127E0F3800512ED1 /* BlenderIntermediate.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBCE127E0F3800512ED1 /* BlenderIntermediate.h */; }; - 8E7ABBD8127E0F3800512ED1 /* BlenderModifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBCF127E0F3800512ED1 /* BlenderModifier.cpp */; }; - 8E7ABBD9127E0F3800512ED1 /* BlenderModifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBD0127E0F3800512ED1 /* BlenderModifier.h */; }; - 8E7ABBDA127E0F3800512ED1 /* BlenderIntermediate.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBCE127E0F3800512ED1 /* BlenderIntermediate.h */; }; - 8E7ABBDB127E0F3800512ED1 /* BlenderModifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBCF127E0F3800512ED1 /* BlenderModifier.cpp */; }; - 8E7ABBDC127E0F3800512ED1 /* BlenderModifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBD0127E0F3800512ED1 /* BlenderModifier.h */; }; - 8E8DEE5C127E2B78005EF64D /* ConvertUTF.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE4B127E2B78005EF64D /* ConvertUTF.c */; }; - 8E8DEE5D127E2B78005EF64D /* ConvertUTF.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE4C127E2B78005EF64D /* ConvertUTF.h */; }; - 8E8DEE5E127E2B78005EF64D /* CXMLReaderImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE4F127E2B78005EF64D /* CXMLReaderImpl.h */; }; - 8E8DEE5F127E2B78005EF64D /* heapsort.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE50127E2B78005EF64D /* heapsort.h */; }; - 8E8DEE60127E2B78005EF64D /* irrArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE51127E2B78005EF64D /* irrArray.h */; }; - 8E8DEE61127E2B78005EF64D /* irrString.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE52127E2B78005EF64D /* irrString.h */; }; - 8E8DEE62127E2B78005EF64D /* irrTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE53127E2B78005EF64D /* irrTypes.h */; }; - 8E8DEE63127E2B78005EF64D /* irrXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE54127E2B78005EF64D /* irrXML.cpp */; }; - 8E8DEE64127E2B78005EF64D /* irrXML.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE55127E2B78005EF64D /* irrXML.h */; }; - 8E8DEE65127E2B78005EF64D /* crypt.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE57127E2B78005EF64D /* crypt.h */; }; - 8E8DEE66127E2B78005EF64D /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE58127E2B78005EF64D /* ioapi.c */; }; - 8E8DEE67127E2B78005EF64D /* ioapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE59127E2B78005EF64D /* ioapi.h */; }; - 8E8DEE68127E2B78005EF64D /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE5A127E2B78005EF64D /* unzip.c */; }; - 8E8DEE69127E2B78005EF64D /* unzip.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE5B127E2B78005EF64D /* unzip.h */; }; - 8E8DEE6A127E2B78005EF64D /* ConvertUTF.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE4B127E2B78005EF64D /* ConvertUTF.c */; }; - 8E8DEE6B127E2B78005EF64D /* ConvertUTF.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE4C127E2B78005EF64D /* ConvertUTF.h */; }; - 8E8DEE6C127E2B78005EF64D /* CXMLReaderImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE4F127E2B78005EF64D /* CXMLReaderImpl.h */; }; - 8E8DEE6D127E2B78005EF64D /* heapsort.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE50127E2B78005EF64D /* heapsort.h */; }; - 8E8DEE6E127E2B78005EF64D /* irrArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE51127E2B78005EF64D /* irrArray.h */; }; - 8E8DEE6F127E2B78005EF64D /* irrString.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE52127E2B78005EF64D /* irrString.h */; }; - 8E8DEE70127E2B78005EF64D /* irrTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE53127E2B78005EF64D /* irrTypes.h */; }; - 8E8DEE71127E2B78005EF64D /* irrXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE54127E2B78005EF64D /* irrXML.cpp */; }; - 8E8DEE72127E2B78005EF64D /* irrXML.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE55127E2B78005EF64D /* irrXML.h */; }; - 8E8DEE73127E2B78005EF64D /* crypt.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE57127E2B78005EF64D /* crypt.h */; }; - 8E8DEE74127E2B78005EF64D /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE58127E2B78005EF64D /* ioapi.c */; }; - 8E8DEE75127E2B78005EF64D /* ioapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE59127E2B78005EF64D /* ioapi.h */; }; - 8E8DEE76127E2B78005EF64D /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE5A127E2B78005EF64D /* unzip.c */; }; - 8E8DEE77127E2B78005EF64D /* unzip.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE5B127E2B78005EF64D /* unzip.h */; }; - 8E8DEE78127E2B78005EF64D /* ConvertUTF.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE4B127E2B78005EF64D /* ConvertUTF.c */; }; - 8E8DEE79127E2B78005EF64D /* ConvertUTF.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE4C127E2B78005EF64D /* ConvertUTF.h */; }; - 8E8DEE7A127E2B78005EF64D /* CXMLReaderImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE4F127E2B78005EF64D /* CXMLReaderImpl.h */; }; - 8E8DEE7B127E2B78005EF64D /* heapsort.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE50127E2B78005EF64D /* heapsort.h */; }; - 8E8DEE7C127E2B78005EF64D /* irrArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE51127E2B78005EF64D /* irrArray.h */; }; - 8E8DEE7D127E2B78005EF64D /* irrString.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE52127E2B78005EF64D /* irrString.h */; }; - 8E8DEE7E127E2B78005EF64D /* irrTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE53127E2B78005EF64D /* irrTypes.h */; }; - 8E8DEE7F127E2B78005EF64D /* irrXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE54127E2B78005EF64D /* irrXML.cpp */; }; - 8E8DEE80127E2B78005EF64D /* irrXML.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE55127E2B78005EF64D /* irrXML.h */; }; - 8E8DEE81127E2B78005EF64D /* crypt.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE57127E2B78005EF64D /* crypt.h */; }; - 8E8DEE82127E2B78005EF64D /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE58127E2B78005EF64D /* ioapi.c */; }; - 8E8DEE83127E2B78005EF64D /* ioapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE59127E2B78005EF64D /* ioapi.h */; }; - 8E8DEE84127E2B78005EF64D /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE5A127E2B78005EF64D /* unzip.c */; }; - 8E8DEE85127E2B78005EF64D /* unzip.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE5B127E2B78005EF64D /* unzip.h */; }; - 8E8DEE86127E2B78005EF64D /* ConvertUTF.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE4B127E2B78005EF64D /* ConvertUTF.c */; }; - 8E8DEE87127E2B78005EF64D /* ConvertUTF.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE4C127E2B78005EF64D /* ConvertUTF.h */; }; - 8E8DEE88127E2B78005EF64D /* CXMLReaderImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE4F127E2B78005EF64D /* CXMLReaderImpl.h */; }; - 8E8DEE89127E2B78005EF64D /* heapsort.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE50127E2B78005EF64D /* heapsort.h */; }; - 8E8DEE8A127E2B78005EF64D /* irrArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE51127E2B78005EF64D /* irrArray.h */; }; - 8E8DEE8B127E2B78005EF64D /* irrString.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE52127E2B78005EF64D /* irrString.h */; }; - 8E8DEE8C127E2B78005EF64D /* irrTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE53127E2B78005EF64D /* irrTypes.h */; }; - 8E8DEE8D127E2B78005EF64D /* irrXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE54127E2B78005EF64D /* irrXML.cpp */; }; - 8E8DEE8E127E2B78005EF64D /* irrXML.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE55127E2B78005EF64D /* irrXML.h */; }; - 8E8DEE8F127E2B78005EF64D /* crypt.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE57127E2B78005EF64D /* crypt.h */; }; - 8E8DEE90127E2B78005EF64D /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE58127E2B78005EF64D /* ioapi.c */; }; - 8E8DEE91127E2B78005EF64D /* ioapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE59127E2B78005EF64D /* ioapi.h */; }; - 8E8DEE92127E2B78005EF64D /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE5A127E2B78005EF64D /* unzip.c */; }; - 8E8DEE93127E2B78005EF64D /* unzip.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE5B127E2B78005EF64D /* unzip.h */; }; - B91974D1163AEA54009C397B /* 3DSHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A880E4B716800207D74 /* 3DSHelper.h */; }; - B91974D2163AEA54009C397B /* 3DSLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A8A0E4B716800207D74 /* 3DSLoader.h */; }; - B91974D3163AEA54009C397B /* ASELoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A8F0E4B716800207D74 /* ASELoader.h */; }; - B91974D4163AEA54009C397B /* ASEParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A910E4B716800207D74 /* ASEParser.h */; }; - B91974E0163AEA54009C397B /* HalfLifeFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AA90E4B716800207D74 /* HalfLifeFileData.h */; }; - B91974E1163AEA54009C397B /* HMPLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AAC0E4B716800207D74 /* HMPLoader.h */; }; - B91974E6163AEA54009C397B /* MD2FileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AB80E4B716800207D74 /* MD2FileData.h */; }; - B91974E7163AEA54009C397B /* MD2Loader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABA0E4B716800207D74 /* MD2Loader.h */; }; - B91974E8163AEA54009C397B /* MD2NormalTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABB0E4B716800207D74 /* MD2NormalTable.h */; }; - B91974E9163AEA54009C397B /* MD3FileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABC0E4B716800207D74 /* MD3FileData.h */; }; - B91974EA163AEA54009C397B /* MD3Loader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABE0E4B716800207D74 /* MD3Loader.h */; }; - B91974EB163AEA54009C397B /* MD5Loader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC30E4B716800207D74 /* MD5Loader.h */; }; - B91974EC163AEA54009C397B /* MD5Parser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC50E4B716800207D74 /* MD5Parser.h */; }; - B91974ED163AEA54009C397B /* MDLDefaultColorMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC60E4B716800207D74 /* MDLDefaultColorMap.h */; }; - B91974EE163AEA54009C397B /* MDLFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC70E4B716800207D74 /* MDLFileData.h */; }; - B91974EF163AEA54009C397B /* MDLLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC90E4B716800207D74 /* MDLLoader.h */; }; - B91974F6163AEA54009C397B /* PlyLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AD50E4B716800207D74 /* PlyLoader.h */; }; - B91974F7163AEA54009C397B /* PlyParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AD70E4B716800207D74 /* PlyParser.h */; }; - B91974FC163AEA54009C397B /* SMDLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AE30E4B716800207D74 /* SMDLoader.h */; }; - B9197506163AEA54009C397B /* XFileHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AF40E4B716800207D74 /* XFileHelper.h */; }; - B9197507163AEA54009C397B /* XFileImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AF60E4B716800207D74 /* XFileImporter.h */; }; - B9197508163AEA54009C397B /* XFileParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AF80E4B716800207D74 /* XFileParser.h */; }; - B9197509163AEA54009C397B /* MDCFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3AB0E50D67A00606590 /* MDCFileData.h */; }; - B919750A163AEA54009C397B /* MDCLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3AD0E50D67A00606590 /* MDCLoader.h */; }; - B919750B163AEA54009C397B /* MDCNormalTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3AE0E50D67A00606590 /* MDCNormalTable.h */; }; - B919750D163AEA54009C397B /* LWOFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3B70E50D6DB00606590 /* LWOFileData.h */; }; - B919750E163AEA54009C397B /* LWOLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3B90E50D6DB00606590 /* LWOLoader.h */; }; - B919750F163AEA54009C397B /* HMPFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3C50E50D77900606590 /* HMPFileData.h */; }; - B9197512163AEA54009C397B /* ACLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFD10F5DD87000124155 /* ACLoader.h */; }; - B9197513163AEA54009C397B /* IRRLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFDA0F5DD90800124155 /* IRRLoader.h */; }; - B9197514163AEA54009C397B /* IRRMeshLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFDC0F5DD90800124155 /* IRRMeshLoader.h */; }; - B9197515163AEA54009C397B /* IRRShared.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFDE0F5DD90800124155 /* IRRShared.h */; }; - B9197519163AEA54009C397B /* NFFLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFF50F5DD96100124155 /* NFFLoader.h */; }; - B919751B163AEA54009C397B /* Q3DLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0070F5DD9DD00124155 /* Q3DLoader.h */; }; - B919751C163AEA54009C397B /* BVHLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB00C0F5DD9F400124155 /* BVHLoader.h */; }; - B919751D163AEA54009C397B /* OFFLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0130F5DDA1400124155 /* OFFLoader.h */; }; - B919751E163AEA54009C397B /* RawLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB01B0F5DDA4400124155 /* RawLoader.h */; }; - B919751F163AEA54009C397B /* DXFLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0210F5DDA5700124155 /* DXFLoader.h */; }; - B9197520163AEA54009C397B /* TerragenLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB02F0F5DDAB500124155 /* TerragenLoader.h */; }; - B9197521163AEA54009C397B /* irrXMLWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0360F5DDB1B00124155 /* irrXMLWrapper.h */; }; - B919752D163AEA54009C397B /* B3DImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0870F5DDE0700124155 /* B3DImporter.h */; }; - B9197535163AEA54009C397B /* CSMLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B14F11416D5E00BCD793 /* CSMLoader.h */; }; - B9197536163AEA54009C397B /* LWSLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B15A11416DDD00BCD793 /* LWSLoader.h */; }; - B9197537163AEA54009C397B /* LWOAnimation.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B16411416DF400BCD793 /* LWOAnimation.h */; }; - B9197538163AEA54009C397B /* MS3DLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B17111416E2500BCD793 /* MS3DLoader.h */; }; - B9197539163AEA54009C397B /* UnrealLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7411B18C11416EBC00BCD793 /* UnrealLoader.h */; }; - B9197545163AEA54009C397B /* BlenderDNA.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB4A11ACBB1000AF885C /* BlenderDNA.h */; }; - B9197546163AEA54009C397B /* BlenderLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB4D11ACBB1000AF885C /* BlenderLoader.h */; }; - B9197547163AEA54009C397B /* BlenderScene.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB4F11ACBB1000AF885C /* BlenderScene.h */; }; - B9197548163AEA54009C397B /* BlenderSceneGen.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB5011ACBB1000AF885C /* BlenderSceneGen.h */; }; - B919754D163AEA54009C397B /* AssimpPCH.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB8711ACBB9900AF885C /* AssimpPCH.h */; }; - B919754E163AEA54009C397B /* COBLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB9411ACBBBC00AF885C /* COBLoader.h */; }; - B919754F163AEA54009C397B /* COBScene.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BB9511ACBBBC00AF885C /* COBScene.h */; }; - B9197550163AEA54009C397B /* revision.h in Headers */ = {isa = PBXBuildFile; fileRef = 74C9BBB311ACBC2600AF885C /* revision.h */; }; - B9197555163AEA54009C397B /* Q3BSPFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA1127E0F1A00512ED1 /* Q3BSPFileData.h */; }; - B9197556163AEA54009C397B /* Q3BSPFileImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA3127E0F1A00512ED1 /* Q3BSPFileImporter.h */; }; - B9197557163AEA54009C397B /* Q3BSPFileParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA5127E0F1A00512ED1 /* Q3BSPFileParser.h */; }; - B9197558163AEA54009C397B /* Q3BSPZipArchive.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBA7127E0F1A00512ED1 /* Q3BSPZipArchive.h */; }; - B9197559163AEA54009C397B /* NDOLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBC5127E0F2A00512ED1 /* NDOLoader.h */; }; - B919755A163AEA54009C397B /* BlenderIntermediate.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBCE127E0F3800512ED1 /* BlenderIntermediate.h */; }; - B919755B163AEA54009C397B /* BlenderModifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E7ABBD0127E0F3800512ED1 /* BlenderModifier.h */; }; - B9197560163AEA54009C397B /* ConvertUTF.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE4C127E2B78005EF64D /* ConvertUTF.h */; }; - B9197561163AEA54009C397B /* CXMLReaderImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE4F127E2B78005EF64D /* CXMLReaderImpl.h */; }; - B9197562163AEA54009C397B /* heapsort.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE50127E2B78005EF64D /* heapsort.h */; }; - B9197563163AEA54009C397B /* irrArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE51127E2B78005EF64D /* irrArray.h */; }; - B9197564163AEA54009C397B /* irrString.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE52127E2B78005EF64D /* irrString.h */; }; - B9197565163AEA54009C397B /* irrTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE53127E2B78005EF64D /* irrTypes.h */; }; - B9197566163AEA54009C397B /* irrXML.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE55127E2B78005EF64D /* irrXML.h */; }; - B9197567163AEA54009C397B /* crypt.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE57127E2B78005EF64D /* crypt.h */; }; - B9197568163AEA54009C397B /* ioapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE59127E2B78005EF64D /* ioapi.h */; }; - B9197569163AEA54009C397B /* unzip.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8DEE5B127E2B78005EF64D /* unzip.h */; }; - B919756A163AEA54009C397B /* anim.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B751543268400E63FFE /* anim.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B919756B163AEA54009C397B /* camera.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B771543268400E63FFE /* camera.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B919756C163AEA54009C397B /* cexport.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B781543268400E63FFE /* cexport.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B919756D163AEA54009C397B /* cfileio.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B791543268400E63FFE /* cfileio.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B919756E163AEA54009C397B /* cimport.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7A1543268400E63FFE /* cimport.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B919756F163AEA54009C397B /* color4.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7B1543268400E63FFE /* color4.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197570163AEA54009C397B /* poppack1.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7E1543268400E63FFE /* poppack1.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197571163AEA54009C397B /* pushpack1.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7F1543268400E63FFE /* pushpack1.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197572163AEA54009C397B /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B801543268400E63FFE /* config.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197573163AEA54009C397B /* DefaultLogger.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B811543268400E63FFE /* DefaultLogger.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197574163AEA54009C397B /* defs.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B821543268400E63FFE /* defs.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197575163AEA54009C397B /* Exporter.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B831543268400E63FFE /* Exporter.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197576163AEA54009C397B /* Importer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B841543268400E63FFE /* Importer.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197577163AEA54009C397B /* importerdesc.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B851543268400E63FFE /* importerdesc.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197578163AEA54009C397B /* IOStream.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B861543268400E63FFE /* IOStream.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197579163AEA54009C397B /* IOSystem.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B871543268400E63FFE /* IOSystem.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - B919757A163AEA54009C397B /* light.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B881543268400E63FFE /* light.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B919757B163AEA54009C397B /* Logger.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B891543268400E63FFE /* Logger.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - B919757C163AEA54009C397B /* LogStream.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8A1543268400E63FFE /* LogStream.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - B919757D163AEA54009C397B /* material.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8B1543268400E63FFE /* material.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B919757E163AEA54009C397B /* matrix3x3.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8D1543268400E63FFE /* matrix3x3.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B919757F163AEA54009C397B /* matrix4x4.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8F1543268400E63FFE /* matrix4x4.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197580163AEA54009C397B /* mesh.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B911543268400E63FFE /* mesh.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197581163AEA54009C397B /* NullLogger.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B921543268400E63FFE /* NullLogger.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197582163AEA54009C397B /* postprocess.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B931543268400E63FFE /* postprocess.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197583163AEA54009C397B /* ProgressHandler.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B941543268400E63FFE /* ProgressHandler.hpp */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197584163AEA54009C397B /* quaternion.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B951543268400E63FFE /* quaternion.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197585163AEA54009C397B /* scene.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B971543268400E63FFE /* scene.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197586163AEA54009C397B /* texture.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B981543268400E63FFE /* texture.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197587163AEA54009C397B /* types.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B991543268400E63FFE /* types.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197588163AEA54009C397B /* vector2.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B9A1543268400E63FFE /* vector2.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B9197589163AEA54009C397B /* vector3.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B9C1543268400E63FFE /* vector3.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B919758A163AEA54009C397B /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B9E1543268400E63FFE /* version.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B919758B163AEA54009C397B /* OgreImporter.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8C36154328B600E63FFE /* OgreImporter.hpp */; }; - B919758C163AEA54009C397B /* OgreXmlHelper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8C3A154328B600E63FFE /* OgreXmlHelper.hpp */; }; - B9197596163AEA54009C397B /* PlyExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = F99A9F3115436269000682F3 /* PlyExporter.h */; }; - B919759C163AEA54009C397B /* crc32.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704B154366AB004D91DD /* crc32.h */; }; - B919759D163AEA54009C397B /* deflate.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704D154366AB004D91DD /* deflate.h */; }; - B919759E163AEA54009C397B /* inffast.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704F154366AB004D91DD /* inffast.h */; }; - B919759F163AEA54009C397B /* inffixed.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607050154366AB004D91DD /* inffixed.h */; }; - B91975A0163AEA54009C397B /* inflate.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607052154366AB004D91DD /* inflate.h */; }; - B91975A1163AEA54009C397B /* inftrees.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607054154366AB004D91DD /* inftrees.h */; }; - B91975A2163AEA54009C397B /* trees.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607057154366AB004D91DD /* trees.h */; }; - B91975A3163AEA54009C397B /* zconf.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607058154366AB004D91DD /* zconf.h */; }; - B91975A4163AEA54009C397B /* zconf.in.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607059154366AB004D91DD /* zconf.in.h */; }; - B91975A5163AEA54009C397B /* zlib.h in Headers */ = {isa = PBXBuildFile; fileRef = F960705A154366AB004D91DD /* zlib.h */; }; - B91975A6163AEA54009C397B /* zutil.h in Headers */ = {isa = PBXBuildFile; fileRef = F960705C154366AB004D91DD /* zutil.h */; }; - B91975A7163AEA54009C397B /* XGLLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070B6154366ED004D91DD /* XGLLoader.h */; }; - B91975A8163AEA54009C397B /* clipper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F96070C61543673B004D91DD /* clipper.hpp */; }; - B91975A9163AEA54009C397B /* shapes.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D31543675E004D91DD /* shapes.h */; }; - B91975AA163AEA54009C397B /* utils.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D41543675E004D91DD /* utils.h */; }; - B91975AB163AEA54009C397B /* poly2tri.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D51543675E004D91DD /* poly2tri.h */; }; - B91975AC163AEA54009C397B /* advancing_front.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D81543675E004D91DD /* advancing_front.h */; }; - B91975AD163AEA54009C397B /* cdt.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070DA1543675E004D91DD /* cdt.h */; }; - B91975AE163AEA54009C397B /* sweep.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070DC1543675E004D91DD /* sweep.h */; }; - B91975AF163AEA54009C397B /* sweep_context.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070DE1543675E004D91DD /* sweep_context.h */; }; - B91975B0163AEA54009C397B /* ai_assert.h in Headers */ = {isa = PBXBuildFile; fileRef = F97BA03515439DB3009EB9DD /* ai_assert.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B91975B7163AEA54009C397B /* 3DSConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A860E4B716800207D74 /* 3DSConverter.cpp */; }; - B91975B8163AEA54009C397B /* 3DSLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A890E4B716800207D74 /* 3DSLoader.cpp */; }; - B91975B9163AEA54009C397B /* ASELoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A8E0E4B716800207D74 /* ASELoader.cpp */; }; - B91975BA163AEA54009C397B /* ASEParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A900E4B716800207D74 /* ASEParser.cpp */; }; - B91975C4163AEA54009C397B /* HMPLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AAB0E4B716800207D74 /* HMPLoader.cpp */; }; - B91975CA163AEA54009C397B /* MD2Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AB90E4B716800207D74 /* MD2Loader.cpp */; }; - B91975CB163AEA54009C397B /* MD3Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45ABD0E4B716800207D74 /* MD3Loader.cpp */; }; - B91975CC163AEA54009C397B /* MD5Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AC20E4B716800207D74 /* MD5Loader.cpp */; }; - B91975CD163AEA54009C397B /* MD5Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AC40E4B716800207D74 /* MD5Parser.cpp */; }; - B91975CE163AEA54009C397B /* MDLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AC80E4B716800207D74 /* MDLLoader.cpp */; }; - B91975CF163AEA54009C397B /* MDLMaterialLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45ACA0E4B716800207D74 /* MDLMaterialLoader.cpp */; }; - B91975D3163AEA54009C397B /* PlyLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AD40E4B716800207D74 /* PlyLoader.cpp */; }; - B91975D4163AEA54009C397B /* PlyParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AD60E4B716800207D74 /* PlyParser.cpp */; }; - B91975D8163AEA54009C397B /* SMDLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AE20E4B716800207D74 /* SMDLoader.cpp */; }; - B91975E0163AEA54009C397B /* XFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AF50E4B716800207D74 /* XFileImporter.cpp */; }; - B91975E1163AEA54009C397B /* XFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AF70E4B716800207D74 /* XFileParser.cpp */; }; - B91975E2163AEA54009C397B /* MDCLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AB8A3AC0E50D67A00606590 /* MDCLoader.cpp */; }; - B91975E4163AEA54009C397B /* LWOLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AB8A3B80E50D6DB00606590 /* LWOLoader.cpp */; }; - B91975E6163AEA54009C397B /* LWOMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AB8A7DC0E53715F00606590 /* LWOMaterial.cpp */; }; - B91975E7163AEA54009C397B /* ACLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFD00F5DD87000124155 /* ACLoader.cpp */; }; - B91975E8163AEA54009C397B /* IRRLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFD90F5DD90800124155 /* IRRLoader.cpp */; }; - B91975E9163AEA54009C397B /* IRRMeshLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFDB0F5DD90800124155 /* IRRMeshLoader.cpp */; }; - B91975EA163AEA54009C397B /* IRRShared.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFDD0F5DD90800124155 /* IRRShared.cpp */; }; - B91975ED163AEA54009C397B /* NFFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFF60F5DD96100124155 /* NFFLoader.cpp */; }; - B91975EF163AEA54009C397B /* Q3DLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0060F5DD9DD00124155 /* Q3DLoader.cpp */; }; - B91975F0163AEA54009C397B /* BVHLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB00D0F5DD9F400124155 /* BVHLoader.cpp */; }; - B91975F1163AEA54009C397B /* OFFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0140F5DDA1400124155 /* OFFLoader.cpp */; }; - B91975F2163AEA54009C397B /* RawLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB01C0F5DDA4400124155 /* RawLoader.cpp */; }; - B91975F3163AEA54009C397B /* DXFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0220F5DDA5700124155 /* DXFLoader.cpp */; }; - B91975F4163AEA54009C397B /* LWOBLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0270F5DDA9200124155 /* LWOBLoader.cpp */; }; - B91975F5163AEA54009C397B /* TerragenLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0300F5DDAB500124155 /* TerragenLoader.cpp */; }; - B9197600163AEA54009C397B /* B3DImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0880F5DDE0700124155 /* B3DImporter.cpp */; }; - B9197601163AEA54009C397B /* CSMLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B14E11416D5E00BCD793 /* CSMLoader.cpp */; }; - B9197602163AEA54009C397B /* LWSLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B15911416DDD00BCD793 /* LWSLoader.cpp */; }; - B9197603163AEA54009C397B /* LWOAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B16311416DF400BCD793 /* LWOAnimation.cpp */; }; - B9197604163AEA54009C397B /* MS3DLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B17011416E2500BCD793 /* MS3DLoader.cpp */; }; - B9197605163AEA54009C397B /* UnrealLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7411B18B11416EBC00BCD793 /* UnrealLoader.cpp */; }; - B919760A163AEA54009C397B /* BlenderDNA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB4911ACBB1000AF885C /* BlenderDNA.cpp */; }; - B919760B163AEA54009C397B /* BlenderLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB4C11ACBB1000AF885C /* BlenderLoader.cpp */; }; - B919760C163AEA54009C397B /* BlenderScene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB4E11ACBB1000AF885C /* BlenderScene.cpp */; }; - B919760E163AEA54009C397B /* AssimpPCH.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB8611ACBB9900AF885C /* AssimpPCH.cpp */; }; - B919760F163AEA54009C397B /* COBLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C9BB9311ACBBBC00AF885C /* COBLoader.cpp */; }; - B9197610163AEA54009C397B /* Q3BSPFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBA2127E0F1A00512ED1 /* Q3BSPFileImporter.cpp */; }; - B9197611163AEA54009C397B /* Q3BSPFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBA4127E0F1A00512ED1 /* Q3BSPFileParser.cpp */; }; - B9197612163AEA54009C397B /* Q3BSPZipArchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBA6127E0F1A00512ED1 /* Q3BSPZipArchive.cpp */; }; - B9197613163AEA54009C397B /* NDOLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBC4127E0F2A00512ED1 /* NDOLoader.cpp */; }; - B9197614163AEA54009C397B /* BlenderModifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E7ABBCF127E0F3800512ED1 /* BlenderModifier.cpp */; }; - B9197615163AEA54009C397B /* ConvertUTF.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE4B127E2B78005EF64D /* ConvertUTF.c */; }; - B9197616163AEA54009C397B /* irrXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE54127E2B78005EF64D /* irrXML.cpp */; }; - B9197617163AEA54009C397B /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE58127E2B78005EF64D /* ioapi.c */; }; - B9197618163AEA54009C397B /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = 8E8DEE5A127E2B78005EF64D /* unzip.c */; }; - B9197619163AEA54009C397B /* OgreImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C35154328B600E63FFE /* OgreImporter.cpp */; }; - B919761A163AEA54009C397B /* OgreMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C37154328B600E63FFE /* OgreMaterial.cpp */; }; - B919761B163AEA54009C397B /* OgreMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C38154328B600E63FFE /* OgreMesh.cpp */; }; - B919761C163AEA54009C397B /* OgreSkeleton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C39154328B600E63FFE /* OgreSkeleton.cpp */; }; - B9197620163AEA54009C397B /* PlyExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F99A9F3015436269000682F3 /* PlyExporter.cpp */; }; - B9197625163AEA54009C397B /* adler32.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607047154366AB004D91DD /* adler32.c */; }; - B9197626163AEA54009C397B /* compress.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607049154366AB004D91DD /* compress.c */; }; - B9197627163AEA54009C397B /* crc32.c in Sources */ = {isa = PBXBuildFile; fileRef = F960704A154366AB004D91DD /* crc32.c */; }; - B9197628163AEA54009C397B /* deflate.c in Sources */ = {isa = PBXBuildFile; fileRef = F960704C154366AB004D91DD /* deflate.c */; }; - B9197629163AEA54009C397B /* inffast.c in Sources */ = {isa = PBXBuildFile; fileRef = F960704E154366AB004D91DD /* inffast.c */; }; - B919762A163AEA54009C397B /* inflate.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607051154366AB004D91DD /* inflate.c */; }; - B919762B163AEA54009C397B /* inftrees.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607053154366AB004D91DD /* inftrees.c */; }; - B919762C163AEA54009C397B /* trees.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607056154366AB004D91DD /* trees.c */; }; - B919762D163AEA54009C397B /* zutil.c in Sources */ = {isa = PBXBuildFile; fileRef = F960705B154366AB004D91DD /* zutil.c */; }; - B919762E163AEA54009C397B /* XGLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F96070B5154366ED004D91DD /* XGLLoader.cpp */; }; - B919762F163AEA54009C397B /* clipper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F96070C51543673B004D91DD /* clipper.cpp */; }; - B9197630163AEA54009C397B /* shapes.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070D21543675E004D91DD /* shapes.cc */; }; - B9197631163AEA54009C397B /* advancing_front.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070D71543675E004D91DD /* advancing_front.cc */; }; - B9197632163AEA54009C397B /* cdt.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070D91543675E004D91DD /* cdt.cc */; }; - B9197633163AEA54009C397B /* sweep.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070DB1543675E004D91DD /* sweep.cc */; }; - B9197634163AEA54009C397B /* sweep_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070DD1543675E004D91DD /* sweep_context.cc */; }; - F90BAFD20F5DD87000124155 /* ACLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFD00F5DD87000124155 /* ACLoader.cpp */; }; - F90BAFD30F5DD87000124155 /* ACLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFD10F5DD87000124155 /* ACLoader.h */; }; - F90BAFDF0F5DD90800124155 /* IRRLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFD90F5DD90800124155 /* IRRLoader.cpp */; }; - F90BAFE00F5DD90800124155 /* IRRLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFDA0F5DD90800124155 /* IRRLoader.h */; }; - F90BAFE10F5DD90800124155 /* IRRMeshLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFDB0F5DD90800124155 /* IRRMeshLoader.cpp */; }; - F90BAFE20F5DD90800124155 /* IRRMeshLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFDC0F5DD90800124155 /* IRRMeshLoader.h */; }; - F90BAFE30F5DD90800124155 /* IRRShared.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFDD0F5DD90800124155 /* IRRShared.cpp */; }; - F90BAFE40F5DD90800124155 /* IRRShared.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFDE0F5DD90800124155 /* IRRShared.h */; }; - F90BAFF70F5DD96100124155 /* NFFLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFF50F5DD96100124155 /* NFFLoader.h */; }; - F90BAFF80F5DD96100124155 /* NFFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFF60F5DD96100124155 /* NFFLoader.cpp */; }; - F90BB0080F5DD9DD00124155 /* Q3DLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0060F5DD9DD00124155 /* Q3DLoader.cpp */; }; - F90BB0090F5DD9DD00124155 /* Q3DLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0070F5DD9DD00124155 /* Q3DLoader.h */; }; - F90BB00E0F5DD9F400124155 /* BVHLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB00C0F5DD9F400124155 /* BVHLoader.h */; }; - F90BB00F0F5DD9F400124155 /* BVHLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB00D0F5DD9F400124155 /* BVHLoader.cpp */; }; - F90BB0150F5DDA1400124155 /* OFFLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0130F5DDA1400124155 /* OFFLoader.h */; }; - F90BB0160F5DDA1400124155 /* OFFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0140F5DDA1400124155 /* OFFLoader.cpp */; }; - F90BB01D0F5DDA4400124155 /* RawLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB01B0F5DDA4400124155 /* RawLoader.h */; }; - F90BB01E0F5DDA4400124155 /* RawLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB01C0F5DDA4400124155 /* RawLoader.cpp */; }; - F90BB0230F5DDA5700124155 /* DXFLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0210F5DDA5700124155 /* DXFLoader.h */; }; - F90BB0240F5DDA5700124155 /* DXFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0220F5DDA5700124155 /* DXFLoader.cpp */; }; - F90BB0280F5DDA9200124155 /* LWOBLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0270F5DDA9200124155 /* LWOBLoader.cpp */; }; - F90BB0310F5DDAB500124155 /* TerragenLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB02F0F5DDAB500124155 /* TerragenLoader.h */; }; - F90BB0320F5DDAB500124155 /* TerragenLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0300F5DDAB500124155 /* TerragenLoader.cpp */; }; - F90BB0370F5DDB1B00124155 /* irrXMLWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0360F5DDB1B00124155 /* irrXMLWrapper.h */; }; - F90BB0890F5DDE0700124155 /* B3DImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0870F5DDE0700124155 /* B3DImporter.h */; }; - F90BB08A0F5DDE0700124155 /* B3DImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0880F5DDE0700124155 /* B3DImporter.cpp */; }; - F960705D154366AB004D91DD /* adler32.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607047154366AB004D91DD /* adler32.c */; }; - F960705E154366AB004D91DD /* compress.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607049154366AB004D91DD /* compress.c */; }; - F960705F154366AB004D91DD /* crc32.c in Sources */ = {isa = PBXBuildFile; fileRef = F960704A154366AB004D91DD /* crc32.c */; }; - F9607060154366AB004D91DD /* crc32.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704B154366AB004D91DD /* crc32.h */; }; - F9607061154366AB004D91DD /* deflate.c in Sources */ = {isa = PBXBuildFile; fileRef = F960704C154366AB004D91DD /* deflate.c */; }; - F9607062154366AB004D91DD /* deflate.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704D154366AB004D91DD /* deflate.h */; }; - F9607063154366AB004D91DD /* inffast.c in Sources */ = {isa = PBXBuildFile; fileRef = F960704E154366AB004D91DD /* inffast.c */; }; - F9607064154366AB004D91DD /* inffast.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704F154366AB004D91DD /* inffast.h */; }; - F9607065154366AB004D91DD /* inffixed.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607050154366AB004D91DD /* inffixed.h */; }; - F9607066154366AB004D91DD /* inflate.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607051154366AB004D91DD /* inflate.c */; }; - F9607067154366AB004D91DD /* inflate.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607052154366AB004D91DD /* inflate.h */; }; - F9607068154366AB004D91DD /* inftrees.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607053154366AB004D91DD /* inftrees.c */; }; - F9607069154366AB004D91DD /* inftrees.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607054154366AB004D91DD /* inftrees.h */; }; - F960706A154366AB004D91DD /* trees.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607056154366AB004D91DD /* trees.c */; }; - F960706B154366AB004D91DD /* trees.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607057154366AB004D91DD /* trees.h */; }; - F960706C154366AB004D91DD /* zconf.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607058154366AB004D91DD /* zconf.h */; }; - F960706D154366AB004D91DD /* zconf.in.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607059154366AB004D91DD /* zconf.in.h */; }; - F960706E154366AB004D91DD /* zlib.h in Headers */ = {isa = PBXBuildFile; fileRef = F960705A154366AB004D91DD /* zlib.h */; }; - F960706F154366AB004D91DD /* zutil.c in Sources */ = {isa = PBXBuildFile; fileRef = F960705B154366AB004D91DD /* zutil.c */; }; - F9607070154366AB004D91DD /* zutil.h in Headers */ = {isa = PBXBuildFile; fileRef = F960705C154366AB004D91DD /* zutil.h */; }; - F9607071154366AB004D91DD /* adler32.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607047154366AB004D91DD /* adler32.c */; }; - F9607072154366AB004D91DD /* compress.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607049154366AB004D91DD /* compress.c */; }; - F9607073154366AB004D91DD /* crc32.c in Sources */ = {isa = PBXBuildFile; fileRef = F960704A154366AB004D91DD /* crc32.c */; }; - F9607074154366AB004D91DD /* crc32.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704B154366AB004D91DD /* crc32.h */; }; - F9607075154366AB004D91DD /* deflate.c in Sources */ = {isa = PBXBuildFile; fileRef = F960704C154366AB004D91DD /* deflate.c */; }; - F9607076154366AB004D91DD /* deflate.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704D154366AB004D91DD /* deflate.h */; }; - F9607077154366AB004D91DD /* inffast.c in Sources */ = {isa = PBXBuildFile; fileRef = F960704E154366AB004D91DD /* inffast.c */; }; - F9607078154366AB004D91DD /* inffast.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704F154366AB004D91DD /* inffast.h */; }; - F9607079154366AB004D91DD /* inffixed.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607050154366AB004D91DD /* inffixed.h */; }; - F960707A154366AB004D91DD /* inflate.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607051154366AB004D91DD /* inflate.c */; }; - F960707B154366AB004D91DD /* inflate.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607052154366AB004D91DD /* inflate.h */; }; - F960707C154366AB004D91DD /* inftrees.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607053154366AB004D91DD /* inftrees.c */; }; - F960707D154366AB004D91DD /* inftrees.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607054154366AB004D91DD /* inftrees.h */; }; - F960707E154366AB004D91DD /* trees.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607056154366AB004D91DD /* trees.c */; }; - F960707F154366AB004D91DD /* trees.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607057154366AB004D91DD /* trees.h */; }; - F9607080154366AB004D91DD /* zconf.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607058154366AB004D91DD /* zconf.h */; }; - F9607081154366AB004D91DD /* zconf.in.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607059154366AB004D91DD /* zconf.in.h */; }; - F9607082154366AB004D91DD /* zlib.h in Headers */ = {isa = PBXBuildFile; fileRef = F960705A154366AB004D91DD /* zlib.h */; }; - F9607083154366AB004D91DD /* zutil.c in Sources */ = {isa = PBXBuildFile; fileRef = F960705B154366AB004D91DD /* zutil.c */; }; - F9607084154366AB004D91DD /* zutil.h in Headers */ = {isa = PBXBuildFile; fileRef = F960705C154366AB004D91DD /* zutil.h */; }; - F9607085154366AB004D91DD /* adler32.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607047154366AB004D91DD /* adler32.c */; }; - F9607086154366AB004D91DD /* compress.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607049154366AB004D91DD /* compress.c */; }; - F9607087154366AB004D91DD /* crc32.c in Sources */ = {isa = PBXBuildFile; fileRef = F960704A154366AB004D91DD /* crc32.c */; }; - F9607088154366AB004D91DD /* crc32.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704B154366AB004D91DD /* crc32.h */; }; - F9607089154366AB004D91DD /* deflate.c in Sources */ = {isa = PBXBuildFile; fileRef = F960704C154366AB004D91DD /* deflate.c */; }; - F960708A154366AB004D91DD /* deflate.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704D154366AB004D91DD /* deflate.h */; }; - F960708B154366AB004D91DD /* inffast.c in Sources */ = {isa = PBXBuildFile; fileRef = F960704E154366AB004D91DD /* inffast.c */; }; - F960708C154366AB004D91DD /* inffast.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704F154366AB004D91DD /* inffast.h */; }; - F960708D154366AB004D91DD /* inffixed.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607050154366AB004D91DD /* inffixed.h */; }; - F960708E154366AB004D91DD /* inflate.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607051154366AB004D91DD /* inflate.c */; }; - F960708F154366AB004D91DD /* inflate.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607052154366AB004D91DD /* inflate.h */; }; - F9607090154366AB004D91DD /* inftrees.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607053154366AB004D91DD /* inftrees.c */; }; - F9607091154366AB004D91DD /* inftrees.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607054154366AB004D91DD /* inftrees.h */; }; - F9607092154366AB004D91DD /* trees.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607056154366AB004D91DD /* trees.c */; }; - F9607093154366AB004D91DD /* trees.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607057154366AB004D91DD /* trees.h */; }; - F9607094154366AB004D91DD /* zconf.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607058154366AB004D91DD /* zconf.h */; }; - F9607095154366AB004D91DD /* zconf.in.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607059154366AB004D91DD /* zconf.in.h */; }; - F9607096154366AB004D91DD /* zlib.h in Headers */ = {isa = PBXBuildFile; fileRef = F960705A154366AB004D91DD /* zlib.h */; }; - F9607097154366AB004D91DD /* zutil.c in Sources */ = {isa = PBXBuildFile; fileRef = F960705B154366AB004D91DD /* zutil.c */; }; - F9607098154366AB004D91DD /* zutil.h in Headers */ = {isa = PBXBuildFile; fileRef = F960705C154366AB004D91DD /* zutil.h */; }; - F9607099154366AB004D91DD /* adler32.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607047154366AB004D91DD /* adler32.c */; }; - F960709A154366AB004D91DD /* compress.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607049154366AB004D91DD /* compress.c */; }; - F960709B154366AB004D91DD /* crc32.c in Sources */ = {isa = PBXBuildFile; fileRef = F960704A154366AB004D91DD /* crc32.c */; }; - F960709C154366AB004D91DD /* crc32.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704B154366AB004D91DD /* crc32.h */; }; - F960709D154366AB004D91DD /* deflate.c in Sources */ = {isa = PBXBuildFile; fileRef = F960704C154366AB004D91DD /* deflate.c */; }; - F960709E154366AB004D91DD /* deflate.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704D154366AB004D91DD /* deflate.h */; }; - F960709F154366AB004D91DD /* inffast.c in Sources */ = {isa = PBXBuildFile; fileRef = F960704E154366AB004D91DD /* inffast.c */; }; - F96070A0154366AB004D91DD /* inffast.h in Headers */ = {isa = PBXBuildFile; fileRef = F960704F154366AB004D91DD /* inffast.h */; }; - F96070A1154366AB004D91DD /* inffixed.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607050154366AB004D91DD /* inffixed.h */; }; - F96070A2154366AB004D91DD /* inflate.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607051154366AB004D91DD /* inflate.c */; }; - F96070A3154366AB004D91DD /* inflate.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607052154366AB004D91DD /* inflate.h */; }; - F96070A4154366AB004D91DD /* inftrees.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607053154366AB004D91DD /* inftrees.c */; }; - F96070A5154366AB004D91DD /* inftrees.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607054154366AB004D91DD /* inftrees.h */; }; - F96070A6154366AB004D91DD /* trees.c in Sources */ = {isa = PBXBuildFile; fileRef = F9607056154366AB004D91DD /* trees.c */; }; - F96070A7154366AB004D91DD /* trees.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607057154366AB004D91DD /* trees.h */; }; - F96070A8154366AB004D91DD /* zconf.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607058154366AB004D91DD /* zconf.h */; }; - F96070A9154366AB004D91DD /* zconf.in.h in Headers */ = {isa = PBXBuildFile; fileRef = F9607059154366AB004D91DD /* zconf.in.h */; }; - F96070AA154366AB004D91DD /* zlib.h in Headers */ = {isa = PBXBuildFile; fileRef = F960705A154366AB004D91DD /* zlib.h */; }; - F96070AB154366AB004D91DD /* zutil.c in Sources */ = {isa = PBXBuildFile; fileRef = F960705B154366AB004D91DD /* zutil.c */; }; - F96070AC154366AB004D91DD /* zutil.h in Headers */ = {isa = PBXBuildFile; fileRef = F960705C154366AB004D91DD /* zutil.h */; }; - F96070B7154366ED004D91DD /* XGLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F96070B5154366ED004D91DD /* XGLLoader.cpp */; }; - F96070B8154366ED004D91DD /* XGLLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070B6154366ED004D91DD /* XGLLoader.h */; }; - F96070B9154366ED004D91DD /* XGLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F96070B5154366ED004D91DD /* XGLLoader.cpp */; }; - F96070BA154366ED004D91DD /* XGLLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070B6154366ED004D91DD /* XGLLoader.h */; }; - F96070BB154366ED004D91DD /* XGLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F96070B5154366ED004D91DD /* XGLLoader.cpp */; }; - F96070BC154366ED004D91DD /* XGLLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070B6154366ED004D91DD /* XGLLoader.h */; }; - F96070BD154366ED004D91DD /* XGLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F96070B5154366ED004D91DD /* XGLLoader.cpp */; }; - F96070BE154366ED004D91DD /* XGLLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070B6154366ED004D91DD /* XGLLoader.h */; }; - F96070C81543673B004D91DD /* clipper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F96070C51543673B004D91DD /* clipper.cpp */; }; - F96070C91543673B004D91DD /* clipper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F96070C61543673B004D91DD /* clipper.hpp */; }; - F96070CA1543673B004D91DD /* clipper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F96070C51543673B004D91DD /* clipper.cpp */; }; - F96070CB1543673B004D91DD /* clipper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F96070C61543673B004D91DD /* clipper.hpp */; }; - F96070CC1543673B004D91DD /* clipper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F96070C51543673B004D91DD /* clipper.cpp */; }; - F96070CD1543673B004D91DD /* clipper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F96070C61543673B004D91DD /* clipper.hpp */; }; - F96070CE1543673B004D91DD /* clipper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F96070C51543673B004D91DD /* clipper.cpp */; }; - F96070CF1543673B004D91DD /* clipper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F96070C61543673B004D91DD /* clipper.hpp */; }; - F96070DF1543675E004D91DD /* shapes.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070D21543675E004D91DD /* shapes.cc */; }; - F96070E01543675E004D91DD /* shapes.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D31543675E004D91DD /* shapes.h */; }; - F96070E11543675E004D91DD /* utils.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D41543675E004D91DD /* utils.h */; }; - F96070E21543675E004D91DD /* poly2tri.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D51543675E004D91DD /* poly2tri.h */; }; - F96070E31543675E004D91DD /* advancing_front.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070D71543675E004D91DD /* advancing_front.cc */; }; - F96070E41543675E004D91DD /* advancing_front.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D81543675E004D91DD /* advancing_front.h */; }; - F96070E51543675E004D91DD /* cdt.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070D91543675E004D91DD /* cdt.cc */; }; - F96070E61543675E004D91DD /* cdt.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070DA1543675E004D91DD /* cdt.h */; }; - F96070E71543675E004D91DD /* sweep.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070DB1543675E004D91DD /* sweep.cc */; }; - F96070E81543675E004D91DD /* sweep.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070DC1543675E004D91DD /* sweep.h */; }; - F96070E91543675E004D91DD /* sweep_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070DD1543675E004D91DD /* sweep_context.cc */; }; - F96070EA1543675E004D91DD /* sweep_context.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070DE1543675E004D91DD /* sweep_context.h */; }; - F96070EB1543675E004D91DD /* shapes.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070D21543675E004D91DD /* shapes.cc */; }; - F96070EC1543675E004D91DD /* shapes.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D31543675E004D91DD /* shapes.h */; }; - F96070ED1543675E004D91DD /* utils.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D41543675E004D91DD /* utils.h */; }; - F96070EE1543675E004D91DD /* poly2tri.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D51543675E004D91DD /* poly2tri.h */; }; - F96070EF1543675E004D91DD /* advancing_front.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070D71543675E004D91DD /* advancing_front.cc */; }; - F96070F01543675E004D91DD /* advancing_front.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D81543675E004D91DD /* advancing_front.h */; }; - F96070F11543675E004D91DD /* cdt.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070D91543675E004D91DD /* cdt.cc */; }; - F96070F21543675E004D91DD /* cdt.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070DA1543675E004D91DD /* cdt.h */; }; - F96070F31543675E004D91DD /* sweep.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070DB1543675E004D91DD /* sweep.cc */; }; - F96070F41543675E004D91DD /* sweep.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070DC1543675E004D91DD /* sweep.h */; }; - F96070F51543675E004D91DD /* sweep_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070DD1543675E004D91DD /* sweep_context.cc */; }; - F96070F61543675E004D91DD /* sweep_context.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070DE1543675E004D91DD /* sweep_context.h */; }; - F96070F71543675E004D91DD /* shapes.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070D21543675E004D91DD /* shapes.cc */; }; - F96070F81543675E004D91DD /* shapes.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D31543675E004D91DD /* shapes.h */; }; - F96070F91543675E004D91DD /* utils.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D41543675E004D91DD /* utils.h */; }; - F96070FA1543675E004D91DD /* poly2tri.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D51543675E004D91DD /* poly2tri.h */; }; - F96070FB1543675E004D91DD /* advancing_front.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070D71543675E004D91DD /* advancing_front.cc */; }; - F96070FC1543675E004D91DD /* advancing_front.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D81543675E004D91DD /* advancing_front.h */; }; - F96070FD1543675E004D91DD /* cdt.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070D91543675E004D91DD /* cdt.cc */; }; - F96070FE1543675E004D91DD /* cdt.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070DA1543675E004D91DD /* cdt.h */; }; - F96070FF1543675E004D91DD /* sweep.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070DB1543675E004D91DD /* sweep.cc */; }; - F96071001543675E004D91DD /* sweep.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070DC1543675E004D91DD /* sweep.h */; }; - F96071011543675E004D91DD /* sweep_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070DD1543675E004D91DD /* sweep_context.cc */; }; - F96071021543675E004D91DD /* sweep_context.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070DE1543675E004D91DD /* sweep_context.h */; }; - F96071031543675E004D91DD /* shapes.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070D21543675E004D91DD /* shapes.cc */; }; - F96071041543675E004D91DD /* shapes.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D31543675E004D91DD /* shapes.h */; }; - F96071051543675E004D91DD /* utils.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D41543675E004D91DD /* utils.h */; }; - F96071061543675E004D91DD /* poly2tri.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D51543675E004D91DD /* poly2tri.h */; }; - F96071071543675E004D91DD /* advancing_front.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070D71543675E004D91DD /* advancing_front.cc */; }; - F96071081543675E004D91DD /* advancing_front.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070D81543675E004D91DD /* advancing_front.h */; }; - F96071091543675E004D91DD /* cdt.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070D91543675E004D91DD /* cdt.cc */; }; - F960710A1543675E004D91DD /* cdt.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070DA1543675E004D91DD /* cdt.h */; }; - F960710B1543675E004D91DD /* sweep.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070DB1543675E004D91DD /* sweep.cc */; }; - F960710C1543675E004D91DD /* sweep.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070DC1543675E004D91DD /* sweep.h */; }; - F960710D1543675E004D91DD /* sweep_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = F96070DD1543675E004D91DD /* sweep_context.cc */; }; - F960710E1543675E004D91DD /* sweep_context.h in Headers */ = {isa = PBXBuildFile; fileRef = F96070DE1543675E004D91DD /* sweep_context.h */; }; - F962E88B0F5DE6C8009A5495 /* 3DSConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A860E4B716800207D74 /* 3DSConverter.cpp */; }; - F962E88C0F5DE6C8009A5495 /* 3DSLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A890E4B716800207D74 /* 3DSLoader.cpp */; }; - F962E88E0F5DE6C8009A5495 /* ASELoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A8E0E4B716800207D74 /* ASELoader.cpp */; }; - F962E88F0F5DE6C8009A5495 /* ASEParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45A900E4B716800207D74 /* ASEParser.cpp */; }; - F962E89A0F5DE6C8009A5495 /* HMPLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AAB0E4B716800207D74 /* HMPLoader.cpp */; }; - F962E8A00F5DE6C8009A5495 /* MD2Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AB90E4B716800207D74 /* MD2Loader.cpp */; }; - F962E8A10F5DE6C8009A5495 /* MD3Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45ABD0E4B716800207D74 /* MD3Loader.cpp */; }; - F962E8A20F5DE6C8009A5495 /* MD5Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AC20E4B716800207D74 /* MD5Loader.cpp */; }; - F962E8A30F5DE6C8009A5495 /* MD5Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AC40E4B716800207D74 /* MD5Parser.cpp */; }; - F962E8A40F5DE6C8009A5495 /* MDLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AC80E4B716800207D74 /* MDLLoader.cpp */; }; - F962E8A50F5DE6C8009A5495 /* MDLMaterialLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45ACA0E4B716800207D74 /* MDLMaterialLoader.cpp */; }; - F962E8A90F5DE6C8009A5495 /* PlyLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AD40E4B716800207D74 /* PlyLoader.cpp */; }; - F962E8AA0F5DE6C8009A5495 /* PlyParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AD60E4B716800207D74 /* PlyParser.cpp */; }; - F962E8AE0F5DE6C8009A5495 /* SMDLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AE20E4B716800207D74 /* SMDLoader.cpp */; }; - F962E8B60F5DE6C8009A5495 /* XFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AF50E4B716800207D74 /* XFileImporter.cpp */; }; - F962E8B70F5DE6C8009A5495 /* XFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AF45AF70E4B716800207D74 /* XFileParser.cpp */; }; - F962E8B80F5DE6C8009A5495 /* MDCLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AB8A3AC0E50D67A00606590 /* MDCLoader.cpp */; }; - F962E8BA0F5DE6C8009A5495 /* LWOLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AB8A3B80E50D6DB00606590 /* LWOLoader.cpp */; }; - F962E8BC0F5DE6C8009A5495 /* LWOMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3AB8A7DC0E53715F00606590 /* LWOMaterial.cpp */; }; - F962E8BD0F5DE6C8009A5495 /* ACLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFD00F5DD87000124155 /* ACLoader.cpp */; }; - F962E8BE0F5DE6C8009A5495 /* IRRLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFD90F5DD90800124155 /* IRRLoader.cpp */; }; - F962E8BF0F5DE6C8009A5495 /* IRRMeshLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFDB0F5DD90800124155 /* IRRMeshLoader.cpp */; }; - F962E8C00F5DE6C8009A5495 /* IRRShared.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFDD0F5DD90800124155 /* IRRShared.cpp */; }; - F962E8C30F5DE6C8009A5495 /* NFFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BAFF60F5DD96100124155 /* NFFLoader.cpp */; }; - F962E8C50F5DE6C8009A5495 /* Q3DLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0060F5DD9DD00124155 /* Q3DLoader.cpp */; }; - F962E8C60F5DE6C8009A5495 /* BVHLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB00D0F5DD9F400124155 /* BVHLoader.cpp */; }; - F962E8C70F5DE6C8009A5495 /* OFFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0140F5DDA1400124155 /* OFFLoader.cpp */; }; - F962E8C80F5DE6C8009A5495 /* RawLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB01C0F5DDA4400124155 /* RawLoader.cpp */; }; - F962E8C90F5DE6C8009A5495 /* DXFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0220F5DDA5700124155 /* DXFLoader.cpp */; }; - F962E8CA0F5DE6C8009A5495 /* LWOBLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0270F5DDA9200124155 /* LWOBLoader.cpp */; }; - F962E8CB0F5DE6C8009A5495 /* TerragenLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0300F5DDAB500124155 /* TerragenLoader.cpp */; }; - F962E8D70F5DE6C8009A5495 /* B3DImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F90BB0880F5DDE0700124155 /* B3DImporter.cpp */; }; - F962E8ED0F5DE6E2009A5495 /* 3DSHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A880E4B716800207D74 /* 3DSHelper.h */; }; - F962E8EE0F5DE6E2009A5495 /* 3DSLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A8A0E4B716800207D74 /* 3DSLoader.h */; }; - F962E8EF0F5DE6E2009A5495 /* ASELoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A8F0E4B716800207D74 /* ASELoader.h */; }; - F962E8F00F5DE6E2009A5495 /* ASEParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45A910E4B716800207D74 /* ASEParser.h */; }; - F962E8FD0F5DE6E2009A5495 /* HalfLifeFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AA90E4B716800207D74 /* HalfLifeFileData.h */; }; - F962E8FE0F5DE6E2009A5495 /* HMPLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AAC0E4B716800207D74 /* HMPLoader.h */; }; - F962E9030F5DE6E2009A5495 /* MD2FileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AB80E4B716800207D74 /* MD2FileData.h */; }; - F962E9040F5DE6E2009A5495 /* MD2Loader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABA0E4B716800207D74 /* MD2Loader.h */; }; - F962E9050F5DE6E2009A5495 /* MD2NormalTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABB0E4B716800207D74 /* MD2NormalTable.h */; }; - F962E9060F5DE6E2009A5495 /* MD3FileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABC0E4B716800207D74 /* MD3FileData.h */; }; - F962E9070F5DE6E2009A5495 /* MD3Loader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45ABE0E4B716800207D74 /* MD3Loader.h */; }; - F962E9080F5DE6E2009A5495 /* MD5Loader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC30E4B716800207D74 /* MD5Loader.h */; }; - F962E9090F5DE6E2009A5495 /* MD5Parser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC50E4B716800207D74 /* MD5Parser.h */; }; - F962E90A0F5DE6E2009A5495 /* MDLDefaultColorMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC60E4B716800207D74 /* MDLDefaultColorMap.h */; }; - F962E90B0F5DE6E2009A5495 /* MDLFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC70E4B716800207D74 /* MDLFileData.h */; }; - F962E90C0F5DE6E2009A5495 /* MDLLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AC90E4B716800207D74 /* MDLLoader.h */; }; - F962E9130F5DE6E2009A5495 /* PlyLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AD50E4B716800207D74 /* PlyLoader.h */; }; - F962E9140F5DE6E2009A5495 /* PlyParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AD70E4B716800207D74 /* PlyParser.h */; }; - F962E9190F5DE6E2009A5495 /* SMDLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AE30E4B716800207D74 /* SMDLoader.h */; }; - F962E9230F5DE6E2009A5495 /* XFileHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AF40E4B716800207D74 /* XFileHelper.h */; }; - F962E9240F5DE6E2009A5495 /* XFileImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AF60E4B716800207D74 /* XFileImporter.h */; }; - F962E9250F5DE6E2009A5495 /* XFileParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AF45AF80E4B716800207D74 /* XFileParser.h */; }; - F962E9280F5DE6E2009A5495 /* MDCFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3AB0E50D67A00606590 /* MDCFileData.h */; }; - F962E9290F5DE6E2009A5495 /* MDCLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3AD0E50D67A00606590 /* MDCLoader.h */; }; - F962E92A0F5DE6E2009A5495 /* MDCNormalTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3AE0E50D67A00606590 /* MDCNormalTable.h */; }; - F962E92C0F5DE6E2009A5495 /* LWOFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3B70E50D6DB00606590 /* LWOFileData.h */; }; - F962E92D0F5DE6E2009A5495 /* LWOLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3B90E50D6DB00606590 /* LWOLoader.h */; }; - F962E92E0F5DE6E2009A5495 /* HMPFileData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AB8A3C50E50D77900606590 /* HMPFileData.h */; }; - F962E9360F5DE6E2009A5495 /* ACLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFD10F5DD87000124155 /* ACLoader.h */; }; - F962E9370F5DE6E2009A5495 /* IRRLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFDA0F5DD90800124155 /* IRRLoader.h */; }; - F962E9380F5DE6E2009A5495 /* IRRMeshLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFDC0F5DD90800124155 /* IRRMeshLoader.h */; }; - F962E9390F5DE6E2009A5495 /* IRRShared.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFDE0F5DD90800124155 /* IRRShared.h */; }; - F962E93D0F5DE6E2009A5495 /* NFFLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BAFF50F5DD96100124155 /* NFFLoader.h */; }; - F962E93F0F5DE6E2009A5495 /* Q3DLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0070F5DD9DD00124155 /* Q3DLoader.h */; }; - F962E9400F5DE6E2009A5495 /* BVHLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB00C0F5DD9F400124155 /* BVHLoader.h */; }; - F962E9410F5DE6E2009A5495 /* OFFLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0130F5DDA1400124155 /* OFFLoader.h */; }; - F962E9420F5DE6E2009A5495 /* RawLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB01B0F5DDA4400124155 /* RawLoader.h */; }; - F962E9430F5DE6E2009A5495 /* DXFLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0210F5DDA5700124155 /* DXFLoader.h */; }; - F962E9440F5DE6E2009A5495 /* TerragenLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB02F0F5DDAB500124155 /* TerragenLoader.h */; }; - F962E9450F5DE6E2009A5495 /* irrXMLWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0360F5DDB1B00124155 /* irrXMLWrapper.h */; }; - F962E9570F5DE6E2009A5495 /* B3DImporter.h in Headers */ = {isa = PBXBuildFile; fileRef = F90BB0870F5DDE0700124155 /* B3DImporter.h */; }; - F97BA03615439DB3009EB9DD /* ai_assert.h in Headers */ = {isa = PBXBuildFile; fileRef = F97BA03515439DB3009EB9DD /* ai_assert.h */; }; - F97BA03715439DB3009EB9DD /* ai_assert.h in Headers */ = {isa = PBXBuildFile; fileRef = F97BA03515439DB3009EB9DD /* ai_assert.h */; }; - F97BA03815439DB3009EB9DD /* ai_assert.h in Headers */ = {isa = PBXBuildFile; fileRef = F97BA03515439DB3009EB9DD /* ai_assert.h */; }; - F97BA03915439DB3009EB9DD /* ai_assert.h in Headers */ = {isa = PBXBuildFile; fileRef = F97BA03515439DB3009EB9DD /* ai_assert.h */; }; - F99A9F3215436269000682F3 /* PlyExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F99A9F3015436269000682F3 /* PlyExporter.cpp */; }; - F99A9F3315436269000682F3 /* PlyExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = F99A9F3115436269000682F3 /* PlyExporter.h */; }; - F99A9F3415436269000682F3 /* PlyExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F99A9F3015436269000682F3 /* PlyExporter.cpp */; }; - F99A9F3515436269000682F3 /* PlyExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = F99A9F3115436269000682F3 /* PlyExporter.h */; }; - F99A9F3615436269000682F3 /* PlyExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F99A9F3015436269000682F3 /* PlyExporter.cpp */; }; - F99A9F3715436269000682F3 /* PlyExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = F99A9F3115436269000682F3 /* PlyExporter.h */; }; - F99A9F3815436269000682F3 /* PlyExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F99A9F3015436269000682F3 /* PlyExporter.cpp */; }; - F99A9F3915436269000682F3 /* PlyExporter.h in Headers */ = {isa = PBXBuildFile; fileRef = F99A9F3115436269000682F3 /* PlyExporter.h */; }; - F9BA8B9F1543268400E63FFE /* anim.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B751543268400E63FFE /* anim.h */; }; - F9BA8BA11543268400E63FFE /* camera.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B771543268400E63FFE /* camera.h */; }; - F9BA8BA21543268400E63FFE /* cexport.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B781543268400E63FFE /* cexport.h */; }; - F9BA8BA31543268400E63FFE /* cfileio.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B791543268400E63FFE /* cfileio.h */; }; - F9BA8BA41543268400E63FFE /* cimport.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7A1543268400E63FFE /* cimport.h */; }; - F9BA8BA51543268400E63FFE /* color4.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7B1543268400E63FFE /* color4.h */; }; - F9BA8BA61543268400E63FFE /* poppack1.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7E1543268400E63FFE /* poppack1.h */; }; - F9BA8BA71543268400E63FFE /* pushpack1.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7F1543268400E63FFE /* pushpack1.h */; }; - F9BA8BA81543268400E63FFE /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B801543268400E63FFE /* config.h */; }; - F9BA8BA91543268400E63FFE /* DefaultLogger.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B811543268400E63FFE /* DefaultLogger.hpp */; }; - F9BA8BAA1543268400E63FFE /* defs.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B821543268400E63FFE /* defs.h */; }; - F9BA8BAB1543268400E63FFE /* Exporter.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B831543268400E63FFE /* Exporter.hpp */; }; - F9BA8BAC1543268400E63FFE /* Importer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B841543268400E63FFE /* Importer.hpp */; }; - F9BA8BAD1543268400E63FFE /* importerdesc.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B851543268400E63FFE /* importerdesc.h */; }; - F9BA8BAE1543268400E63FFE /* IOStream.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B861543268400E63FFE /* IOStream.hpp */; }; - F9BA8BAF1543268400E63FFE /* IOSystem.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B871543268400E63FFE /* IOSystem.hpp */; }; - F9BA8BB01543268400E63FFE /* light.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B881543268400E63FFE /* light.h */; }; - F9BA8BB11543268400E63FFE /* Logger.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B891543268400E63FFE /* Logger.hpp */; }; - F9BA8BB21543268400E63FFE /* LogStream.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8A1543268400E63FFE /* LogStream.hpp */; }; - F9BA8BB31543268400E63FFE /* material.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8B1543268400E63FFE /* material.h */; }; - F9BA8BB41543268400E63FFE /* matrix3x3.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8D1543268400E63FFE /* matrix3x3.h */; }; - F9BA8BB51543268400E63FFE /* matrix4x4.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8F1543268400E63FFE /* matrix4x4.h */; }; - F9BA8BB61543268400E63FFE /* mesh.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B911543268400E63FFE /* mesh.h */; }; - F9BA8BB71543268400E63FFE /* NullLogger.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B921543268400E63FFE /* NullLogger.hpp */; }; - F9BA8BB81543268400E63FFE /* postprocess.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B931543268400E63FFE /* postprocess.h */; }; - F9BA8BB91543268400E63FFE /* ProgressHandler.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B941543268400E63FFE /* ProgressHandler.hpp */; }; - F9BA8BBA1543268400E63FFE /* quaternion.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B951543268400E63FFE /* quaternion.h */; }; - F9BA8BBB1543268400E63FFE /* scene.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B971543268400E63FFE /* scene.h */; }; - F9BA8BBC1543268400E63FFE /* texture.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B981543268400E63FFE /* texture.h */; }; - F9BA8BBD1543268400E63FFE /* types.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B991543268400E63FFE /* types.h */; }; - F9BA8BBE1543268400E63FFE /* vector2.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B9A1543268400E63FFE /* vector2.h */; }; - F9BA8BBF1543268400E63FFE /* vector3.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B9C1543268400E63FFE /* vector3.h */; }; - F9BA8BC01543268400E63FFE /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B9E1543268400E63FFE /* version.h */; }; - F9BA8BC11543268400E63FFE /* anim.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B751543268400E63FFE /* anim.h */; }; - F9BA8BC31543268400E63FFE /* camera.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B771543268400E63FFE /* camera.h */; }; - F9BA8BC41543268400E63FFE /* cexport.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B781543268400E63FFE /* cexport.h */; }; - F9BA8BC51543268400E63FFE /* cfileio.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B791543268400E63FFE /* cfileio.h */; }; - F9BA8BC61543268400E63FFE /* cimport.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7A1543268400E63FFE /* cimport.h */; }; - F9BA8BC71543268400E63FFE /* color4.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7B1543268400E63FFE /* color4.h */; }; - F9BA8BC81543268400E63FFE /* poppack1.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7E1543268400E63FFE /* poppack1.h */; }; - F9BA8BC91543268400E63FFE /* pushpack1.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7F1543268400E63FFE /* pushpack1.h */; }; - F9BA8BCA1543268400E63FFE /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B801543268400E63FFE /* config.h */; }; - F9BA8BCB1543268400E63FFE /* DefaultLogger.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B811543268400E63FFE /* DefaultLogger.hpp */; }; - F9BA8BCC1543268400E63FFE /* defs.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B821543268400E63FFE /* defs.h */; }; - F9BA8BCD1543268400E63FFE /* Exporter.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B831543268400E63FFE /* Exporter.hpp */; }; - F9BA8BCE1543268400E63FFE /* Importer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B841543268400E63FFE /* Importer.hpp */; }; - F9BA8BCF1543268400E63FFE /* importerdesc.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B851543268400E63FFE /* importerdesc.h */; }; - F9BA8BD01543268400E63FFE /* IOStream.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B861543268400E63FFE /* IOStream.hpp */; }; - F9BA8BD11543268400E63FFE /* IOSystem.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B871543268400E63FFE /* IOSystem.hpp */; }; - F9BA8BD21543268400E63FFE /* light.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B881543268400E63FFE /* light.h */; }; - F9BA8BD31543268400E63FFE /* Logger.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B891543268400E63FFE /* Logger.hpp */; }; - F9BA8BD41543268400E63FFE /* LogStream.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8A1543268400E63FFE /* LogStream.hpp */; }; - F9BA8BD51543268400E63FFE /* material.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8B1543268400E63FFE /* material.h */; }; - F9BA8BD61543268400E63FFE /* matrix3x3.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8D1543268400E63FFE /* matrix3x3.h */; }; - F9BA8BD71543268400E63FFE /* matrix4x4.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8F1543268400E63FFE /* matrix4x4.h */; }; - F9BA8BD81543268400E63FFE /* mesh.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B911543268400E63FFE /* mesh.h */; }; - F9BA8BD91543268400E63FFE /* NullLogger.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B921543268400E63FFE /* NullLogger.hpp */; }; - F9BA8BDA1543268400E63FFE /* postprocess.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B931543268400E63FFE /* postprocess.h */; }; - F9BA8BDB1543268400E63FFE /* ProgressHandler.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B941543268400E63FFE /* ProgressHandler.hpp */; }; - F9BA8BDC1543268400E63FFE /* quaternion.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B951543268400E63FFE /* quaternion.h */; }; - F9BA8BDD1543268400E63FFE /* scene.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B971543268400E63FFE /* scene.h */; }; - F9BA8BDE1543268400E63FFE /* texture.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B981543268400E63FFE /* texture.h */; }; - F9BA8BDF1543268400E63FFE /* types.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B991543268400E63FFE /* types.h */; }; - F9BA8BE01543268400E63FFE /* vector2.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B9A1543268400E63FFE /* vector2.h */; }; - F9BA8BE11543268400E63FFE /* vector3.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B9C1543268400E63FFE /* vector3.h */; }; - F9BA8BE21543268400E63FFE /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B9E1543268400E63FFE /* version.h */; }; - F9BA8BE31543268400E63FFE /* anim.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B751543268400E63FFE /* anim.h */; }; - F9BA8BE51543268400E63FFE /* camera.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B771543268400E63FFE /* camera.h */; }; - F9BA8BE61543268400E63FFE /* cexport.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B781543268400E63FFE /* cexport.h */; }; - F9BA8BE71543268400E63FFE /* cfileio.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B791543268400E63FFE /* cfileio.h */; }; - F9BA8BE81543268400E63FFE /* cimport.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7A1543268400E63FFE /* cimport.h */; }; - F9BA8BE91543268400E63FFE /* color4.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7B1543268400E63FFE /* color4.h */; }; - F9BA8BEA1543268400E63FFE /* poppack1.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7E1543268400E63FFE /* poppack1.h */; }; - F9BA8BEB1543268400E63FFE /* pushpack1.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7F1543268400E63FFE /* pushpack1.h */; }; - F9BA8BEC1543268400E63FFE /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B801543268400E63FFE /* config.h */; }; - F9BA8BED1543268400E63FFE /* DefaultLogger.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B811543268400E63FFE /* DefaultLogger.hpp */; }; - F9BA8BEE1543268400E63FFE /* defs.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B821543268400E63FFE /* defs.h */; }; - F9BA8BEF1543268400E63FFE /* Exporter.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B831543268400E63FFE /* Exporter.hpp */; }; - F9BA8BF01543268400E63FFE /* Importer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B841543268400E63FFE /* Importer.hpp */; }; - F9BA8BF11543268400E63FFE /* importerdesc.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B851543268400E63FFE /* importerdesc.h */; }; - F9BA8BF21543268400E63FFE /* IOStream.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B861543268400E63FFE /* IOStream.hpp */; }; - F9BA8BF31543268400E63FFE /* IOSystem.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B871543268400E63FFE /* IOSystem.hpp */; }; - F9BA8BF41543268400E63FFE /* light.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B881543268400E63FFE /* light.h */; }; - F9BA8BF51543268400E63FFE /* Logger.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B891543268400E63FFE /* Logger.hpp */; }; - F9BA8BF61543268400E63FFE /* LogStream.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8A1543268400E63FFE /* LogStream.hpp */; }; - F9BA8BF71543268400E63FFE /* material.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8B1543268400E63FFE /* material.h */; }; - F9BA8BF81543268400E63FFE /* matrix3x3.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8D1543268400E63FFE /* matrix3x3.h */; }; - F9BA8BF91543268400E63FFE /* matrix4x4.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8F1543268400E63FFE /* matrix4x4.h */; }; - F9BA8BFA1543268400E63FFE /* mesh.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B911543268400E63FFE /* mesh.h */; }; - F9BA8BFB1543268400E63FFE /* NullLogger.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B921543268400E63FFE /* NullLogger.hpp */; }; - F9BA8BFC1543268400E63FFE /* postprocess.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B931543268400E63FFE /* postprocess.h */; }; - F9BA8BFD1543268400E63FFE /* ProgressHandler.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B941543268400E63FFE /* ProgressHandler.hpp */; }; - F9BA8BFE1543268400E63FFE /* quaternion.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B951543268400E63FFE /* quaternion.h */; }; - F9BA8BFF1543268400E63FFE /* scene.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B971543268400E63FFE /* scene.h */; }; - F9BA8C001543268400E63FFE /* texture.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B981543268400E63FFE /* texture.h */; }; - F9BA8C011543268400E63FFE /* types.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B991543268400E63FFE /* types.h */; }; - F9BA8C021543268400E63FFE /* vector2.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B9A1543268400E63FFE /* vector2.h */; }; - F9BA8C031543268400E63FFE /* vector3.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B9C1543268400E63FFE /* vector3.h */; }; - F9BA8C041543268400E63FFE /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B9E1543268400E63FFE /* version.h */; }; - F9BA8C051543268400E63FFE /* anim.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B751543268400E63FFE /* anim.h */; }; - F9BA8C071543268400E63FFE /* camera.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B771543268400E63FFE /* camera.h */; }; - F9BA8C081543268400E63FFE /* cexport.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B781543268400E63FFE /* cexport.h */; }; - F9BA8C091543268400E63FFE /* cfileio.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B791543268400E63FFE /* cfileio.h */; }; - F9BA8C0A1543268400E63FFE /* cimport.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7A1543268400E63FFE /* cimport.h */; }; - F9BA8C0B1543268400E63FFE /* color4.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7B1543268400E63FFE /* color4.h */; }; - F9BA8C0C1543268400E63FFE /* poppack1.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7E1543268400E63FFE /* poppack1.h */; }; - F9BA8C0D1543268400E63FFE /* pushpack1.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B7F1543268400E63FFE /* pushpack1.h */; }; - F9BA8C0E1543268400E63FFE /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B801543268400E63FFE /* config.h */; }; - F9BA8C0F1543268400E63FFE /* DefaultLogger.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B811543268400E63FFE /* DefaultLogger.hpp */; }; - F9BA8C101543268400E63FFE /* defs.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B821543268400E63FFE /* defs.h */; }; - F9BA8C111543268400E63FFE /* Exporter.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B831543268400E63FFE /* Exporter.hpp */; }; - F9BA8C121543268400E63FFE /* Importer.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B841543268400E63FFE /* Importer.hpp */; }; - F9BA8C131543268400E63FFE /* importerdesc.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B851543268400E63FFE /* importerdesc.h */; }; - F9BA8C141543268400E63FFE /* IOStream.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B861543268400E63FFE /* IOStream.hpp */; }; - F9BA8C151543268400E63FFE /* IOSystem.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B871543268400E63FFE /* IOSystem.hpp */; }; - F9BA8C161543268400E63FFE /* light.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B881543268400E63FFE /* light.h */; }; - F9BA8C171543268400E63FFE /* Logger.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B891543268400E63FFE /* Logger.hpp */; }; - F9BA8C181543268400E63FFE /* LogStream.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8A1543268400E63FFE /* LogStream.hpp */; }; - F9BA8C191543268400E63FFE /* material.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8B1543268400E63FFE /* material.h */; }; - F9BA8C1A1543268400E63FFE /* matrix3x3.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8D1543268400E63FFE /* matrix3x3.h */; }; - F9BA8C1B1543268400E63FFE /* matrix4x4.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B8F1543268400E63FFE /* matrix4x4.h */; }; - F9BA8C1C1543268400E63FFE /* mesh.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B911543268400E63FFE /* mesh.h */; }; - F9BA8C1D1543268400E63FFE /* NullLogger.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B921543268400E63FFE /* NullLogger.hpp */; }; - F9BA8C1E1543268400E63FFE /* postprocess.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B931543268400E63FFE /* postprocess.h */; }; - F9BA8C1F1543268400E63FFE /* ProgressHandler.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B941543268400E63FFE /* ProgressHandler.hpp */; }; - F9BA8C201543268400E63FFE /* quaternion.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B951543268400E63FFE /* quaternion.h */; }; - F9BA8C211543268400E63FFE /* scene.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B971543268400E63FFE /* scene.h */; }; - F9BA8C221543268400E63FFE /* texture.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B981543268400E63FFE /* texture.h */; }; - F9BA8C231543268400E63FFE /* types.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B991543268400E63FFE /* types.h */; }; - F9BA8C241543268400E63FFE /* vector2.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B9A1543268400E63FFE /* vector2.h */; }; - F9BA8C251543268400E63FFE /* vector3.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B9C1543268400E63FFE /* vector3.h */; }; - F9BA8C261543268400E63FFE /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8B9E1543268400E63FFE /* version.h */; }; - F9BA8C3B154328B600E63FFE /* OgreImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C35154328B600E63FFE /* OgreImporter.cpp */; }; - F9BA8C3C154328B600E63FFE /* OgreImporter.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8C36154328B600E63FFE /* OgreImporter.hpp */; }; - F9BA8C3D154328B600E63FFE /* OgreMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C37154328B600E63FFE /* OgreMaterial.cpp */; }; - F9BA8C3E154328B600E63FFE /* OgreMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C38154328B600E63FFE /* OgreMesh.cpp */; }; - F9BA8C3F154328B600E63FFE /* OgreSkeleton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C39154328B600E63FFE /* OgreSkeleton.cpp */; }; - F9BA8C40154328B600E63FFE /* OgreXmlHelper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8C3A154328B600E63FFE /* OgreXmlHelper.hpp */; }; - F9BA8C41154328B600E63FFE /* OgreImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C35154328B600E63FFE /* OgreImporter.cpp */; }; - F9BA8C42154328B600E63FFE /* OgreImporter.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8C36154328B600E63FFE /* OgreImporter.hpp */; }; - F9BA8C43154328B600E63FFE /* OgreMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C37154328B600E63FFE /* OgreMaterial.cpp */; }; - F9BA8C44154328B600E63FFE /* OgreMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C38154328B600E63FFE /* OgreMesh.cpp */; }; - F9BA8C45154328B600E63FFE /* OgreSkeleton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C39154328B600E63FFE /* OgreSkeleton.cpp */; }; - F9BA8C46154328B600E63FFE /* OgreXmlHelper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8C3A154328B600E63FFE /* OgreXmlHelper.hpp */; }; - F9BA8C47154328B600E63FFE /* OgreImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C35154328B600E63FFE /* OgreImporter.cpp */; }; - F9BA8C48154328B600E63FFE /* OgreImporter.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8C36154328B600E63FFE /* OgreImporter.hpp */; }; - F9BA8C49154328B600E63FFE /* OgreMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C37154328B600E63FFE /* OgreMaterial.cpp */; }; - F9BA8C4A154328B600E63FFE /* OgreMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C38154328B600E63FFE /* OgreMesh.cpp */; }; - F9BA8C4B154328B600E63FFE /* OgreSkeleton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C39154328B600E63FFE /* OgreSkeleton.cpp */; }; - F9BA8C4C154328B600E63FFE /* OgreXmlHelper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8C3A154328B600E63FFE /* OgreXmlHelper.hpp */; }; - F9BA8C4D154328B600E63FFE /* OgreImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C35154328B600E63FFE /* OgreImporter.cpp */; }; - F9BA8C4E154328B600E63FFE /* OgreImporter.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8C36154328B600E63FFE /* OgreImporter.hpp */; }; - F9BA8C4F154328B600E63FFE /* OgreMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C37154328B600E63FFE /* OgreMaterial.cpp */; }; - F9BA8C50154328B600E63FFE /* OgreMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C38154328B600E63FFE /* OgreMesh.cpp */; }; - F9BA8C51154328B600E63FFE /* OgreSkeleton.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9BA8C39154328B600E63FFE /* OgreSkeleton.cpp */; }; - F9BA8C52154328B600E63FFE /* OgreXmlHelper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F9BA8C3A154328B600E63FFE /* OgreXmlHelper.hpp */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 2B7F456D1708365100A106A9 /* assbin_chunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assbin_chunks.h; sourceTree = ""; }; - 2B7F456E1708365100A106A9 /* Assimp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Assimp.cpp; sourceTree = ""; }; - 2B7F456F1708365100A106A9 /* AssimpCExport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AssimpCExport.cpp; sourceTree = ""; }; - 2B7F45741708365100A106A9 /* BaseImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BaseImporter.cpp; sourceTree = ""; }; - 2B7F45751708365100A106A9 /* BaseImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseImporter.h; sourceTree = ""; }; - 2B7F45761708365100A106A9 /* BaseProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BaseProcess.cpp; sourceTree = ""; }; - 2B7F45771708365100A106A9 /* BaseProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseProcess.h; sourceTree = ""; }; - 2B7F45831708365100A106A9 /* BlobIOSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlobIOSystem.h; sourceTree = ""; }; - 2B7F45861708365100A106A9 /* foreach.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = foreach.hpp; sourceTree = ""; }; - 2B7F45871708365100A106A9 /* format.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = format.hpp; sourceTree = ""; }; - 2B7F45881708365100A106A9 /* lexical_cast.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = lexical_cast.hpp; sourceTree = ""; }; - 2B7F45891708365100A106A9 /* LICENSE_1_0.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE_1_0.txt; sourceTree = ""; }; - 2B7F458A1708365100A106A9 /* make_shared.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = make_shared.hpp; sourceTree = ""; }; - 2B7F458C1708365100A106A9 /* common_factor_rt.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = common_factor_rt.hpp; sourceTree = ""; }; - 2B7F458D1708365100A106A9 /* noncopyable.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = noncopyable.hpp; sourceTree = ""; }; - 2B7F458E1708365100A106A9 /* pointer_cast.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = pointer_cast.hpp; sourceTree = ""; }; - 2B7F458F1708365100A106A9 /* scoped_array.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = scoped_array.hpp; sourceTree = ""; }; - 2B7F45901708365100A106A9 /* scoped_ptr.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = scoped_ptr.hpp; sourceTree = ""; }; - 2B7F45911708365100A106A9 /* shared_array.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = shared_array.hpp; sourceTree = ""; }; - 2B7F45921708365100A106A9 /* shared_ptr.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = shared_ptr.hpp; sourceTree = ""; }; - 2B7F45931708365100A106A9 /* static_assert.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = static_assert.hpp; sourceTree = ""; }; - 2B7F45941708365100A106A9 /* timer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = timer.hpp; sourceTree = ""; }; - 2B7F45961708365100A106A9 /* tuple.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = tuple.hpp; sourceTree = ""; }; - 2B7F45991708365100A106A9 /* ByteSwapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ByteSwapper.h; sourceTree = ""; }; - 2B7F459A1708365100A106A9 /* CalcTangentsProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CalcTangentsProcess.cpp; sourceTree = ""; }; - 2B7F459B1708365100A106A9 /* CalcTangentsProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CalcTangentsProcess.h; sourceTree = ""; }; - 2B7F459C1708365100A106A9 /* CInterfaceIOWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CInterfaceIOWrapper.h; sourceTree = ""; }; - 2B7F45A11708365100A106A9 /* ColladaExporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ColladaExporter.cpp; sourceTree = ""; }; - 2B7F45A21708365100A106A9 /* ColladaExporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ColladaExporter.h; sourceTree = ""; }; - 2B7F45A31708365100A106A9 /* ColladaHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ColladaHelper.h; sourceTree = ""; }; - 2B7F45A41708365100A106A9 /* ColladaLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ColladaLoader.cpp; sourceTree = ""; }; - 2B7F45A51708365100A106A9 /* ColladaLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ColladaLoader.h; sourceTree = ""; }; - 2B7F45A61708365100A106A9 /* ColladaParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ColladaParser.cpp; sourceTree = ""; }; - 2B7F45A71708365100A106A9 /* ColladaParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ColladaParser.h; sourceTree = ""; }; - 2B7F45A81708365100A106A9 /* ComputeUVMappingProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ComputeUVMappingProcess.cpp; sourceTree = ""; }; - 2B7F45A91708365100A106A9 /* ComputeUVMappingProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ComputeUVMappingProcess.h; sourceTree = ""; }; - 2B7F45AA1708365100A106A9 /* ConvertToLHProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConvertToLHProcess.cpp; sourceTree = ""; }; - 2B7F45AB1708365100A106A9 /* ConvertToLHProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConvertToLHProcess.h; sourceTree = ""; }; - 2B7F45AE1708365100A106A9 /* DeboneProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeboneProcess.cpp; sourceTree = ""; }; - 2B7F45AF1708365100A106A9 /* DeboneProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeboneProcess.h; sourceTree = ""; }; - 2B7F45B01708365100A106A9 /* DefaultIOStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DefaultIOStream.cpp; sourceTree = ""; }; - 2B7F45B11708365100A106A9 /* DefaultIOStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DefaultIOStream.h; sourceTree = ""; }; - 2B7F45B21708365100A106A9 /* DefaultIOSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DefaultIOSystem.cpp; sourceTree = ""; }; - 2B7F45B31708365100A106A9 /* DefaultIOSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DefaultIOSystem.h; sourceTree = ""; }; - 2B7F45B41708365100A106A9 /* DefaultLogger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DefaultLogger.cpp; sourceTree = ""; }; - 2B7F45B51708365100A106A9 /* DefaultProgressHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DefaultProgressHandler.h; sourceTree = ""; }; - 2B7F45B91708365100A106A9 /* Exceptional.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exceptional.h; sourceTree = ""; }; - 2B7F45BA1708365100A106A9 /* Exporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exporter.cpp; sourceTree = ""; }; - 2B7F45BB1708365100A106A9 /* fast_atof.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fast_atof.h; sourceTree = ""; }; - 2B7F45BC1708365100A106A9 /* FBXAnimation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBXAnimation.cpp; sourceTree = ""; }; - 2B7F45BD1708365100A106A9 /* FBXBinaryTokenizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBXBinaryTokenizer.cpp; sourceTree = ""; }; - 2B7F45BE1708365100A106A9 /* FBXCompileConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBXCompileConfig.h; sourceTree = ""; }; - 2B7F45BF1708365100A106A9 /* FBXConverter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBXConverter.cpp; sourceTree = ""; }; - 2B7F45C01708365100A106A9 /* FBXConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBXConverter.h; sourceTree = ""; }; - 2B7F45C11708365100A106A9 /* FBXDeformer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBXDeformer.cpp; sourceTree = ""; }; - 2B7F45C21708365100A106A9 /* FBXDocument.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBXDocument.cpp; sourceTree = ""; }; - 2B7F45C31708365100A106A9 /* FBXDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBXDocument.h; sourceTree = ""; }; - 2B7F45C41708365100A106A9 /* FBXDocumentUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBXDocumentUtil.cpp; sourceTree = ""; }; - 2B7F45C51708365100A106A9 /* FBXDocumentUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBXDocumentUtil.h; sourceTree = ""; }; - 2B7F45C61708365100A106A9 /* FBXImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBXImporter.cpp; sourceTree = ""; }; - 2B7F45C71708365100A106A9 /* FBXImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBXImporter.h; sourceTree = ""; }; - 2B7F45C81708365100A106A9 /* FBXImportSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBXImportSettings.h; sourceTree = ""; }; - 2B7F45C91708365100A106A9 /* FBXMaterial.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBXMaterial.cpp; sourceTree = ""; }; - 2B7F45CA1708365100A106A9 /* FBXMeshGeometry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBXMeshGeometry.cpp; sourceTree = ""; }; - 2B7F45CB1708365100A106A9 /* FBXModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBXModel.cpp; sourceTree = ""; }; - 2B7F45CC1708365100A106A9 /* FBXNodeAttribute.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBXNodeAttribute.cpp; sourceTree = ""; }; - 2B7F45CD1708365100A106A9 /* FBXParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBXParser.cpp; sourceTree = ""; }; - 2B7F45CE1708365100A106A9 /* FBXParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBXParser.h; sourceTree = ""; }; - 2B7F45CF1708365100A106A9 /* FBXProperties.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBXProperties.cpp; sourceTree = ""; }; - 2B7F45D01708365100A106A9 /* FBXProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBXProperties.h; sourceTree = ""; }; - 2B7F45D11708365100A106A9 /* FBXTokenizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBXTokenizer.cpp; sourceTree = ""; }; - 2B7F45D21708365100A106A9 /* FBXTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBXTokenizer.h; sourceTree = ""; }; - 2B7F45D31708365100A106A9 /* FBXUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBXUtil.cpp; sourceTree = ""; }; - 2B7F45D41708365100A106A9 /* FBXUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBXUtil.h; sourceTree = ""; }; - 2B7F45D51708365100A106A9 /* FileLogStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileLogStream.h; sourceTree = ""; }; - 2B7F45D61708365100A106A9 /* FileSystemFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileSystemFilter.h; sourceTree = ""; }; - 2B7F45D71708365100A106A9 /* FindDegenerates.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FindDegenerates.cpp; sourceTree = ""; }; - 2B7F45D81708365100A106A9 /* FindDegenerates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FindDegenerates.h; sourceTree = ""; }; - 2B7F45D91708365100A106A9 /* FindInstancesProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FindInstancesProcess.cpp; sourceTree = ""; }; - 2B7F45DA1708365100A106A9 /* FindInstancesProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FindInstancesProcess.h; sourceTree = ""; }; - 2B7F45DB1708365100A106A9 /* FindInvalidDataProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FindInvalidDataProcess.cpp; sourceTree = ""; }; - 2B7F45DC1708365100A106A9 /* FindInvalidDataProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FindInvalidDataProcess.h; sourceTree = ""; }; - 2B7F45DD1708365100A106A9 /* FixNormalsStep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FixNormalsStep.cpp; sourceTree = ""; }; - 2B7F45DE1708365100A106A9 /* FixNormalsStep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FixNormalsStep.h; sourceTree = ""; }; - 2B7F45DF1708365100A106A9 /* GenericProperty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenericProperty.h; sourceTree = ""; }; - 2B7F45E01708365100A106A9 /* GenFaceNormalsProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GenFaceNormalsProcess.cpp; sourceTree = ""; }; - 2B7F45E11708365100A106A9 /* GenFaceNormalsProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenFaceNormalsProcess.h; sourceTree = ""; }; - 2B7F45E21708365100A106A9 /* GenVertexNormalsProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GenVertexNormalsProcess.cpp; sourceTree = ""; }; - 2B7F45E31708365100A106A9 /* GenVertexNormalsProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenVertexNormalsProcess.h; sourceTree = ""; }; - 2B7F45E51708365100A106A9 /* Hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Hash.h; sourceTree = ""; }; - 2B7F45E91708365100A106A9 /* IFCBoolean.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IFCBoolean.cpp; path = ../../code/IFCBoolean.cpp; sourceTree = ""; }; - 2B7F45EA1708365100A106A9 /* IFCCurve.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IFCCurve.cpp; path = ../../code/IFCCurve.cpp; sourceTree = ""; }; - 2B7F45EB1708365100A106A9 /* IFCGeometry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IFCGeometry.cpp; path = ../../code/IFCGeometry.cpp; sourceTree = ""; }; - 2B7F45EC1708365100A106A9 /* IFCLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IFCLoader.cpp; path = ../../code/IFCLoader.cpp; sourceTree = ""; }; - 2B7F45ED1708365100A106A9 /* IFCLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IFCLoader.h; path = ../../code/IFCLoader.h; sourceTree = ""; }; - 2B7F45EE1708365100A106A9 /* IFCMaterial.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IFCMaterial.cpp; path = ../../code/IFCMaterial.cpp; sourceTree = ""; }; - 2B7F45EF1708365100A106A9 /* IFCOpenings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IFCOpenings.cpp; path = ../../code/IFCOpenings.cpp; sourceTree = ""; }; - 2B7F45F01708365100A106A9 /* IFCProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IFCProfile.cpp; path = ../../code/IFCProfile.cpp; sourceTree = ""; }; - 2B7F45F11708365100A106A9 /* IFCReaderGen.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IFCReaderGen.cpp; path = ../../code/IFCReaderGen.cpp; sourceTree = ""; }; - 2B7F45F21708365100A106A9 /* IFCReaderGen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IFCReaderGen.h; path = ../../code/IFCReaderGen.h; sourceTree = ""; }; - 2B7F45F31708365100A106A9 /* IFCUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IFCUtil.cpp; path = ../../code/IFCUtil.cpp; sourceTree = ""; }; - 2B7F45F41708365100A106A9 /* IFCUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IFCUtil.h; path = ../../code/IFCUtil.h; sourceTree = ""; }; - 2B7F45F51708365100A106A9 /* IFF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IFF.h; sourceTree = ""; }; - 2B7F45F61708365100A106A9 /* Importer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Importer.cpp; sourceTree = ""; }; - 2B7F45F71708365100A106A9 /* Importer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Importer.h; sourceTree = ""; }; - 2B7F45F81708365100A106A9 /* ImporterRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImporterRegistry.cpp; sourceTree = ""; }; - 2B7F45F91708365100A106A9 /* ImproveCacheLocality.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImproveCacheLocality.cpp; sourceTree = ""; }; - 2B7F45FA1708365100A106A9 /* ImproveCacheLocality.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImproveCacheLocality.h; sourceTree = ""; }; - 2B7F46021708365100A106A9 /* JoinVerticesProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JoinVerticesProcess.cpp; sourceTree = ""; }; - 2B7F46031708365100A106A9 /* JoinVerticesProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JoinVerticesProcess.h; sourceTree = ""; }; - 2B7F46041708365100A106A9 /* LimitBoneWeightsProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LimitBoneWeightsProcess.cpp; sourceTree = ""; }; - 2B7F46051708365100A106A9 /* LimitBoneWeightsProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LimitBoneWeightsProcess.h; sourceTree = ""; }; - 2B7F46061708365100A106A9 /* LineSplitter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LineSplitter.h; sourceTree = ""; }; - 2B7F46071708365100A106A9 /* LogAux.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LogAux.h; sourceTree = ""; }; - 2B7F46141708365200A106A9 /* MakeVerboseFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MakeVerboseFormat.cpp; sourceTree = ""; }; - 2B7F46151708365200A106A9 /* MakeVerboseFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MakeVerboseFormat.h; sourceTree = ""; }; - 2B7F46161708365200A106A9 /* MaterialSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MaterialSystem.cpp; sourceTree = ""; }; - 2B7F46171708365200A106A9 /* MaterialSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MaterialSystem.h; sourceTree = ""; }; - 2B7F461F1708365200A106A9 /* MD4FileData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MD4FileData.h; sourceTree = ""; }; - 2B7F462D1708365200A106A9 /* MemoryIOWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryIOWrapper.h; sourceTree = ""; }; - 2B7F46341708365200A106A9 /* ObjExporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjExporter.cpp; sourceTree = ""; }; - 2B7F46351708365200A106A9 /* ObjExporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjExporter.h; sourceTree = ""; }; - 2B7F46361708365200A106A9 /* ObjFileData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjFileData.h; sourceTree = ""; }; - 2B7F46371708365200A106A9 /* ObjFileImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjFileImporter.cpp; sourceTree = ""; }; - 2B7F46381708365200A106A9 /* ObjFileImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjFileImporter.h; sourceTree = ""; }; - 2B7F46391708365200A106A9 /* ObjFileMtlImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjFileMtlImporter.cpp; sourceTree = ""; }; - 2B7F463A1708365200A106A9 /* ObjFileMtlImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjFileMtlImporter.h; sourceTree = ""; }; - 2B7F463B1708365200A106A9 /* ObjFileParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjFileParser.cpp; sourceTree = ""; }; - 2B7F463C1708365200A106A9 /* ObjFileParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjFileParser.h; sourceTree = ""; }; - 2B7F463D1708365200A106A9 /* ObjTools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjTools.h; sourceTree = ""; }; - 2B7F46461708365200A106A9 /* OptimizeGraph.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OptimizeGraph.cpp; sourceTree = ""; }; - 2B7F46471708365200A106A9 /* OptimizeGraph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OptimizeGraph.h; sourceTree = ""; }; - 2B7F46481708365200A106A9 /* OptimizeMeshes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OptimizeMeshes.cpp; sourceTree = ""; }; - 2B7F46491708365200A106A9 /* OptimizeMeshes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OptimizeMeshes.h; sourceTree = ""; }; - 2B7F464A1708365200A106A9 /* ParsingUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParsingUtils.h; sourceTree = ""; }; - 2B7F46511708365200A106A9 /* PolyTools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolyTools.h; sourceTree = ""; }; - 2B7F46521708365200A106A9 /* PostStepRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PostStepRegistry.cpp; sourceTree = ""; }; - 2B7F46531708365200A106A9 /* PretransformVertices.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PretransformVertices.cpp; sourceTree = ""; }; - 2B7F46541708365200A106A9 /* PretransformVertices.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PretransformVertices.h; sourceTree = ""; }; - 2B7F46551708365200A106A9 /* ProcessHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessHelper.cpp; sourceTree = ""; }; - 2B7F46561708365200A106A9 /* ProcessHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessHelper.h; sourceTree = ""; }; - 2B7F46571708365200A106A9 /* Profiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Profiler.h; sourceTree = ""; }; - 2B7F46581708365200A106A9 /* pstdint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pstdint.h; sourceTree = ""; }; - 2B7F46621708365200A106A9 /* qnan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = qnan.h; sourceTree = ""; }; - 2B7F46651708365200A106A9 /* RemoveComments.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RemoveComments.cpp; sourceTree = ""; }; - 2B7F46661708365200A106A9 /* RemoveComments.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoveComments.h; sourceTree = ""; }; - 2B7F46671708365200A106A9 /* RemoveRedundantMaterials.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RemoveRedundantMaterials.cpp; sourceTree = ""; }; - 2B7F46681708365200A106A9 /* RemoveRedundantMaterials.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoveRedundantMaterials.h; sourceTree = ""; }; - 2B7F46691708365200A106A9 /* RemoveVCProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RemoveVCProcess.cpp; sourceTree = ""; }; - 2B7F466A1708365200A106A9 /* RemoveVCProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoveVCProcess.h; sourceTree = ""; }; - 2B7F466E1708365200A106A9 /* SceneCombiner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SceneCombiner.cpp; sourceTree = ""; }; - 2B7F466F1708365200A106A9 /* SceneCombiner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SceneCombiner.h; sourceTree = ""; }; - 2B7F46701708365200A106A9 /* ScenePreprocessor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScenePreprocessor.cpp; sourceTree = ""; }; - 2B7F46711708365200A106A9 /* ScenePreprocessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScenePreprocessor.h; sourceTree = ""; }; - 2B7F46721708365200A106A9 /* ScenePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScenePrivate.h; sourceTree = ""; }; - 2B7F46731708365200A106A9 /* SGSpatialSort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SGSpatialSort.cpp; sourceTree = ""; }; - 2B7F46741708365200A106A9 /* SGSpatialSort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGSpatialSort.h; sourceTree = ""; }; - 2B7F46751708365200A106A9 /* SkeletonMeshBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SkeletonMeshBuilder.cpp; sourceTree = ""; }; - 2B7F46761708365200A106A9 /* SkeletonMeshBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SkeletonMeshBuilder.h; sourceTree = ""; }; - 2B7F46791708365200A106A9 /* SmoothingGroups.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SmoothingGroups.h; sourceTree = ""; }; - 2B7F467A1708365200A106A9 /* SmoothingGroups.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SmoothingGroups.inl; sourceTree = ""; }; - 2B7F467B1708365200A106A9 /* SortByPTypeProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SortByPTypeProcess.cpp; sourceTree = ""; }; - 2B7F467C1708365200A106A9 /* SortByPTypeProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SortByPTypeProcess.h; sourceTree = ""; }; - 2B7F467D1708365200A106A9 /* SpatialSort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpatialSort.cpp; sourceTree = ""; }; - 2B7F467E1708365200A106A9 /* SpatialSort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpatialSort.h; sourceTree = ""; }; - 2B7F467F1708365200A106A9 /* SplitByBoneCountProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SplitByBoneCountProcess.cpp; sourceTree = ""; }; - 2B7F46801708365200A106A9 /* SplitByBoneCountProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SplitByBoneCountProcess.h; sourceTree = ""; }; - 2B7F46811708365200A106A9 /* SplitLargeMeshes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SplitLargeMeshes.cpp; sourceTree = ""; }; - 2B7F46821708365200A106A9 /* SplitLargeMeshes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SplitLargeMeshes.h; sourceTree = ""; }; - 2B7F46831708365200A106A9 /* StandardShapes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StandardShapes.cpp; sourceTree = ""; }; - 2B7F46841708365200A106A9 /* StandardShapes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StandardShapes.h; sourceTree = ""; }; - 2B7F46851708365200A106A9 /* StdOStreamLogStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StdOStreamLogStream.h; sourceTree = ""; }; - 2B7F46861708365200A106A9 /* STEPFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = STEPFile.h; path = ../../code/STEPFile.h; sourceTree = ""; }; - 2B7F46871708365200A106A9 /* STEPFileEncoding.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = STEPFileEncoding.cpp; path = ../../code/STEPFileEncoding.cpp; sourceTree = ""; }; - 2B7F46881708365200A106A9 /* STEPFileEncoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = STEPFileEncoding.h; path = ../../code/STEPFileEncoding.h; sourceTree = ""; }; - 2B7F46891708365200A106A9 /* STEPFileReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = STEPFileReader.cpp; path = ../../code/STEPFileReader.cpp; sourceTree = ""; }; - 2B7F468A1708365200A106A9 /* STEPFileReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = STEPFileReader.h; path = ../../code/STEPFileReader.h; sourceTree = ""; }; - 2B7F468B1708365200A106A9 /* STLExporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = STLExporter.cpp; sourceTree = ""; }; - 2B7F468C1708365200A106A9 /* STLExporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STLExporter.h; sourceTree = ""; }; - 2B7F468D1708365200A106A9 /* STLLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = STLLoader.cpp; sourceTree = ""; }; - 2B7F468E1708365200A106A9 /* STLLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STLLoader.h; sourceTree = ""; }; - 2B7F468F1708365200A106A9 /* StreamReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StreamReader.h; sourceTree = ""; }; - 2B7F46901708365200A106A9 /* StringComparison.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringComparison.h; sourceTree = ""; }; - 2B7F46911708365200A106A9 /* Subdivision.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Subdivision.cpp; sourceTree = ""; }; - 2B7F46921708365200A106A9 /* Subdivision.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Subdivision.h; sourceTree = ""; }; - 2B7F46931708365200A106A9 /* TargetAnimation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TargetAnimation.cpp; sourceTree = ""; }; - 2B7F46941708365200A106A9 /* TargetAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TargetAnimation.h; sourceTree = ""; }; - 2B7F46971708365200A106A9 /* TextureTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextureTransform.cpp; sourceTree = ""; }; - 2B7F46981708365200A106A9 /* TextureTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextureTransform.h; sourceTree = ""; }; - 2B7F46991708365200A106A9 /* TinyFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TinyFormatter.h; sourceTree = ""; }; - 2B7F469A1708365200A106A9 /* TriangulateProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TriangulateProcess.cpp; sourceTree = ""; }; - 2B7F469B1708365200A106A9 /* TriangulateProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TriangulateProcess.h; sourceTree = ""; }; - 2B7F469E1708365200A106A9 /* ValidateDataStructure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ValidateDataStructure.cpp; sourceTree = ""; }; - 2B7F469F1708365200A106A9 /* ValidateDataStructure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValidateDataStructure.h; sourceTree = ""; }; - 2B7F46A01708365200A106A9 /* Vertex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Vertex.h; sourceTree = ""; }; - 2B7F46A11708365200A106A9 /* VertexTriangleAdjacency.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VertexTriangleAdjacency.cpp; sourceTree = ""; }; - 2B7F46A21708365200A106A9 /* VertexTriangleAdjacency.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VertexTriangleAdjacency.h; sourceTree = ""; }; - 2B7F46A31708365200A106A9 /* Win32DebugLogStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Win32DebugLogStream.h; sourceTree = ""; }; - 2BA44E10170862D800C78A66 /* libstdc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libstdc++.dylib"; path = "Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/usr/lib/libstdc++.dylib"; sourceTree = DEVELOPER_DIR; }; - 3AB8A3AB0E50D67A00606590 /* MDCFileData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDCFileData.h; sourceTree = ""; }; - 3AB8A3AC0E50D67A00606590 /* MDCLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MDCLoader.cpp; sourceTree = ""; }; - 3AB8A3AD0E50D67A00606590 /* MDCLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDCLoader.h; sourceTree = ""; }; - 3AB8A3AE0E50D67A00606590 /* MDCNormalTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDCNormalTable.h; sourceTree = ""; }; - 3AB8A3B70E50D6DB00606590 /* LWOFileData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LWOFileData.h; sourceTree = ""; }; - 3AB8A3B80E50D6DB00606590 /* LWOLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LWOLoader.cpp; sourceTree = ""; }; - 3AB8A3B90E50D6DB00606590 /* LWOLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LWOLoader.h; sourceTree = ""; }; - 3AB8A3C50E50D77900606590 /* HMPFileData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HMPFileData.h; sourceTree = ""; }; - 3AB8A7DC0E53715F00606590 /* LWOMaterial.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LWOMaterial.cpp; sourceTree = ""; }; - 3AF45A860E4B716800207D74 /* 3DSConverter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 3DSConverter.cpp; sourceTree = ""; }; - 3AF45A880E4B716800207D74 /* 3DSHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 3DSHelper.h; sourceTree = ""; }; - 3AF45A890E4B716800207D74 /* 3DSLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = 3DSLoader.cpp; sourceTree = ""; }; - 3AF45A8A0E4B716800207D74 /* 3DSLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 3DSLoader.h; sourceTree = ""; }; - 3AF45A8E0E4B716800207D74 /* ASELoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ASELoader.cpp; sourceTree = ""; }; - 3AF45A8F0E4B716800207D74 /* ASELoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASELoader.h; sourceTree = ""; }; - 3AF45A900E4B716800207D74 /* ASEParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ASEParser.cpp; sourceTree = ""; }; - 3AF45A910E4B716800207D74 /* ASEParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASEParser.h; sourceTree = ""; }; - 3AF45AA90E4B716800207D74 /* HalfLifeFileData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HalfLifeFileData.h; sourceTree = ""; }; - 3AF45AAB0E4B716800207D74 /* HMPLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HMPLoader.cpp; sourceTree = ""; }; - 3AF45AAC0E4B716800207D74 /* HMPLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HMPLoader.h; sourceTree = ""; }; - 3AF45AB80E4B716800207D74 /* MD2FileData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MD2FileData.h; sourceTree = ""; }; - 3AF45AB90E4B716800207D74 /* MD2Loader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MD2Loader.cpp; sourceTree = ""; }; - 3AF45ABA0E4B716800207D74 /* MD2Loader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MD2Loader.h; sourceTree = ""; }; - 3AF45ABB0E4B716800207D74 /* MD2NormalTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MD2NormalTable.h; sourceTree = ""; }; - 3AF45ABC0E4B716800207D74 /* MD3FileData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MD3FileData.h; sourceTree = ""; }; - 3AF45ABD0E4B716800207D74 /* MD3Loader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MD3Loader.cpp; sourceTree = ""; }; - 3AF45ABE0E4B716800207D74 /* MD3Loader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MD3Loader.h; sourceTree = ""; }; - 3AF45AC20E4B716800207D74 /* MD5Loader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MD5Loader.cpp; sourceTree = ""; }; - 3AF45AC30E4B716800207D74 /* MD5Loader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MD5Loader.h; sourceTree = ""; }; - 3AF45AC40E4B716800207D74 /* MD5Parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MD5Parser.cpp; sourceTree = ""; }; - 3AF45AC50E4B716800207D74 /* MD5Parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MD5Parser.h; sourceTree = ""; }; - 3AF45AC60E4B716800207D74 /* MDLDefaultColorMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDLDefaultColorMap.h; sourceTree = ""; }; - 3AF45AC70E4B716800207D74 /* MDLFileData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDLFileData.h; sourceTree = ""; }; - 3AF45AC80E4B716800207D74 /* MDLLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MDLLoader.cpp; sourceTree = ""; }; - 3AF45AC90E4B716800207D74 /* MDLLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDLLoader.h; sourceTree = ""; }; - 3AF45ACA0E4B716800207D74 /* MDLMaterialLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MDLMaterialLoader.cpp; sourceTree = ""; }; - 3AF45AD40E4B716800207D74 /* PlyLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlyLoader.cpp; sourceTree = ""; }; - 3AF45AD50E4B716800207D74 /* PlyLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlyLoader.h; sourceTree = ""; }; - 3AF45AD60E4B716800207D74 /* PlyParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlyParser.cpp; sourceTree = ""; }; - 3AF45AD70E4B716800207D74 /* PlyParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlyParser.h; sourceTree = ""; }; - 3AF45AE20E4B716800207D74 /* SMDLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SMDLoader.cpp; sourceTree = ""; }; - 3AF45AE30E4B716800207D74 /* SMDLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SMDLoader.h; sourceTree = ""; }; - 3AF45AF40E4B716800207D74 /* XFileHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFileHelper.h; sourceTree = ""; }; - 3AF45AF50E4B716800207D74 /* XFileImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XFileImporter.cpp; sourceTree = ""; }; - 3AF45AF60E4B716800207D74 /* XFileImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFileImporter.h; sourceTree = ""; }; - 3AF45AF70E4B716800207D74 /* XFileParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XFileParser.cpp; sourceTree = ""; }; - 3AF45AF80E4B716800207D74 /* XFileParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XFileParser.h; sourceTree = ""; }; - 7411B14E11416D5E00BCD793 /* CSMLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CSMLoader.cpp; path = ../../code/CSMLoader.cpp; sourceTree = SOURCE_ROOT; }; - 7411B14F11416D5E00BCD793 /* CSMLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CSMLoader.h; path = ../../code/CSMLoader.h; sourceTree = SOURCE_ROOT; }; - 7411B15911416DDD00BCD793 /* LWSLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LWSLoader.cpp; path = ../../code/LWSLoader.cpp; sourceTree = SOURCE_ROOT; }; - 7411B15A11416DDD00BCD793 /* LWSLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LWSLoader.h; path = ../../code/LWSLoader.h; sourceTree = SOURCE_ROOT; }; - 7411B16311416DF400BCD793 /* LWOAnimation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LWOAnimation.cpp; path = ../../code/LWOAnimation.cpp; sourceTree = SOURCE_ROOT; }; - 7411B16411416DF400BCD793 /* LWOAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LWOAnimation.h; path = ../../code/LWOAnimation.h; sourceTree = SOURCE_ROOT; }; - 7411B17011416E2500BCD793 /* MS3DLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MS3DLoader.cpp; path = ../../code/MS3DLoader.cpp; sourceTree = SOURCE_ROOT; }; - 7411B17111416E2500BCD793 /* MS3DLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MS3DLoader.h; path = ../../code/MS3DLoader.h; sourceTree = SOURCE_ROOT; }; - 7411B18B11416EBC00BCD793 /* UnrealLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnrealLoader.cpp; path = ../../code/UnrealLoader.cpp; sourceTree = SOURCE_ROOT; }; - 7411B18C11416EBC00BCD793 /* UnrealLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UnrealLoader.h; path = ../../code/UnrealLoader.h; sourceTree = SOURCE_ROOT; }; - 74C9BB4911ACBB1000AF885C /* BlenderDNA.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BlenderDNA.cpp; path = ../../code/BlenderDNA.cpp; sourceTree = SOURCE_ROOT; }; - 74C9BB4A11ACBB1000AF885C /* BlenderDNA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BlenderDNA.h; path = ../../code/BlenderDNA.h; sourceTree = SOURCE_ROOT; }; - 74C9BB4B11ACBB1000AF885C /* BlenderDNA.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = BlenderDNA.inl; path = ../../code/BlenderDNA.inl; sourceTree = SOURCE_ROOT; }; - 74C9BB4C11ACBB1000AF885C /* BlenderLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BlenderLoader.cpp; path = ../../code/BlenderLoader.cpp; sourceTree = SOURCE_ROOT; }; - 74C9BB4D11ACBB1000AF885C /* BlenderLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BlenderLoader.h; path = ../../code/BlenderLoader.h; sourceTree = SOURCE_ROOT; }; - 74C9BB4E11ACBB1000AF885C /* BlenderScene.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BlenderScene.cpp; path = ../../code/BlenderScene.cpp; sourceTree = SOURCE_ROOT; }; - 74C9BB4F11ACBB1000AF885C /* BlenderScene.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BlenderScene.h; path = ../../code/BlenderScene.h; sourceTree = SOURCE_ROOT; }; - 74C9BB5011ACBB1000AF885C /* BlenderSceneGen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BlenderSceneGen.h; path = ../../code/BlenderSceneGen.h; sourceTree = SOURCE_ROOT; }; - 74C9BB8611ACBB9900AF885C /* AssimpPCH.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AssimpPCH.cpp; path = ../../code/AssimpPCH.cpp; sourceTree = SOURCE_ROOT; }; - 74C9BB8711ACBB9900AF885C /* AssimpPCH.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AssimpPCH.h; path = ../../code/AssimpPCH.h; sourceTree = SOURCE_ROOT; }; - 74C9BB9311ACBBBC00AF885C /* COBLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = COBLoader.cpp; path = ../../code/COBLoader.cpp; sourceTree = SOURCE_ROOT; }; - 74C9BB9411ACBBBC00AF885C /* COBLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = COBLoader.h; path = ../../code/COBLoader.h; sourceTree = SOURCE_ROOT; }; - 74C9BB9511ACBBBC00AF885C /* COBScene.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = COBScene.h; path = ../../code/COBScene.h; sourceTree = SOURCE_ROOT; }; - 74C9BBB311ACBC2600AF885C /* revision.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = revision.h; path = ../../revision.h; sourceTree = SOURCE_ROOT; }; - 8E7ABBA1127E0F1A00512ED1 /* Q3BSPFileData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Q3BSPFileData.h; path = ../../code/Q3BSPFileData.h; sourceTree = SOURCE_ROOT; }; - 8E7ABBA2127E0F1A00512ED1 /* Q3BSPFileImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Q3BSPFileImporter.cpp; path = ../../code/Q3BSPFileImporter.cpp; sourceTree = SOURCE_ROOT; }; - 8E7ABBA3127E0F1A00512ED1 /* Q3BSPFileImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Q3BSPFileImporter.h; path = ../../code/Q3BSPFileImporter.h; sourceTree = SOURCE_ROOT; }; - 8E7ABBA4127E0F1A00512ED1 /* Q3BSPFileParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Q3BSPFileParser.cpp; path = ../../code/Q3BSPFileParser.cpp; sourceTree = SOURCE_ROOT; }; - 8E7ABBA5127E0F1A00512ED1 /* Q3BSPFileParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Q3BSPFileParser.h; path = ../../code/Q3BSPFileParser.h; sourceTree = SOURCE_ROOT; }; - 8E7ABBA6127E0F1A00512ED1 /* Q3BSPZipArchive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Q3BSPZipArchive.cpp; path = ../../code/Q3BSPZipArchive.cpp; sourceTree = SOURCE_ROOT; }; - 8E7ABBA7127E0F1A00512ED1 /* Q3BSPZipArchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Q3BSPZipArchive.h; path = ../../code/Q3BSPZipArchive.h; sourceTree = SOURCE_ROOT; }; - 8E7ABBC4127E0F2A00512ED1 /* NDOLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NDOLoader.cpp; path = ../../code/NDOLoader.cpp; sourceTree = SOURCE_ROOT; }; - 8E7ABBC5127E0F2A00512ED1 /* NDOLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NDOLoader.h; path = ../../code/NDOLoader.h; sourceTree = SOURCE_ROOT; }; - 8E7ABBCE127E0F3800512ED1 /* BlenderIntermediate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BlenderIntermediate.h; path = ../../code/BlenderIntermediate.h; sourceTree = SOURCE_ROOT; }; - 8E7ABBCF127E0F3800512ED1 /* BlenderModifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BlenderModifier.cpp; path = ../../code/BlenderModifier.cpp; sourceTree = SOURCE_ROOT; }; - 8E7ABBD0127E0F3800512ED1 /* BlenderModifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BlenderModifier.h; path = ../../code/BlenderModifier.h; sourceTree = SOURCE_ROOT; }; - 8E8DEE4B127E2B78005EF64D /* ConvertUTF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ConvertUTF.c; sourceTree = ""; }; - 8E8DEE4C127E2B78005EF64D /* ConvertUTF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConvertUTF.h; sourceTree = ""; }; - 8E8DEE4F127E2B78005EF64D /* CXMLReaderImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CXMLReaderImpl.h; sourceTree = ""; }; - 8E8DEE50127E2B78005EF64D /* heapsort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = heapsort.h; sourceTree = ""; }; - 8E8DEE51127E2B78005EF64D /* irrArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = irrArray.h; sourceTree = ""; }; - 8E8DEE52127E2B78005EF64D /* irrString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = irrString.h; sourceTree = ""; }; - 8E8DEE53127E2B78005EF64D /* irrTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = irrTypes.h; sourceTree = ""; }; - 8E8DEE54127E2B78005EF64D /* irrXML.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = irrXML.cpp; sourceTree = ""; }; - 8E8DEE55127E2B78005EF64D /* irrXML.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = irrXML.h; sourceTree = ""; }; - 8E8DEE57127E2B78005EF64D /* crypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypt.h; sourceTree = ""; }; - 8E8DEE58127E2B78005EF64D /* ioapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioapi.c; sourceTree = ""; }; - 8E8DEE59127E2B78005EF64D /* ioapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioapi.h; sourceTree = ""; }; - 8E8DEE5A127E2B78005EF64D /* unzip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unzip.c; sourceTree = ""; }; - 8E8DEE5B127E2B78005EF64D /* unzip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unzip.h; sourceTree = ""; }; - 8E8DEEA3127E2D59005EF64D /* libassimpd.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libassimpd.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; - 8E8DEEA4127E2D59005EF64D /* libassimpd.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libassimpd.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 8E8DEEA5127E2D59005EF64D /* libassimpd.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libassimpd.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; - 8E8DEEA6127E2D59005EF64D /* libassimpd.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libassimpd.a; sourceTree = BUILT_PRODUCTS_DIR; }; - B919763F163AEA54009C397B /* libassimp-ios.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libassimp-ios.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - F90BAFD00F5DD87000124155 /* ACLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ACLoader.cpp; sourceTree = ""; }; - F90BAFD10F5DD87000124155 /* ACLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ACLoader.h; sourceTree = ""; }; - F90BAFD90F5DD90800124155 /* IRRLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IRRLoader.cpp; sourceTree = ""; }; - F90BAFDA0F5DD90800124155 /* IRRLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IRRLoader.h; sourceTree = ""; }; - F90BAFDB0F5DD90800124155 /* IRRMeshLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IRRMeshLoader.cpp; sourceTree = ""; }; - F90BAFDC0F5DD90800124155 /* IRRMeshLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IRRMeshLoader.h; sourceTree = ""; }; - F90BAFDD0F5DD90800124155 /* IRRShared.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IRRShared.cpp; sourceTree = ""; }; - F90BAFDE0F5DD90800124155 /* IRRShared.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IRRShared.h; sourceTree = ""; }; - F90BAFF50F5DD96100124155 /* NFFLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NFFLoader.h; sourceTree = ""; }; - F90BAFF60F5DD96100124155 /* NFFLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NFFLoader.cpp; sourceTree = ""; }; - F90BB0060F5DD9DD00124155 /* Q3DLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Q3DLoader.cpp; sourceTree = ""; }; - F90BB0070F5DD9DD00124155 /* Q3DLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Q3DLoader.h; sourceTree = ""; }; - F90BB00C0F5DD9F400124155 /* BVHLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BVHLoader.h; sourceTree = ""; }; - F90BB00D0F5DD9F400124155 /* BVHLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BVHLoader.cpp; sourceTree = ""; }; - F90BB0130F5DDA1400124155 /* OFFLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OFFLoader.h; sourceTree = ""; }; - F90BB0140F5DDA1400124155 /* OFFLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OFFLoader.cpp; sourceTree = ""; }; - F90BB01B0F5DDA4400124155 /* RawLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RawLoader.h; sourceTree = ""; }; - F90BB01C0F5DDA4400124155 /* RawLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RawLoader.cpp; sourceTree = ""; }; - F90BB0210F5DDA5700124155 /* DXFLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DXFLoader.h; sourceTree = ""; }; - F90BB0220F5DDA5700124155 /* DXFLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DXFLoader.cpp; sourceTree = ""; }; - F90BB0270F5DDA9200124155 /* LWOBLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LWOBLoader.cpp; sourceTree = ""; }; - F90BB02F0F5DDAB500124155 /* TerragenLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TerragenLoader.h; sourceTree = ""; }; - F90BB0300F5DDAB500124155 /* TerragenLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TerragenLoader.cpp; sourceTree = ""; }; - F90BB0360F5DDB1B00124155 /* irrXMLWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = irrXMLWrapper.h; sourceTree = ""; }; - F90BB0870F5DDE0700124155 /* B3DImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3DImporter.h; path = ../../code/B3DImporter.h; sourceTree = SOURCE_ROOT; }; - F90BB0880F5DDE0700124155 /* B3DImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3DImporter.cpp; path = ../../code/B3DImporter.cpp; sourceTree = SOURCE_ROOT; }; - F9607047154366AB004D91DD /* adler32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = adler32.c; sourceTree = ""; }; - F9607049154366AB004D91DD /* compress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = compress.c; sourceTree = ""; }; - F960704A154366AB004D91DD /* crc32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = crc32.c; sourceTree = ""; }; - F960704B154366AB004D91DD /* crc32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crc32.h; sourceTree = ""; }; - F960704C154366AB004D91DD /* deflate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = deflate.c; sourceTree = ""; }; - F960704D154366AB004D91DD /* deflate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = deflate.h; sourceTree = ""; }; - F960704E154366AB004D91DD /* inffast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = inffast.c; sourceTree = ""; }; - F960704F154366AB004D91DD /* inffast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = inffast.h; sourceTree = ""; }; - F9607050154366AB004D91DD /* inffixed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = inffixed.h; sourceTree = ""; }; - F9607051154366AB004D91DD /* inflate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = inflate.c; sourceTree = ""; }; - F9607052154366AB004D91DD /* inflate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = inflate.h; sourceTree = ""; }; - F9607053154366AB004D91DD /* inftrees.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = inftrees.c; sourceTree = ""; }; - F9607054154366AB004D91DD /* inftrees.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = inftrees.h; sourceTree = ""; }; - F9607056154366AB004D91DD /* trees.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = trees.c; sourceTree = ""; }; - F9607057154366AB004D91DD /* trees.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = trees.h; sourceTree = ""; }; - F9607058154366AB004D91DD /* zconf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zconf.h; sourceTree = ""; }; - F9607059154366AB004D91DD /* zconf.in.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zconf.in.h; sourceTree = ""; }; - F960705A154366AB004D91DD /* zlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zlib.h; sourceTree = ""; }; - F960705B154366AB004D91DD /* zutil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zutil.c; sourceTree = ""; }; - F960705C154366AB004D91DD /* zutil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zutil.h; sourceTree = ""; }; - F96070B5154366ED004D91DD /* XGLLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = XGLLoader.cpp; path = ../../code/XGLLoader.cpp; sourceTree = SOURCE_ROOT; }; - F96070B6154366ED004D91DD /* XGLLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XGLLoader.h; path = ../../code/XGLLoader.h; sourceTree = SOURCE_ROOT; }; - F96070C51543673B004D91DD /* clipper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clipper.cpp; sourceTree = ""; }; - F96070C61543673B004D91DD /* clipper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = clipper.hpp; sourceTree = ""; }; - F96070D21543675E004D91DD /* shapes.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shapes.cc; sourceTree = ""; }; - F96070D31543675E004D91DD /* shapes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = shapes.h; sourceTree = ""; }; - F96070D41543675E004D91DD /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = ""; }; - F96070D51543675E004D91DD /* poly2tri.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = poly2tri.h; sourceTree = ""; }; - F96070D71543675E004D91DD /* advancing_front.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = advancing_front.cc; sourceTree = ""; }; - F96070D81543675E004D91DD /* advancing_front.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = advancing_front.h; sourceTree = ""; }; - F96070D91543675E004D91DD /* cdt.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cdt.cc; sourceTree = ""; }; - F96070DA1543675E004D91DD /* cdt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cdt.h; sourceTree = ""; }; - F96070DB1543675E004D91DD /* sweep.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sweep.cc; sourceTree = ""; }; - F96070DC1543675E004D91DD /* sweep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sweep.h; sourceTree = ""; }; - F96070DD1543675E004D91DD /* sweep_context.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sweep_context.cc; sourceTree = ""; }; - F96070DE1543675E004D91DD /* sweep_context.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sweep_context.h; sourceTree = ""; }; - F97BA03515439DB3009EB9DD /* ai_assert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ai_assert.h; sourceTree = ""; }; - F99A9F3015436269000682F3 /* PlyExporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlyExporter.cpp; sourceTree = ""; }; - F99A9F3115436269000682F3 /* PlyExporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlyExporter.h; sourceTree = ""; }; - F9BA8B751543268400E63FFE /* anim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = anim.h; sourceTree = ""; }; - F9BA8B771543268400E63FFE /* camera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = camera.h; sourceTree = ""; }; - F9BA8B781543268400E63FFE /* cexport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cexport.h; sourceTree = ""; }; - F9BA8B791543268400E63FFE /* cfileio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cfileio.h; sourceTree = ""; }; - F9BA8B7A1543268400E63FFE /* cimport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cimport.h; sourceTree = ""; }; - F9BA8B7B1543268400E63FFE /* color4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = color4.h; sourceTree = ""; }; - F9BA8B7C1543268400E63FFE /* color4.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = color4.inl; sourceTree = ""; }; - F9BA8B7E1543268400E63FFE /* poppack1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = poppack1.h; sourceTree = ""; }; - F9BA8B7F1543268400E63FFE /* pushpack1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pushpack1.h; sourceTree = ""; }; - F9BA8B801543268400E63FFE /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; - F9BA8B811543268400E63FFE /* DefaultLogger.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = DefaultLogger.hpp; sourceTree = ""; }; - F9BA8B821543268400E63FFE /* defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = defs.h; sourceTree = ""; }; - F9BA8B831543268400E63FFE /* Exporter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Exporter.hpp; sourceTree = ""; }; - F9BA8B841543268400E63FFE /* Importer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Importer.hpp; sourceTree = ""; }; - F9BA8B851543268400E63FFE /* importerdesc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = importerdesc.h; sourceTree = ""; }; - F9BA8B861543268400E63FFE /* IOStream.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = IOStream.hpp; sourceTree = ""; }; - F9BA8B871543268400E63FFE /* IOSystem.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = IOSystem.hpp; sourceTree = ""; }; - F9BA8B881543268400E63FFE /* light.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = light.h; sourceTree = ""; }; - F9BA8B891543268400E63FFE /* Logger.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Logger.hpp; sourceTree = ""; }; - F9BA8B8A1543268400E63FFE /* LogStream.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = LogStream.hpp; sourceTree = ""; }; - F9BA8B8B1543268400E63FFE /* material.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = material.h; sourceTree = ""; }; - F9BA8B8C1543268400E63FFE /* material.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = material.inl; sourceTree = ""; }; - F9BA8B8D1543268400E63FFE /* matrix3x3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = matrix3x3.h; sourceTree = ""; }; - F9BA8B8E1543268400E63FFE /* matrix3x3.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = matrix3x3.inl; sourceTree = ""; }; - F9BA8B8F1543268400E63FFE /* matrix4x4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = matrix4x4.h; sourceTree = ""; }; - F9BA8B901543268400E63FFE /* matrix4x4.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = matrix4x4.inl; sourceTree = ""; }; - F9BA8B911543268400E63FFE /* mesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mesh.h; sourceTree = ""; }; - F9BA8B921543268400E63FFE /* NullLogger.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = NullLogger.hpp; sourceTree = ""; }; - F9BA8B931543268400E63FFE /* postprocess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = postprocess.h; sourceTree = ""; }; - F9BA8B941543268400E63FFE /* ProgressHandler.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ProgressHandler.hpp; sourceTree = ""; }; - F9BA8B951543268400E63FFE /* quaternion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = quaternion.h; sourceTree = ""; }; - F9BA8B961543268400E63FFE /* quaternion.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = quaternion.inl; sourceTree = ""; }; - F9BA8B971543268400E63FFE /* scene.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scene.h; sourceTree = ""; }; - F9BA8B981543268400E63FFE /* texture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = texture.h; sourceTree = ""; }; - F9BA8B991543268400E63FFE /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = ""; }; - F9BA8B9A1543268400E63FFE /* vector2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vector2.h; sourceTree = ""; }; - F9BA8B9B1543268400E63FFE /* vector2.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = vector2.inl; sourceTree = ""; }; - F9BA8B9C1543268400E63FFE /* vector3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vector3.h; sourceTree = ""; }; - F9BA8B9D1543268400E63FFE /* vector3.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = vector3.inl; sourceTree = ""; }; - F9BA8B9E1543268400E63FFE /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; - F9BA8C35154328B600E63FFE /* OgreImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OgreImporter.cpp; path = ../../code/OgreImporter.cpp; sourceTree = SOURCE_ROOT; }; - F9BA8C36154328B600E63FFE /* OgreImporter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = OgreImporter.hpp; path = ../../code/OgreImporter.hpp; sourceTree = SOURCE_ROOT; }; - F9BA8C37154328B600E63FFE /* OgreMaterial.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OgreMaterial.cpp; path = ../../code/OgreMaterial.cpp; sourceTree = SOURCE_ROOT; }; - F9BA8C38154328B600E63FFE /* OgreMesh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OgreMesh.cpp; path = ../../code/OgreMesh.cpp; sourceTree = SOURCE_ROOT; }; - F9BA8C39154328B600E63FFE /* OgreSkeleton.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OgreSkeleton.cpp; path = ../../code/OgreSkeleton.cpp; sourceTree = SOURCE_ROOT; }; - F9BA8C3A154328B600E63FFE /* OgreXmlHelper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = OgreXmlHelper.hpp; path = ../../code/OgreXmlHelper.hpp; sourceTree = SOURCE_ROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 745FF8AB113ECB080020C31B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 2BA44E13170862E400C78A66 /* libstdc++.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 745FF98E113ECC660020C31B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 2BA44E14170862EA00C78A66 /* libstdc++.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B91975B4163AEA54009C397B /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 2BA44E1A1708680600C78A66 /* libstdc++.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - D2AAC09B05546B4700DB518D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 2BA44E11170862D800C78A66 /* libstdc++.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - F962E8820F5DE66A009A5495 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 2BA44E12170862DE00C78A66 /* libstdc++.dylib in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 034768DDFF38A45A11DB9C8B /* Products */ = { - isa = PBXGroup; - children = ( - 8E8DEEA3127E2D59005EF64D /* libassimpd.dylib */, - 8E8DEEA4127E2D59005EF64D /* libassimpd.a */, - 8E8DEEA5127E2D59005EF64D /* libassimpd.dylib */, - 8E8DEEA6127E2D59005EF64D /* libassimpd.a */, - B919763F163AEA54009C397B /* libassimp-ios.a */, - ); - name = Products; - sourceTree = ""; - }; - 0867D691FE84028FC02AAC07 /* assimp */ = { - isa = PBXGroup; - children = ( - 08FB77ACFE841707C02AAC07 /* Source */, - F90BB0700F5DDD7000124155 /* 3rd party libs */, - 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */, - 034768DDFF38A45A11DB9C8B /* Products */, - ); - name = assimp; - sourceTree = ""; - }; - 0867D69AFE84028FC02AAC07 /* External Frameworks and Libraries */ = { - isa = PBXGroup; - children = ( - 2BA44E10170862D800C78A66 /* libstdc++.dylib */, - ); - name = "External Frameworks and Libraries"; - sourceTree = ""; - }; - 08FB77ACFE841707C02AAC07 /* Source */ = { - isa = PBXGroup; - children = ( - 2B7F45621708365100A106A9 /* code */, - F90BB0830F5DDDC700124155 /* importers */, - 3AF45A520E4B715000207D74 /* include */, - 74C9BB8611ACBB9900AF885C /* AssimpPCH.cpp */, - 74C9BB8711ACBB9900AF885C /* AssimpPCH.h */, - 74C9BBB311ACBC2600AF885C /* revision.h */, - ); - name = Source; - sourceTree = ""; - }; - 2B7F45621708365100A106A9 /* code */ = { - isa = PBXGroup; - children = ( - 2B7F45841708365100A106A9 /* BoostWorkaround */, - 2B7F456D1708365100A106A9 /* assbin_chunks.h */, - 2B7F456E1708365100A106A9 /* Assimp.cpp */, - 2B7F456F1708365100A106A9 /* AssimpCExport.cpp */, - 2B7F45741708365100A106A9 /* BaseImporter.cpp */, - 2B7F45751708365100A106A9 /* BaseImporter.h */, - 2B7F45761708365100A106A9 /* BaseProcess.cpp */, - 2B7F45771708365100A106A9 /* BaseProcess.h */, - 2B7F45831708365100A106A9 /* BlobIOSystem.h */, - 2B7F45991708365100A106A9 /* ByteSwapper.h */, - 2B7F459A1708365100A106A9 /* CalcTangentsProcess.cpp */, - 2B7F459B1708365100A106A9 /* CalcTangentsProcess.h */, - 2B7F459C1708365100A106A9 /* CInterfaceIOWrapper.h */, - 2B7F45A81708365100A106A9 /* ComputeUVMappingProcess.cpp */, - 2B7F45A91708365100A106A9 /* ComputeUVMappingProcess.h */, - 2B7F45AA1708365100A106A9 /* ConvertToLHProcess.cpp */, - 2B7F45AB1708365100A106A9 /* ConvertToLHProcess.h */, - 2B7F45AE1708365100A106A9 /* DeboneProcess.cpp */, - 2B7F45AF1708365100A106A9 /* DeboneProcess.h */, - 2B7F45B01708365100A106A9 /* DefaultIOStream.cpp */, - 2B7F45B11708365100A106A9 /* DefaultIOStream.h */, - 2B7F45B21708365100A106A9 /* DefaultIOSystem.cpp */, - 2B7F45B31708365100A106A9 /* DefaultIOSystem.h */, - 2B7F45B41708365100A106A9 /* DefaultLogger.cpp */, - 2B7F45B51708365100A106A9 /* DefaultProgressHandler.h */, - 2B7F45B91708365100A106A9 /* Exceptional.h */, - 2B7F45BA1708365100A106A9 /* Exporter.cpp */, - 2B7F45BB1708365100A106A9 /* fast_atof.h */, - 2B7F45BC1708365100A106A9 /* FBXAnimation.cpp */, - 2B7F45BD1708365100A106A9 /* FBXBinaryTokenizer.cpp */, - 2B7F45BE1708365100A106A9 /* FBXCompileConfig.h */, - 2B7F45BF1708365100A106A9 /* FBXConverter.cpp */, - 2B7F45C01708365100A106A9 /* FBXConverter.h */, - 2B7F45C11708365100A106A9 /* FBXDeformer.cpp */, - 2B7F45C21708365100A106A9 /* FBXDocument.cpp */, - 2B7F45C31708365100A106A9 /* FBXDocument.h */, - 2B7F45C41708365100A106A9 /* FBXDocumentUtil.cpp */, - 2B7F45C51708365100A106A9 /* FBXDocumentUtil.h */, - 2B7F45C61708365100A106A9 /* FBXImporter.cpp */, - 2B7F45C71708365100A106A9 /* FBXImporter.h */, - 2B7F45C81708365100A106A9 /* FBXImportSettings.h */, - 2B7F45C91708365100A106A9 /* FBXMaterial.cpp */, - 2B7F45CA1708365100A106A9 /* FBXMeshGeometry.cpp */, - 2B7F45CB1708365100A106A9 /* FBXModel.cpp */, - 2B7F45CC1708365100A106A9 /* FBXNodeAttribute.cpp */, - 2B7F45CD1708365100A106A9 /* FBXParser.cpp */, - 2B7F45CE1708365100A106A9 /* FBXParser.h */, - 2B7F45CF1708365100A106A9 /* FBXProperties.cpp */, - 2B7F45D01708365100A106A9 /* FBXProperties.h */, - 2B7F45D11708365100A106A9 /* FBXTokenizer.cpp */, - 2B7F45D21708365100A106A9 /* FBXTokenizer.h */, - 2B7F45D31708365100A106A9 /* FBXUtil.cpp */, - 2B7F45D41708365100A106A9 /* FBXUtil.h */, - 2B7F45D51708365100A106A9 /* FileLogStream.h */, - 2B7F45D61708365100A106A9 /* FileSystemFilter.h */, - 2B7F45D71708365100A106A9 /* FindDegenerates.cpp */, - 2B7F45D81708365100A106A9 /* FindDegenerates.h */, - 2B7F45D91708365100A106A9 /* FindInstancesProcess.cpp */, - 2B7F45DA1708365100A106A9 /* FindInstancesProcess.h */, - 2B7F45DB1708365100A106A9 /* FindInvalidDataProcess.cpp */, - 2B7F45DC1708365100A106A9 /* FindInvalidDataProcess.h */, - 2B7F45DD1708365100A106A9 /* FixNormalsStep.cpp */, - 2B7F45DE1708365100A106A9 /* FixNormalsStep.h */, - 2B7F45DF1708365100A106A9 /* GenericProperty.h */, - 2B7F45E01708365100A106A9 /* GenFaceNormalsProcess.cpp */, - 2B7F45E11708365100A106A9 /* GenFaceNormalsProcess.h */, - 2B7F45E21708365100A106A9 /* GenVertexNormalsProcess.cpp */, - 2B7F45E31708365100A106A9 /* GenVertexNormalsProcess.h */, - 2B7F45E51708365100A106A9 /* Hash.h */, - 2B7F45F51708365100A106A9 /* IFF.h */, - 2B7F45F61708365100A106A9 /* Importer.cpp */, - 2B7F45F71708365100A106A9 /* Importer.h */, - 2B7F45F81708365100A106A9 /* ImporterRegistry.cpp */, - 2B7F45F91708365100A106A9 /* ImproveCacheLocality.cpp */, - 2B7F45FA1708365100A106A9 /* ImproveCacheLocality.h */, - 2B7F46021708365100A106A9 /* JoinVerticesProcess.cpp */, - 2B7F46031708365100A106A9 /* JoinVerticesProcess.h */, - 2B7F46041708365100A106A9 /* LimitBoneWeightsProcess.cpp */, - 2B7F46051708365100A106A9 /* LimitBoneWeightsProcess.h */, - 2B7F46061708365100A106A9 /* LineSplitter.h */, - 2B7F46071708365100A106A9 /* LogAux.h */, - 2B7F46141708365200A106A9 /* MakeVerboseFormat.cpp */, - 2B7F46151708365200A106A9 /* MakeVerboseFormat.h */, - 2B7F46161708365200A106A9 /* MaterialSystem.cpp */, - 2B7F46171708365200A106A9 /* MaterialSystem.h */, - 2B7F461F1708365200A106A9 /* MD4FileData.h */, - 2B7F462D1708365200A106A9 /* MemoryIOWrapper.h */, - 2B7F46461708365200A106A9 /* OptimizeGraph.cpp */, - 2B7F46471708365200A106A9 /* OptimizeGraph.h */, - 2B7F46481708365200A106A9 /* OptimizeMeshes.cpp */, - 2B7F46491708365200A106A9 /* OptimizeMeshes.h */, - 2B7F464A1708365200A106A9 /* ParsingUtils.h */, - 2B7F46511708365200A106A9 /* PolyTools.h */, - 2B7F46521708365200A106A9 /* PostStepRegistry.cpp */, - 2B7F46531708365200A106A9 /* PretransformVertices.cpp */, - 2B7F46541708365200A106A9 /* PretransformVertices.h */, - 2B7F46551708365200A106A9 /* ProcessHelper.cpp */, - 2B7F46561708365200A106A9 /* ProcessHelper.h */, - 2B7F46571708365200A106A9 /* Profiler.h */, - 2B7F46581708365200A106A9 /* pstdint.h */, - 2B7F46621708365200A106A9 /* qnan.h */, - 2B7F46651708365200A106A9 /* RemoveComments.cpp */, - 2B7F46661708365200A106A9 /* RemoveComments.h */, - 2B7F46671708365200A106A9 /* RemoveRedundantMaterials.cpp */, - 2B7F46681708365200A106A9 /* RemoveRedundantMaterials.h */, - 2B7F46691708365200A106A9 /* RemoveVCProcess.cpp */, - 2B7F466A1708365200A106A9 /* RemoveVCProcess.h */, - 2B7F466E1708365200A106A9 /* SceneCombiner.cpp */, - 2B7F466F1708365200A106A9 /* SceneCombiner.h */, - 2B7F46701708365200A106A9 /* ScenePreprocessor.cpp */, - 2B7F46711708365200A106A9 /* ScenePreprocessor.h */, - 2B7F46721708365200A106A9 /* ScenePrivate.h */, - 2B7F46731708365200A106A9 /* SGSpatialSort.cpp */, - 2B7F46741708365200A106A9 /* SGSpatialSort.h */, - 2B7F46751708365200A106A9 /* SkeletonMeshBuilder.cpp */, - 2B7F46761708365200A106A9 /* SkeletonMeshBuilder.h */, - 2B7F46791708365200A106A9 /* SmoothingGroups.h */, - 2B7F467A1708365200A106A9 /* SmoothingGroups.inl */, - 2B7F467B1708365200A106A9 /* SortByPTypeProcess.cpp */, - 2B7F467C1708365200A106A9 /* SortByPTypeProcess.h */, - 2B7F467D1708365200A106A9 /* SpatialSort.cpp */, - 2B7F467E1708365200A106A9 /* SpatialSort.h */, - 2B7F467F1708365200A106A9 /* SplitByBoneCountProcess.cpp */, - 2B7F46801708365200A106A9 /* SplitByBoneCountProcess.h */, - 2B7F46811708365200A106A9 /* SplitLargeMeshes.cpp */, - 2B7F46821708365200A106A9 /* SplitLargeMeshes.h */, - 2B7F46831708365200A106A9 /* StandardShapes.cpp */, - 2B7F46841708365200A106A9 /* StandardShapes.h */, - 2B7F46851708365200A106A9 /* StdOStreamLogStream.h */, - 2B7F468F1708365200A106A9 /* StreamReader.h */, - 2B7F46901708365200A106A9 /* StringComparison.h */, - 2B7F46911708365200A106A9 /* Subdivision.cpp */, - 2B7F46921708365200A106A9 /* Subdivision.h */, - 2B7F46931708365200A106A9 /* TargetAnimation.cpp */, - 2B7F46941708365200A106A9 /* TargetAnimation.h */, - 2B7F46971708365200A106A9 /* TextureTransform.cpp */, - 2B7F46981708365200A106A9 /* TextureTransform.h */, - 2B7F46991708365200A106A9 /* TinyFormatter.h */, - 2B7F469A1708365200A106A9 /* TriangulateProcess.cpp */, - 2B7F469B1708365200A106A9 /* TriangulateProcess.h */, - 2B7F469E1708365200A106A9 /* ValidateDataStructure.cpp */, - 2B7F469F1708365200A106A9 /* ValidateDataStructure.h */, - 2B7F46A01708365200A106A9 /* Vertex.h */, - 2B7F46A11708365200A106A9 /* VertexTriangleAdjacency.cpp */, - 2B7F46A21708365200A106A9 /* VertexTriangleAdjacency.h */, - 2B7F46A31708365200A106A9 /* Win32DebugLogStream.h */, - ); - name = code; - path = ../../code; - sourceTree = ""; - }; - 2B7F45841708365100A106A9 /* BoostWorkaround */ = { - isa = PBXGroup; - children = ( - 2B7F45851708365100A106A9 /* boost */, - ); - path = BoostWorkaround; - sourceTree = ""; - }; - 2B7F45851708365100A106A9 /* boost */ = { - isa = PBXGroup; - children = ( - 2B7F45861708365100A106A9 /* foreach.hpp */, - 2B7F45871708365100A106A9 /* format.hpp */, - 2B7F45881708365100A106A9 /* lexical_cast.hpp */, - 2B7F45891708365100A106A9 /* LICENSE_1_0.txt */, - 2B7F458A1708365100A106A9 /* make_shared.hpp */, - 2B7F458B1708365100A106A9 /* math */, - 2B7F458D1708365100A106A9 /* noncopyable.hpp */, - 2B7F458E1708365100A106A9 /* pointer_cast.hpp */, - 2B7F458F1708365100A106A9 /* scoped_array.hpp */, - 2B7F45901708365100A106A9 /* scoped_ptr.hpp */, - 2B7F45911708365100A106A9 /* shared_array.hpp */, - 2B7F45921708365100A106A9 /* shared_ptr.hpp */, - 2B7F45931708365100A106A9 /* static_assert.hpp */, - 2B7F45941708365100A106A9 /* timer.hpp */, - 2B7F45951708365100A106A9 /* tuple */, - ); - path = boost; - sourceTree = ""; - }; - 2B7F458B1708365100A106A9 /* math */ = { - isa = PBXGroup; - children = ( - 2B7F458C1708365100A106A9 /* common_factor_rt.hpp */, - ); - path = math; - sourceTree = ""; - }; - 2B7F45951708365100A106A9 /* tuple */ = { - isa = PBXGroup; - children = ( - 2B7F45961708365100A106A9 /* tuple.hpp */, - ); - path = tuple; - sourceTree = ""; - }; - 3AB8A3A70E50D59500606590 /* MDC */ = { - isa = PBXGroup; - children = ( - 3AB8A3AB0E50D67A00606590 /* MDCFileData.h */, - 3AB8A3AC0E50D67A00606590 /* MDCLoader.cpp */, - 3AB8A3AD0E50D67A00606590 /* MDCLoader.h */, - 3AB8A3AE0E50D67A00606590 /* MDCNormalTable.h */, - ); - name = MDC; - path = ../../code; - sourceTree = ""; - }; - 3AB8A3A80E50D5F400606590 /* LWO */ = { - isa = PBXGroup; - children = ( - 7411B16311416DF400BCD793 /* LWOAnimation.cpp */, - 7411B16411416DF400BCD793 /* LWOAnimation.h */, - F90BB0270F5DDA9200124155 /* LWOBLoader.cpp */, - 3AB8A3B70E50D6DB00606590 /* LWOFileData.h */, - 3AB8A3B80E50D6DB00606590 /* LWOLoader.cpp */, - 3AB8A3B90E50D6DB00606590 /* LWOLoader.h */, - 3AB8A7DC0E53715F00606590 /* LWOMaterial.cpp */, - ); - name = LWO; - path = ../../code; - sourceTree = ""; - }; - 3AF45A520E4B715000207D74 /* include */ = { - isa = PBXGroup; - children = ( - F9BA8B741543268400E63FFE /* assimp */, - ); - name = include; - path = ../../include; - sourceTree = SOURCE_ROOT; - }; - 3AF45B690E4B722000207D74 /* 3DS */ = { - isa = PBXGroup; - children = ( - 3AF45A860E4B716800207D74 /* 3DSConverter.cpp */, - 3AF45A880E4B716800207D74 /* 3DSHelper.h */, - 3AF45A890E4B716800207D74 /* 3DSLoader.cpp */, - 3AF45A8A0E4B716800207D74 /* 3DSLoader.h */, - ); - name = 3DS; - path = ../../code; - sourceTree = ""; - }; - 3AF45B6A0E4B726700207D74 /* ASE */ = { - isa = PBXGroup; - children = ( - 3AF45A8E0E4B716800207D74 /* ASELoader.cpp */, - 3AF45A8F0E4B716800207D74 /* ASELoader.h */, - 3AF45A900E4B716800207D74 /* ASEParser.cpp */, - 3AF45A910E4B716800207D74 /* ASEParser.h */, - ); - name = ASE; - path = ../../code; - sourceTree = ""; - }; - 3AF45B6C0E4B72C600207D74 /* HMP */ = { - isa = PBXGroup; - children = ( - 3AB8A3C50E50D77900606590 /* HMPFileData.h */, - 3AF45AAB0E4B716800207D74 /* HMPLoader.cpp */, - 3AF45AAC0E4B716800207D74 /* HMPLoader.h */, - ); - name = HMP; - path = ../../code; - sourceTree = ""; - }; - 3AF45B870E4B74DA00207D74 /* MD2 */ = { - isa = PBXGroup; - children = ( - 3AF45AB80E4B716800207D74 /* MD2FileData.h */, - 3AF45AB90E4B716800207D74 /* MD2Loader.cpp */, - 3AF45ABA0E4B716800207D74 /* MD2Loader.h */, - 3AF45ABB0E4B716800207D74 /* MD2NormalTable.h */, - ); - name = MD2; - path = ../../code; - sourceTree = ""; - }; - 3AF45B880E4B751000207D74 /* MD3 */ = { - isa = PBXGroup; - children = ( - 3AF45ABC0E4B716800207D74 /* MD3FileData.h */, - 3AF45ABD0E4B716800207D74 /* MD3Loader.cpp */, - 3AF45ABE0E4B716800207D74 /* MD3Loader.h */, - ); - name = MD3; - path = ../../code; - sourceTree = ""; - }; - 3AF45B8A0E4B755E00207D74 /* MD5 */ = { - isa = PBXGroup; - children = ( - 3AF45AC20E4B716800207D74 /* MD5Loader.cpp */, - 3AF45AC30E4B716800207D74 /* MD5Loader.h */, - 3AF45AC40E4B716800207D74 /* MD5Parser.cpp */, - 3AF45AC50E4B716800207D74 /* MD5Parser.h */, - ); - name = MD5; - path = ../../code; - sourceTree = ""; - }; - 3AF45B8B0E4B75BC00207D74 /* MDL */ = { - isa = PBXGroup; - children = ( - 3AF45AA90E4B716800207D74 /* HalfLifeFileData.h */, - 3AF45AC60E4B716800207D74 /* MDLDefaultColorMap.h */, - 3AF45AC70E4B716800207D74 /* MDLFileData.h */, - 3AF45AC80E4B716800207D74 /* MDLLoader.cpp */, - 3AF45AC90E4B716800207D74 /* MDLLoader.h */, - 3AF45ACA0E4B716800207D74 /* MDLMaterialLoader.cpp */, - ); - name = MDL; - path = ../../code; - sourceTree = ""; - }; - 3AF45B8C0E4B75F200207D74 /* Obj */ = { - isa = PBXGroup; - children = ( - 2B7F46341708365200A106A9 /* ObjExporter.cpp */, - 2B7F46351708365200A106A9 /* ObjExporter.h */, - 2B7F46361708365200A106A9 /* ObjFileData.h */, - 2B7F46371708365200A106A9 /* ObjFileImporter.cpp */, - 2B7F46381708365200A106A9 /* ObjFileImporter.h */, - 2B7F46391708365200A106A9 /* ObjFileMtlImporter.cpp */, - 2B7F463A1708365200A106A9 /* ObjFileMtlImporter.h */, - 2B7F463B1708365200A106A9 /* ObjFileParser.cpp */, - 2B7F463C1708365200A106A9 /* ObjFileParser.h */, - 2B7F463D1708365200A106A9 /* ObjTools.h */, - ); - name = Obj; - path = ../../code; - sourceTree = ""; - }; - 3AF45B8D0E4B761A00207D74 /* Ply */ = { - isa = PBXGroup; - children = ( - F99A9F3015436269000682F3 /* PlyExporter.cpp */, - F99A9F3115436269000682F3 /* PlyExporter.h */, - 3AF45AD40E4B716800207D74 /* PlyLoader.cpp */, - 3AF45AD50E4B716800207D74 /* PlyLoader.h */, - 3AF45AD60E4B716800207D74 /* PlyParser.cpp */, - 3AF45AD70E4B716800207D74 /* PlyParser.h */, - ); - name = Ply; - path = ../../code; - sourceTree = ""; - }; - 3AF45B8E0E4B764400207D74 /* SMD */ = { - isa = PBXGroup; - children = ( - 3AF45AE20E4B716800207D74 /* SMDLoader.cpp */, - 3AF45AE30E4B716800207D74 /* SMDLoader.h */, - ); - name = SMD; - path = ../../code; - sourceTree = ""; - }; - 3AF45B8F0E4B766700207D74 /* X */ = { - isa = PBXGroup; - children = ( - 3AF45AF40E4B716800207D74 /* XFileHelper.h */, - 3AF45AF50E4B716800207D74 /* XFileImporter.cpp */, - 3AF45AF60E4B716800207D74 /* XFileImporter.h */, - 3AF45AF70E4B716800207D74 /* XFileParser.cpp */, - 3AF45AF80E4B716800207D74 /* XFileParser.h */, - ); - name = X; - path = ../../code; - sourceTree = ""; - }; - 3AF45B910E4B77BE00207D74 /* STL */ = { - isa = PBXGroup; - children = ( - 2B7F468B1708365200A106A9 /* STLExporter.cpp */, - 2B7F468C1708365200A106A9 /* STLExporter.h */, - 2B7F468D1708365200A106A9 /* STLLoader.cpp */, - 2B7F468E1708365200A106A9 /* STLLoader.h */, - ); - name = STL; - path = ../../code; - sourceTree = ""; - }; - 7411B14711416C3F00BCD793 /* CSM */ = { - isa = PBXGroup; - children = ( - 7411B14E11416D5E00BCD793 /* CSMLoader.cpp */, - 7411B14F11416D5E00BCD793 /* CSMLoader.h */, - ); - name = CSM; - sourceTree = ""; - }; - 7411B15811416D6600BCD793 /* LWS */ = { - isa = PBXGroup; - children = ( - 7411B15911416DDD00BCD793 /* LWSLoader.cpp */, - 7411B15A11416DDD00BCD793 /* LWSLoader.h */, - ); - name = LWS; - sourceTree = ""; - }; - 7411B16F11416E0400BCD793 /* MS3D */ = { - isa = PBXGroup; - children = ( - 7411B17011416E2500BCD793 /* MS3DLoader.cpp */, - 7411B17111416E2500BCD793 /* MS3DLoader.h */, - ); - name = MS3D; - sourceTree = ""; - }; - 7411B17A11416E2E00BCD793 /* Ogre */ = { - isa = PBXGroup; - children = ( - F9BA8C35154328B600E63FFE /* OgreImporter.cpp */, - F9BA8C36154328B600E63FFE /* OgreImporter.hpp */, - F9BA8C37154328B600E63FFE /* OgreMaterial.cpp */, - F9BA8C38154328B600E63FFE /* OgreMesh.cpp */, - F9BA8C39154328B600E63FFE /* OgreSkeleton.cpp */, - F9BA8C3A154328B600E63FFE /* OgreXmlHelper.hpp */, - ); - name = Ogre; - sourceTree = ""; - }; - 7411B18A11416EA100BCD793 /* Unreal */ = { - isa = PBXGroup; - children = ( - 7411B18B11416EBC00BCD793 /* UnrealLoader.cpp */, - 7411B18C11416EBC00BCD793 /* UnrealLoader.h */, - ); - name = Unreal; - sourceTree = ""; - }; - 74C9BB4611ACBAE500AF885C /* Blender */ = { - isa = PBXGroup; - children = ( - 74C9BB4911ACBB1000AF885C /* BlenderDNA.cpp */, - 74C9BB4A11ACBB1000AF885C /* BlenderDNA.h */, - 74C9BB4B11ACBB1000AF885C /* BlenderDNA.inl */, - 8E7ABBCE127E0F3800512ED1 /* BlenderIntermediate.h */, - 74C9BB4C11ACBB1000AF885C /* BlenderLoader.cpp */, - 74C9BB4D11ACBB1000AF885C /* BlenderLoader.h */, - 8E7ABBCF127E0F3800512ED1 /* BlenderModifier.cpp */, - 8E7ABBD0127E0F3800512ED1 /* BlenderModifier.h */, - 74C9BB4E11ACBB1000AF885C /* BlenderScene.cpp */, - 74C9BB4F11ACBB1000AF885C /* BlenderScene.h */, - 74C9BB5011ACBB1000AF885C /* BlenderSceneGen.h */, - ); - name = Blender; - sourceTree = ""; - }; - 74C9BB9211ACBBA600AF885C /* COB */ = { - isa = PBXGroup; - children = ( - 74C9BB9311ACBBBC00AF885C /* COBLoader.cpp */, - 74C9BB9411ACBBBC00AF885C /* COBLoader.h */, - 74C9BB9511ACBBBC00AF885C /* COBScene.h */, - ); - name = COB; - sourceTree = ""; - }; - 8E7ABB99127E0EE000512ED1 /* NDO */ = { - isa = PBXGroup; - children = ( - 8E7ABBC4127E0F2A00512ED1 /* NDOLoader.cpp */, - 8E7ABBC5127E0F2A00512ED1 /* NDOLoader.h */, - ); - name = NDO; - sourceTree = ""; - }; - 8E7ABB9C127E0EFD00512ED1 /* Q3BSP */ = { - isa = PBXGroup; - children = ( - 8E7ABBA1127E0F1A00512ED1 /* Q3BSPFileData.h */, - 8E7ABBA2127E0F1A00512ED1 /* Q3BSPFileImporter.cpp */, - 8E7ABBA3127E0F1A00512ED1 /* Q3BSPFileImporter.h */, - 8E7ABBA4127E0F1A00512ED1 /* Q3BSPFileParser.cpp */, - 8E7ABBA5127E0F1A00512ED1 /* Q3BSPFileParser.h */, - 8E7ABBA6127E0F1A00512ED1 /* Q3BSPZipArchive.cpp */, - 8E7ABBA7127E0F1A00512ED1 /* Q3BSPZipArchive.h */, - ); - name = Q3BSP; - sourceTree = ""; - }; - 8E8DEE4A127E2B78005EF64D /* ConvertUTF */ = { - isa = PBXGroup; - children = ( - 8E8DEE4B127E2B78005EF64D /* ConvertUTF.c */, - 8E8DEE4C127E2B78005EF64D /* ConvertUTF.h */, - ); - path = ConvertUTF; - sourceTree = ""; - }; - 8E8DEE4E127E2B78005EF64D /* irrXML */ = { - isa = PBXGroup; - children = ( - 8E8DEE4F127E2B78005EF64D /* CXMLReaderImpl.h */, - 8E8DEE50127E2B78005EF64D /* heapsort.h */, - 8E8DEE51127E2B78005EF64D /* irrArray.h */, - 8E8DEE52127E2B78005EF64D /* irrString.h */, - 8E8DEE53127E2B78005EF64D /* irrTypes.h */, - 8E8DEE54127E2B78005EF64D /* irrXML.cpp */, - 8E8DEE55127E2B78005EF64D /* irrXML.h */, - ); - path = irrXML; - sourceTree = ""; - }; - 8E8DEE56127E2B78005EF64D /* unzip */ = { - isa = PBXGroup; - children = ( - 8E8DEE57127E2B78005EF64D /* crypt.h */, - 8E8DEE58127E2B78005EF64D /* ioapi.c */, - 8E8DEE59127E2B78005EF64D /* ioapi.h */, - 8E8DEE5A127E2B78005EF64D /* unzip.c */, - 8E8DEE5B127E2B78005EF64D /* unzip.h */, - ); - path = unzip; - sourceTree = ""; - }; - F90BAFCE0F5DD85F00124155 /* AC */ = { - isa = PBXGroup; - children = ( - F90BAFD00F5DD87000124155 /* ACLoader.cpp */, - F90BAFD10F5DD87000124155 /* ACLoader.h */, - ); - name = AC; - path = ../../code; - sourceTree = ""; - }; - F90BAFD40F5DD8F200124155 /* IRR */ = { - isa = PBXGroup; - children = ( - F90BAFD90F5DD90800124155 /* IRRLoader.cpp */, - F90BAFDA0F5DD90800124155 /* IRRLoader.h */, - F90BAFDB0F5DD90800124155 /* IRRMeshLoader.cpp */, - F90BAFDC0F5DD90800124155 /* IRRMeshLoader.h */, - F90BAFDD0F5DD90800124155 /* IRRShared.cpp */, - F90BAFDE0F5DD90800124155 /* IRRShared.h */, - F90BB0360F5DDB1B00124155 /* irrXMLWrapper.h */, - ); - name = IRR; - path = ../../code; - sourceTree = ""; - }; - F90BAFE60F5DD91F00124155 /* COLLADA */ = { - isa = PBXGroup; - children = ( - 2B7F45A11708365100A106A9 /* ColladaExporter.cpp */, - 2B7F45A21708365100A106A9 /* ColladaExporter.h */, - 2B7F45A31708365100A106A9 /* ColladaHelper.h */, - 2B7F45A41708365100A106A9 /* ColladaLoader.cpp */, - 2B7F45A51708365100A106A9 /* ColladaLoader.h */, - 2B7F45A61708365100A106A9 /* ColladaParser.cpp */, - 2B7F45A71708365100A106A9 /* ColladaParser.h */, - ); - name = COLLADA; - path = ../../code; - sourceTree = ""; - }; - F90BAFF30F5DD95600124155 /* NFF */ = { - isa = PBXGroup; - children = ( - F90BAFF50F5DD96100124155 /* NFFLoader.h */, - F90BAFF60F5DD96100124155 /* NFFLoader.cpp */, - ); - name = NFF; - path = ../../code; - sourceTree = ""; - }; - F90BB0040F5DD9CD00124155 /* Q3D */ = { - isa = PBXGroup; - children = ( - F90BB0060F5DD9DD00124155 /* Q3DLoader.cpp */, - F90BB0070F5DD9DD00124155 /* Q3DLoader.h */, - ); - name = Q3D; - path = ../../code; - sourceTree = ""; - }; - F90BB00A0F5DD9E800124155 /* BVH */ = { - isa = PBXGroup; - children = ( - F90BB00C0F5DD9F400124155 /* BVHLoader.h */, - F90BB00D0F5DD9F400124155 /* BVHLoader.cpp */, - ); - name = BVH; - path = ../../code; - sourceTree = ""; - }; - F90BB0110F5DDA0B00124155 /* OFF */ = { - isa = PBXGroup; - children = ( - F90BB0130F5DDA1400124155 /* OFFLoader.h */, - F90BB0140F5DDA1400124155 /* OFFLoader.cpp */, - ); - name = OFF; - path = ../../code; - sourceTree = ""; - }; - F90BB0190F5DDA3100124155 /* RAW */ = { - isa = PBXGroup; - children = ( - F90BB01B0F5DDA4400124155 /* RawLoader.h */, - F90BB01C0F5DDA4400124155 /* RawLoader.cpp */, - ); - name = RAW; - path = ../../code; - sourceTree = ""; - }; - F90BB01F0F5DDA4A00124155 /* DXF */ = { - isa = PBXGroup; - children = ( - F90BB0210F5DDA5700124155 /* DXFLoader.h */, - F90BB0220F5DDA5700124155 /* DXFLoader.cpp */, - ); - name = DXF; - path = ../../code; - sourceTree = ""; - }; - F90BB02A0F5DDAA900124155 /* Terragen */ = { - isa = PBXGroup; - children = ( - F90BB02F0F5DDAB500124155 /* TerragenLoader.h */, - F90BB0300F5DDAB500124155 /* TerragenLoader.cpp */, - ); - name = Terragen; - path = ../../code; - sourceTree = ""; - }; - F90BB0700F5DDD7000124155 /* 3rd party libs */ = { - isa = PBXGroup; - children = ( - F96070C41543673B004D91DD /* clipper */, - 8E8DEE4A127E2B78005EF64D /* ConvertUTF */, - 8E8DEE4E127E2B78005EF64D /* irrXML */, - F96070D01543675E004D91DD /* poly2tri */, - 8E8DEE56127E2B78005EF64D /* unzip */, - F9607046154366AB004D91DD /* zlib */, - ); - name = "3rd party libs"; - path = ../../contrib; - sourceTree = ""; - }; - F90BB0830F5DDDC700124155 /* importers */ = { - isa = PBXGroup; - children = ( - 3AF45B690E4B722000207D74 /* 3DS */, - F90BAFCE0F5DD85F00124155 /* AC */, - 3AF45B6A0E4B726700207D74 /* ASE */, - F90BB0850F5DDDF800124155 /* B3D */, - 74C9BB4611ACBAE500AF885C /* Blender */, - F90BB00A0F5DD9E800124155 /* BVH */, - 74C9BB9211ACBBA600AF885C /* COB */, - F90BAFE60F5DD91F00124155 /* COLLADA */, - 7411B14711416C3F00BCD793 /* CSM */, - F90BB01F0F5DDA4A00124155 /* DXF */, - 3AF45B6C0E4B72C600207D74 /* HMP */, - F97BA06415439FB2009EB9DD /* IFC */, - F90BAFD40F5DD8F200124155 /* IRR */, - 3AB8A3A80E50D5F400606590 /* LWO */, - 7411B15811416D6600BCD793 /* LWS */, - 3AF45B870E4B74DA00207D74 /* MD2 */, - 3AF45B880E4B751000207D74 /* MD3 */, - 3AF45B8A0E4B755E00207D74 /* MD5 */, - 3AB8A3A70E50D59500606590 /* MDC */, - 3AF45B8B0E4B75BC00207D74 /* MDL */, - 7411B16F11416E0400BCD793 /* MS3D */, - 8E7ABB99127E0EE000512ED1 /* NDO */, - F90BAFF30F5DD95600124155 /* NFF */, - 3AF45B8C0E4B75F200207D74 /* Obj */, - F90BB0110F5DDA0B00124155 /* OFF */, - 7411B17A11416E2E00BCD793 /* Ogre */, - 3AF45B8D0E4B761A00207D74 /* Ply */, - 8E7ABB9C127E0EFD00512ED1 /* Q3BSP */, - F90BB0040F5DD9CD00124155 /* Q3D */, - F90BB0190F5DDA3100124155 /* RAW */, - 3AF45B8E0E4B764400207D74 /* SMD */, - F99A9F5315436318000682F3 /* STEP */, - 3AF45B910E4B77BE00207D74 /* STL */, - F90BB02A0F5DDAA900124155 /* Terragen */, - 7411B18A11416EA100BCD793 /* Unreal */, - 3AF45B8F0E4B766700207D74 /* X */, - F96070B1154366E3004D91DD /* XGL */, - ); - name = importers; - sourceTree = ""; - }; - F90BB0850F5DDDF800124155 /* B3D */ = { - isa = PBXGroup; - children = ( - F90BB0870F5DDE0700124155 /* B3DImporter.h */, - F90BB0880F5DDE0700124155 /* B3DImporter.cpp */, - ); - name = B3D; - sourceTree = ""; - }; - F9607046154366AB004D91DD /* zlib */ = { - isa = PBXGroup; - children = ( - F9607047154366AB004D91DD /* adler32.c */, - F9607049154366AB004D91DD /* compress.c */, - F960704A154366AB004D91DD /* crc32.c */, - F960704B154366AB004D91DD /* crc32.h */, - F960704C154366AB004D91DD /* deflate.c */, - F960704D154366AB004D91DD /* deflate.h */, - F960704E154366AB004D91DD /* inffast.c */, - F960704F154366AB004D91DD /* inffast.h */, - F9607050154366AB004D91DD /* inffixed.h */, - F9607051154366AB004D91DD /* inflate.c */, - F9607052154366AB004D91DD /* inflate.h */, - F9607053154366AB004D91DD /* inftrees.c */, - F9607054154366AB004D91DD /* inftrees.h */, - F9607056154366AB004D91DD /* trees.c */, - F9607057154366AB004D91DD /* trees.h */, - F9607058154366AB004D91DD /* zconf.h */, - F9607059154366AB004D91DD /* zconf.in.h */, - F960705A154366AB004D91DD /* zlib.h */, - F960705B154366AB004D91DD /* zutil.c */, - F960705C154366AB004D91DD /* zutil.h */, - ); - path = zlib; - sourceTree = ""; - }; - F96070B1154366E3004D91DD /* XGL */ = { - isa = PBXGroup; - children = ( - F96070B5154366ED004D91DD /* XGLLoader.cpp */, - F96070B6154366ED004D91DD /* XGLLoader.h */, - ); - name = XGL; - sourceTree = ""; - }; - F96070C41543673B004D91DD /* clipper */ = { - isa = PBXGroup; - children = ( - F96070C51543673B004D91DD /* clipper.cpp */, - F96070C61543673B004D91DD /* clipper.hpp */, - ); - path = clipper; - sourceTree = ""; - }; - F96070D01543675E004D91DD /* poly2tri */ = { - isa = PBXGroup; - children = ( - F96070D11543675E004D91DD /* common */, - F96070D51543675E004D91DD /* poly2tri.h */, - F96070D61543675E004D91DD /* sweep */, - ); - name = poly2tri; - path = poly2tri/poly2tri; - sourceTree = ""; - }; - F96070D11543675E004D91DD /* common */ = { - isa = PBXGroup; - children = ( - F96070D21543675E004D91DD /* shapes.cc */, - F96070D31543675E004D91DD /* shapes.h */, - F96070D41543675E004D91DD /* utils.h */, - ); - path = common; - sourceTree = ""; - }; - F96070D61543675E004D91DD /* sweep */ = { - isa = PBXGroup; - children = ( - F96070D71543675E004D91DD /* advancing_front.cc */, - F96070D81543675E004D91DD /* advancing_front.h */, - F96070D91543675E004D91DD /* cdt.cc */, - F96070DA1543675E004D91DD /* cdt.h */, - F96070DB1543675E004D91DD /* sweep.cc */, - F96070DC1543675E004D91DD /* sweep.h */, - F96070DD1543675E004D91DD /* sweep_context.cc */, - F96070DE1543675E004D91DD /* sweep_context.h */, - ); - path = sweep; - sourceTree = ""; - }; - F97BA06415439FB2009EB9DD /* IFC */ = { - isa = PBXGroup; - children = ( - 2B7F45E91708365100A106A9 /* IFCBoolean.cpp */, - 2B7F45EA1708365100A106A9 /* IFCCurve.cpp */, - 2B7F45EB1708365100A106A9 /* IFCGeometry.cpp */, - 2B7F45EC1708365100A106A9 /* IFCLoader.cpp */, - 2B7F45ED1708365100A106A9 /* IFCLoader.h */, - 2B7F45EE1708365100A106A9 /* IFCMaterial.cpp */, - 2B7F45EF1708365100A106A9 /* IFCOpenings.cpp */, - 2B7F45F01708365100A106A9 /* IFCProfile.cpp */, - 2B7F45F11708365100A106A9 /* IFCReaderGen.cpp */, - 2B7F45F21708365100A106A9 /* IFCReaderGen.h */, - 2B7F45F31708365100A106A9 /* IFCUtil.cpp */, - 2B7F45F41708365100A106A9 /* IFCUtil.h */, - ); - name = IFC; - sourceTree = ""; - }; - F99A9F5315436318000682F3 /* STEP */ = { - isa = PBXGroup; - children = ( - 2B7F46861708365200A106A9 /* STEPFile.h */, - 2B7F46871708365200A106A9 /* STEPFileEncoding.cpp */, - 2B7F46881708365200A106A9 /* STEPFileEncoding.h */, - 2B7F46891708365200A106A9 /* STEPFileReader.cpp */, - 2B7F468A1708365200A106A9 /* STEPFileReader.h */, - ); - name = STEP; - sourceTree = ""; - }; - F9BA8B741543268400E63FFE /* assimp */ = { - isa = PBXGroup; - children = ( - F97BA03515439DB3009EB9DD /* ai_assert.h */, - F9BA8B751543268400E63FFE /* anim.h */, - F9BA8B771543268400E63FFE /* camera.h */, - F9BA8B781543268400E63FFE /* cexport.h */, - F9BA8B791543268400E63FFE /* cfileio.h */, - F9BA8B7A1543268400E63FFE /* cimport.h */, - F9BA8B7B1543268400E63FFE /* color4.h */, - F9BA8B7C1543268400E63FFE /* color4.inl */, - F9BA8B7D1543268400E63FFE /* Compiler */, - F9BA8B801543268400E63FFE /* config.h */, - F9BA8B811543268400E63FFE /* DefaultLogger.hpp */, - F9BA8B821543268400E63FFE /* defs.h */, - F9BA8B831543268400E63FFE /* Exporter.hpp */, - F9BA8B841543268400E63FFE /* Importer.hpp */, - F9BA8B851543268400E63FFE /* importerdesc.h */, - F9BA8B861543268400E63FFE /* IOStream.hpp */, - F9BA8B871543268400E63FFE /* IOSystem.hpp */, - F9BA8B881543268400E63FFE /* light.h */, - F9BA8B891543268400E63FFE /* Logger.hpp */, - F9BA8B8A1543268400E63FFE /* LogStream.hpp */, - F9BA8B8B1543268400E63FFE /* material.h */, - F9BA8B8C1543268400E63FFE /* material.inl */, - F9BA8B8D1543268400E63FFE /* matrix3x3.h */, - F9BA8B8E1543268400E63FFE /* matrix3x3.inl */, - F9BA8B8F1543268400E63FFE /* matrix4x4.h */, - F9BA8B901543268400E63FFE /* matrix4x4.inl */, - F9BA8B911543268400E63FFE /* mesh.h */, - F9BA8B921543268400E63FFE /* NullLogger.hpp */, - F9BA8B931543268400E63FFE /* postprocess.h */, - F9BA8B941543268400E63FFE /* ProgressHandler.hpp */, - F9BA8B951543268400E63FFE /* quaternion.h */, - F9BA8B961543268400E63FFE /* quaternion.inl */, - F9BA8B971543268400E63FFE /* scene.h */, - F9BA8B981543268400E63FFE /* texture.h */, - F9BA8B991543268400E63FFE /* types.h */, - F9BA8B9A1543268400E63FFE /* vector2.h */, - F9BA8B9B1543268400E63FFE /* vector2.inl */, - F9BA8B9C1543268400E63FFE /* vector3.h */, - F9BA8B9D1543268400E63FFE /* vector3.inl */, - F9BA8B9E1543268400E63FFE /* version.h */, - ); - path = assimp; - sourceTree = ""; - }; - F9BA8B7D1543268400E63FFE /* Compiler */ = { - isa = PBXGroup; - children = ( - F9BA8B7E1543268400E63FFE /* poppack1.h */, - F9BA8B7F1543268400E63FFE /* pushpack1.h */, - ); - path = Compiler; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 745FF82A113ECB080020C31B /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 745FF840113ECB080020C31B /* 3DSHelper.h in Headers */, - 745FF841113ECB080020C31B /* 3DSLoader.h in Headers */, - 745FF842113ECB080020C31B /* ASELoader.h in Headers */, - 745FF843113ECB080020C31B /* ASEParser.h in Headers */, - 745FF850113ECB080020C31B /* HalfLifeFileData.h in Headers */, - 745FF851113ECB080020C31B /* HMPLoader.h in Headers */, - 745FF856113ECB080020C31B /* MD2FileData.h in Headers */, - 745FF857113ECB080020C31B /* MD2Loader.h in Headers */, - 745FF858113ECB080020C31B /* MD2NormalTable.h in Headers */, - 745FF859113ECB080020C31B /* MD3FileData.h in Headers */, - 745FF85A113ECB080020C31B /* MD3Loader.h in Headers */, - 745FF85B113ECB080020C31B /* MD5Loader.h in Headers */, - 745FF85C113ECB080020C31B /* MD5Parser.h in Headers */, - 745FF85D113ECB080020C31B /* MDLDefaultColorMap.h in Headers */, - 745FF85E113ECB080020C31B /* MDLFileData.h in Headers */, - 745FF85F113ECB080020C31B /* MDLLoader.h in Headers */, - 745FF866113ECB080020C31B /* PlyLoader.h in Headers */, - 745FF867113ECB080020C31B /* PlyParser.h in Headers */, - 745FF86C113ECB080020C31B /* SMDLoader.h in Headers */, - 745FF876113ECB080020C31B /* XFileHelper.h in Headers */, - 745FF877113ECB080020C31B /* XFileImporter.h in Headers */, - 745FF878113ECB080020C31B /* XFileParser.h in Headers */, - 745FF87B113ECB080020C31B /* MDCFileData.h in Headers */, - 745FF87C113ECB080020C31B /* MDCLoader.h in Headers */, - 745FF87D113ECB080020C31B /* MDCNormalTable.h in Headers */, - 745FF87F113ECB080020C31B /* LWOFileData.h in Headers */, - 745FF880113ECB080020C31B /* LWOLoader.h in Headers */, - 745FF881113ECB080020C31B /* HMPFileData.h in Headers */, - 745FF889113ECB080020C31B /* ACLoader.h in Headers */, - 745FF88A113ECB080020C31B /* IRRLoader.h in Headers */, - 745FF88B113ECB080020C31B /* IRRMeshLoader.h in Headers */, - 745FF88C113ECB080020C31B /* IRRShared.h in Headers */, - 745FF890113ECB080020C31B /* NFFLoader.h in Headers */, - 745FF892113ECB080020C31B /* Q3DLoader.h in Headers */, - 745FF893113ECB080020C31B /* BVHLoader.h in Headers */, - 745FF894113ECB080020C31B /* OFFLoader.h in Headers */, - 745FF895113ECB080020C31B /* RawLoader.h in Headers */, - 745FF896113ECB080020C31B /* DXFLoader.h in Headers */, - 745FF897113ECB080020C31B /* TerragenLoader.h in Headers */, - 745FF898113ECB080020C31B /* irrXMLWrapper.h in Headers */, - 745FF8AA113ECB080020C31B /* B3DImporter.h in Headers */, - 7411B15311416D5E00BCD793 /* CSMLoader.h in Headers */, - 7411B15E11416DDD00BCD793 /* LWSLoader.h in Headers */, - 7411B16811416DF400BCD793 /* LWOAnimation.h in Headers */, - 7411B17511416E2500BCD793 /* MS3DLoader.h in Headers */, - 7411B19011416EBC00BCD793 /* UnrealLoader.h in Headers */, - 74C9BB6011ACBB1000AF885C /* BlenderDNA.h in Headers */, - 74C9BB6211ACBB1000AF885C /* BlenderLoader.h in Headers */, - 74C9BB6411ACBB1000AF885C /* BlenderScene.h in Headers */, - 74C9BB6511ACBB1000AF885C /* BlenderSceneGen.h in Headers */, - 74C9BB8911ACBB9900AF885C /* AssimpPCH.h in Headers */, - 74C9BB9711ACBBBC00AF885C /* COBLoader.h in Headers */, - 74C9BB9811ACBBBC00AF885C /* COBScene.h in Headers */, - 74C9BBB411ACBC2600AF885C /* revision.h in Headers */, - 8E7ABBA8127E0F1A00512ED1 /* Q3BSPFileData.h in Headers */, - 8E7ABBAA127E0F1A00512ED1 /* Q3BSPFileImporter.h in Headers */, - 8E7ABBAC127E0F1A00512ED1 /* Q3BSPFileParser.h in Headers */, - 8E7ABBAE127E0F1A00512ED1 /* Q3BSPZipArchive.h in Headers */, - 8E7ABBC7127E0F2A00512ED1 /* NDOLoader.h in Headers */, - 8E7ABBD1127E0F3800512ED1 /* BlenderIntermediate.h in Headers */, - 8E7ABBD3127E0F3800512ED1 /* BlenderModifier.h in Headers */, - 8E8DEE5D127E2B78005EF64D /* ConvertUTF.h in Headers */, - 8E8DEE5E127E2B78005EF64D /* CXMLReaderImpl.h in Headers */, - 8E8DEE5F127E2B78005EF64D /* heapsort.h in Headers */, - 8E8DEE60127E2B78005EF64D /* irrArray.h in Headers */, - 8E8DEE61127E2B78005EF64D /* irrString.h in Headers */, - 8E8DEE62127E2B78005EF64D /* irrTypes.h in Headers */, - 8E8DEE64127E2B78005EF64D /* irrXML.h in Headers */, - 8E8DEE65127E2B78005EF64D /* crypt.h in Headers */, - 8E8DEE67127E2B78005EF64D /* ioapi.h in Headers */, - 8E8DEE69127E2B78005EF64D /* unzip.h in Headers */, - F9BA8BE31543268400E63FFE /* anim.h in Headers */, - F9BA8BE51543268400E63FFE /* camera.h in Headers */, - F9BA8BE61543268400E63FFE /* cexport.h in Headers */, - F9BA8BE71543268400E63FFE /* cfileio.h in Headers */, - F9BA8BE81543268400E63FFE /* cimport.h in Headers */, - F9BA8BE91543268400E63FFE /* color4.h in Headers */, - F9BA8BEA1543268400E63FFE /* poppack1.h in Headers */, - F9BA8BEB1543268400E63FFE /* pushpack1.h in Headers */, - F9BA8BEC1543268400E63FFE /* config.h in Headers */, - F9BA8BED1543268400E63FFE /* DefaultLogger.hpp in Headers */, - F9BA8BEE1543268400E63FFE /* defs.h in Headers */, - F9BA8BEF1543268400E63FFE /* Exporter.hpp in Headers */, - F9BA8BF01543268400E63FFE /* Importer.hpp in Headers */, - F9BA8BF11543268400E63FFE /* importerdesc.h in Headers */, - F9BA8BF21543268400E63FFE /* IOStream.hpp in Headers */, - F9BA8BF31543268400E63FFE /* IOSystem.hpp in Headers */, - F9BA8BF41543268400E63FFE /* light.h in Headers */, - F9BA8BF51543268400E63FFE /* Logger.hpp in Headers */, - F9BA8BF61543268400E63FFE /* LogStream.hpp in Headers */, - F9BA8BF71543268400E63FFE /* material.h in Headers */, - F9BA8BF81543268400E63FFE /* matrix3x3.h in Headers */, - F9BA8BF91543268400E63FFE /* matrix4x4.h in Headers */, - F9BA8BFA1543268400E63FFE /* mesh.h in Headers */, - F9BA8BFB1543268400E63FFE /* NullLogger.hpp in Headers */, - F9BA8BFC1543268400E63FFE /* postprocess.h in Headers */, - F9BA8BFD1543268400E63FFE /* ProgressHandler.hpp in Headers */, - F9BA8BFE1543268400E63FFE /* quaternion.h in Headers */, - F9BA8BFF1543268400E63FFE /* scene.h in Headers */, - F9BA8C001543268400E63FFE /* texture.h in Headers */, - F9BA8C011543268400E63FFE /* types.h in Headers */, - F9BA8C021543268400E63FFE /* vector2.h in Headers */, - F9BA8C031543268400E63FFE /* vector3.h in Headers */, - F9BA8C041543268400E63FFE /* version.h in Headers */, - F9BA8C48154328B600E63FFE /* OgreImporter.hpp in Headers */, - F9BA8C4C154328B600E63FFE /* OgreXmlHelper.hpp in Headers */, - F99A9F3715436269000682F3 /* PlyExporter.h in Headers */, - F9607088154366AB004D91DD /* crc32.h in Headers */, - F960708A154366AB004D91DD /* deflate.h in Headers */, - F960708C154366AB004D91DD /* inffast.h in Headers */, - F960708D154366AB004D91DD /* inffixed.h in Headers */, - F960708F154366AB004D91DD /* inflate.h in Headers */, - F9607091154366AB004D91DD /* inftrees.h in Headers */, - F9607093154366AB004D91DD /* trees.h in Headers */, - F9607094154366AB004D91DD /* zconf.h in Headers */, - F9607095154366AB004D91DD /* zconf.in.h in Headers */, - F9607096154366AB004D91DD /* zlib.h in Headers */, - F9607098154366AB004D91DD /* zutil.h in Headers */, - F96070BC154366ED004D91DD /* XGLLoader.h in Headers */, - F96070CD1543673B004D91DD /* clipper.hpp in Headers */, - F96070F81543675E004D91DD /* shapes.h in Headers */, - F96070F91543675E004D91DD /* utils.h in Headers */, - F96070FA1543675E004D91DD /* poly2tri.h in Headers */, - F96070FC1543675E004D91DD /* advancing_front.h in Headers */, - F96070FE1543675E004D91DD /* cdt.h in Headers */, - F96071001543675E004D91DD /* sweep.h in Headers */, - F96071021543675E004D91DD /* sweep_context.h in Headers */, - F97BA03815439DB3009EB9DD /* ai_assert.h in Headers */, - 2B7F46DF1708365200A106A9 /* assbin_chunks.h in Headers */, - 2B7F47071708365200A106A9 /* BaseImporter.h in Headers */, - 2B7F47111708365200A106A9 /* BaseProcess.h in Headers */, - 2B7F47481708365200A106A9 /* BlobIOSystem.h in Headers */, - 2B7F474D1708365200A106A9 /* foreach.hpp in Headers */, - 2B7F47521708365200A106A9 /* format.hpp in Headers */, - 2B7F47571708365200A106A9 /* lexical_cast.hpp in Headers */, - 2B7F475C1708365200A106A9 /* make_shared.hpp in Headers */, - 2B7F47611708365200A106A9 /* common_factor_rt.hpp in Headers */, - 2B7F47661708365200A106A9 /* noncopyable.hpp in Headers */, - 2B7F476B1708365200A106A9 /* pointer_cast.hpp in Headers */, - 2B7F47701708365200A106A9 /* scoped_array.hpp in Headers */, - 2B7F47751708365200A106A9 /* scoped_ptr.hpp in Headers */, - 2B7F477A1708365200A106A9 /* shared_array.hpp in Headers */, - 2B7F477F1708365200A106A9 /* shared_ptr.hpp in Headers */, - 2B7F47841708365200A106A9 /* static_assert.hpp in Headers */, - 2B7F47891708365200A106A9 /* timer.hpp in Headers */, - 2B7F478E1708365200A106A9 /* tuple.hpp in Headers */, - 2B7F479D1708365200A106A9 /* ByteSwapper.h in Headers */, - 2B7F47A71708365200A106A9 /* CalcTangentsProcess.h in Headers */, - 2B7F47AC1708365200A106A9 /* CInterfaceIOWrapper.h in Headers */, - 2B7F47C51708365200A106A9 /* ColladaExporter.h in Headers */, - 2B7F47CA1708365200A106A9 /* ColladaHelper.h in Headers */, - 2B7F47D41708365200A106A9 /* ColladaLoader.h in Headers */, - 2B7F47DE1708365200A106A9 /* ColladaParser.h in Headers */, - 2B7F47E81708365200A106A9 /* ComputeUVMappingProcess.h in Headers */, - 2B7F47F21708365200A106A9 /* ConvertToLHProcess.h in Headers */, - 2B7F48061708365200A106A9 /* DeboneProcess.h in Headers */, - 2B7F48101708365200A106A9 /* DefaultIOStream.h in Headers */, - 2B7F481A1708365200A106A9 /* DefaultIOSystem.h in Headers */, - 2B7F48241708365200A106A9 /* DefaultProgressHandler.h in Headers */, - 2B7F48381708365200A106A9 /* Exceptional.h in Headers */, - 2B7F48421708365200A106A9 /* fast_atof.h in Headers */, - 2B7F48511708365200A106A9 /* FBXCompileConfig.h in Headers */, - 2B7F485B1708365200A106A9 /* FBXConverter.h in Headers */, - 2B7F486A1708365200A106A9 /* FBXDocument.h in Headers */, - 2B7F48741708365200A106A9 /* FBXDocumentUtil.h in Headers */, - 2B7F487E1708365200A106A9 /* FBXImporter.h in Headers */, - 2B7F48831708365200A106A9 /* FBXImportSettings.h in Headers */, - 2B7F48A11708365200A106A9 /* FBXParser.h in Headers */, - 2B7F48AB1708365200A106A9 /* FBXProperties.h in Headers */, - 2B7F48B51708365200A106A9 /* FBXTokenizer.h in Headers */, - 2B7F48BF1708365200A106A9 /* FBXUtil.h in Headers */, - 2B7F48C41708365200A106A9 /* FileLogStream.h in Headers */, - 2B7F48C91708365200A106A9 /* FileSystemFilter.h in Headers */, - 2B7F48D31708365200A106A9 /* FindDegenerates.h in Headers */, - 2B7F48DD1708365200A106A9 /* FindInstancesProcess.h in Headers */, - 2B7F48E71708365200A106A9 /* FindInvalidDataProcess.h in Headers */, - 2B7F48F11708365200A106A9 /* FixNormalsStep.h in Headers */, - 2B7F48F61708365200A106A9 /* GenericProperty.h in Headers */, - 2B7F49001708365200A106A9 /* GenFaceNormalsProcess.h in Headers */, - 2B7F490A1708365200A106A9 /* GenVertexNormalsProcess.h in Headers */, - 2B7F49141708365200A106A9 /* Hash.h in Headers */, - 2B7F493C1708365200A106A9 /* IFCLoader.h in Headers */, - 2B7F49551708365200A106A9 /* IFCReaderGen.h in Headers */, - 2B7F495F1708365200A106A9 /* IFCUtil.h in Headers */, - 2B7F49641708365200A106A9 /* IFF.h in Headers */, - 2B7F496E1708365200A106A9 /* Importer.h in Headers */, - 2B7F497D1708365200A106A9 /* ImproveCacheLocality.h in Headers */, - 2B7F49AA1708365200A106A9 /* JoinVerticesProcess.h in Headers */, - 2B7F49B41708365200A106A9 /* LimitBoneWeightsProcess.h in Headers */, - 2B7F49B91708365200A106A9 /* LineSplitter.h in Headers */, - 2B7F49BE1708365200A106A9 /* LogAux.h in Headers */, - 2B7F49FF1708365200A106A9 /* MakeVerboseFormat.h in Headers */, - 2B7F4A091708365200A106A9 /* MaterialSystem.h in Headers */, - 2B7F4A311708365200A106A9 /* MD4FileData.h in Headers */, - 2B7F4A771708365200A106A9 /* MemoryIOWrapper.h in Headers */, - 2B7F4A9F1708365200A106A9 /* ObjExporter.h in Headers */, - 2B7F4AA41708365200A106A9 /* ObjFileData.h in Headers */, - 2B7F4AAE1708365200A106A9 /* ObjFileImporter.h in Headers */, - 2B7F4AB81708365200A106A9 /* ObjFileMtlImporter.h in Headers */, - 2B7F4AC21708365200A106A9 /* ObjFileParser.h in Headers */, - 2B7F4AC71708365200A106A9 /* ObjTools.h in Headers */, - 2B7F4AF91708365200A106A9 /* OptimizeGraph.h in Headers */, - 2B7F4B031708365200A106A9 /* OptimizeMeshes.h in Headers */, - 2B7F4B081708365200A106A9 /* ParsingUtils.h in Headers */, - 2B7F4B2B1708365200A106A9 /* PolyTools.h in Headers */, - 2B7F4B3A1708365200A106A9 /* PretransformVertices.h in Headers */, - 2B7F4B441708365200A106A9 /* ProcessHelper.h in Headers */, - 2B7F4B491708365200A106A9 /* Profiler.h in Headers */, - 2B7F4B4E1708365200A106A9 /* pstdint.h in Headers */, - 2B7F4B801708365200A106A9 /* qnan.h in Headers */, - 2B7F4B941708365200A106A9 /* RemoveComments.h in Headers */, - 2B7F4B9E1708365200A106A9 /* RemoveRedundantMaterials.h in Headers */, - 2B7F4BA81708365200A106A9 /* RemoveVCProcess.h in Headers */, - 2B7F4BB71708365200A106A9 /* SceneCombiner.h in Headers */, - 2B7F4BC11708365200A106A9 /* ScenePreprocessor.h in Headers */, - 2B7F4BC61708365200A106A9 /* ScenePrivate.h in Headers */, - 2B7F4BD01708365200A106A9 /* SGSpatialSort.h in Headers */, - 2B7F4BDA1708365200A106A9 /* SkeletonMeshBuilder.h in Headers */, - 2B7F4BE91708365200A106A9 /* SmoothingGroups.h in Headers */, - 2B7F4BF31708365200A106A9 /* SortByPTypeProcess.h in Headers */, - 2B7F4BFD1708365200A106A9 /* SpatialSort.h in Headers */, - 2B7F4C071708365200A106A9 /* SplitByBoneCountProcess.h in Headers */, - 2B7F4C111708365200A106A9 /* SplitLargeMeshes.h in Headers */, - 2B7F4C1B1708365200A106A9 /* StandardShapes.h in Headers */, - 2B7F4C201708365200A106A9 /* StdOStreamLogStream.h in Headers */, - 2B7F4C251708365200A106A9 /* STEPFile.h in Headers */, - 2B7F4C2F1708365200A106A9 /* STEPFileEncoding.h in Headers */, - 2B7F4C391708365200A106A9 /* STEPFileReader.h in Headers */, - 2B7F4C431708365200A106A9 /* STLExporter.h in Headers */, - 2B7F4C4D1708365200A106A9 /* STLLoader.h in Headers */, - 2B7F4C521708365200A106A9 /* StreamReader.h in Headers */, - 2B7F4C571708365200A106A9 /* StringComparison.h in Headers */, - 2B7F4C611708365200A106A9 /* Subdivision.h in Headers */, - 2B7F4C6B1708365200A106A9 /* TargetAnimation.h in Headers */, - 2B7F4C7F1708365200A106A9 /* TextureTransform.h in Headers */, - 2B7F4C841708365200A106A9 /* TinyFormatter.h in Headers */, - 2B7F4C8E1708365200A106A9 /* TriangulateProcess.h in Headers */, - 2B7F4CA21708365200A106A9 /* ValidateDataStructure.h in Headers */, - 2B7F4CA71708365200A106A9 /* Vertex.h in Headers */, - 2B7F4CB11708365200A106A9 /* VertexTriangleAdjacency.h in Headers */, - 2B7F4CB61708365200A106A9 /* Win32DebugLogStream.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 745FF90D113ECC660020C31B /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 745FF923113ECC660020C31B /* 3DSHelper.h in Headers */, - 745FF924113ECC660020C31B /* 3DSLoader.h in Headers */, - 745FF925113ECC660020C31B /* ASELoader.h in Headers */, - 745FF926113ECC660020C31B /* ASEParser.h in Headers */, - 745FF933113ECC660020C31B /* HalfLifeFileData.h in Headers */, - 745FF934113ECC660020C31B /* HMPLoader.h in Headers */, - 745FF939113ECC660020C31B /* MD2FileData.h in Headers */, - 745FF93A113ECC660020C31B /* MD2Loader.h in Headers */, - 745FF93B113ECC660020C31B /* MD2NormalTable.h in Headers */, - 745FF93C113ECC660020C31B /* MD3FileData.h in Headers */, - 745FF93D113ECC660020C31B /* MD3Loader.h in Headers */, - 745FF93E113ECC660020C31B /* MD5Loader.h in Headers */, - 745FF93F113ECC660020C31B /* MD5Parser.h in Headers */, - 745FF940113ECC660020C31B /* MDLDefaultColorMap.h in Headers */, - 745FF941113ECC660020C31B /* MDLFileData.h in Headers */, - 745FF942113ECC660020C31B /* MDLLoader.h in Headers */, - 745FF949113ECC660020C31B /* PlyLoader.h in Headers */, - 745FF94A113ECC660020C31B /* PlyParser.h in Headers */, - 745FF94F113ECC660020C31B /* SMDLoader.h in Headers */, - 745FF959113ECC660020C31B /* XFileHelper.h in Headers */, - 745FF95A113ECC660020C31B /* XFileImporter.h in Headers */, - 745FF95B113ECC660020C31B /* XFileParser.h in Headers */, - 745FF95E113ECC660020C31B /* MDCFileData.h in Headers */, - 745FF95F113ECC660020C31B /* MDCLoader.h in Headers */, - 745FF960113ECC660020C31B /* MDCNormalTable.h in Headers */, - 745FF962113ECC660020C31B /* LWOFileData.h in Headers */, - 745FF963113ECC660020C31B /* LWOLoader.h in Headers */, - 745FF964113ECC660020C31B /* HMPFileData.h in Headers */, - 745FF96C113ECC660020C31B /* ACLoader.h in Headers */, - 745FF96D113ECC660020C31B /* IRRLoader.h in Headers */, - 745FF96E113ECC660020C31B /* IRRMeshLoader.h in Headers */, - 745FF96F113ECC660020C31B /* IRRShared.h in Headers */, - 745FF973113ECC660020C31B /* NFFLoader.h in Headers */, - 745FF975113ECC660020C31B /* Q3DLoader.h in Headers */, - 745FF976113ECC660020C31B /* BVHLoader.h in Headers */, - 745FF977113ECC660020C31B /* OFFLoader.h in Headers */, - 745FF978113ECC660020C31B /* RawLoader.h in Headers */, - 745FF979113ECC660020C31B /* DXFLoader.h in Headers */, - 745FF97A113ECC660020C31B /* TerragenLoader.h in Headers */, - 745FF97B113ECC660020C31B /* irrXMLWrapper.h in Headers */, - 745FF98D113ECC660020C31B /* B3DImporter.h in Headers */, - 7411B15111416D5E00BCD793 /* CSMLoader.h in Headers */, - 7411B15C11416DDD00BCD793 /* LWSLoader.h in Headers */, - 7411B16611416DF400BCD793 /* LWOAnimation.h in Headers */, - 7411B17311416E2500BCD793 /* MS3DLoader.h in Headers */, - 7411B18E11416EBC00BCD793 /* UnrealLoader.h in Headers */, - 74C9BB6711ACBB1000AF885C /* BlenderDNA.h in Headers */, - 74C9BB6911ACBB1000AF885C /* BlenderLoader.h in Headers */, - 74C9BB6B11ACBB1000AF885C /* BlenderScene.h in Headers */, - 74C9BB6C11ACBB1000AF885C /* BlenderSceneGen.h in Headers */, - 74C9BB8B11ACBB9900AF885C /* AssimpPCH.h in Headers */, - 74C9BB9A11ACBBBC00AF885C /* COBLoader.h in Headers */, - 74C9BB9B11ACBBBC00AF885C /* COBScene.h in Headers */, - 74C9BBB511ACBC2600AF885C /* revision.h in Headers */, - 8E7ABBBD127E0F1A00512ED1 /* Q3BSPFileData.h in Headers */, - 8E7ABBBF127E0F1A00512ED1 /* Q3BSPFileImporter.h in Headers */, - 8E7ABBC1127E0F1A00512ED1 /* Q3BSPFileParser.h in Headers */, - 8E7ABBC3127E0F1A00512ED1 /* Q3BSPZipArchive.h in Headers */, - 8E7ABBCD127E0F2A00512ED1 /* NDOLoader.h in Headers */, - 8E7ABBDA127E0F3800512ED1 /* BlenderIntermediate.h in Headers */, - 8E7ABBDC127E0F3800512ED1 /* BlenderModifier.h in Headers */, - 8E8DEE87127E2B78005EF64D /* ConvertUTF.h in Headers */, - 8E8DEE88127E2B78005EF64D /* CXMLReaderImpl.h in Headers */, - 8E8DEE89127E2B78005EF64D /* heapsort.h in Headers */, - 8E8DEE8A127E2B78005EF64D /* irrArray.h in Headers */, - 8E8DEE8B127E2B78005EF64D /* irrString.h in Headers */, - 8E8DEE8C127E2B78005EF64D /* irrTypes.h in Headers */, - 8E8DEE8E127E2B78005EF64D /* irrXML.h in Headers */, - 8E8DEE8F127E2B78005EF64D /* crypt.h in Headers */, - 8E8DEE91127E2B78005EF64D /* ioapi.h in Headers */, - 8E8DEE93127E2B78005EF64D /* unzip.h in Headers */, - F9BA8C051543268400E63FFE /* anim.h in Headers */, - F9BA8C071543268400E63FFE /* camera.h in Headers */, - F9BA8C081543268400E63FFE /* cexport.h in Headers */, - F9BA8C091543268400E63FFE /* cfileio.h in Headers */, - F9BA8C0A1543268400E63FFE /* cimport.h in Headers */, - F9BA8C0B1543268400E63FFE /* color4.h in Headers */, - F9BA8C0C1543268400E63FFE /* poppack1.h in Headers */, - F9BA8C0D1543268400E63FFE /* pushpack1.h in Headers */, - F9BA8C0E1543268400E63FFE /* config.h in Headers */, - F9BA8C0F1543268400E63FFE /* DefaultLogger.hpp in Headers */, - F9BA8C101543268400E63FFE /* defs.h in Headers */, - F9BA8C111543268400E63FFE /* Exporter.hpp in Headers */, - F9BA8C121543268400E63FFE /* Importer.hpp in Headers */, - F9BA8C131543268400E63FFE /* importerdesc.h in Headers */, - F9BA8C141543268400E63FFE /* IOStream.hpp in Headers */, - F9BA8C151543268400E63FFE /* IOSystem.hpp in Headers */, - F9BA8C161543268400E63FFE /* light.h in Headers */, - F9BA8C171543268400E63FFE /* Logger.hpp in Headers */, - F9BA8C181543268400E63FFE /* LogStream.hpp in Headers */, - F9BA8C191543268400E63FFE /* material.h in Headers */, - F9BA8C1A1543268400E63FFE /* matrix3x3.h in Headers */, - F9BA8C1B1543268400E63FFE /* matrix4x4.h in Headers */, - F9BA8C1C1543268400E63FFE /* mesh.h in Headers */, - F9BA8C1D1543268400E63FFE /* NullLogger.hpp in Headers */, - F9BA8C1E1543268400E63FFE /* postprocess.h in Headers */, - F9BA8C1F1543268400E63FFE /* ProgressHandler.hpp in Headers */, - F9BA8C201543268400E63FFE /* quaternion.h in Headers */, - F9BA8C211543268400E63FFE /* scene.h in Headers */, - F9BA8C221543268400E63FFE /* texture.h in Headers */, - F9BA8C231543268400E63FFE /* types.h in Headers */, - F9BA8C241543268400E63FFE /* vector2.h in Headers */, - F9BA8C251543268400E63FFE /* vector3.h in Headers */, - F9BA8C261543268400E63FFE /* version.h in Headers */, - F9BA8C4E154328B600E63FFE /* OgreImporter.hpp in Headers */, - F9BA8C52154328B600E63FFE /* OgreXmlHelper.hpp in Headers */, - F99A9F3915436269000682F3 /* PlyExporter.h in Headers */, - F960709C154366AB004D91DD /* crc32.h in Headers */, - F960709E154366AB004D91DD /* deflate.h in Headers */, - F96070A0154366AB004D91DD /* inffast.h in Headers */, - F96070A1154366AB004D91DD /* inffixed.h in Headers */, - F96070A3154366AB004D91DD /* inflate.h in Headers */, - F96070A5154366AB004D91DD /* inftrees.h in Headers */, - F96070A7154366AB004D91DD /* trees.h in Headers */, - F96070A8154366AB004D91DD /* zconf.h in Headers */, - F96070A9154366AB004D91DD /* zconf.in.h in Headers */, - F96070AA154366AB004D91DD /* zlib.h in Headers */, - F96070AC154366AB004D91DD /* zutil.h in Headers */, - F96070BE154366ED004D91DD /* XGLLoader.h in Headers */, - F96070CF1543673B004D91DD /* clipper.hpp in Headers */, - F96071041543675E004D91DD /* shapes.h in Headers */, - F96071051543675E004D91DD /* utils.h in Headers */, - F96071061543675E004D91DD /* poly2tri.h in Headers */, - F96071081543675E004D91DD /* advancing_front.h in Headers */, - F960710A1543675E004D91DD /* cdt.h in Headers */, - F960710C1543675E004D91DD /* sweep.h in Headers */, - F960710E1543675E004D91DD /* sweep_context.h in Headers */, - F97BA03915439DB3009EB9DD /* ai_assert.h in Headers */, - 2B7F46E01708365200A106A9 /* assbin_chunks.h in Headers */, - 2B7F47081708365200A106A9 /* BaseImporter.h in Headers */, - 2B7F47121708365200A106A9 /* BaseProcess.h in Headers */, - 2B7F47491708365200A106A9 /* BlobIOSystem.h in Headers */, - 2B7F474E1708365200A106A9 /* foreach.hpp in Headers */, - 2B7F47531708365200A106A9 /* format.hpp in Headers */, - 2B7F47581708365200A106A9 /* lexical_cast.hpp in Headers */, - 2B7F475D1708365200A106A9 /* make_shared.hpp in Headers */, - 2B7F47621708365200A106A9 /* common_factor_rt.hpp in Headers */, - 2B7F47671708365200A106A9 /* noncopyable.hpp in Headers */, - 2B7F476C1708365200A106A9 /* pointer_cast.hpp in Headers */, - 2B7F47711708365200A106A9 /* scoped_array.hpp in Headers */, - 2B7F47761708365200A106A9 /* scoped_ptr.hpp in Headers */, - 2B7F477B1708365200A106A9 /* shared_array.hpp in Headers */, - 2B7F47801708365200A106A9 /* shared_ptr.hpp in Headers */, - 2B7F47851708365200A106A9 /* static_assert.hpp in Headers */, - 2B7F478A1708365200A106A9 /* timer.hpp in Headers */, - 2B7F478F1708365200A106A9 /* tuple.hpp in Headers */, - 2B7F479E1708365200A106A9 /* ByteSwapper.h in Headers */, - 2B7F47A81708365200A106A9 /* CalcTangentsProcess.h in Headers */, - 2B7F47AD1708365200A106A9 /* CInterfaceIOWrapper.h in Headers */, - 2B7F47C61708365200A106A9 /* ColladaExporter.h in Headers */, - 2B7F47CB1708365200A106A9 /* ColladaHelper.h in Headers */, - 2B7F47D51708365200A106A9 /* ColladaLoader.h in Headers */, - 2B7F47DF1708365200A106A9 /* ColladaParser.h in Headers */, - 2B7F47E91708365200A106A9 /* ComputeUVMappingProcess.h in Headers */, - 2B7F47F31708365200A106A9 /* ConvertToLHProcess.h in Headers */, - 2B7F48071708365200A106A9 /* DeboneProcess.h in Headers */, - 2B7F48111708365200A106A9 /* DefaultIOStream.h in Headers */, - 2B7F481B1708365200A106A9 /* DefaultIOSystem.h in Headers */, - 2B7F48251708365200A106A9 /* DefaultProgressHandler.h in Headers */, - 2B7F48391708365200A106A9 /* Exceptional.h in Headers */, - 2B7F48431708365200A106A9 /* fast_atof.h in Headers */, - 2B7F48521708365200A106A9 /* FBXCompileConfig.h in Headers */, - 2B7F485C1708365200A106A9 /* FBXConverter.h in Headers */, - 2B7F486B1708365200A106A9 /* FBXDocument.h in Headers */, - 2B7F48751708365200A106A9 /* FBXDocumentUtil.h in Headers */, - 2B7F487F1708365200A106A9 /* FBXImporter.h in Headers */, - 2B7F48841708365200A106A9 /* FBXImportSettings.h in Headers */, - 2B7F48A21708365200A106A9 /* FBXParser.h in Headers */, - 2B7F48AC1708365200A106A9 /* FBXProperties.h in Headers */, - 2B7F48B61708365200A106A9 /* FBXTokenizer.h in Headers */, - 2B7F48C01708365200A106A9 /* FBXUtil.h in Headers */, - 2B7F48C51708365200A106A9 /* FileLogStream.h in Headers */, - 2B7F48CA1708365200A106A9 /* FileSystemFilter.h in Headers */, - 2B7F48D41708365200A106A9 /* FindDegenerates.h in Headers */, - 2B7F48DE1708365200A106A9 /* FindInstancesProcess.h in Headers */, - 2B7F48E81708365200A106A9 /* FindInvalidDataProcess.h in Headers */, - 2B7F48F21708365200A106A9 /* FixNormalsStep.h in Headers */, - 2B7F48F71708365200A106A9 /* GenericProperty.h in Headers */, - 2B7F49011708365200A106A9 /* GenFaceNormalsProcess.h in Headers */, - 2B7F490B1708365200A106A9 /* GenVertexNormalsProcess.h in Headers */, - 2B7F49151708365200A106A9 /* Hash.h in Headers */, - 2B7F493D1708365200A106A9 /* IFCLoader.h in Headers */, - 2B7F49561708365200A106A9 /* IFCReaderGen.h in Headers */, - 2B7F49601708365200A106A9 /* IFCUtil.h in Headers */, - 2B7F49651708365200A106A9 /* IFF.h in Headers */, - 2B7F496F1708365200A106A9 /* Importer.h in Headers */, - 2B7F497E1708365200A106A9 /* ImproveCacheLocality.h in Headers */, - 2B7F49AB1708365200A106A9 /* JoinVerticesProcess.h in Headers */, - 2B7F49B51708365200A106A9 /* LimitBoneWeightsProcess.h in Headers */, - 2B7F49BA1708365200A106A9 /* LineSplitter.h in Headers */, - 2B7F49BF1708365200A106A9 /* LogAux.h in Headers */, - 2B7F4A001708365200A106A9 /* MakeVerboseFormat.h in Headers */, - 2B7F4A0A1708365200A106A9 /* MaterialSystem.h in Headers */, - 2B7F4A321708365200A106A9 /* MD4FileData.h in Headers */, - 2B7F4A781708365200A106A9 /* MemoryIOWrapper.h in Headers */, - 2B7F4AA01708365200A106A9 /* ObjExporter.h in Headers */, - 2B7F4AA51708365200A106A9 /* ObjFileData.h in Headers */, - 2B7F4AAF1708365200A106A9 /* ObjFileImporter.h in Headers */, - 2B7F4AB91708365200A106A9 /* ObjFileMtlImporter.h in Headers */, - 2B7F4AC31708365200A106A9 /* ObjFileParser.h in Headers */, - 2B7F4AC81708365200A106A9 /* ObjTools.h in Headers */, - 2B7F4AFA1708365200A106A9 /* OptimizeGraph.h in Headers */, - 2B7F4B041708365200A106A9 /* OptimizeMeshes.h in Headers */, - 2B7F4B091708365200A106A9 /* ParsingUtils.h in Headers */, - 2B7F4B2C1708365200A106A9 /* PolyTools.h in Headers */, - 2B7F4B3B1708365200A106A9 /* PretransformVertices.h in Headers */, - 2B7F4B451708365200A106A9 /* ProcessHelper.h in Headers */, - 2B7F4B4A1708365200A106A9 /* Profiler.h in Headers */, - 2B7F4B4F1708365200A106A9 /* pstdint.h in Headers */, - 2B7F4B811708365200A106A9 /* qnan.h in Headers */, - 2B7F4B951708365200A106A9 /* RemoveComments.h in Headers */, - 2B7F4B9F1708365200A106A9 /* RemoveRedundantMaterials.h in Headers */, - 2B7F4BA91708365200A106A9 /* RemoveVCProcess.h in Headers */, - 2B7F4BB81708365200A106A9 /* SceneCombiner.h in Headers */, - 2B7F4BC21708365200A106A9 /* ScenePreprocessor.h in Headers */, - 2B7F4BC71708365200A106A9 /* ScenePrivate.h in Headers */, - 2B7F4BD11708365200A106A9 /* SGSpatialSort.h in Headers */, - 2B7F4BDB1708365200A106A9 /* SkeletonMeshBuilder.h in Headers */, - 2B7F4BEA1708365200A106A9 /* SmoothingGroups.h in Headers */, - 2B7F4BF41708365200A106A9 /* SortByPTypeProcess.h in Headers */, - 2B7F4BFE1708365200A106A9 /* SpatialSort.h in Headers */, - 2B7F4C081708365200A106A9 /* SplitByBoneCountProcess.h in Headers */, - 2B7F4C121708365200A106A9 /* SplitLargeMeshes.h in Headers */, - 2B7F4C1C1708365200A106A9 /* StandardShapes.h in Headers */, - 2B7F4C211708365200A106A9 /* StdOStreamLogStream.h in Headers */, - 2B7F4C261708365200A106A9 /* STEPFile.h in Headers */, - 2B7F4C301708365200A106A9 /* STEPFileEncoding.h in Headers */, - 2B7F4C3A1708365200A106A9 /* STEPFileReader.h in Headers */, - 2B7F4C441708365200A106A9 /* STLExporter.h in Headers */, - 2B7F4C4E1708365200A106A9 /* STLLoader.h in Headers */, - 2B7F4C531708365200A106A9 /* StreamReader.h in Headers */, - 2B7F4C581708365200A106A9 /* StringComparison.h in Headers */, - 2B7F4C621708365200A106A9 /* Subdivision.h in Headers */, - 2B7F4C6C1708365200A106A9 /* TargetAnimation.h in Headers */, - 2B7F4C801708365200A106A9 /* TextureTransform.h in Headers */, - 2B7F4C851708365200A106A9 /* TinyFormatter.h in Headers */, - 2B7F4C8F1708365200A106A9 /* TriangulateProcess.h in Headers */, - 2B7F4CA31708365200A106A9 /* ValidateDataStructure.h in Headers */, - 2B7F4CA81708365200A106A9 /* Vertex.h in Headers */, - 2B7F4CB21708365200A106A9 /* VertexTriangleAdjacency.h in Headers */, - 2B7F4CB71708365200A106A9 /* Win32DebugLogStream.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B91974D0163AEA54009C397B /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - B91974D1163AEA54009C397B /* 3DSHelper.h in Headers */, - B91974D2163AEA54009C397B /* 3DSLoader.h in Headers */, - B91974D3163AEA54009C397B /* ASELoader.h in Headers */, - B91974D4163AEA54009C397B /* ASEParser.h in Headers */, - B91974E0163AEA54009C397B /* HalfLifeFileData.h in Headers */, - B91974E1163AEA54009C397B /* HMPLoader.h in Headers */, - B91974E6163AEA54009C397B /* MD2FileData.h in Headers */, - B91974E7163AEA54009C397B /* MD2Loader.h in Headers */, - B91974E8163AEA54009C397B /* MD2NormalTable.h in Headers */, - B91974E9163AEA54009C397B /* MD3FileData.h in Headers */, - B91974EA163AEA54009C397B /* MD3Loader.h in Headers */, - B91974EB163AEA54009C397B /* MD5Loader.h in Headers */, - B91974EC163AEA54009C397B /* MD5Parser.h in Headers */, - B91974ED163AEA54009C397B /* MDLDefaultColorMap.h in Headers */, - B91974EE163AEA54009C397B /* MDLFileData.h in Headers */, - B91974EF163AEA54009C397B /* MDLLoader.h in Headers */, - B91974F6163AEA54009C397B /* PlyLoader.h in Headers */, - B91974F7163AEA54009C397B /* PlyParser.h in Headers */, - B91974FC163AEA54009C397B /* SMDLoader.h in Headers */, - B9197506163AEA54009C397B /* XFileHelper.h in Headers */, - B9197507163AEA54009C397B /* XFileImporter.h in Headers */, - B9197508163AEA54009C397B /* XFileParser.h in Headers */, - B9197509163AEA54009C397B /* MDCFileData.h in Headers */, - B919750A163AEA54009C397B /* MDCLoader.h in Headers */, - B919750B163AEA54009C397B /* MDCNormalTable.h in Headers */, - B919750D163AEA54009C397B /* LWOFileData.h in Headers */, - B919750E163AEA54009C397B /* LWOLoader.h in Headers */, - B919750F163AEA54009C397B /* HMPFileData.h in Headers */, - B9197512163AEA54009C397B /* ACLoader.h in Headers */, - B9197513163AEA54009C397B /* IRRLoader.h in Headers */, - B9197514163AEA54009C397B /* IRRMeshLoader.h in Headers */, - B9197515163AEA54009C397B /* IRRShared.h in Headers */, - B9197519163AEA54009C397B /* NFFLoader.h in Headers */, - B919751B163AEA54009C397B /* Q3DLoader.h in Headers */, - B919751C163AEA54009C397B /* BVHLoader.h in Headers */, - B919751D163AEA54009C397B /* OFFLoader.h in Headers */, - B919751E163AEA54009C397B /* RawLoader.h in Headers */, - B919751F163AEA54009C397B /* DXFLoader.h in Headers */, - B9197520163AEA54009C397B /* TerragenLoader.h in Headers */, - B9197521163AEA54009C397B /* irrXMLWrapper.h in Headers */, - B919752D163AEA54009C397B /* B3DImporter.h in Headers */, - B9197535163AEA54009C397B /* CSMLoader.h in Headers */, - B9197536163AEA54009C397B /* LWSLoader.h in Headers */, - B9197537163AEA54009C397B /* LWOAnimation.h in Headers */, - B9197538163AEA54009C397B /* MS3DLoader.h in Headers */, - B9197539163AEA54009C397B /* UnrealLoader.h in Headers */, - B9197545163AEA54009C397B /* BlenderDNA.h in Headers */, - B9197546163AEA54009C397B /* BlenderLoader.h in Headers */, - B9197547163AEA54009C397B /* BlenderScene.h in Headers */, - B9197548163AEA54009C397B /* BlenderSceneGen.h in Headers */, - B919754D163AEA54009C397B /* AssimpPCH.h in Headers */, - B919754E163AEA54009C397B /* COBLoader.h in Headers */, - B919754F163AEA54009C397B /* COBScene.h in Headers */, - B9197550163AEA54009C397B /* revision.h in Headers */, - B9197555163AEA54009C397B /* Q3BSPFileData.h in Headers */, - B9197556163AEA54009C397B /* Q3BSPFileImporter.h in Headers */, - B9197557163AEA54009C397B /* Q3BSPFileParser.h in Headers */, - B9197558163AEA54009C397B /* Q3BSPZipArchive.h in Headers */, - B9197559163AEA54009C397B /* NDOLoader.h in Headers */, - B919755A163AEA54009C397B /* BlenderIntermediate.h in Headers */, - B919755B163AEA54009C397B /* BlenderModifier.h in Headers */, - B9197560163AEA54009C397B /* ConvertUTF.h in Headers */, - B9197561163AEA54009C397B /* CXMLReaderImpl.h in Headers */, - B9197562163AEA54009C397B /* heapsort.h in Headers */, - B9197563163AEA54009C397B /* irrArray.h in Headers */, - B9197564163AEA54009C397B /* irrString.h in Headers */, - B9197565163AEA54009C397B /* irrTypes.h in Headers */, - B9197566163AEA54009C397B /* irrXML.h in Headers */, - B9197567163AEA54009C397B /* crypt.h in Headers */, - B9197568163AEA54009C397B /* ioapi.h in Headers */, - B9197569163AEA54009C397B /* unzip.h in Headers */, - B919756A163AEA54009C397B /* anim.h in Headers */, - B919756B163AEA54009C397B /* camera.h in Headers */, - B919756C163AEA54009C397B /* cexport.h in Headers */, - B919756D163AEA54009C397B /* cfileio.h in Headers */, - B919756E163AEA54009C397B /* cimport.h in Headers */, - B919756F163AEA54009C397B /* color4.h in Headers */, - B9197570163AEA54009C397B /* poppack1.h in Headers */, - B9197571163AEA54009C397B /* pushpack1.h in Headers */, - B9197572163AEA54009C397B /* config.h in Headers */, - B9197573163AEA54009C397B /* DefaultLogger.hpp in Headers */, - B9197574163AEA54009C397B /* defs.h in Headers */, - B9197575163AEA54009C397B /* Exporter.hpp in Headers */, - B9197576163AEA54009C397B /* Importer.hpp in Headers */, - B9197577163AEA54009C397B /* importerdesc.h in Headers */, - B9197578163AEA54009C397B /* IOStream.hpp in Headers */, - B9197579163AEA54009C397B /* IOSystem.hpp in Headers */, - B919757A163AEA54009C397B /* light.h in Headers */, - B919757B163AEA54009C397B /* Logger.hpp in Headers */, - B919757C163AEA54009C397B /* LogStream.hpp in Headers */, - B919757D163AEA54009C397B /* material.h in Headers */, - B919757E163AEA54009C397B /* matrix3x3.h in Headers */, - B919757F163AEA54009C397B /* matrix4x4.h in Headers */, - B9197580163AEA54009C397B /* mesh.h in Headers */, - B9197581163AEA54009C397B /* NullLogger.hpp in Headers */, - B9197582163AEA54009C397B /* postprocess.h in Headers */, - B9197583163AEA54009C397B /* ProgressHandler.hpp in Headers */, - B9197584163AEA54009C397B /* quaternion.h in Headers */, - B9197585163AEA54009C397B /* scene.h in Headers */, - B9197586163AEA54009C397B /* texture.h in Headers */, - B9197587163AEA54009C397B /* types.h in Headers */, - B9197588163AEA54009C397B /* vector2.h in Headers */, - B9197589163AEA54009C397B /* vector3.h in Headers */, - B919758A163AEA54009C397B /* version.h in Headers */, - B919758B163AEA54009C397B /* OgreImporter.hpp in Headers */, - B919758C163AEA54009C397B /* OgreXmlHelper.hpp in Headers */, - B9197596163AEA54009C397B /* PlyExporter.h in Headers */, - B919759C163AEA54009C397B /* crc32.h in Headers */, - B919759D163AEA54009C397B /* deflate.h in Headers */, - B919759E163AEA54009C397B /* inffast.h in Headers */, - B919759F163AEA54009C397B /* inffixed.h in Headers */, - B91975A0163AEA54009C397B /* inflate.h in Headers */, - B91975A1163AEA54009C397B /* inftrees.h in Headers */, - B91975A2163AEA54009C397B /* trees.h in Headers */, - B91975A3163AEA54009C397B /* zconf.h in Headers */, - B91975A4163AEA54009C397B /* zconf.in.h in Headers */, - B91975A5163AEA54009C397B /* zlib.h in Headers */, - B91975A6163AEA54009C397B /* zutil.h in Headers */, - B91975A7163AEA54009C397B /* XGLLoader.h in Headers */, - B91975A8163AEA54009C397B /* clipper.hpp in Headers */, - B91975A9163AEA54009C397B /* shapes.h in Headers */, - B91975AA163AEA54009C397B /* utils.h in Headers */, - B91975AB163AEA54009C397B /* poly2tri.h in Headers */, - B91975AC163AEA54009C397B /* advancing_front.h in Headers */, - B91975AD163AEA54009C397B /* cdt.h in Headers */, - B91975AE163AEA54009C397B /* sweep.h in Headers */, - B91975AF163AEA54009C397B /* sweep_context.h in Headers */, - B91975B0163AEA54009C397B /* ai_assert.h in Headers */, - 2B7F46E11708365200A106A9 /* assbin_chunks.h in Headers */, - 2B7F47091708365200A106A9 /* BaseImporter.h in Headers */, - 2B7F47131708365200A106A9 /* BaseProcess.h in Headers */, - 2B7F474A1708365200A106A9 /* BlobIOSystem.h in Headers */, - 2B7F474F1708365200A106A9 /* foreach.hpp in Headers */, - 2B7F47541708365200A106A9 /* format.hpp in Headers */, - 2B7F47591708365200A106A9 /* lexical_cast.hpp in Headers */, - 2B7F475E1708365200A106A9 /* make_shared.hpp in Headers */, - 2B7F47631708365200A106A9 /* common_factor_rt.hpp in Headers */, - 2B7F47681708365200A106A9 /* noncopyable.hpp in Headers */, - 2B7F476D1708365200A106A9 /* pointer_cast.hpp in Headers */, - 2B7F47721708365200A106A9 /* scoped_array.hpp in Headers */, - 2B7F47771708365200A106A9 /* scoped_ptr.hpp in Headers */, - 2B7F477C1708365200A106A9 /* shared_array.hpp in Headers */, - 2B7F47811708365200A106A9 /* shared_ptr.hpp in Headers */, - 2B7F47861708365200A106A9 /* static_assert.hpp in Headers */, - 2B7F478B1708365200A106A9 /* timer.hpp in Headers */, - 2B7F47901708365200A106A9 /* tuple.hpp in Headers */, - 2B7F479F1708365200A106A9 /* ByteSwapper.h in Headers */, - 2B7F47A91708365200A106A9 /* CalcTangentsProcess.h in Headers */, - 2B7F47AE1708365200A106A9 /* CInterfaceIOWrapper.h in Headers */, - 2B7F47C71708365200A106A9 /* ColladaExporter.h in Headers */, - 2B7F47CC1708365200A106A9 /* ColladaHelper.h in Headers */, - 2B7F47D61708365200A106A9 /* ColladaLoader.h in Headers */, - 2B7F47E01708365200A106A9 /* ColladaParser.h in Headers */, - 2B7F47EA1708365200A106A9 /* ComputeUVMappingProcess.h in Headers */, - 2B7F47F41708365200A106A9 /* ConvertToLHProcess.h in Headers */, - 2B7F48081708365200A106A9 /* DeboneProcess.h in Headers */, - 2B7F48121708365200A106A9 /* DefaultIOStream.h in Headers */, - 2B7F481C1708365200A106A9 /* DefaultIOSystem.h in Headers */, - 2B7F48261708365200A106A9 /* DefaultProgressHandler.h in Headers */, - 2B7F483A1708365200A106A9 /* Exceptional.h in Headers */, - 2B7F48441708365200A106A9 /* fast_atof.h in Headers */, - 2B7F48531708365200A106A9 /* FBXCompileConfig.h in Headers */, - 2B7F485D1708365200A106A9 /* FBXConverter.h in Headers */, - 2B7F486C1708365200A106A9 /* FBXDocument.h in Headers */, - 2B7F48761708365200A106A9 /* FBXDocumentUtil.h in Headers */, - 2B7F48801708365200A106A9 /* FBXImporter.h in Headers */, - 2B7F48851708365200A106A9 /* FBXImportSettings.h in Headers */, - 2B7F48A31708365200A106A9 /* FBXParser.h in Headers */, - 2B7F48AD1708365200A106A9 /* FBXProperties.h in Headers */, - 2B7F48B71708365200A106A9 /* FBXTokenizer.h in Headers */, - 2B7F48C11708365200A106A9 /* FBXUtil.h in Headers */, - 2B7F48C61708365200A106A9 /* FileLogStream.h in Headers */, - 2B7F48CB1708365200A106A9 /* FileSystemFilter.h in Headers */, - 2B7F48D51708365200A106A9 /* FindDegenerates.h in Headers */, - 2B7F48DF1708365200A106A9 /* FindInstancesProcess.h in Headers */, - 2B7F48E91708365200A106A9 /* FindInvalidDataProcess.h in Headers */, - 2B7F48F31708365200A106A9 /* FixNormalsStep.h in Headers */, - 2B7F48F81708365200A106A9 /* GenericProperty.h in Headers */, - 2B7F49021708365200A106A9 /* GenFaceNormalsProcess.h in Headers */, - 2B7F490C1708365200A106A9 /* GenVertexNormalsProcess.h in Headers */, - 2B7F49161708365200A106A9 /* Hash.h in Headers */, - 2B7F493E1708365200A106A9 /* IFCLoader.h in Headers */, - 2B7F49571708365200A106A9 /* IFCReaderGen.h in Headers */, - 2B7F49611708365200A106A9 /* IFCUtil.h in Headers */, - 2B7F49661708365200A106A9 /* IFF.h in Headers */, - 2B7F49701708365200A106A9 /* Importer.h in Headers */, - 2B7F497F1708365200A106A9 /* ImproveCacheLocality.h in Headers */, - 2B7F49AC1708365200A106A9 /* JoinVerticesProcess.h in Headers */, - 2B7F49B61708365200A106A9 /* LimitBoneWeightsProcess.h in Headers */, - 2B7F49BB1708365200A106A9 /* LineSplitter.h in Headers */, - 2B7F49C01708365200A106A9 /* LogAux.h in Headers */, - 2B7F4A011708365200A106A9 /* MakeVerboseFormat.h in Headers */, - 2B7F4A0B1708365200A106A9 /* MaterialSystem.h in Headers */, - 2B7F4A331708365200A106A9 /* MD4FileData.h in Headers */, - 2B7F4A791708365200A106A9 /* MemoryIOWrapper.h in Headers */, - 2B7F4AA11708365200A106A9 /* ObjExporter.h in Headers */, - 2B7F4AA61708365200A106A9 /* ObjFileData.h in Headers */, - 2B7F4AB01708365200A106A9 /* ObjFileImporter.h in Headers */, - 2B7F4ABA1708365200A106A9 /* ObjFileMtlImporter.h in Headers */, - 2B7F4AC41708365200A106A9 /* ObjFileParser.h in Headers */, - 2B7F4AC91708365200A106A9 /* ObjTools.h in Headers */, - 2B7F4AFB1708365200A106A9 /* OptimizeGraph.h in Headers */, - 2B7F4B051708365200A106A9 /* OptimizeMeshes.h in Headers */, - 2B7F4B0A1708365200A106A9 /* ParsingUtils.h in Headers */, - 2B7F4B2D1708365200A106A9 /* PolyTools.h in Headers */, - 2B7F4B3C1708365200A106A9 /* PretransformVertices.h in Headers */, - 2B7F4B461708365200A106A9 /* ProcessHelper.h in Headers */, - 2B7F4B4B1708365200A106A9 /* Profiler.h in Headers */, - 2B7F4B501708365200A106A9 /* pstdint.h in Headers */, - 2B7F4B821708365200A106A9 /* qnan.h in Headers */, - 2B7F4B961708365200A106A9 /* RemoveComments.h in Headers */, - 2B7F4BA01708365200A106A9 /* RemoveRedundantMaterials.h in Headers */, - 2B7F4BAA1708365200A106A9 /* RemoveVCProcess.h in Headers */, - 2B7F4BB91708365200A106A9 /* SceneCombiner.h in Headers */, - 2B7F4BC31708365200A106A9 /* ScenePreprocessor.h in Headers */, - 2B7F4BC81708365200A106A9 /* ScenePrivate.h in Headers */, - 2B7F4BD21708365200A106A9 /* SGSpatialSort.h in Headers */, - 2B7F4BDC1708365200A106A9 /* SkeletonMeshBuilder.h in Headers */, - 2B7F4BEB1708365200A106A9 /* SmoothingGroups.h in Headers */, - 2B7F4BF51708365200A106A9 /* SortByPTypeProcess.h in Headers */, - 2B7F4BFF1708365200A106A9 /* SpatialSort.h in Headers */, - 2B7F4C091708365200A106A9 /* SplitByBoneCountProcess.h in Headers */, - 2B7F4C131708365200A106A9 /* SplitLargeMeshes.h in Headers */, - 2B7F4C1D1708365200A106A9 /* StandardShapes.h in Headers */, - 2B7F4C221708365200A106A9 /* StdOStreamLogStream.h in Headers */, - 2B7F4C271708365200A106A9 /* STEPFile.h in Headers */, - 2B7F4C311708365200A106A9 /* STEPFileEncoding.h in Headers */, - 2B7F4C3B1708365200A106A9 /* STEPFileReader.h in Headers */, - 2B7F4C451708365200A106A9 /* STLExporter.h in Headers */, - 2B7F4C4F1708365200A106A9 /* STLLoader.h in Headers */, - 2B7F4C541708365200A106A9 /* StreamReader.h in Headers */, - 2B7F4C591708365200A106A9 /* StringComparison.h in Headers */, - 2B7F4C631708365200A106A9 /* Subdivision.h in Headers */, - 2B7F4C6D1708365200A106A9 /* TargetAnimation.h in Headers */, - 2B7F4C811708365200A106A9 /* TextureTransform.h in Headers */, - 2B7F4C861708365200A106A9 /* TinyFormatter.h in Headers */, - 2B7F4C901708365200A106A9 /* TriangulateProcess.h in Headers */, - 2B7F4CA41708365200A106A9 /* ValidateDataStructure.h in Headers */, - 2B7F4CA91708365200A106A9 /* Vertex.h in Headers */, - 2B7F4CB31708365200A106A9 /* VertexTriangleAdjacency.h in Headers */, - 2B7F4CB81708365200A106A9 /* Win32DebugLogStream.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - D2AAC09905546B4700DB518D /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 3AF45AFB0E4B716800207D74 /* 3DSHelper.h in Headers */, - 3AF45AFD0E4B716800207D74 /* 3DSLoader.h in Headers */, - 3AF45B020E4B716800207D74 /* ASELoader.h in Headers */, - 3AF45B040E4B716800207D74 /* ASEParser.h in Headers */, - 3AF45B1B0E4B716800207D74 /* HalfLifeFileData.h in Headers */, - 3AF45B1E0E4B716800207D74 /* HMPLoader.h in Headers */, - 3AF45B2A0E4B716800207D74 /* MD2FileData.h in Headers */, - 3AF45B2C0E4B716800207D74 /* MD2Loader.h in Headers */, - 3AF45B2D0E4B716800207D74 /* MD2NormalTable.h in Headers */, - 3AF45B2E0E4B716800207D74 /* MD3FileData.h in Headers */, - 3AF45B300E4B716800207D74 /* MD3Loader.h in Headers */, - 3AF45B350E4B716800207D74 /* MD5Loader.h in Headers */, - 3AF45B370E4B716800207D74 /* MD5Parser.h in Headers */, - 3AF45B380E4B716800207D74 /* MDLDefaultColorMap.h in Headers */, - 3AF45B390E4B716800207D74 /* MDLFileData.h in Headers */, - 3AF45B3B0E4B716800207D74 /* MDLLoader.h in Headers */, - 3AF45B470E4B716800207D74 /* PlyLoader.h in Headers */, - 3AF45B490E4B716800207D74 /* PlyParser.h in Headers */, - 3AF45B530E4B716800207D74 /* SMDLoader.h in Headers */, - 3AF45B640E4B716800207D74 /* XFileHelper.h in Headers */, - 3AF45B660E4B716800207D74 /* XFileImporter.h in Headers */, - 3AF45B680E4B716800207D74 /* XFileParser.h in Headers */, - 3AB8A3AF0E50D67A00606590 /* MDCFileData.h in Headers */, - 3AB8A3B10E50D67A00606590 /* MDCLoader.h in Headers */, - 3AB8A3B20E50D67A00606590 /* MDCNormalTable.h in Headers */, - 3AB8A3BA0E50D6DB00606590 /* LWOFileData.h in Headers */, - 3AB8A3BC0E50D6DB00606590 /* LWOLoader.h in Headers */, - 3AB8A3C60E50D77900606590 /* HMPFileData.h in Headers */, - F90BAFD30F5DD87000124155 /* ACLoader.h in Headers */, - F90BAFE00F5DD90800124155 /* IRRLoader.h in Headers */, - F90BAFE20F5DD90800124155 /* IRRMeshLoader.h in Headers */, - F90BAFE40F5DD90800124155 /* IRRShared.h in Headers */, - F90BAFF70F5DD96100124155 /* NFFLoader.h in Headers */, - F90BB0090F5DD9DD00124155 /* Q3DLoader.h in Headers */, - F90BB00E0F5DD9F400124155 /* BVHLoader.h in Headers */, - F90BB0150F5DDA1400124155 /* OFFLoader.h in Headers */, - F90BB01D0F5DDA4400124155 /* RawLoader.h in Headers */, - F90BB0230F5DDA5700124155 /* DXFLoader.h in Headers */, - F90BB0310F5DDAB500124155 /* TerragenLoader.h in Headers */, - F90BB0370F5DDB1B00124155 /* irrXMLWrapper.h in Headers */, - F90BB0890F5DDE0700124155 /* B3DImporter.h in Headers */, - 7411B15511416D5E00BCD793 /* CSMLoader.h in Headers */, - 7411B16011416DDD00BCD793 /* LWSLoader.h in Headers */, - 7411B16A11416DF400BCD793 /* LWOAnimation.h in Headers */, - 7411B17711416E2500BCD793 /* MS3DLoader.h in Headers */, - 7411B19211416EBC00BCD793 /* UnrealLoader.h in Headers */, - 74C9BB5211ACBB1000AF885C /* BlenderDNA.h in Headers */, - 74C9BB5411ACBB1000AF885C /* BlenderLoader.h in Headers */, - 74C9BB5611ACBB1000AF885C /* BlenderScene.h in Headers */, - 74C9BB5711ACBB1000AF885C /* BlenderSceneGen.h in Headers */, - 74C9BB8D11ACBB9900AF885C /* AssimpPCH.h in Headers */, - 74C9BB9D11ACBBBC00AF885C /* COBLoader.h in Headers */, - 74C9BB9E11ACBBBC00AF885C /* COBScene.h in Headers */, - 74C9BBB611ACBC2600AF885C /* revision.h in Headers */, - 8E7ABBAF127E0F1A00512ED1 /* Q3BSPFileData.h in Headers */, - 8E7ABBB1127E0F1A00512ED1 /* Q3BSPFileImporter.h in Headers */, - 8E7ABBB3127E0F1A00512ED1 /* Q3BSPFileParser.h in Headers */, - 8E7ABBB5127E0F1A00512ED1 /* Q3BSPZipArchive.h in Headers */, - 8E7ABBC9127E0F2A00512ED1 /* NDOLoader.h in Headers */, - 8E7ABBD4127E0F3800512ED1 /* BlenderIntermediate.h in Headers */, - 8E7ABBD6127E0F3800512ED1 /* BlenderModifier.h in Headers */, - 8E8DEE6B127E2B78005EF64D /* ConvertUTF.h in Headers */, - 8E8DEE6C127E2B78005EF64D /* CXMLReaderImpl.h in Headers */, - 8E8DEE6D127E2B78005EF64D /* heapsort.h in Headers */, - 8E8DEE6E127E2B78005EF64D /* irrArray.h in Headers */, - 8E8DEE6F127E2B78005EF64D /* irrString.h in Headers */, - 8E8DEE70127E2B78005EF64D /* irrTypes.h in Headers */, - 8E8DEE72127E2B78005EF64D /* irrXML.h in Headers */, - 8E8DEE73127E2B78005EF64D /* crypt.h in Headers */, - 8E8DEE75127E2B78005EF64D /* ioapi.h in Headers */, - 8E8DEE77127E2B78005EF64D /* unzip.h in Headers */, - F9BA8B9F1543268400E63FFE /* anim.h in Headers */, - F9BA8BA11543268400E63FFE /* camera.h in Headers */, - F9BA8BA21543268400E63FFE /* cexport.h in Headers */, - F9BA8BA31543268400E63FFE /* cfileio.h in Headers */, - F9BA8BA41543268400E63FFE /* cimport.h in Headers */, - F9BA8BA51543268400E63FFE /* color4.h in Headers */, - F9BA8BA61543268400E63FFE /* poppack1.h in Headers */, - F9BA8BA71543268400E63FFE /* pushpack1.h in Headers */, - F9BA8BA81543268400E63FFE /* config.h in Headers */, - F9BA8BA91543268400E63FFE /* DefaultLogger.hpp in Headers */, - F9BA8BAA1543268400E63FFE /* defs.h in Headers */, - F9BA8BAB1543268400E63FFE /* Exporter.hpp in Headers */, - F9BA8BAC1543268400E63FFE /* Importer.hpp in Headers */, - F9BA8BAD1543268400E63FFE /* importerdesc.h in Headers */, - F9BA8BAE1543268400E63FFE /* IOStream.hpp in Headers */, - F9BA8BAF1543268400E63FFE /* IOSystem.hpp in Headers */, - F9BA8BB01543268400E63FFE /* light.h in Headers */, - F9BA8BB11543268400E63FFE /* Logger.hpp in Headers */, - F9BA8BB21543268400E63FFE /* LogStream.hpp in Headers */, - F9BA8BB31543268400E63FFE /* material.h in Headers */, - F9BA8BB41543268400E63FFE /* matrix3x3.h in Headers */, - F9BA8BB51543268400E63FFE /* matrix4x4.h in Headers */, - F9BA8BB61543268400E63FFE /* mesh.h in Headers */, - F9BA8BB71543268400E63FFE /* NullLogger.hpp in Headers */, - F9BA8BB81543268400E63FFE /* postprocess.h in Headers */, - F9BA8BB91543268400E63FFE /* ProgressHandler.hpp in Headers */, - F9BA8BBA1543268400E63FFE /* quaternion.h in Headers */, - F9BA8BBB1543268400E63FFE /* scene.h in Headers */, - F9BA8BBC1543268400E63FFE /* texture.h in Headers */, - F9BA8BBD1543268400E63FFE /* types.h in Headers */, - F9BA8BBE1543268400E63FFE /* vector2.h in Headers */, - F9BA8BBF1543268400E63FFE /* vector3.h in Headers */, - F9BA8BC01543268400E63FFE /* version.h in Headers */, - F9BA8C3C154328B600E63FFE /* OgreImporter.hpp in Headers */, - F9BA8C40154328B600E63FFE /* OgreXmlHelper.hpp in Headers */, - F99A9F3315436269000682F3 /* PlyExporter.h in Headers */, - F9607060154366AB004D91DD /* crc32.h in Headers */, - F9607062154366AB004D91DD /* deflate.h in Headers */, - F9607064154366AB004D91DD /* inffast.h in Headers */, - F9607065154366AB004D91DD /* inffixed.h in Headers */, - F9607067154366AB004D91DD /* inflate.h in Headers */, - F9607069154366AB004D91DD /* inftrees.h in Headers */, - F960706B154366AB004D91DD /* trees.h in Headers */, - F960706C154366AB004D91DD /* zconf.h in Headers */, - F960706D154366AB004D91DD /* zconf.in.h in Headers */, - F960706E154366AB004D91DD /* zlib.h in Headers */, - F9607070154366AB004D91DD /* zutil.h in Headers */, - F96070B8154366ED004D91DD /* XGLLoader.h in Headers */, - F96070C91543673B004D91DD /* clipper.hpp in Headers */, - F96070E01543675E004D91DD /* shapes.h in Headers */, - F96070E11543675E004D91DD /* utils.h in Headers */, - F96070E21543675E004D91DD /* poly2tri.h in Headers */, - F96070E41543675E004D91DD /* advancing_front.h in Headers */, - F96070E61543675E004D91DD /* cdt.h in Headers */, - F96070E81543675E004D91DD /* sweep.h in Headers */, - F96070EA1543675E004D91DD /* sweep_context.h in Headers */, - F97BA03615439DB3009EB9DD /* ai_assert.h in Headers */, - 2B7F46DD1708365200A106A9 /* assbin_chunks.h in Headers */, - 2B7F47051708365200A106A9 /* BaseImporter.h in Headers */, - 2B7F470F1708365200A106A9 /* BaseProcess.h in Headers */, - 2B7F47461708365200A106A9 /* BlobIOSystem.h in Headers */, - 2B7F474B1708365200A106A9 /* foreach.hpp in Headers */, - 2B7F47501708365200A106A9 /* format.hpp in Headers */, - 2B7F47551708365200A106A9 /* lexical_cast.hpp in Headers */, - 2B7F475A1708365200A106A9 /* make_shared.hpp in Headers */, - 2B7F475F1708365200A106A9 /* common_factor_rt.hpp in Headers */, - 2B7F47641708365200A106A9 /* noncopyable.hpp in Headers */, - 2B7F47691708365200A106A9 /* pointer_cast.hpp in Headers */, - 2B7F476E1708365200A106A9 /* scoped_array.hpp in Headers */, - 2B7F47731708365200A106A9 /* scoped_ptr.hpp in Headers */, - 2B7F47781708365200A106A9 /* shared_array.hpp in Headers */, - 2B7F477D1708365200A106A9 /* shared_ptr.hpp in Headers */, - 2B7F47821708365200A106A9 /* static_assert.hpp in Headers */, - 2B7F47871708365200A106A9 /* timer.hpp in Headers */, - 2B7F478C1708365200A106A9 /* tuple.hpp in Headers */, - 2B7F479B1708365200A106A9 /* ByteSwapper.h in Headers */, - 2B7F47A51708365200A106A9 /* CalcTangentsProcess.h in Headers */, - 2B7F47AA1708365200A106A9 /* CInterfaceIOWrapper.h in Headers */, - 2B7F47C31708365200A106A9 /* ColladaExporter.h in Headers */, - 2B7F47C81708365200A106A9 /* ColladaHelper.h in Headers */, - 2B7F47D21708365200A106A9 /* ColladaLoader.h in Headers */, - 2B7F47DC1708365200A106A9 /* ColladaParser.h in Headers */, - 2B7F47E61708365200A106A9 /* ComputeUVMappingProcess.h in Headers */, - 2B7F47F01708365200A106A9 /* ConvertToLHProcess.h in Headers */, - 2B7F48041708365200A106A9 /* DeboneProcess.h in Headers */, - 2B7F480E1708365200A106A9 /* DefaultIOStream.h in Headers */, - 2B7F48181708365200A106A9 /* DefaultIOSystem.h in Headers */, - 2B7F48221708365200A106A9 /* DefaultProgressHandler.h in Headers */, - 2B7F48361708365200A106A9 /* Exceptional.h in Headers */, - 2B7F48401708365200A106A9 /* fast_atof.h in Headers */, - 2B7F484F1708365200A106A9 /* FBXCompileConfig.h in Headers */, - 2B7F48591708365200A106A9 /* FBXConverter.h in Headers */, - 2B7F48681708365200A106A9 /* FBXDocument.h in Headers */, - 2B7F48721708365200A106A9 /* FBXDocumentUtil.h in Headers */, - 2B7F487C1708365200A106A9 /* FBXImporter.h in Headers */, - 2B7F48811708365200A106A9 /* FBXImportSettings.h in Headers */, - 2B7F489F1708365200A106A9 /* FBXParser.h in Headers */, - 2B7F48A91708365200A106A9 /* FBXProperties.h in Headers */, - 2B7F48B31708365200A106A9 /* FBXTokenizer.h in Headers */, - 2B7F48BD1708365200A106A9 /* FBXUtil.h in Headers */, - 2B7F48C21708365200A106A9 /* FileLogStream.h in Headers */, - 2B7F48C71708365200A106A9 /* FileSystemFilter.h in Headers */, - 2B7F48D11708365200A106A9 /* FindDegenerates.h in Headers */, - 2B7F48DB1708365200A106A9 /* FindInstancesProcess.h in Headers */, - 2B7F48E51708365200A106A9 /* FindInvalidDataProcess.h in Headers */, - 2B7F48EF1708365200A106A9 /* FixNormalsStep.h in Headers */, - 2B7F48F41708365200A106A9 /* GenericProperty.h in Headers */, - 2B7F48FE1708365200A106A9 /* GenFaceNormalsProcess.h in Headers */, - 2B7F49081708365200A106A9 /* GenVertexNormalsProcess.h in Headers */, - 2B7F49121708365200A106A9 /* Hash.h in Headers */, - 2B7F493A1708365200A106A9 /* IFCLoader.h in Headers */, - 2B7F49531708365200A106A9 /* IFCReaderGen.h in Headers */, - 2B7F495D1708365200A106A9 /* IFCUtil.h in Headers */, - 2B7F49621708365200A106A9 /* IFF.h in Headers */, - 2B7F496C1708365200A106A9 /* Importer.h in Headers */, - 2B7F497B1708365200A106A9 /* ImproveCacheLocality.h in Headers */, - 2B7F49A81708365200A106A9 /* JoinVerticesProcess.h in Headers */, - 2B7F49B21708365200A106A9 /* LimitBoneWeightsProcess.h in Headers */, - 2B7F49B71708365200A106A9 /* LineSplitter.h in Headers */, - 2B7F49BC1708365200A106A9 /* LogAux.h in Headers */, - 2B7F49FD1708365200A106A9 /* MakeVerboseFormat.h in Headers */, - 2B7F4A071708365200A106A9 /* MaterialSystem.h in Headers */, - 2B7F4A2F1708365200A106A9 /* MD4FileData.h in Headers */, - 2B7F4A751708365200A106A9 /* MemoryIOWrapper.h in Headers */, - 2B7F4A9D1708365200A106A9 /* ObjExporter.h in Headers */, - 2B7F4AA21708365200A106A9 /* ObjFileData.h in Headers */, - 2B7F4AAC1708365200A106A9 /* ObjFileImporter.h in Headers */, - 2B7F4AB61708365200A106A9 /* ObjFileMtlImporter.h in Headers */, - 2B7F4AC01708365200A106A9 /* ObjFileParser.h in Headers */, - 2B7F4AC51708365200A106A9 /* ObjTools.h in Headers */, - 2B7F4AF71708365200A106A9 /* OptimizeGraph.h in Headers */, - 2B7F4B011708365200A106A9 /* OptimizeMeshes.h in Headers */, - 2B7F4B061708365200A106A9 /* ParsingUtils.h in Headers */, - 2B7F4B291708365200A106A9 /* PolyTools.h in Headers */, - 2B7F4B381708365200A106A9 /* PretransformVertices.h in Headers */, - 2B7F4B421708365200A106A9 /* ProcessHelper.h in Headers */, - 2B7F4B471708365200A106A9 /* Profiler.h in Headers */, - 2B7F4B4C1708365200A106A9 /* pstdint.h in Headers */, - 2B7F4B7E1708365200A106A9 /* qnan.h in Headers */, - 2B7F4B921708365200A106A9 /* RemoveComments.h in Headers */, - 2B7F4B9C1708365200A106A9 /* RemoveRedundantMaterials.h in Headers */, - 2B7F4BA61708365200A106A9 /* RemoveVCProcess.h in Headers */, - 2B7F4BB51708365200A106A9 /* SceneCombiner.h in Headers */, - 2B7F4BBF1708365200A106A9 /* ScenePreprocessor.h in Headers */, - 2B7F4BC41708365200A106A9 /* ScenePrivate.h in Headers */, - 2B7F4BCE1708365200A106A9 /* SGSpatialSort.h in Headers */, - 2B7F4BD81708365200A106A9 /* SkeletonMeshBuilder.h in Headers */, - 2B7F4BE71708365200A106A9 /* SmoothingGroups.h in Headers */, - 2B7F4BF11708365200A106A9 /* SortByPTypeProcess.h in Headers */, - 2B7F4BFB1708365200A106A9 /* SpatialSort.h in Headers */, - 2B7F4C051708365200A106A9 /* SplitByBoneCountProcess.h in Headers */, - 2B7F4C0F1708365200A106A9 /* SplitLargeMeshes.h in Headers */, - 2B7F4C191708365200A106A9 /* StandardShapes.h in Headers */, - 2B7F4C1E1708365200A106A9 /* StdOStreamLogStream.h in Headers */, - 2B7F4C231708365200A106A9 /* STEPFile.h in Headers */, - 2B7F4C2D1708365200A106A9 /* STEPFileEncoding.h in Headers */, - 2B7F4C371708365200A106A9 /* STEPFileReader.h in Headers */, - 2B7F4C411708365200A106A9 /* STLExporter.h in Headers */, - 2B7F4C4B1708365200A106A9 /* STLLoader.h in Headers */, - 2B7F4C501708365200A106A9 /* StreamReader.h in Headers */, - 2B7F4C551708365200A106A9 /* StringComparison.h in Headers */, - 2B7F4C5F1708365200A106A9 /* Subdivision.h in Headers */, - 2B7F4C691708365200A106A9 /* TargetAnimation.h in Headers */, - 2B7F4C7D1708365200A106A9 /* TextureTransform.h in Headers */, - 2B7F4C821708365200A106A9 /* TinyFormatter.h in Headers */, - 2B7F4C8C1708365200A106A9 /* TriangulateProcess.h in Headers */, - 2B7F4CA01708365200A106A9 /* ValidateDataStructure.h in Headers */, - 2B7F4CA51708365200A106A9 /* Vertex.h in Headers */, - 2B7F4CAF1708365200A106A9 /* VertexTriangleAdjacency.h in Headers */, - 2B7F4CB41708365200A106A9 /* Win32DebugLogStream.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - F962E8800F5DE66A009A5495 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - F962E8ED0F5DE6E2009A5495 /* 3DSHelper.h in Headers */, - F962E8EE0F5DE6E2009A5495 /* 3DSLoader.h in Headers */, - F962E8EF0F5DE6E2009A5495 /* ASELoader.h in Headers */, - F962E8F00F5DE6E2009A5495 /* ASEParser.h in Headers */, - F962E8FD0F5DE6E2009A5495 /* HalfLifeFileData.h in Headers */, - F962E8FE0F5DE6E2009A5495 /* HMPLoader.h in Headers */, - F962E9030F5DE6E2009A5495 /* MD2FileData.h in Headers */, - F962E9040F5DE6E2009A5495 /* MD2Loader.h in Headers */, - F962E9050F5DE6E2009A5495 /* MD2NormalTable.h in Headers */, - F962E9060F5DE6E2009A5495 /* MD3FileData.h in Headers */, - F962E9070F5DE6E2009A5495 /* MD3Loader.h in Headers */, - F962E9080F5DE6E2009A5495 /* MD5Loader.h in Headers */, - F962E9090F5DE6E2009A5495 /* MD5Parser.h in Headers */, - F962E90A0F5DE6E2009A5495 /* MDLDefaultColorMap.h in Headers */, - F962E90B0F5DE6E2009A5495 /* MDLFileData.h in Headers */, - F962E90C0F5DE6E2009A5495 /* MDLLoader.h in Headers */, - F962E9130F5DE6E2009A5495 /* PlyLoader.h in Headers */, - F962E9140F5DE6E2009A5495 /* PlyParser.h in Headers */, - F962E9190F5DE6E2009A5495 /* SMDLoader.h in Headers */, - F962E9230F5DE6E2009A5495 /* XFileHelper.h in Headers */, - F962E9240F5DE6E2009A5495 /* XFileImporter.h in Headers */, - F962E9250F5DE6E2009A5495 /* XFileParser.h in Headers */, - F962E9280F5DE6E2009A5495 /* MDCFileData.h in Headers */, - F962E9290F5DE6E2009A5495 /* MDCLoader.h in Headers */, - F962E92A0F5DE6E2009A5495 /* MDCNormalTable.h in Headers */, - F962E92C0F5DE6E2009A5495 /* LWOFileData.h in Headers */, - F962E92D0F5DE6E2009A5495 /* LWOLoader.h in Headers */, - F962E92E0F5DE6E2009A5495 /* HMPFileData.h in Headers */, - F962E9360F5DE6E2009A5495 /* ACLoader.h in Headers */, - F962E9370F5DE6E2009A5495 /* IRRLoader.h in Headers */, - F962E9380F5DE6E2009A5495 /* IRRMeshLoader.h in Headers */, - F962E9390F5DE6E2009A5495 /* IRRShared.h in Headers */, - F962E93D0F5DE6E2009A5495 /* NFFLoader.h in Headers */, - F962E93F0F5DE6E2009A5495 /* Q3DLoader.h in Headers */, - F962E9400F5DE6E2009A5495 /* BVHLoader.h in Headers */, - F962E9410F5DE6E2009A5495 /* OFFLoader.h in Headers */, - F962E9420F5DE6E2009A5495 /* RawLoader.h in Headers */, - F962E9430F5DE6E2009A5495 /* DXFLoader.h in Headers */, - F962E9440F5DE6E2009A5495 /* TerragenLoader.h in Headers */, - F962E9450F5DE6E2009A5495 /* irrXMLWrapper.h in Headers */, - F962E9570F5DE6E2009A5495 /* B3DImporter.h in Headers */, - 7411B15711416D5E00BCD793 /* CSMLoader.h in Headers */, - 7411B16211416DDD00BCD793 /* LWSLoader.h in Headers */, - 7411B16C11416DF400BCD793 /* LWOAnimation.h in Headers */, - 7411B17911416E2500BCD793 /* MS3DLoader.h in Headers */, - 7411B19411416EBC00BCD793 /* UnrealLoader.h in Headers */, - 74C9BB5911ACBB1000AF885C /* BlenderDNA.h in Headers */, - 74C9BB5B11ACBB1000AF885C /* BlenderLoader.h in Headers */, - 74C9BB5D11ACBB1000AF885C /* BlenderScene.h in Headers */, - 74C9BB5E11ACBB1000AF885C /* BlenderSceneGen.h in Headers */, - 74C9BB8F11ACBB9900AF885C /* AssimpPCH.h in Headers */, - 74C9BBA011ACBBBC00AF885C /* COBLoader.h in Headers */, - 74C9BBA111ACBBBC00AF885C /* COBScene.h in Headers */, - 74C9BBB711ACBC2600AF885C /* revision.h in Headers */, - 8E7ABBB6127E0F1A00512ED1 /* Q3BSPFileData.h in Headers */, - 8E7ABBB8127E0F1A00512ED1 /* Q3BSPFileImporter.h in Headers */, - 8E7ABBBA127E0F1A00512ED1 /* Q3BSPFileParser.h in Headers */, - 8E7ABBBC127E0F1A00512ED1 /* Q3BSPZipArchive.h in Headers */, - 8E7ABBCB127E0F2A00512ED1 /* NDOLoader.h in Headers */, - 8E7ABBD7127E0F3800512ED1 /* BlenderIntermediate.h in Headers */, - 8E7ABBD9127E0F3800512ED1 /* BlenderModifier.h in Headers */, - 8E8DEE79127E2B78005EF64D /* ConvertUTF.h in Headers */, - 8E8DEE7A127E2B78005EF64D /* CXMLReaderImpl.h in Headers */, - 8E8DEE7B127E2B78005EF64D /* heapsort.h in Headers */, - 8E8DEE7C127E2B78005EF64D /* irrArray.h in Headers */, - 8E8DEE7D127E2B78005EF64D /* irrString.h in Headers */, - 8E8DEE7E127E2B78005EF64D /* irrTypes.h in Headers */, - 8E8DEE80127E2B78005EF64D /* irrXML.h in Headers */, - 8E8DEE81127E2B78005EF64D /* crypt.h in Headers */, - 8E8DEE83127E2B78005EF64D /* ioapi.h in Headers */, - 8E8DEE85127E2B78005EF64D /* unzip.h in Headers */, - F9BA8BC11543268400E63FFE /* anim.h in Headers */, - F9BA8BC31543268400E63FFE /* camera.h in Headers */, - F9BA8BC41543268400E63FFE /* cexport.h in Headers */, - F9BA8BC51543268400E63FFE /* cfileio.h in Headers */, - F9BA8BC61543268400E63FFE /* cimport.h in Headers */, - F9BA8BC71543268400E63FFE /* color4.h in Headers */, - F9BA8BC81543268400E63FFE /* poppack1.h in Headers */, - F9BA8BC91543268400E63FFE /* pushpack1.h in Headers */, - F9BA8BCA1543268400E63FFE /* config.h in Headers */, - F9BA8BCB1543268400E63FFE /* DefaultLogger.hpp in Headers */, - F9BA8BCC1543268400E63FFE /* defs.h in Headers */, - F9BA8BCD1543268400E63FFE /* Exporter.hpp in Headers */, - F9BA8BCE1543268400E63FFE /* Importer.hpp in Headers */, - F9BA8BCF1543268400E63FFE /* importerdesc.h in Headers */, - F9BA8BD01543268400E63FFE /* IOStream.hpp in Headers */, - F9BA8BD11543268400E63FFE /* IOSystem.hpp in Headers */, - F9BA8BD21543268400E63FFE /* light.h in Headers */, - F9BA8BD31543268400E63FFE /* Logger.hpp in Headers */, - F9BA8BD41543268400E63FFE /* LogStream.hpp in Headers */, - F9BA8BD51543268400E63FFE /* material.h in Headers */, - F9BA8BD61543268400E63FFE /* matrix3x3.h in Headers */, - F9BA8BD71543268400E63FFE /* matrix4x4.h in Headers */, - F9BA8BD81543268400E63FFE /* mesh.h in Headers */, - F9BA8BD91543268400E63FFE /* NullLogger.hpp in Headers */, - F9BA8BDA1543268400E63FFE /* postprocess.h in Headers */, - F9BA8BDB1543268400E63FFE /* ProgressHandler.hpp in Headers */, - F9BA8BDC1543268400E63FFE /* quaternion.h in Headers */, - F9BA8BDD1543268400E63FFE /* scene.h in Headers */, - F9BA8BDE1543268400E63FFE /* texture.h in Headers */, - F9BA8BDF1543268400E63FFE /* types.h in Headers */, - F9BA8BE01543268400E63FFE /* vector2.h in Headers */, - F9BA8BE11543268400E63FFE /* vector3.h in Headers */, - F9BA8BE21543268400E63FFE /* version.h in Headers */, - F9BA8C42154328B600E63FFE /* OgreImporter.hpp in Headers */, - F9BA8C46154328B600E63FFE /* OgreXmlHelper.hpp in Headers */, - F99A9F3515436269000682F3 /* PlyExporter.h in Headers */, - F9607074154366AB004D91DD /* crc32.h in Headers */, - F9607076154366AB004D91DD /* deflate.h in Headers */, - F9607078154366AB004D91DD /* inffast.h in Headers */, - F9607079154366AB004D91DD /* inffixed.h in Headers */, - F960707B154366AB004D91DD /* inflate.h in Headers */, - F960707D154366AB004D91DD /* inftrees.h in Headers */, - F960707F154366AB004D91DD /* trees.h in Headers */, - F9607080154366AB004D91DD /* zconf.h in Headers */, - F9607081154366AB004D91DD /* zconf.in.h in Headers */, - F9607082154366AB004D91DD /* zlib.h in Headers */, - F9607084154366AB004D91DD /* zutil.h in Headers */, - F96070BA154366ED004D91DD /* XGLLoader.h in Headers */, - F96070CB1543673B004D91DD /* clipper.hpp in Headers */, - F96070EC1543675E004D91DD /* shapes.h in Headers */, - F96070ED1543675E004D91DD /* utils.h in Headers */, - F96070EE1543675E004D91DD /* poly2tri.h in Headers */, - F96070F01543675E004D91DD /* advancing_front.h in Headers */, - F96070F21543675E004D91DD /* cdt.h in Headers */, - F96070F41543675E004D91DD /* sweep.h in Headers */, - F96070F61543675E004D91DD /* sweep_context.h in Headers */, - F97BA03715439DB3009EB9DD /* ai_assert.h in Headers */, - 2B7F46DE1708365200A106A9 /* assbin_chunks.h in Headers */, - 2B7F47061708365200A106A9 /* BaseImporter.h in Headers */, - 2B7F47101708365200A106A9 /* BaseProcess.h in Headers */, - 2B7F47471708365200A106A9 /* BlobIOSystem.h in Headers */, - 2B7F474C1708365200A106A9 /* foreach.hpp in Headers */, - 2B7F47511708365200A106A9 /* format.hpp in Headers */, - 2B7F47561708365200A106A9 /* lexical_cast.hpp in Headers */, - 2B7F475B1708365200A106A9 /* make_shared.hpp in Headers */, - 2B7F47601708365200A106A9 /* common_factor_rt.hpp in Headers */, - 2B7F47651708365200A106A9 /* noncopyable.hpp in Headers */, - 2B7F476A1708365200A106A9 /* pointer_cast.hpp in Headers */, - 2B7F476F1708365200A106A9 /* scoped_array.hpp in Headers */, - 2B7F47741708365200A106A9 /* scoped_ptr.hpp in Headers */, - 2B7F47791708365200A106A9 /* shared_array.hpp in Headers */, - 2B7F477E1708365200A106A9 /* shared_ptr.hpp in Headers */, - 2B7F47831708365200A106A9 /* static_assert.hpp in Headers */, - 2B7F47881708365200A106A9 /* timer.hpp in Headers */, - 2B7F478D1708365200A106A9 /* tuple.hpp in Headers */, - 2B7F479C1708365200A106A9 /* ByteSwapper.h in Headers */, - 2B7F47A61708365200A106A9 /* CalcTangentsProcess.h in Headers */, - 2B7F47AB1708365200A106A9 /* CInterfaceIOWrapper.h in Headers */, - 2B7F47C41708365200A106A9 /* ColladaExporter.h in Headers */, - 2B7F47C91708365200A106A9 /* ColladaHelper.h in Headers */, - 2B7F47D31708365200A106A9 /* ColladaLoader.h in Headers */, - 2B7F47DD1708365200A106A9 /* ColladaParser.h in Headers */, - 2B7F47E71708365200A106A9 /* ComputeUVMappingProcess.h in Headers */, - 2B7F47F11708365200A106A9 /* ConvertToLHProcess.h in Headers */, - 2B7F48051708365200A106A9 /* DeboneProcess.h in Headers */, - 2B7F480F1708365200A106A9 /* DefaultIOStream.h in Headers */, - 2B7F48191708365200A106A9 /* DefaultIOSystem.h in Headers */, - 2B7F48231708365200A106A9 /* DefaultProgressHandler.h in Headers */, - 2B7F48371708365200A106A9 /* Exceptional.h in Headers */, - 2B7F48411708365200A106A9 /* fast_atof.h in Headers */, - 2B7F48501708365200A106A9 /* FBXCompileConfig.h in Headers */, - 2B7F485A1708365200A106A9 /* FBXConverter.h in Headers */, - 2B7F48691708365200A106A9 /* FBXDocument.h in Headers */, - 2B7F48731708365200A106A9 /* FBXDocumentUtil.h in Headers */, - 2B7F487D1708365200A106A9 /* FBXImporter.h in Headers */, - 2B7F48821708365200A106A9 /* FBXImportSettings.h in Headers */, - 2B7F48A01708365200A106A9 /* FBXParser.h in Headers */, - 2B7F48AA1708365200A106A9 /* FBXProperties.h in Headers */, - 2B7F48B41708365200A106A9 /* FBXTokenizer.h in Headers */, - 2B7F48BE1708365200A106A9 /* FBXUtil.h in Headers */, - 2B7F48C31708365200A106A9 /* FileLogStream.h in Headers */, - 2B7F48C81708365200A106A9 /* FileSystemFilter.h in Headers */, - 2B7F48D21708365200A106A9 /* FindDegenerates.h in Headers */, - 2B7F48DC1708365200A106A9 /* FindInstancesProcess.h in Headers */, - 2B7F48E61708365200A106A9 /* FindInvalidDataProcess.h in Headers */, - 2B7F48F01708365200A106A9 /* FixNormalsStep.h in Headers */, - 2B7F48F51708365200A106A9 /* GenericProperty.h in Headers */, - 2B7F48FF1708365200A106A9 /* GenFaceNormalsProcess.h in Headers */, - 2B7F49091708365200A106A9 /* GenVertexNormalsProcess.h in Headers */, - 2B7F49131708365200A106A9 /* Hash.h in Headers */, - 2B7F493B1708365200A106A9 /* IFCLoader.h in Headers */, - 2B7F49541708365200A106A9 /* IFCReaderGen.h in Headers */, - 2B7F495E1708365200A106A9 /* IFCUtil.h in Headers */, - 2B7F49631708365200A106A9 /* IFF.h in Headers */, - 2B7F496D1708365200A106A9 /* Importer.h in Headers */, - 2B7F497C1708365200A106A9 /* ImproveCacheLocality.h in Headers */, - 2B7F49A91708365200A106A9 /* JoinVerticesProcess.h in Headers */, - 2B7F49B31708365200A106A9 /* LimitBoneWeightsProcess.h in Headers */, - 2B7F49B81708365200A106A9 /* LineSplitter.h in Headers */, - 2B7F49BD1708365200A106A9 /* LogAux.h in Headers */, - 2B7F49FE1708365200A106A9 /* MakeVerboseFormat.h in Headers */, - 2B7F4A081708365200A106A9 /* MaterialSystem.h in Headers */, - 2B7F4A301708365200A106A9 /* MD4FileData.h in Headers */, - 2B7F4A761708365200A106A9 /* MemoryIOWrapper.h in Headers */, - 2B7F4A9E1708365200A106A9 /* ObjExporter.h in Headers */, - 2B7F4AA31708365200A106A9 /* ObjFileData.h in Headers */, - 2B7F4AAD1708365200A106A9 /* ObjFileImporter.h in Headers */, - 2B7F4AB71708365200A106A9 /* ObjFileMtlImporter.h in Headers */, - 2B7F4AC11708365200A106A9 /* ObjFileParser.h in Headers */, - 2B7F4AC61708365200A106A9 /* ObjTools.h in Headers */, - 2B7F4AF81708365200A106A9 /* OptimizeGraph.h in Headers */, - 2B7F4B021708365200A106A9 /* OptimizeMeshes.h in Headers */, - 2B7F4B071708365200A106A9 /* ParsingUtils.h in Headers */, - 2B7F4B2A1708365200A106A9 /* PolyTools.h in Headers */, - 2B7F4B391708365200A106A9 /* PretransformVertices.h in Headers */, - 2B7F4B431708365200A106A9 /* ProcessHelper.h in Headers */, - 2B7F4B481708365200A106A9 /* Profiler.h in Headers */, - 2B7F4B4D1708365200A106A9 /* pstdint.h in Headers */, - 2B7F4B7F1708365200A106A9 /* qnan.h in Headers */, - 2B7F4B931708365200A106A9 /* RemoveComments.h in Headers */, - 2B7F4B9D1708365200A106A9 /* RemoveRedundantMaterials.h in Headers */, - 2B7F4BA71708365200A106A9 /* RemoveVCProcess.h in Headers */, - 2B7F4BB61708365200A106A9 /* SceneCombiner.h in Headers */, - 2B7F4BC01708365200A106A9 /* ScenePreprocessor.h in Headers */, - 2B7F4BC51708365200A106A9 /* ScenePrivate.h in Headers */, - 2B7F4BCF1708365200A106A9 /* SGSpatialSort.h in Headers */, - 2B7F4BD91708365200A106A9 /* SkeletonMeshBuilder.h in Headers */, - 2B7F4BE81708365200A106A9 /* SmoothingGroups.h in Headers */, - 2B7F4BF21708365200A106A9 /* SortByPTypeProcess.h in Headers */, - 2B7F4BFC1708365200A106A9 /* SpatialSort.h in Headers */, - 2B7F4C061708365200A106A9 /* SplitByBoneCountProcess.h in Headers */, - 2B7F4C101708365200A106A9 /* SplitLargeMeshes.h in Headers */, - 2B7F4C1A1708365200A106A9 /* StandardShapes.h in Headers */, - 2B7F4C1F1708365200A106A9 /* StdOStreamLogStream.h in Headers */, - 2B7F4C241708365200A106A9 /* STEPFile.h in Headers */, - 2B7F4C2E1708365200A106A9 /* STEPFileEncoding.h in Headers */, - 2B7F4C381708365200A106A9 /* STEPFileReader.h in Headers */, - 2B7F4C421708365200A106A9 /* STLExporter.h in Headers */, - 2B7F4C4C1708365200A106A9 /* STLLoader.h in Headers */, - 2B7F4C511708365200A106A9 /* StreamReader.h in Headers */, - 2B7F4C561708365200A106A9 /* StringComparison.h in Headers */, - 2B7F4C601708365200A106A9 /* Subdivision.h in Headers */, - 2B7F4C6A1708365200A106A9 /* TargetAnimation.h in Headers */, - 2B7F4C7E1708365200A106A9 /* TextureTransform.h in Headers */, - 2B7F4C831708365200A106A9 /* TinyFormatter.h in Headers */, - 2B7F4C8D1708365200A106A9 /* TriangulateProcess.h in Headers */, - 2B7F4CA11708365200A106A9 /* ValidateDataStructure.h in Headers */, - 2B7F4CA61708365200A106A9 /* Vertex.h in Headers */, - 2B7F4CB01708365200A106A9 /* VertexTriangleAdjacency.h in Headers */, - 2B7F4CB51708365200A106A9 /* Win32DebugLogStream.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 745FF829113ECB080020C31B /* assimp-no-boost */ = { - isa = PBXNativeTarget; - buildConfigurationList = 745FF8FD113ECB080020C31B /* Build configuration list for PBXNativeTarget "assimp-no-boost" */; - buildPhases = ( - 745FF82A113ECB080020C31B /* Headers */, - 745FF8AB113ECB080020C31B /* Frameworks */, - 745FF8AF113ECB080020C31B /* Sources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "assimp-no-boost"; - productName = libassimp; - productReference = 8E8DEEA5127E2D59005EF64D /* libassimpd.dylib */; - productType = "com.apple.product-type.library.dynamic"; - }; - 745FF90C113ECC660020C31B /* assimp-static-no-boost */ = { - isa = PBXNativeTarget; - buildConfigurationList = 745FF9E0113ECC660020C31B /* Build configuration list for PBXNativeTarget "assimp-static-no-boost" */; - buildPhases = ( - 745FF90D113ECC660020C31B /* Headers */, - 745FF98E113ECC660020C31B /* Frameworks */, - 745FF992113ECC660020C31B /* Sources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "assimp-static-no-boost"; - productName = "assimp-static"; - productReference = 8E8DEEA6127E2D59005EF64D /* libassimpd.a */; - productType = "com.apple.product-type.library.static"; - }; - B91974CF163AEA54009C397B /* assimp-ios-static-no-boost */ = { - isa = PBXNativeTarget; - buildConfigurationList = B919763C163AEA54009C397B /* Build configuration list for PBXNativeTarget "assimp-ios-static-no-boost" */; - buildPhases = ( - B91974D0163AEA54009C397B /* Headers */, - B91975B4163AEA54009C397B /* Frameworks */, - B91975B6163AEA54009C397B /* Sources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "assimp-ios-static-no-boost"; - productName = "assimp-static"; - productReference = B919763F163AEA54009C397B /* libassimp-ios.a */; - productType = "com.apple.product-type.library.static"; - }; - D2AAC09C05546B4700DB518D /* assimp */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1DEB916008733D950010E9CD /* Build configuration list for PBXNativeTarget "assimp" */; - buildPhases = ( - D2AAC09905546B4700DB518D /* Headers */, - D2AAC09B05546B4700DB518D /* Frameworks */, - D2AAC09A05546B4700DB518D /* Sources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = assimp; - productName = libassimp; - productReference = 8E8DEEA3127E2D59005EF64D /* libassimpd.dylib */; - productType = "com.apple.product-type.library.dynamic"; - }; - F962E8830F5DE66A009A5495 /* assimp-static */ = { - isa = PBXNativeTarget; - buildConfigurationList = F962E8870F5DE689009A5495 /* Build configuration list for PBXNativeTarget "assimp-static" */; - buildPhases = ( - F962E8800F5DE66A009A5495 /* Headers */, - F962E8820F5DE66A009A5495 /* Frameworks */, - F962E8810F5DE66A009A5495 /* Sources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "assimp-static"; - productName = "assimp-static"; - productReference = 8E8DEEA4127E2D59005EF64D /* libassimpd.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 0867D690FE84028FC02AAC07 /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 0460; - }; - buildConfigurationList = 1DEB916408733D950010E9CD /* Build configuration list for PBXProject "assimp" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 1; - knownRegions = ( - English, - Japanese, - French, - German, - ); - mainGroup = 0867D691FE84028FC02AAC07 /* assimp */; - productRefGroup = 034768DDFF38A45A11DB9C8B /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - D2AAC09C05546B4700DB518D /* assimp */, - F962E8830F5DE66A009A5495 /* assimp-static */, - 745FF829113ECB080020C31B /* assimp-no-boost */, - 745FF90C113ECC660020C31B /* assimp-static-no-boost */, - B91974CF163AEA54009C397B /* assimp-ios-static-no-boost */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 745FF8AF113ECB080020C31B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 745FF8B0113ECB080020C31B /* 3DSConverter.cpp in Sources */, - 745FF8B1113ECB080020C31B /* 3DSLoader.cpp in Sources */, - 745FF8B3113ECB080020C31B /* ASELoader.cpp in Sources */, - 745FF8B4113ECB080020C31B /* ASEParser.cpp in Sources */, - 745FF8BF113ECB080020C31B /* HMPLoader.cpp in Sources */, - 745FF8C5113ECB080020C31B /* MD2Loader.cpp in Sources */, - 745FF8C6113ECB080020C31B /* MD3Loader.cpp in Sources */, - 745FF8C7113ECB080020C31B /* MD5Loader.cpp in Sources */, - 745FF8C8113ECB080020C31B /* MD5Parser.cpp in Sources */, - 745FF8C9113ECB080020C31B /* MDLLoader.cpp in Sources */, - 745FF8CA113ECB080020C31B /* MDLMaterialLoader.cpp in Sources */, - 745FF8CE113ECB080020C31B /* PlyLoader.cpp in Sources */, - 745FF8CF113ECB080020C31B /* PlyParser.cpp in Sources */, - 745FF8D3113ECB080020C31B /* SMDLoader.cpp in Sources */, - 745FF8DB113ECB080020C31B /* XFileImporter.cpp in Sources */, - 745FF8DC113ECB080020C31B /* XFileParser.cpp in Sources */, - 745FF8DD113ECB080020C31B /* MDCLoader.cpp in Sources */, - 745FF8DF113ECB080020C31B /* LWOLoader.cpp in Sources */, - 745FF8E1113ECB080020C31B /* LWOMaterial.cpp in Sources */, - 745FF8E2113ECB080020C31B /* ACLoader.cpp in Sources */, - 745FF8E3113ECB080020C31B /* IRRLoader.cpp in Sources */, - 745FF8E4113ECB080020C31B /* IRRMeshLoader.cpp in Sources */, - 745FF8E5113ECB080020C31B /* IRRShared.cpp in Sources */, - 745FF8E8113ECB080020C31B /* NFFLoader.cpp in Sources */, - 745FF8EA113ECB080020C31B /* Q3DLoader.cpp in Sources */, - 745FF8EB113ECB080020C31B /* BVHLoader.cpp in Sources */, - 745FF8EC113ECB080020C31B /* OFFLoader.cpp in Sources */, - 745FF8ED113ECB080020C31B /* RawLoader.cpp in Sources */, - 745FF8EE113ECB080020C31B /* DXFLoader.cpp in Sources */, - 745FF8EF113ECB080020C31B /* LWOBLoader.cpp in Sources */, - 745FF8F0113ECB080020C31B /* TerragenLoader.cpp in Sources */, - 745FF8FC113ECB080020C31B /* B3DImporter.cpp in Sources */, - 7411B15211416D5E00BCD793 /* CSMLoader.cpp in Sources */, - 7411B15D11416DDD00BCD793 /* LWSLoader.cpp in Sources */, - 7411B16711416DF400BCD793 /* LWOAnimation.cpp in Sources */, - 7411B17411416E2500BCD793 /* MS3DLoader.cpp in Sources */, - 7411B18F11416EBC00BCD793 /* UnrealLoader.cpp in Sources */, - 74C9BB5F11ACBB1000AF885C /* BlenderDNA.cpp in Sources */, - 74C9BB6111ACBB1000AF885C /* BlenderLoader.cpp in Sources */, - 74C9BB6311ACBB1000AF885C /* BlenderScene.cpp in Sources */, - 74C9BB8811ACBB9900AF885C /* AssimpPCH.cpp in Sources */, - 74C9BB9611ACBBBC00AF885C /* COBLoader.cpp in Sources */, - 8E7ABBA9127E0F1A00512ED1 /* Q3BSPFileImporter.cpp in Sources */, - 8E7ABBAB127E0F1A00512ED1 /* Q3BSPFileParser.cpp in Sources */, - 8E7ABBAD127E0F1A00512ED1 /* Q3BSPZipArchive.cpp in Sources */, - 8E7ABBC6127E0F2A00512ED1 /* NDOLoader.cpp in Sources */, - 8E7ABBD2127E0F3800512ED1 /* BlenderModifier.cpp in Sources */, - 8E8DEE5C127E2B78005EF64D /* ConvertUTF.c in Sources */, - 8E8DEE63127E2B78005EF64D /* irrXML.cpp in Sources */, - 8E8DEE66127E2B78005EF64D /* ioapi.c in Sources */, - 8E8DEE68127E2B78005EF64D /* unzip.c in Sources */, - F9BA8C47154328B600E63FFE /* OgreImporter.cpp in Sources */, - F9BA8C49154328B600E63FFE /* OgreMaterial.cpp in Sources */, - F9BA8C4A154328B600E63FFE /* OgreMesh.cpp in Sources */, - F9BA8C4B154328B600E63FFE /* OgreSkeleton.cpp in Sources */, - F99A9F3615436269000682F3 /* PlyExporter.cpp in Sources */, - F9607085154366AB004D91DD /* adler32.c in Sources */, - F9607086154366AB004D91DD /* compress.c in Sources */, - F9607087154366AB004D91DD /* crc32.c in Sources */, - F9607089154366AB004D91DD /* deflate.c in Sources */, - F960708B154366AB004D91DD /* inffast.c in Sources */, - F960708E154366AB004D91DD /* inflate.c in Sources */, - F9607090154366AB004D91DD /* inftrees.c in Sources */, - F9607092154366AB004D91DD /* trees.c in Sources */, - F9607097154366AB004D91DD /* zutil.c in Sources */, - F96070BB154366ED004D91DD /* XGLLoader.cpp in Sources */, - F96070CC1543673B004D91DD /* clipper.cpp in Sources */, - F96070F71543675E004D91DD /* shapes.cc in Sources */, - F96070FB1543675E004D91DD /* advancing_front.cc in Sources */, - F96070FD1543675E004D91DD /* cdt.cc in Sources */, - F96070FF1543675E004D91DD /* sweep.cc in Sources */, - F96071011543675E004D91DD /* sweep_context.cc in Sources */, - 2B7F46E41708365200A106A9 /* Assimp.cpp in Sources */, - 2B7F46E91708365200A106A9 /* AssimpCExport.cpp in Sources */, - 2B7F47021708365200A106A9 /* BaseImporter.cpp in Sources */, - 2B7F470C1708365200A106A9 /* BaseProcess.cpp in Sources */, - 2B7F47A21708365200A106A9 /* CalcTangentsProcess.cpp in Sources */, - 2B7F47C01708365200A106A9 /* ColladaExporter.cpp in Sources */, - 2B7F47CF1708365200A106A9 /* ColladaLoader.cpp in Sources */, - 2B7F47D91708365200A106A9 /* ColladaParser.cpp in Sources */, - 2B7F47E31708365200A106A9 /* ComputeUVMappingProcess.cpp in Sources */, - 2B7F47ED1708365200A106A9 /* ConvertToLHProcess.cpp in Sources */, - 2B7F48011708365200A106A9 /* DeboneProcess.cpp in Sources */, - 2B7F480B1708365200A106A9 /* DefaultIOStream.cpp in Sources */, - 2B7F48151708365200A106A9 /* DefaultIOSystem.cpp in Sources */, - 2B7F481F1708365200A106A9 /* DefaultLogger.cpp in Sources */, - 2B7F483D1708365200A106A9 /* Exporter.cpp in Sources */, - 2B7F48471708365200A106A9 /* FBXAnimation.cpp in Sources */, - 2B7F484C1708365200A106A9 /* FBXBinaryTokenizer.cpp in Sources */, - 2B7F48561708365200A106A9 /* FBXConverter.cpp in Sources */, - 2B7F48601708365200A106A9 /* FBXDeformer.cpp in Sources */, - 2B7F48651708365200A106A9 /* FBXDocument.cpp in Sources */, - 2B7F486F1708365200A106A9 /* FBXDocumentUtil.cpp in Sources */, - 2B7F48791708365200A106A9 /* FBXImporter.cpp in Sources */, - 2B7F48881708365200A106A9 /* FBXMaterial.cpp in Sources */, - 2B7F488D1708365200A106A9 /* FBXMeshGeometry.cpp in Sources */, - 2B7F48921708365200A106A9 /* FBXModel.cpp in Sources */, - 2B7F48971708365200A106A9 /* FBXNodeAttribute.cpp in Sources */, - 2B7F489C1708365200A106A9 /* FBXParser.cpp in Sources */, - 2B7F48A61708365200A106A9 /* FBXProperties.cpp in Sources */, - 2B7F48B01708365200A106A9 /* FBXTokenizer.cpp in Sources */, - 2B7F48BA1708365200A106A9 /* FBXUtil.cpp in Sources */, - 2B7F48CE1708365200A106A9 /* FindDegenerates.cpp in Sources */, - 2B7F48D81708365200A106A9 /* FindInstancesProcess.cpp in Sources */, - 2B7F48E21708365200A106A9 /* FindInvalidDataProcess.cpp in Sources */, - 2B7F48EC1708365200A106A9 /* FixNormalsStep.cpp in Sources */, - 2B7F48FB1708365200A106A9 /* GenFaceNormalsProcess.cpp in Sources */, - 2B7F49051708365200A106A9 /* GenVertexNormalsProcess.cpp in Sources */, - 2B7F49281708365200A106A9 /* IFCBoolean.cpp in Sources */, - 2B7F492D1708365200A106A9 /* IFCCurve.cpp in Sources */, - 2B7F49321708365200A106A9 /* IFCGeometry.cpp in Sources */, - 2B7F49371708365200A106A9 /* IFCLoader.cpp in Sources */, - 2B7F49411708365200A106A9 /* IFCMaterial.cpp in Sources */, - 2B7F49461708365200A106A9 /* IFCOpenings.cpp in Sources */, - 2B7F494B1708365200A106A9 /* IFCProfile.cpp in Sources */, - 2B7F49501708365200A106A9 /* IFCReaderGen.cpp in Sources */, - 2B7F495A1708365200A106A9 /* IFCUtil.cpp in Sources */, - 2B7F49691708365200A106A9 /* Importer.cpp in Sources */, - 2B7F49731708365200A106A9 /* ImporterRegistry.cpp in Sources */, - 2B7F49781708365200A106A9 /* ImproveCacheLocality.cpp in Sources */, - 2B7F49A51708365200A106A9 /* JoinVerticesProcess.cpp in Sources */, - 2B7F49AF1708365200A106A9 /* LimitBoneWeightsProcess.cpp in Sources */, - 2B7F49FA1708365200A106A9 /* MakeVerboseFormat.cpp in Sources */, - 2B7F4A041708365200A106A9 /* MaterialSystem.cpp in Sources */, - 2B7F4A9A1708365200A106A9 /* ObjExporter.cpp in Sources */, - 2B7F4AA91708365200A106A9 /* ObjFileImporter.cpp in Sources */, - 2B7F4AB31708365200A106A9 /* ObjFileMtlImporter.cpp in Sources */, - 2B7F4ABD1708365200A106A9 /* ObjFileParser.cpp in Sources */, - 2B7F4AF41708365200A106A9 /* OptimizeGraph.cpp in Sources */, - 2B7F4AFE1708365200A106A9 /* OptimizeMeshes.cpp in Sources */, - 2B7F4B301708365200A106A9 /* PostStepRegistry.cpp in Sources */, - 2B7F4B351708365200A106A9 /* PretransformVertices.cpp in Sources */, - 2B7F4B3F1708365200A106A9 /* ProcessHelper.cpp in Sources */, - 2B7F4B8F1708365200A106A9 /* RemoveComments.cpp in Sources */, - 2B7F4B991708365200A106A9 /* RemoveRedundantMaterials.cpp in Sources */, - 2B7F4BA31708365200A106A9 /* RemoveVCProcess.cpp in Sources */, - 2B7F4BB21708365200A106A9 /* SceneCombiner.cpp in Sources */, - 2B7F4BBC1708365200A106A9 /* ScenePreprocessor.cpp in Sources */, - 2B7F4BCB1708365200A106A9 /* SGSpatialSort.cpp in Sources */, - 2B7F4BD51708365200A106A9 /* SkeletonMeshBuilder.cpp in Sources */, - 2B7F4BEE1708365200A106A9 /* SortByPTypeProcess.cpp in Sources */, - 2B7F4BF81708365200A106A9 /* SpatialSort.cpp in Sources */, - 2B7F4C021708365200A106A9 /* SplitByBoneCountProcess.cpp in Sources */, - 2B7F4C0C1708365200A106A9 /* SplitLargeMeshes.cpp in Sources */, - 2B7F4C161708365200A106A9 /* StandardShapes.cpp in Sources */, - 2B7F4C2A1708365200A106A9 /* STEPFileEncoding.cpp in Sources */, - 2B7F4C341708365200A106A9 /* STEPFileReader.cpp in Sources */, - 2B7F4C3E1708365200A106A9 /* STLExporter.cpp in Sources */, - 2B7F4C481708365200A106A9 /* STLLoader.cpp in Sources */, - 2B7F4C5C1708365200A106A9 /* Subdivision.cpp in Sources */, - 2B7F4C661708365200A106A9 /* TargetAnimation.cpp in Sources */, - 2B7F4C7A1708365200A106A9 /* TextureTransform.cpp in Sources */, - 2B7F4C891708365200A106A9 /* TriangulateProcess.cpp in Sources */, - 2B7F4C9D1708365200A106A9 /* ValidateDataStructure.cpp in Sources */, - 2B7F4CAC1708365200A106A9 /* VertexTriangleAdjacency.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 745FF992113ECC660020C31B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 745FF993113ECC660020C31B /* 3DSConverter.cpp in Sources */, - 745FF994113ECC660020C31B /* 3DSLoader.cpp in Sources */, - 745FF996113ECC660020C31B /* ASELoader.cpp in Sources */, - 745FF997113ECC660020C31B /* ASEParser.cpp in Sources */, - 745FF9A2113ECC660020C31B /* HMPLoader.cpp in Sources */, - 745FF9A8113ECC660020C31B /* MD2Loader.cpp in Sources */, - 745FF9A9113ECC660020C31B /* MD3Loader.cpp in Sources */, - 745FF9AA113ECC660020C31B /* MD5Loader.cpp in Sources */, - 745FF9AB113ECC660020C31B /* MD5Parser.cpp in Sources */, - 745FF9AC113ECC660020C31B /* MDLLoader.cpp in Sources */, - 745FF9AD113ECC660020C31B /* MDLMaterialLoader.cpp in Sources */, - 745FF9B1113ECC660020C31B /* PlyLoader.cpp in Sources */, - 745FF9B2113ECC660020C31B /* PlyParser.cpp in Sources */, - 745FF9B6113ECC660020C31B /* SMDLoader.cpp in Sources */, - 745FF9BE113ECC660020C31B /* XFileImporter.cpp in Sources */, - 745FF9BF113ECC660020C31B /* XFileParser.cpp in Sources */, - 745FF9C0113ECC660020C31B /* MDCLoader.cpp in Sources */, - 745FF9C2113ECC660020C31B /* LWOLoader.cpp in Sources */, - 745FF9C4113ECC660020C31B /* LWOMaterial.cpp in Sources */, - 745FF9C5113ECC660020C31B /* ACLoader.cpp in Sources */, - 745FF9C6113ECC660020C31B /* IRRLoader.cpp in Sources */, - 745FF9C7113ECC660020C31B /* IRRMeshLoader.cpp in Sources */, - 745FF9C8113ECC660020C31B /* IRRShared.cpp in Sources */, - 745FF9CB113ECC660020C31B /* NFFLoader.cpp in Sources */, - 745FF9CD113ECC660020C31B /* Q3DLoader.cpp in Sources */, - 745FF9CE113ECC660020C31B /* BVHLoader.cpp in Sources */, - 745FF9CF113ECC660020C31B /* OFFLoader.cpp in Sources */, - 745FF9D0113ECC660020C31B /* RawLoader.cpp in Sources */, - 745FF9D1113ECC660020C31B /* DXFLoader.cpp in Sources */, - 745FF9D2113ECC660020C31B /* LWOBLoader.cpp in Sources */, - 745FF9D3113ECC660020C31B /* TerragenLoader.cpp in Sources */, - 745FF9DF113ECC660020C31B /* B3DImporter.cpp in Sources */, - 7411B15011416D5E00BCD793 /* CSMLoader.cpp in Sources */, - 7411B15B11416DDD00BCD793 /* LWSLoader.cpp in Sources */, - 7411B16511416DF400BCD793 /* LWOAnimation.cpp in Sources */, - 7411B17211416E2500BCD793 /* MS3DLoader.cpp in Sources */, - 7411B18D11416EBC00BCD793 /* UnrealLoader.cpp in Sources */, - 74C9BB6611ACBB1000AF885C /* BlenderDNA.cpp in Sources */, - 74C9BB6811ACBB1000AF885C /* BlenderLoader.cpp in Sources */, - 74C9BB6A11ACBB1000AF885C /* BlenderScene.cpp in Sources */, - 74C9BB8A11ACBB9900AF885C /* AssimpPCH.cpp in Sources */, - 74C9BB9911ACBBBC00AF885C /* COBLoader.cpp in Sources */, - 8E7ABBBE127E0F1A00512ED1 /* Q3BSPFileImporter.cpp in Sources */, - 8E7ABBC0127E0F1A00512ED1 /* Q3BSPFileParser.cpp in Sources */, - 8E7ABBC2127E0F1A00512ED1 /* Q3BSPZipArchive.cpp in Sources */, - 8E7ABBCC127E0F2A00512ED1 /* NDOLoader.cpp in Sources */, - 8E7ABBDB127E0F3800512ED1 /* BlenderModifier.cpp in Sources */, - 8E8DEE86127E2B78005EF64D /* ConvertUTF.c in Sources */, - 8E8DEE8D127E2B78005EF64D /* irrXML.cpp in Sources */, - 8E8DEE90127E2B78005EF64D /* ioapi.c in Sources */, - 8E8DEE92127E2B78005EF64D /* unzip.c in Sources */, - F9BA8C4D154328B600E63FFE /* OgreImporter.cpp in Sources */, - F9BA8C4F154328B600E63FFE /* OgreMaterial.cpp in Sources */, - F9BA8C50154328B600E63FFE /* OgreMesh.cpp in Sources */, - F9BA8C51154328B600E63FFE /* OgreSkeleton.cpp in Sources */, - F99A9F3815436269000682F3 /* PlyExporter.cpp in Sources */, - F9607099154366AB004D91DD /* adler32.c in Sources */, - F960709A154366AB004D91DD /* compress.c in Sources */, - F960709B154366AB004D91DD /* crc32.c in Sources */, - F960709D154366AB004D91DD /* deflate.c in Sources */, - F960709F154366AB004D91DD /* inffast.c in Sources */, - F96070A2154366AB004D91DD /* inflate.c in Sources */, - F96070A4154366AB004D91DD /* inftrees.c in Sources */, - F96070A6154366AB004D91DD /* trees.c in Sources */, - F96070AB154366AB004D91DD /* zutil.c in Sources */, - F96070BD154366ED004D91DD /* XGLLoader.cpp in Sources */, - F96070CE1543673B004D91DD /* clipper.cpp in Sources */, - F96071031543675E004D91DD /* shapes.cc in Sources */, - F96071071543675E004D91DD /* advancing_front.cc in Sources */, - F96071091543675E004D91DD /* cdt.cc in Sources */, - F960710B1543675E004D91DD /* sweep.cc in Sources */, - F960710D1543675E004D91DD /* sweep_context.cc in Sources */, - 2B7F46E51708365200A106A9 /* Assimp.cpp in Sources */, - 2B7F46EA1708365200A106A9 /* AssimpCExport.cpp in Sources */, - 2B7F47031708365200A106A9 /* BaseImporter.cpp in Sources */, - 2B7F470D1708365200A106A9 /* BaseProcess.cpp in Sources */, - 2B7F47A31708365200A106A9 /* CalcTangentsProcess.cpp in Sources */, - 2B7F47C11708365200A106A9 /* ColladaExporter.cpp in Sources */, - 2B7F47D01708365200A106A9 /* ColladaLoader.cpp in Sources */, - 2B7F47DA1708365200A106A9 /* ColladaParser.cpp in Sources */, - 2B7F47E41708365200A106A9 /* ComputeUVMappingProcess.cpp in Sources */, - 2B7F47EE1708365200A106A9 /* ConvertToLHProcess.cpp in Sources */, - 2B7F48021708365200A106A9 /* DeboneProcess.cpp in Sources */, - 2B7F480C1708365200A106A9 /* DefaultIOStream.cpp in Sources */, - 2B7F48161708365200A106A9 /* DefaultIOSystem.cpp in Sources */, - 2B7F48201708365200A106A9 /* DefaultLogger.cpp in Sources */, - 2B7F483E1708365200A106A9 /* Exporter.cpp in Sources */, - 2B7F48481708365200A106A9 /* FBXAnimation.cpp in Sources */, - 2B7F484D1708365200A106A9 /* FBXBinaryTokenizer.cpp in Sources */, - 2B7F48571708365200A106A9 /* FBXConverter.cpp in Sources */, - 2B7F48611708365200A106A9 /* FBXDeformer.cpp in Sources */, - 2B7F48661708365200A106A9 /* FBXDocument.cpp in Sources */, - 2B7F48701708365200A106A9 /* FBXDocumentUtil.cpp in Sources */, - 2B7F487A1708365200A106A9 /* FBXImporter.cpp in Sources */, - 2B7F48891708365200A106A9 /* FBXMaterial.cpp in Sources */, - 2B7F488E1708365200A106A9 /* FBXMeshGeometry.cpp in Sources */, - 2B7F48931708365200A106A9 /* FBXModel.cpp in Sources */, - 2B7F48981708365200A106A9 /* FBXNodeAttribute.cpp in Sources */, - 2B7F489D1708365200A106A9 /* FBXParser.cpp in Sources */, - 2B7F48A71708365200A106A9 /* FBXProperties.cpp in Sources */, - 2B7F48B11708365200A106A9 /* FBXTokenizer.cpp in Sources */, - 2B7F48BB1708365200A106A9 /* FBXUtil.cpp in Sources */, - 2B7F48CF1708365200A106A9 /* FindDegenerates.cpp in Sources */, - 2B7F48D91708365200A106A9 /* FindInstancesProcess.cpp in Sources */, - 2B7F48E31708365200A106A9 /* FindInvalidDataProcess.cpp in Sources */, - 2B7F48ED1708365200A106A9 /* FixNormalsStep.cpp in Sources */, - 2B7F48FC1708365200A106A9 /* GenFaceNormalsProcess.cpp in Sources */, - 2B7F49061708365200A106A9 /* GenVertexNormalsProcess.cpp in Sources */, - 2B7F49291708365200A106A9 /* IFCBoolean.cpp in Sources */, - 2B7F492E1708365200A106A9 /* IFCCurve.cpp in Sources */, - 2B7F49331708365200A106A9 /* IFCGeometry.cpp in Sources */, - 2B7F49381708365200A106A9 /* IFCLoader.cpp in Sources */, - 2B7F49421708365200A106A9 /* IFCMaterial.cpp in Sources */, - 2B7F49471708365200A106A9 /* IFCOpenings.cpp in Sources */, - 2B7F494C1708365200A106A9 /* IFCProfile.cpp in Sources */, - 2B7F49511708365200A106A9 /* IFCReaderGen.cpp in Sources */, - 2B7F495B1708365200A106A9 /* IFCUtil.cpp in Sources */, - 2B7F496A1708365200A106A9 /* Importer.cpp in Sources */, - 2B7F49741708365200A106A9 /* ImporterRegistry.cpp in Sources */, - 2B7F49791708365200A106A9 /* ImproveCacheLocality.cpp in Sources */, - 2B7F49A61708365200A106A9 /* JoinVerticesProcess.cpp in Sources */, - 2B7F49B01708365200A106A9 /* LimitBoneWeightsProcess.cpp in Sources */, - 2B7F49FB1708365200A106A9 /* MakeVerboseFormat.cpp in Sources */, - 2B7F4A051708365200A106A9 /* MaterialSystem.cpp in Sources */, - 2B7F4A9B1708365200A106A9 /* ObjExporter.cpp in Sources */, - 2B7F4AAA1708365200A106A9 /* ObjFileImporter.cpp in Sources */, - 2B7F4AB41708365200A106A9 /* ObjFileMtlImporter.cpp in Sources */, - 2B7F4ABE1708365200A106A9 /* ObjFileParser.cpp in Sources */, - 2B7F4AF51708365200A106A9 /* OptimizeGraph.cpp in Sources */, - 2B7F4AFF1708365200A106A9 /* OptimizeMeshes.cpp in Sources */, - 2B7F4B311708365200A106A9 /* PostStepRegistry.cpp in Sources */, - 2B7F4B361708365200A106A9 /* PretransformVertices.cpp in Sources */, - 2B7F4B401708365200A106A9 /* ProcessHelper.cpp in Sources */, - 2B7F4B901708365200A106A9 /* RemoveComments.cpp in Sources */, - 2B7F4B9A1708365200A106A9 /* RemoveRedundantMaterials.cpp in Sources */, - 2B7F4BA41708365200A106A9 /* RemoveVCProcess.cpp in Sources */, - 2B7F4BB31708365200A106A9 /* SceneCombiner.cpp in Sources */, - 2B7F4BBD1708365200A106A9 /* ScenePreprocessor.cpp in Sources */, - 2B7F4BCC1708365200A106A9 /* SGSpatialSort.cpp in Sources */, - 2B7F4BD61708365200A106A9 /* SkeletonMeshBuilder.cpp in Sources */, - 2B7F4BEF1708365200A106A9 /* SortByPTypeProcess.cpp in Sources */, - 2B7F4BF91708365200A106A9 /* SpatialSort.cpp in Sources */, - 2B7F4C031708365200A106A9 /* SplitByBoneCountProcess.cpp in Sources */, - 2B7F4C0D1708365200A106A9 /* SplitLargeMeshes.cpp in Sources */, - 2B7F4C171708365200A106A9 /* StandardShapes.cpp in Sources */, - 2B7F4C2B1708365200A106A9 /* STEPFileEncoding.cpp in Sources */, - 2B7F4C351708365200A106A9 /* STEPFileReader.cpp in Sources */, - 2B7F4C3F1708365200A106A9 /* STLExporter.cpp in Sources */, - 2B7F4C491708365200A106A9 /* STLLoader.cpp in Sources */, - 2B7F4C5D1708365200A106A9 /* Subdivision.cpp in Sources */, - 2B7F4C671708365200A106A9 /* TargetAnimation.cpp in Sources */, - 2B7F4C7B1708365200A106A9 /* TextureTransform.cpp in Sources */, - 2B7F4C8A1708365200A106A9 /* TriangulateProcess.cpp in Sources */, - 2B7F4C9E1708365200A106A9 /* ValidateDataStructure.cpp in Sources */, - 2B7F4CAD1708365200A106A9 /* VertexTriangleAdjacency.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B91975B6163AEA54009C397B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - B91975B7163AEA54009C397B /* 3DSConverter.cpp in Sources */, - B91975B8163AEA54009C397B /* 3DSLoader.cpp in Sources */, - B91975B9163AEA54009C397B /* ASELoader.cpp in Sources */, - B91975BA163AEA54009C397B /* ASEParser.cpp in Sources */, - B91975C4163AEA54009C397B /* HMPLoader.cpp in Sources */, - B91975CA163AEA54009C397B /* MD2Loader.cpp in Sources */, - B91975CB163AEA54009C397B /* MD3Loader.cpp in Sources */, - B91975CC163AEA54009C397B /* MD5Loader.cpp in Sources */, - B91975CD163AEA54009C397B /* MD5Parser.cpp in Sources */, - B91975CE163AEA54009C397B /* MDLLoader.cpp in Sources */, - B91975CF163AEA54009C397B /* MDLMaterialLoader.cpp in Sources */, - B91975D3163AEA54009C397B /* PlyLoader.cpp in Sources */, - B91975D4163AEA54009C397B /* PlyParser.cpp in Sources */, - B91975D8163AEA54009C397B /* SMDLoader.cpp in Sources */, - B91975E0163AEA54009C397B /* XFileImporter.cpp in Sources */, - B91975E1163AEA54009C397B /* XFileParser.cpp in Sources */, - B91975E2163AEA54009C397B /* MDCLoader.cpp in Sources */, - B91975E4163AEA54009C397B /* LWOLoader.cpp in Sources */, - B91975E6163AEA54009C397B /* LWOMaterial.cpp in Sources */, - B91975E7163AEA54009C397B /* ACLoader.cpp in Sources */, - B91975E8163AEA54009C397B /* IRRLoader.cpp in Sources */, - B91975E9163AEA54009C397B /* IRRMeshLoader.cpp in Sources */, - B91975EA163AEA54009C397B /* IRRShared.cpp in Sources */, - B91975ED163AEA54009C397B /* NFFLoader.cpp in Sources */, - B91975EF163AEA54009C397B /* Q3DLoader.cpp in Sources */, - B91975F0163AEA54009C397B /* BVHLoader.cpp in Sources */, - B91975F1163AEA54009C397B /* OFFLoader.cpp in Sources */, - B91975F2163AEA54009C397B /* RawLoader.cpp in Sources */, - B91975F3163AEA54009C397B /* DXFLoader.cpp in Sources */, - B91975F4163AEA54009C397B /* LWOBLoader.cpp in Sources */, - B91975F5163AEA54009C397B /* TerragenLoader.cpp in Sources */, - B9197600163AEA54009C397B /* B3DImporter.cpp in Sources */, - B9197601163AEA54009C397B /* CSMLoader.cpp in Sources */, - B9197602163AEA54009C397B /* LWSLoader.cpp in Sources */, - B9197603163AEA54009C397B /* LWOAnimation.cpp in Sources */, - B9197604163AEA54009C397B /* MS3DLoader.cpp in Sources */, - B9197605163AEA54009C397B /* UnrealLoader.cpp in Sources */, - B919760A163AEA54009C397B /* BlenderDNA.cpp in Sources */, - B919760B163AEA54009C397B /* BlenderLoader.cpp in Sources */, - B919760C163AEA54009C397B /* BlenderScene.cpp in Sources */, - B919760E163AEA54009C397B /* AssimpPCH.cpp in Sources */, - B919760F163AEA54009C397B /* COBLoader.cpp in Sources */, - B9197610163AEA54009C397B /* Q3BSPFileImporter.cpp in Sources */, - B9197611163AEA54009C397B /* Q3BSPFileParser.cpp in Sources */, - B9197612163AEA54009C397B /* Q3BSPZipArchive.cpp in Sources */, - B9197613163AEA54009C397B /* NDOLoader.cpp in Sources */, - B9197614163AEA54009C397B /* BlenderModifier.cpp in Sources */, - B9197615163AEA54009C397B /* ConvertUTF.c in Sources */, - B9197616163AEA54009C397B /* irrXML.cpp in Sources */, - B9197617163AEA54009C397B /* ioapi.c in Sources */, - B9197618163AEA54009C397B /* unzip.c in Sources */, - B9197619163AEA54009C397B /* OgreImporter.cpp in Sources */, - B919761A163AEA54009C397B /* OgreMaterial.cpp in Sources */, - B919761B163AEA54009C397B /* OgreMesh.cpp in Sources */, - B919761C163AEA54009C397B /* OgreSkeleton.cpp in Sources */, - B9197620163AEA54009C397B /* PlyExporter.cpp in Sources */, - B9197625163AEA54009C397B /* adler32.c in Sources */, - B9197626163AEA54009C397B /* compress.c in Sources */, - B9197627163AEA54009C397B /* crc32.c in Sources */, - B9197628163AEA54009C397B /* deflate.c in Sources */, - B9197629163AEA54009C397B /* inffast.c in Sources */, - B919762A163AEA54009C397B /* inflate.c in Sources */, - B919762B163AEA54009C397B /* inftrees.c in Sources */, - B919762C163AEA54009C397B /* trees.c in Sources */, - B919762D163AEA54009C397B /* zutil.c in Sources */, - B919762E163AEA54009C397B /* XGLLoader.cpp in Sources */, - B919762F163AEA54009C397B /* clipper.cpp in Sources */, - B9197630163AEA54009C397B /* shapes.cc in Sources */, - B9197631163AEA54009C397B /* advancing_front.cc in Sources */, - B9197632163AEA54009C397B /* cdt.cc in Sources */, - B9197633163AEA54009C397B /* sweep.cc in Sources */, - B9197634163AEA54009C397B /* sweep_context.cc in Sources */, - 2B7F46E61708365200A106A9 /* Assimp.cpp in Sources */, - 2B7F46EB1708365200A106A9 /* AssimpCExport.cpp in Sources */, - 2B7F47041708365200A106A9 /* BaseImporter.cpp in Sources */, - 2B7F470E1708365200A106A9 /* BaseProcess.cpp in Sources */, - 2B7F47A41708365200A106A9 /* CalcTangentsProcess.cpp in Sources */, - 2B7F47C21708365200A106A9 /* ColladaExporter.cpp in Sources */, - 2B7F47D11708365200A106A9 /* ColladaLoader.cpp in Sources */, - 2B7F47DB1708365200A106A9 /* ColladaParser.cpp in Sources */, - 2B7F47E51708365200A106A9 /* ComputeUVMappingProcess.cpp in Sources */, - 2B7F47EF1708365200A106A9 /* ConvertToLHProcess.cpp in Sources */, - 2B7F48031708365200A106A9 /* DeboneProcess.cpp in Sources */, - 2B7F480D1708365200A106A9 /* DefaultIOStream.cpp in Sources */, - 2B7F48171708365200A106A9 /* DefaultIOSystem.cpp in Sources */, - 2B7F48211708365200A106A9 /* DefaultLogger.cpp in Sources */, - 2B7F483F1708365200A106A9 /* Exporter.cpp in Sources */, - 2B7F48491708365200A106A9 /* FBXAnimation.cpp in Sources */, - 2B7F484E1708365200A106A9 /* FBXBinaryTokenizer.cpp in Sources */, - 2B7F48581708365200A106A9 /* FBXConverter.cpp in Sources */, - 2B7F48621708365200A106A9 /* FBXDeformer.cpp in Sources */, - 2B7F48671708365200A106A9 /* FBXDocument.cpp in Sources */, - 2B7F48711708365200A106A9 /* FBXDocumentUtil.cpp in Sources */, - 2B7F487B1708365200A106A9 /* FBXImporter.cpp in Sources */, - 2B7F488A1708365200A106A9 /* FBXMaterial.cpp in Sources */, - 2B7F488F1708365200A106A9 /* FBXMeshGeometry.cpp in Sources */, - 2B7F48941708365200A106A9 /* FBXModel.cpp in Sources */, - 2B7F48991708365200A106A9 /* FBXNodeAttribute.cpp in Sources */, - 2B7F489E1708365200A106A9 /* FBXParser.cpp in Sources */, - 2B7F48A81708365200A106A9 /* FBXProperties.cpp in Sources */, - 2B7F48B21708365200A106A9 /* FBXTokenizer.cpp in Sources */, - 2B7F48BC1708365200A106A9 /* FBXUtil.cpp in Sources */, - 2B7F48D01708365200A106A9 /* FindDegenerates.cpp in Sources */, - 2B7F48DA1708365200A106A9 /* FindInstancesProcess.cpp in Sources */, - 2B7F48E41708365200A106A9 /* FindInvalidDataProcess.cpp in Sources */, - 2B7F48EE1708365200A106A9 /* FixNormalsStep.cpp in Sources */, - 2B7F48FD1708365200A106A9 /* GenFaceNormalsProcess.cpp in Sources */, - 2B7F49071708365200A106A9 /* GenVertexNormalsProcess.cpp in Sources */, - 2B7F492A1708365200A106A9 /* IFCBoolean.cpp in Sources */, - 2B7F492F1708365200A106A9 /* IFCCurve.cpp in Sources */, - 2B7F49341708365200A106A9 /* IFCGeometry.cpp in Sources */, - 2B7F49391708365200A106A9 /* IFCLoader.cpp in Sources */, - 2B7F49431708365200A106A9 /* IFCMaterial.cpp in Sources */, - 2B7F49481708365200A106A9 /* IFCOpenings.cpp in Sources */, - 2B7F494D1708365200A106A9 /* IFCProfile.cpp in Sources */, - 2B7F49521708365200A106A9 /* IFCReaderGen.cpp in Sources */, - 2B7F495C1708365200A106A9 /* IFCUtil.cpp in Sources */, - 2B7F496B1708365200A106A9 /* Importer.cpp in Sources */, - 2B7F49751708365200A106A9 /* ImporterRegistry.cpp in Sources */, - 2B7F497A1708365200A106A9 /* ImproveCacheLocality.cpp in Sources */, - 2B7F49A71708365200A106A9 /* JoinVerticesProcess.cpp in Sources */, - 2B7F49B11708365200A106A9 /* LimitBoneWeightsProcess.cpp in Sources */, - 2B7F49FC1708365200A106A9 /* MakeVerboseFormat.cpp in Sources */, - 2B7F4A061708365200A106A9 /* MaterialSystem.cpp in Sources */, - 2B7F4A9C1708365200A106A9 /* ObjExporter.cpp in Sources */, - 2B7F4AAB1708365200A106A9 /* ObjFileImporter.cpp in Sources */, - 2B7F4AB51708365200A106A9 /* ObjFileMtlImporter.cpp in Sources */, - 2B7F4ABF1708365200A106A9 /* ObjFileParser.cpp in Sources */, - 2B7F4AF61708365200A106A9 /* OptimizeGraph.cpp in Sources */, - 2B7F4B001708365200A106A9 /* OptimizeMeshes.cpp in Sources */, - 2B7F4B321708365200A106A9 /* PostStepRegistry.cpp in Sources */, - 2B7F4B371708365200A106A9 /* PretransformVertices.cpp in Sources */, - 2B7F4B411708365200A106A9 /* ProcessHelper.cpp in Sources */, - 2B7F4B911708365200A106A9 /* RemoveComments.cpp in Sources */, - 2B7F4B9B1708365200A106A9 /* RemoveRedundantMaterials.cpp in Sources */, - 2B7F4BA51708365200A106A9 /* RemoveVCProcess.cpp in Sources */, - 2B7F4BB41708365200A106A9 /* SceneCombiner.cpp in Sources */, - 2B7F4BBE1708365200A106A9 /* ScenePreprocessor.cpp in Sources */, - 2B7F4BCD1708365200A106A9 /* SGSpatialSort.cpp in Sources */, - 2B7F4BD71708365200A106A9 /* SkeletonMeshBuilder.cpp in Sources */, - 2B7F4BF01708365200A106A9 /* SortByPTypeProcess.cpp in Sources */, - 2B7F4BFA1708365200A106A9 /* SpatialSort.cpp in Sources */, - 2B7F4C041708365200A106A9 /* SplitByBoneCountProcess.cpp in Sources */, - 2B7F4C0E1708365200A106A9 /* SplitLargeMeshes.cpp in Sources */, - 2B7F4C181708365200A106A9 /* StandardShapes.cpp in Sources */, - 2B7F4C2C1708365200A106A9 /* STEPFileEncoding.cpp in Sources */, - 2B7F4C361708365200A106A9 /* STEPFileReader.cpp in Sources */, - 2B7F4C401708365200A106A9 /* STLExporter.cpp in Sources */, - 2B7F4C4A1708365200A106A9 /* STLLoader.cpp in Sources */, - 2B7F4C5E1708365200A106A9 /* Subdivision.cpp in Sources */, - 2B7F4C681708365200A106A9 /* TargetAnimation.cpp in Sources */, - 2B7F4C7C1708365200A106A9 /* TextureTransform.cpp in Sources */, - 2B7F4C8B1708365200A106A9 /* TriangulateProcess.cpp in Sources */, - 2B7F4C9F1708365200A106A9 /* ValidateDataStructure.cpp in Sources */, - 2B7F4CAE1708365200A106A9 /* VertexTriangleAdjacency.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - D2AAC09A05546B4700DB518D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 3AF45AF90E4B716800207D74 /* 3DSConverter.cpp in Sources */, - 3AF45AFC0E4B716800207D74 /* 3DSLoader.cpp in Sources */, - 3AF45B010E4B716800207D74 /* ASELoader.cpp in Sources */, - 3AF45B030E4B716800207D74 /* ASEParser.cpp in Sources */, - 3AF45B1D0E4B716800207D74 /* HMPLoader.cpp in Sources */, - 3AF45B2B0E4B716800207D74 /* MD2Loader.cpp in Sources */, - 3AF45B2F0E4B716800207D74 /* MD3Loader.cpp in Sources */, - 3AF45B340E4B716800207D74 /* MD5Loader.cpp in Sources */, - 3AF45B360E4B716800207D74 /* MD5Parser.cpp in Sources */, - 3AF45B3A0E4B716800207D74 /* MDLLoader.cpp in Sources */, - 3AF45B3C0E4B716800207D74 /* MDLMaterialLoader.cpp in Sources */, - 3AF45B460E4B716800207D74 /* PlyLoader.cpp in Sources */, - 3AF45B480E4B716800207D74 /* PlyParser.cpp in Sources */, - 3AF45B520E4B716800207D74 /* SMDLoader.cpp in Sources */, - 3AF45B650E4B716800207D74 /* XFileImporter.cpp in Sources */, - 3AF45B670E4B716800207D74 /* XFileParser.cpp in Sources */, - 3AB8A3B00E50D67A00606590 /* MDCLoader.cpp in Sources */, - 3AB8A3BB0E50D6DB00606590 /* LWOLoader.cpp in Sources */, - 3AB8A7DD0E53715F00606590 /* LWOMaterial.cpp in Sources */, - F90BAFD20F5DD87000124155 /* ACLoader.cpp in Sources */, - F90BAFDF0F5DD90800124155 /* IRRLoader.cpp in Sources */, - F90BAFE10F5DD90800124155 /* IRRMeshLoader.cpp in Sources */, - F90BAFE30F5DD90800124155 /* IRRShared.cpp in Sources */, - F90BAFF80F5DD96100124155 /* NFFLoader.cpp in Sources */, - F90BB0080F5DD9DD00124155 /* Q3DLoader.cpp in Sources */, - F90BB00F0F5DD9F400124155 /* BVHLoader.cpp in Sources */, - F90BB0160F5DDA1400124155 /* OFFLoader.cpp in Sources */, - F90BB01E0F5DDA4400124155 /* RawLoader.cpp in Sources */, - F90BB0240F5DDA5700124155 /* DXFLoader.cpp in Sources */, - F90BB0280F5DDA9200124155 /* LWOBLoader.cpp in Sources */, - F90BB0320F5DDAB500124155 /* TerragenLoader.cpp in Sources */, - F90BB08A0F5DDE0700124155 /* B3DImporter.cpp in Sources */, - 7411B15411416D5E00BCD793 /* CSMLoader.cpp in Sources */, - 7411B15F11416DDD00BCD793 /* LWSLoader.cpp in Sources */, - 7411B16911416DF400BCD793 /* LWOAnimation.cpp in Sources */, - 7411B17611416E2500BCD793 /* MS3DLoader.cpp in Sources */, - 7411B19111416EBC00BCD793 /* UnrealLoader.cpp in Sources */, - 74C9BB5111ACBB1000AF885C /* BlenderDNA.cpp in Sources */, - 74C9BB5311ACBB1000AF885C /* BlenderLoader.cpp in Sources */, - 74C9BB5511ACBB1000AF885C /* BlenderScene.cpp in Sources */, - 74C9BB8C11ACBB9900AF885C /* AssimpPCH.cpp in Sources */, - 74C9BB9C11ACBBBC00AF885C /* COBLoader.cpp in Sources */, - 8E7ABBB0127E0F1A00512ED1 /* Q3BSPFileImporter.cpp in Sources */, - 8E7ABBB2127E0F1A00512ED1 /* Q3BSPFileParser.cpp in Sources */, - 8E7ABBB4127E0F1A00512ED1 /* Q3BSPZipArchive.cpp in Sources */, - 8E7ABBC8127E0F2A00512ED1 /* NDOLoader.cpp in Sources */, - 8E7ABBD5127E0F3800512ED1 /* BlenderModifier.cpp in Sources */, - 8E8DEE6A127E2B78005EF64D /* ConvertUTF.c in Sources */, - 8E8DEE71127E2B78005EF64D /* irrXML.cpp in Sources */, - 8E8DEE74127E2B78005EF64D /* ioapi.c in Sources */, - 8E8DEE76127E2B78005EF64D /* unzip.c in Sources */, - F9BA8C3B154328B600E63FFE /* OgreImporter.cpp in Sources */, - F9BA8C3D154328B600E63FFE /* OgreMaterial.cpp in Sources */, - F9BA8C3E154328B600E63FFE /* OgreMesh.cpp in Sources */, - F9BA8C3F154328B600E63FFE /* OgreSkeleton.cpp in Sources */, - F99A9F3215436269000682F3 /* PlyExporter.cpp in Sources */, - F960705D154366AB004D91DD /* adler32.c in Sources */, - F960705E154366AB004D91DD /* compress.c in Sources */, - F960705F154366AB004D91DD /* crc32.c in Sources */, - F9607061154366AB004D91DD /* deflate.c in Sources */, - F9607063154366AB004D91DD /* inffast.c in Sources */, - F9607066154366AB004D91DD /* inflate.c in Sources */, - F9607068154366AB004D91DD /* inftrees.c in Sources */, - F960706A154366AB004D91DD /* trees.c in Sources */, - F960706F154366AB004D91DD /* zutil.c in Sources */, - F96070B7154366ED004D91DD /* XGLLoader.cpp in Sources */, - F96070C81543673B004D91DD /* clipper.cpp in Sources */, - F96070DF1543675E004D91DD /* shapes.cc in Sources */, - F96070E31543675E004D91DD /* advancing_front.cc in Sources */, - F96070E51543675E004D91DD /* cdt.cc in Sources */, - F96070E71543675E004D91DD /* sweep.cc in Sources */, - F96070E91543675E004D91DD /* sweep_context.cc in Sources */, - 2B7F46E21708365200A106A9 /* Assimp.cpp in Sources */, - 2B7F46E71708365200A106A9 /* AssimpCExport.cpp in Sources */, - 2B7F47001708365200A106A9 /* BaseImporter.cpp in Sources */, - 2B7F470A1708365200A106A9 /* BaseProcess.cpp in Sources */, - 2B7F47A01708365200A106A9 /* CalcTangentsProcess.cpp in Sources */, - 2B7F47BE1708365200A106A9 /* ColladaExporter.cpp in Sources */, - 2B7F47CD1708365200A106A9 /* ColladaLoader.cpp in Sources */, - 2B7F47D71708365200A106A9 /* ColladaParser.cpp in Sources */, - 2B7F47E11708365200A106A9 /* ComputeUVMappingProcess.cpp in Sources */, - 2B7F47EB1708365200A106A9 /* ConvertToLHProcess.cpp in Sources */, - 2B7F47FF1708365200A106A9 /* DeboneProcess.cpp in Sources */, - 2B7F48091708365200A106A9 /* DefaultIOStream.cpp in Sources */, - 2B7F48131708365200A106A9 /* DefaultIOSystem.cpp in Sources */, - 2B7F481D1708365200A106A9 /* DefaultLogger.cpp in Sources */, - 2B7F483B1708365200A106A9 /* Exporter.cpp in Sources */, - 2B7F48451708365200A106A9 /* FBXAnimation.cpp in Sources */, - 2B7F484A1708365200A106A9 /* FBXBinaryTokenizer.cpp in Sources */, - 2B7F48541708365200A106A9 /* FBXConverter.cpp in Sources */, - 2B7F485E1708365200A106A9 /* FBXDeformer.cpp in Sources */, - 2B7F48631708365200A106A9 /* FBXDocument.cpp in Sources */, - 2B7F486D1708365200A106A9 /* FBXDocumentUtil.cpp in Sources */, - 2B7F48771708365200A106A9 /* FBXImporter.cpp in Sources */, - 2B7F48861708365200A106A9 /* FBXMaterial.cpp in Sources */, - 2B7F488B1708365200A106A9 /* FBXMeshGeometry.cpp in Sources */, - 2B7F48901708365200A106A9 /* FBXModel.cpp in Sources */, - 2B7F48951708365200A106A9 /* FBXNodeAttribute.cpp in Sources */, - 2B7F489A1708365200A106A9 /* FBXParser.cpp in Sources */, - 2B7F48A41708365200A106A9 /* FBXProperties.cpp in Sources */, - 2B7F48AE1708365200A106A9 /* FBXTokenizer.cpp in Sources */, - 2B7F48B81708365200A106A9 /* FBXUtil.cpp in Sources */, - 2B7F48CC1708365200A106A9 /* FindDegenerates.cpp in Sources */, - 2B7F48D61708365200A106A9 /* FindInstancesProcess.cpp in Sources */, - 2B7F48E01708365200A106A9 /* FindInvalidDataProcess.cpp in Sources */, - 2B7F48EA1708365200A106A9 /* FixNormalsStep.cpp in Sources */, - 2B7F48F91708365200A106A9 /* GenFaceNormalsProcess.cpp in Sources */, - 2B7F49031708365200A106A9 /* GenVertexNormalsProcess.cpp in Sources */, - 2B7F49261708365200A106A9 /* IFCBoolean.cpp in Sources */, - 2B7F492B1708365200A106A9 /* IFCCurve.cpp in Sources */, - 2B7F49301708365200A106A9 /* IFCGeometry.cpp in Sources */, - 2B7F49351708365200A106A9 /* IFCLoader.cpp in Sources */, - 2B7F493F1708365200A106A9 /* IFCMaterial.cpp in Sources */, - 2B7F49441708365200A106A9 /* IFCOpenings.cpp in Sources */, - 2B7F49491708365200A106A9 /* IFCProfile.cpp in Sources */, - 2B7F494E1708365200A106A9 /* IFCReaderGen.cpp in Sources */, - 2B7F49581708365200A106A9 /* IFCUtil.cpp in Sources */, - 2B7F49671708365200A106A9 /* Importer.cpp in Sources */, - 2B7F49711708365200A106A9 /* ImporterRegistry.cpp in Sources */, - 2B7F49761708365200A106A9 /* ImproveCacheLocality.cpp in Sources */, - 2B7F49A31708365200A106A9 /* JoinVerticesProcess.cpp in Sources */, - 2B7F49AD1708365200A106A9 /* LimitBoneWeightsProcess.cpp in Sources */, - 2B7F49F81708365200A106A9 /* MakeVerboseFormat.cpp in Sources */, - 2B7F4A021708365200A106A9 /* MaterialSystem.cpp in Sources */, - 2B7F4A981708365200A106A9 /* ObjExporter.cpp in Sources */, - 2B7F4AA71708365200A106A9 /* ObjFileImporter.cpp in Sources */, - 2B7F4AB11708365200A106A9 /* ObjFileMtlImporter.cpp in Sources */, - 2B7F4ABB1708365200A106A9 /* ObjFileParser.cpp in Sources */, - 2B7F4AF21708365200A106A9 /* OptimizeGraph.cpp in Sources */, - 2B7F4AFC1708365200A106A9 /* OptimizeMeshes.cpp in Sources */, - 2B7F4B2E1708365200A106A9 /* PostStepRegistry.cpp in Sources */, - 2B7F4B331708365200A106A9 /* PretransformVertices.cpp in Sources */, - 2B7F4B3D1708365200A106A9 /* ProcessHelper.cpp in Sources */, - 2B7F4B8D1708365200A106A9 /* RemoveComments.cpp in Sources */, - 2B7F4B971708365200A106A9 /* RemoveRedundantMaterials.cpp in Sources */, - 2B7F4BA11708365200A106A9 /* RemoveVCProcess.cpp in Sources */, - 2B7F4BB01708365200A106A9 /* SceneCombiner.cpp in Sources */, - 2B7F4BBA1708365200A106A9 /* ScenePreprocessor.cpp in Sources */, - 2B7F4BC91708365200A106A9 /* SGSpatialSort.cpp in Sources */, - 2B7F4BD31708365200A106A9 /* SkeletonMeshBuilder.cpp in Sources */, - 2B7F4BEC1708365200A106A9 /* SortByPTypeProcess.cpp in Sources */, - 2B7F4BF61708365200A106A9 /* SpatialSort.cpp in Sources */, - 2B7F4C001708365200A106A9 /* SplitByBoneCountProcess.cpp in Sources */, - 2B7F4C0A1708365200A106A9 /* SplitLargeMeshes.cpp in Sources */, - 2B7F4C141708365200A106A9 /* StandardShapes.cpp in Sources */, - 2B7F4C281708365200A106A9 /* STEPFileEncoding.cpp in Sources */, - 2B7F4C321708365200A106A9 /* STEPFileReader.cpp in Sources */, - 2B7F4C3C1708365200A106A9 /* STLExporter.cpp in Sources */, - 2B7F4C461708365200A106A9 /* STLLoader.cpp in Sources */, - 2B7F4C5A1708365200A106A9 /* Subdivision.cpp in Sources */, - 2B7F4C641708365200A106A9 /* TargetAnimation.cpp in Sources */, - 2B7F4C781708365200A106A9 /* TextureTransform.cpp in Sources */, - 2B7F4C871708365200A106A9 /* TriangulateProcess.cpp in Sources */, - 2B7F4C9B1708365200A106A9 /* ValidateDataStructure.cpp in Sources */, - 2B7F4CAA1708365200A106A9 /* VertexTriangleAdjacency.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - F962E8810F5DE66A009A5495 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - F962E88B0F5DE6C8009A5495 /* 3DSConverter.cpp in Sources */, - F962E88C0F5DE6C8009A5495 /* 3DSLoader.cpp in Sources */, - F962E88E0F5DE6C8009A5495 /* ASELoader.cpp in Sources */, - F962E88F0F5DE6C8009A5495 /* ASEParser.cpp in Sources */, - F962E89A0F5DE6C8009A5495 /* HMPLoader.cpp in Sources */, - F962E8A00F5DE6C8009A5495 /* MD2Loader.cpp in Sources */, - F962E8A10F5DE6C8009A5495 /* MD3Loader.cpp in Sources */, - F962E8A20F5DE6C8009A5495 /* MD5Loader.cpp in Sources */, - F962E8A30F5DE6C8009A5495 /* MD5Parser.cpp in Sources */, - F962E8A40F5DE6C8009A5495 /* MDLLoader.cpp in Sources */, - F962E8A50F5DE6C8009A5495 /* MDLMaterialLoader.cpp in Sources */, - F962E8A90F5DE6C8009A5495 /* PlyLoader.cpp in Sources */, - F962E8AA0F5DE6C8009A5495 /* PlyParser.cpp in Sources */, - F962E8AE0F5DE6C8009A5495 /* SMDLoader.cpp in Sources */, - F962E8B60F5DE6C8009A5495 /* XFileImporter.cpp in Sources */, - F962E8B70F5DE6C8009A5495 /* XFileParser.cpp in Sources */, - F962E8B80F5DE6C8009A5495 /* MDCLoader.cpp in Sources */, - F962E8BA0F5DE6C8009A5495 /* LWOLoader.cpp in Sources */, - F962E8BC0F5DE6C8009A5495 /* LWOMaterial.cpp in Sources */, - F962E8BD0F5DE6C8009A5495 /* ACLoader.cpp in Sources */, - F962E8BE0F5DE6C8009A5495 /* IRRLoader.cpp in Sources */, - F962E8BF0F5DE6C8009A5495 /* IRRMeshLoader.cpp in Sources */, - F962E8C00F5DE6C8009A5495 /* IRRShared.cpp in Sources */, - F962E8C30F5DE6C8009A5495 /* NFFLoader.cpp in Sources */, - F962E8C50F5DE6C8009A5495 /* Q3DLoader.cpp in Sources */, - F962E8C60F5DE6C8009A5495 /* BVHLoader.cpp in Sources */, - F962E8C70F5DE6C8009A5495 /* OFFLoader.cpp in Sources */, - F962E8C80F5DE6C8009A5495 /* RawLoader.cpp in Sources */, - F962E8C90F5DE6C8009A5495 /* DXFLoader.cpp in Sources */, - F962E8CA0F5DE6C8009A5495 /* LWOBLoader.cpp in Sources */, - F962E8CB0F5DE6C8009A5495 /* TerragenLoader.cpp in Sources */, - F962E8D70F5DE6C8009A5495 /* B3DImporter.cpp in Sources */, - 7411B15611416D5E00BCD793 /* CSMLoader.cpp in Sources */, - 7411B16111416DDD00BCD793 /* LWSLoader.cpp in Sources */, - 7411B16B11416DF400BCD793 /* LWOAnimation.cpp in Sources */, - 7411B17811416E2500BCD793 /* MS3DLoader.cpp in Sources */, - 7411B19311416EBC00BCD793 /* UnrealLoader.cpp in Sources */, - 74C9BB5811ACBB1000AF885C /* BlenderDNA.cpp in Sources */, - 74C9BB5A11ACBB1000AF885C /* BlenderLoader.cpp in Sources */, - 74C9BB5C11ACBB1000AF885C /* BlenderScene.cpp in Sources */, - 74C9BB8E11ACBB9900AF885C /* AssimpPCH.cpp in Sources */, - 74C9BB9F11ACBBBC00AF885C /* COBLoader.cpp in Sources */, - 8E7ABBB7127E0F1A00512ED1 /* Q3BSPFileImporter.cpp in Sources */, - 8E7ABBB9127E0F1A00512ED1 /* Q3BSPFileParser.cpp in Sources */, - 8E7ABBBB127E0F1A00512ED1 /* Q3BSPZipArchive.cpp in Sources */, - 8E7ABBCA127E0F2A00512ED1 /* NDOLoader.cpp in Sources */, - 8E7ABBD8127E0F3800512ED1 /* BlenderModifier.cpp in Sources */, - 8E8DEE78127E2B78005EF64D /* ConvertUTF.c in Sources */, - 8E8DEE7F127E2B78005EF64D /* irrXML.cpp in Sources */, - 8E8DEE82127E2B78005EF64D /* ioapi.c in Sources */, - 8E8DEE84127E2B78005EF64D /* unzip.c in Sources */, - F9BA8C41154328B600E63FFE /* OgreImporter.cpp in Sources */, - F9BA8C43154328B600E63FFE /* OgreMaterial.cpp in Sources */, - F9BA8C44154328B600E63FFE /* OgreMesh.cpp in Sources */, - F9BA8C45154328B600E63FFE /* OgreSkeleton.cpp in Sources */, - F99A9F3415436269000682F3 /* PlyExporter.cpp in Sources */, - F9607071154366AB004D91DD /* adler32.c in Sources */, - F9607072154366AB004D91DD /* compress.c in Sources */, - F9607073154366AB004D91DD /* crc32.c in Sources */, - F9607075154366AB004D91DD /* deflate.c in Sources */, - F9607077154366AB004D91DD /* inffast.c in Sources */, - F960707A154366AB004D91DD /* inflate.c in Sources */, - F960707C154366AB004D91DD /* inftrees.c in Sources */, - F960707E154366AB004D91DD /* trees.c in Sources */, - F9607083154366AB004D91DD /* zutil.c in Sources */, - F96070B9154366ED004D91DD /* XGLLoader.cpp in Sources */, - F96070CA1543673B004D91DD /* clipper.cpp in Sources */, - F96070EB1543675E004D91DD /* shapes.cc in Sources */, - F96070EF1543675E004D91DD /* advancing_front.cc in Sources */, - F96070F11543675E004D91DD /* cdt.cc in Sources */, - F96070F31543675E004D91DD /* sweep.cc in Sources */, - F96070F51543675E004D91DD /* sweep_context.cc in Sources */, - 2B7F46E31708365200A106A9 /* Assimp.cpp in Sources */, - 2B7F46E81708365200A106A9 /* AssimpCExport.cpp in Sources */, - 2B7F47011708365200A106A9 /* BaseImporter.cpp in Sources */, - 2B7F470B1708365200A106A9 /* BaseProcess.cpp in Sources */, - 2B7F47A11708365200A106A9 /* CalcTangentsProcess.cpp in Sources */, - 2B7F47BF1708365200A106A9 /* ColladaExporter.cpp in Sources */, - 2B7F47CE1708365200A106A9 /* ColladaLoader.cpp in Sources */, - 2B7F47D81708365200A106A9 /* ColladaParser.cpp in Sources */, - 2B7F47E21708365200A106A9 /* ComputeUVMappingProcess.cpp in Sources */, - 2B7F47EC1708365200A106A9 /* ConvertToLHProcess.cpp in Sources */, - 2B7F48001708365200A106A9 /* DeboneProcess.cpp in Sources */, - 2B7F480A1708365200A106A9 /* DefaultIOStream.cpp in Sources */, - 2B7F48141708365200A106A9 /* DefaultIOSystem.cpp in Sources */, - 2B7F481E1708365200A106A9 /* DefaultLogger.cpp in Sources */, - 2B7F483C1708365200A106A9 /* Exporter.cpp in Sources */, - 2B7F48461708365200A106A9 /* FBXAnimation.cpp in Sources */, - 2B7F484B1708365200A106A9 /* FBXBinaryTokenizer.cpp in Sources */, - 2B7F48551708365200A106A9 /* FBXConverter.cpp in Sources */, - 2B7F485F1708365200A106A9 /* FBXDeformer.cpp in Sources */, - 2B7F48641708365200A106A9 /* FBXDocument.cpp in Sources */, - 2B7F486E1708365200A106A9 /* FBXDocumentUtil.cpp in Sources */, - 2B7F48781708365200A106A9 /* FBXImporter.cpp in Sources */, - 2B7F48871708365200A106A9 /* FBXMaterial.cpp in Sources */, - 2B7F488C1708365200A106A9 /* FBXMeshGeometry.cpp in Sources */, - 2B7F48911708365200A106A9 /* FBXModel.cpp in Sources */, - 2B7F48961708365200A106A9 /* FBXNodeAttribute.cpp in Sources */, - 2B7F489B1708365200A106A9 /* FBXParser.cpp in Sources */, - 2B7F48A51708365200A106A9 /* FBXProperties.cpp in Sources */, - 2B7F48AF1708365200A106A9 /* FBXTokenizer.cpp in Sources */, - 2B7F48B91708365200A106A9 /* FBXUtil.cpp in Sources */, - 2B7F48CD1708365200A106A9 /* FindDegenerates.cpp in Sources */, - 2B7F48D71708365200A106A9 /* FindInstancesProcess.cpp in Sources */, - 2B7F48E11708365200A106A9 /* FindInvalidDataProcess.cpp in Sources */, - 2B7F48EB1708365200A106A9 /* FixNormalsStep.cpp in Sources */, - 2B7F48FA1708365200A106A9 /* GenFaceNormalsProcess.cpp in Sources */, - 2B7F49041708365200A106A9 /* GenVertexNormalsProcess.cpp in Sources */, - 2B7F49271708365200A106A9 /* IFCBoolean.cpp in Sources */, - 2B7F492C1708365200A106A9 /* IFCCurve.cpp in Sources */, - 2B7F49311708365200A106A9 /* IFCGeometry.cpp in Sources */, - 2B7F49361708365200A106A9 /* IFCLoader.cpp in Sources */, - 2B7F49401708365200A106A9 /* IFCMaterial.cpp in Sources */, - 2B7F49451708365200A106A9 /* IFCOpenings.cpp in Sources */, - 2B7F494A1708365200A106A9 /* IFCProfile.cpp in Sources */, - 2B7F494F1708365200A106A9 /* IFCReaderGen.cpp in Sources */, - 2B7F49591708365200A106A9 /* IFCUtil.cpp in Sources */, - 2B7F49681708365200A106A9 /* Importer.cpp in Sources */, - 2B7F49721708365200A106A9 /* ImporterRegistry.cpp in Sources */, - 2B7F49771708365200A106A9 /* ImproveCacheLocality.cpp in Sources */, - 2B7F49A41708365200A106A9 /* JoinVerticesProcess.cpp in Sources */, - 2B7F49AE1708365200A106A9 /* LimitBoneWeightsProcess.cpp in Sources */, - 2B7F49F91708365200A106A9 /* MakeVerboseFormat.cpp in Sources */, - 2B7F4A031708365200A106A9 /* MaterialSystem.cpp in Sources */, - 2B7F4A991708365200A106A9 /* ObjExporter.cpp in Sources */, - 2B7F4AA81708365200A106A9 /* ObjFileImporter.cpp in Sources */, - 2B7F4AB21708365200A106A9 /* ObjFileMtlImporter.cpp in Sources */, - 2B7F4ABC1708365200A106A9 /* ObjFileParser.cpp in Sources */, - 2B7F4AF31708365200A106A9 /* OptimizeGraph.cpp in Sources */, - 2B7F4AFD1708365200A106A9 /* OptimizeMeshes.cpp in Sources */, - 2B7F4B2F1708365200A106A9 /* PostStepRegistry.cpp in Sources */, - 2B7F4B341708365200A106A9 /* PretransformVertices.cpp in Sources */, - 2B7F4B3E1708365200A106A9 /* ProcessHelper.cpp in Sources */, - 2B7F4B8E1708365200A106A9 /* RemoveComments.cpp in Sources */, - 2B7F4B981708365200A106A9 /* RemoveRedundantMaterials.cpp in Sources */, - 2B7F4BA21708365200A106A9 /* RemoveVCProcess.cpp in Sources */, - 2B7F4BB11708365200A106A9 /* SceneCombiner.cpp in Sources */, - 2B7F4BBB1708365200A106A9 /* ScenePreprocessor.cpp in Sources */, - 2B7F4BCA1708365200A106A9 /* SGSpatialSort.cpp in Sources */, - 2B7F4BD41708365200A106A9 /* SkeletonMeshBuilder.cpp in Sources */, - 2B7F4BED1708365200A106A9 /* SortByPTypeProcess.cpp in Sources */, - 2B7F4BF71708365200A106A9 /* SpatialSort.cpp in Sources */, - 2B7F4C011708365200A106A9 /* SplitByBoneCountProcess.cpp in Sources */, - 2B7F4C0B1708365200A106A9 /* SplitLargeMeshes.cpp in Sources */, - 2B7F4C151708365200A106A9 /* StandardShapes.cpp in Sources */, - 2B7F4C291708365200A106A9 /* STEPFileEncoding.cpp in Sources */, - 2B7F4C331708365200A106A9 /* STEPFileReader.cpp in Sources */, - 2B7F4C3D1708365200A106A9 /* STLExporter.cpp in Sources */, - 2B7F4C471708365200A106A9 /* STLLoader.cpp in Sources */, - 2B7F4C5B1708365200A106A9 /* Subdivision.cpp in Sources */, - 2B7F4C651708365200A106A9 /* TargetAnimation.cpp in Sources */, - 2B7F4C791708365200A106A9 /* TextureTransform.cpp in Sources */, - 2B7F4C881708365200A106A9 /* TriangulateProcess.cpp in Sources */, - 2B7F4C9C1708365200A106A9 /* ValidateDataStructure.cpp in Sources */, - 2B7F4CAB1708365200A106A9 /* VertexTriangleAdjacency.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 1DEB916108733D950010E9CD /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = stabs; - EXECUTABLE_PREFIX = lib; - GCC_DYNAMIC_NO_PIC = NO; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ""; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - HEADER_SEARCH_PATHS = /usr/local/include; - LD_DYLIB_INSTALL_NAME = libassimpd.dylib; - LIBRARY_SEARCH_PATHS = "$(inherited)"; - PRODUCT_NAME = assimpd; - SDKROOT = macosx; - VALID_ARCHS = "i386 x86_64 armv7 armv6"; - ZERO_LINK = YES; - }; - name = Debug; - }; - 1DEB916208733D950010E9CD /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - DEBUG_INFORMATION_FORMAT = stabs; - EXECUTABLE_PREFIX = lib; - GCC_MODEL_TUNING = G5; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - HEADER_SEARCH_PATHS = /usr/local/include; - LIBRARY_SEARCH_PATHS = "$(inherited)"; - PRODUCT_NAME = assimp; - SDKROOT = macosx; - STRIP_INSTALLED_PRODUCT = YES; - STRIP_STYLE = "non-global"; - VALID_ARCHS = "i386 x86_64 armv7 armv6"; - }; - name = Release; - }; - 1DEB916508733D950010E9CD /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CONFIGURATION_BUILD_DIR = "$(SYMROOT)"; - CONFIGURATION_TEMP_DIR = "$(OBJROOT)"; - GCC_DEBUGGING_SYMBOLS = full; - GCC_INCREASE_PRECOMPILED_HEADER_SHARING = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PFE_FILE_C_DIALECTS = "c++"; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = ../../code/AssimpPCH.h; - GCC_PREPROCESSOR_DEFINITIONS = DEBUG; - GCC_VERSION = com.apple.compilers.llvmgcc42; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = "/usr/local/include/boost-1_38"; - LD_DYLIB_INSTALL_NAME = libassimp.dylib; - LIBRARY_SEARCH_PATHS = /usr/local/lib; - OBJROOT = "../../obj/$(PROJECT_NAME)_$(CONFIGURATION)_MacOSX"; - ONLY_ACTIVE_ARCH = YES; - OTHER_LDFLAGS = ""; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk"; - SYMROOT = "../../bin/$(PROJECT_NAME)_$(CONFIGURATION)_MacOSX"; - }; - name = Debug; - }; - 1DEB916608733D950010E9CD /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CONFIGURATION_BUILD_DIR = "$(SYMROOT)"; - CONFIGURATION_TEMP_DIR = "$(OBJROOT)"; - GCC_INCREASE_PRECOMPILED_HEADER_SHARING = YES; - GCC_PFE_FILE_C_DIALECTS = "c++"; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = ../../code/AssimpPCH.h; - GCC_PREPROCESSOR_DEFINITIONS = NDEBUG; - GCC_VERSION = com.apple.compilers.llvmgcc42; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = "/usr/local/include/boost-1_38"; - LD_DYLIB_INSTALL_NAME = libassimp.dylib; - LIBRARY_SEARCH_PATHS = /usr/local/lib; - OBJROOT = "../../obj/$(PROJECT_NAME)_$(CONFIGURATION)_MacOSX"; - OTHER_LDFLAGS = ""; - SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk"; - SYMROOT = "../../bin/$(PROJECT_NAME)_$(CONFIGURATION)_MacOSX"; - }; - name = Release; - }; - 745FF8FE113ECB080020C31B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = stabs; - EXECUTABLE_PREFIX = lib; - GCC_DYNAMIC_NO_PIC = NO; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ASSIMP_BUILD_BOOST_WORKAROUND; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - HEADER_SEARCH_PATHS = "${SRCROOT}/../../code/BoostWorkaround"; - LD_DYLIB_INSTALL_NAME = libassimpd.dylib; - LIBRARY_SEARCH_PATHS = "$(inherited)"; - PRODUCT_NAME = assimpd; - SDKROOT = macosx; - VALID_ARCHS = "i386 x86_64 armv6 armv7"; - ZERO_LINK = YES; - }; - name = Debug; - }; - 745FF8FF113ECB080020C31B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - COMBINE_HIDPI_IMAGES = YES; - DEBUG_INFORMATION_FORMAT = stabs; - EXECUTABLE_PREFIX = lib; - GCC_MODEL_TUNING = G5; - GCC_PREPROCESSOR_DEFINITIONS = ( - NDEBUG, - ASSIMP_BUILD_BOOST_WORKAROUND, - ); - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - HEADER_SEARCH_PATHS = "${SRCROOT}/../../code/BoostWorkaround"; - LIBRARY_SEARCH_PATHS = "$(inherited)"; - PRODUCT_NAME = assimp; - SDKROOT = macosx; - STRIP_INSTALLED_PRODUCT = YES; - STRIP_STYLE = "non-global"; - VALID_ARCHS = "i386 x86_64 armv6 armv7"; - }; - name = Release; - }; - 745FF9E1113ECC660020C31B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_SYMBOL_SEPARATION = NO; - GCC_INLINES_ARE_PRIVATE_EXTERN = YES; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ASSIMP_BUILD_BOOST_WORKAROUND; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - HEADER_SEARCH_PATHS = "${SRCROOT}/../../code/BoostWorkaround"; - INSTALL_PATH = /usr/local/lib; - LD_DYLIB_INSTALL_NAME = ""; - ONLY_ACTIVE_ARCH = NO; - PRODUCT_NAME = assimpd; - SDKROOT = macosx; - SEPARATE_STRIP = NO; - SKIP_INSTALL = YES; - STRIP_INSTALLED_PRODUCT = NO; - VALID_ARCHS = "x86_64 i386"; - }; - name = Debug; - }; - 745FF9E2113ECC660020C31B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = YES; - GCC_ENABLE_SYMBOL_SEPARATION = NO; - GCC_INLINES_ARE_PRIVATE_EXTERN = YES; - GCC_MODEL_TUNING = G5; - GCC_PREPROCESSOR_DEFINITIONS = ( - NDEBUG, - ASSIMP_BUILD_BOOST_WORKAROUND, - ); - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - HEADER_SEARCH_PATHS = "${SRCROOT}/../../code/BoostWorkaround"; - INSTALL_PATH = /usr/local/lib; - PRODUCT_NAME = assimp; - SDKROOT = macosx; - SEPARATE_STRIP = NO; - SKIP_INSTALL = YES; - STRIP_INSTALLED_PRODUCT = NO; - VALID_ARCHS = "x86_64 i386"; - ZERO_LINK = NO; - }; - name = Release; - }; - B919763D163AEA54009C397B /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = NO; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_SYMBOL_SEPARATION = NO; - GCC_INLINES_ARE_PRIVATE_EXTERN = YES; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ASSIMP_BUILD_BOOST_WORKAROUND; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - HEADER_SEARCH_PATHS = "${SRCROOT}/../../code/BoostWorkaround"; - INSTALL_PATH = /usr/local/lib; - LD_DYLIB_INSTALL_NAME = ""; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/usr/lib\"", - ); - OBJROOT = "../../obj/$(PROJECT_NAME)_$(CONFIGURATION)_iOS"; - ONLY_ACTIVE_ARCH = NO; - PRODUCT_NAME = "assimp-ios"; - SDKROOT = iphoneos; - SEPARATE_STRIP = NO; - SKIP_INSTALL = YES; - STRIP_INSTALLED_PRODUCT = NO; - SYMROOT = "../../bin/$(PROJECT_NAME)_$(CONFIGURATION)_iOS"; - }; - name = Debug; - }; - B919763E163AEA54009C397B /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - COPY_PHASE_STRIP = YES; - GCC_ENABLE_SYMBOL_SEPARATION = NO; - GCC_INLINES_ARE_PRIVATE_EXTERN = YES; - GCC_MODEL_TUNING = G5; - GCC_PREPROCESSOR_DEFINITIONS = ( - NDEBUG, - ASSIMP_BUILD_BOOST_WORKAROUND, - ); - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - HEADER_SEARCH_PATHS = "${SRCROOT}/../../code/BoostWorkaround"; - INSTALL_PATH = /usr/local/lib; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SYSTEM_APPS_DIR)/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/usr/lib\"", - ); - OBJROOT = "../../obj/$(PROJECT_NAME)_$(CONFIGURATION)_iOS"; - ONLY_ACTIVE_ARCH = NO; - PRODUCT_NAME = "assimp-ios"; - SDKROOT = iphoneos; - SEPARATE_STRIP = NO; - SKIP_INSTALL = YES; - STRIP_INSTALLED_PRODUCT = NO; - SYMROOT = "../../bin/$(PROJECT_NAME)_$(CONFIGURATION)_iOS"; - ZERO_LINK = NO; - }; - name = Release; - }; - F962E8850F5DE66B009A5495 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = stabs; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_SYMBOL_SEPARATION = NO; - GCC_INLINES_ARE_PRIVATE_EXTERN = YES; - GCC_MODEL_TUNING = G5; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ""; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - HEADER_SEARCH_PATHS = /usr/local/include; - INSTALL_PATH = /usr/local/lib; - LD_DYLIB_INSTALL_NAME = ""; - PRODUCT_NAME = assimpd; - SDKROOT = macosx; - SEPARATE_STRIP = NO; - SKIP_INSTALL = YES; - STRIP_INSTALLED_PRODUCT = NO; - VALID_ARCHS = "i386 x86_64 armv7 armv6"; - }; - name = Debug; - }; - F962E8860F5DE66B009A5495 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_ENABLE_SYMBOL_SEPARATION = NO; - GCC_INLINES_ARE_PRIVATE_EXTERN = YES; - GCC_MODEL_TUNING = G5; - GCC_VERSION = com.apple.compilers.llvm.clang.1_0; - HEADER_SEARCH_PATHS = /usr/local/include; - INSTALL_PATH = /usr/local/lib; - PRODUCT_NAME = assimp; - SDKROOT = macosx; - SEPARATE_STRIP = NO; - SKIP_INSTALL = YES; - STRIP_INSTALLED_PRODUCT = NO; - VALID_ARCHS = "i386 x86_64 armv7 armv6"; - ZERO_LINK = NO; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 1DEB916008733D950010E9CD /* Build configuration list for PBXNativeTarget "assimp" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1DEB916108733D950010E9CD /* Debug */, - 1DEB916208733D950010E9CD /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 1DEB916408733D950010E9CD /* Build configuration list for PBXProject "assimp" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1DEB916508733D950010E9CD /* Debug */, - 1DEB916608733D950010E9CD /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 745FF8FD113ECB080020C31B /* Build configuration list for PBXNativeTarget "assimp-no-boost" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 745FF8FE113ECB080020C31B /* Debug */, - 745FF8FF113ECB080020C31B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 745FF9E0113ECC660020C31B /* Build configuration list for PBXNativeTarget "assimp-static-no-boost" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 745FF9E1113ECC660020C31B /* Debug */, - 745FF9E2113ECC660020C31B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - B919763C163AEA54009C397B /* Build configuration list for PBXNativeTarget "assimp-ios-static-no-boost" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - B919763D163AEA54009C397B /* Debug */, - B919763E163AEA54009C397B /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - F962E8870F5DE689009A5495 /* Build configuration list for PBXNativeTarget "assimp-static" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - F962E8850F5DE66B009A5495 /* Debug */, - F962E8860F5DE66B009A5495 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 0867D690FE84028FC02AAC07 /* Project object */; -} diff --git a/workspaces/xcode3/info.txt b/workspaces/xcode3/info.txt deleted file mode 100644 index d22a76b6f..000000000 --- a/workspaces/xcode3/info.txt +++ /dev/null @@ -1,6 +0,0 @@ -The xcode project files in this directory are contributed by Andy Maloney and are not continuously updated. -Currently, it's for Assimp r352. If you're using a newer revision, watch out for missing files/includes/... - -See Andy's description at -http://sourceforge.net/tracker/index.php?func=detail&aid=2659135&group_id=226462&atid=1067634 (Tracker item 2659135) -for more information. diff --git a/workspaces/xcode6/Assimp.xcodeproj/project.pbxproj b/workspaces/xcode6/Assimp.xcodeproj/project.pbxproj deleted file mode 100644 index 249aba3a3..000000000 --- a/workspaces/xcode6/Assimp.xcodeproj/project.pbxproj +++ /dev/null @@ -1,2074 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 2DC891CA1D2CFA22001E0B0E /* D3MFImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2DC891C61D2CFA22001E0B0E /* D3MFImporter.cpp */; }; - 2DC891CB1D2CFA22001E0B0E /* D3MFOpcPackage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2DC891C81D2CFA22001E0B0E /* D3MFOpcPackage.cpp */; }; - 2DC891D01D2CFA75001E0B0E /* C4DImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2DC891CE1D2CFA75001E0B0E /* C4DImporter.cpp */; }; - 7F79242A1AB43E20005A8E5D /* 3DSConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 15221A74FC9C4B2AAA7306E3 /* 3DSConverter.cpp */; }; - 7F79242B1AB43E20005A8E5D /* 3DSExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ECCBBF2D75A44335AB93C84A /* 3DSExporter.cpp */; }; - 7F79242C1AB43E20005A8E5D /* 3DSLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02E9476D129940BF84DE6682 /* 3DSLoader.cpp */; }; - 7F79242D1AB43E20005A8E5D /* ACLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F1076BAC69DB4935A93045A8 /* ACLoader.cpp */; }; - 7F79242E1AB43E20005A8E5D /* ASELoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C477FA4D89548F1BCEDC5A0 /* ASELoader.cpp */; }; - 7F79242F1AB43E20005A8E5D /* ASEParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 929F59CCA32549EC884A5033 /* ASEParser.cpp */; }; - 7F7924301AB43E20005A8E5D /* AssbinExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6389F68312384CFD847B1D13 /* AssbinExporter.cpp */; }; - 7F7924311AB43E20005A8E5D /* AssbinLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D9FEEF58B24548F782A5D53C /* AssbinLoader.cpp */; }; - 7F7924321AB43E20005A8E5D /* Assimp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 705D30EE141A48F292783F0E /* Assimp.cpp */; }; - 7F7924331AB43E20005A8E5D /* AssimpCExport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1A9535EDF9A4FF2B8DABD7D /* AssimpCExport.cpp */; }; - 7F7924351AB43E20005A8E5D /* AssxmlExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B3E8A1BEF8E74F04AE06871B /* AssxmlExporter.cpp */; }; - 7F7924361AB43E20005A8E5D /* B3DImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FCCB4BB481FB461688FE2F29 /* B3DImporter.cpp */; }; - 7F7924371AB43E20005A8E5D /* BVHLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C80B9A3AF4204AE08AA50BAE /* BVHLoader.cpp */; }; - 7F7924381AB43E20005A8E5D /* BaseImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A58410FEAA884A2D8D73ACCE /* BaseImporter.cpp */; }; - 7F7924391AB43E20005A8E5D /* BaseProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAB6BC13FCFE40F5801D0972 /* BaseProcess.cpp */; }; - 7F79243A1AB43E20005A8E5D /* Bitmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 10238FBD7A9D401A82D667CB /* Bitmap.cpp */; }; - 7F79243B1AB43E20005A8E5D /* BlenderBMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 603AFA882AFF49AEAC2C8FA2 /* BlenderBMesh.cpp */; }; - 7F79243C1AB43E20005A8E5D /* BlenderDNA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B65258E349704523BC43904D /* BlenderDNA.cpp */; }; - 7F79243D1AB43E20005A8E5D /* BlenderLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 906F71D342544BF381E1318E /* BlenderLoader.cpp */; }; - 7F79243E1AB43E20005A8E5D /* BlenderModifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3106D75C13874F5AB3EBBFE7 /* BlenderModifier.cpp */; }; - 7F79243F1AB43E20005A8E5D /* BlenderScene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE0D259917354C80BE1CC791 /* BlenderScene.cpp */; }; - 7F7924401AB43E20005A8E5D /* BlenderTessellator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 12C5DD7A285042EDB1897FAE /* BlenderTessellator.cpp */; }; - 7F7924411AB43E20005A8E5D /* COBLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C84DA0E6CE13493D833BA1C1 /* COBLoader.cpp */; }; - 7F7924421AB43E20005A8E5D /* CSMLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 77908990BEF04D0881E8AE80 /* CSMLoader.cpp */; }; - 7F7924431AB43E20005A8E5D /* CalcTangentsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90DD6CA40A5E41458E11FF3E /* CalcTangentsProcess.cpp */; }; - 7F7924441AB43E20005A8E5D /* ColladaExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1C0527629078403F81CFD117 /* ColladaExporter.cpp */; }; - 7F7924451AB43E20005A8E5D /* ColladaLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A4706D216414D4F8AA72EC9 /* ColladaLoader.cpp */; }; - 7F7924461AB43E20005A8E5D /* ColladaParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 420D77ED33554D54AA4D50EF /* ColladaParser.cpp */; }; - 7F7924471AB43E20005A8E5D /* ComputeUVMappingProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ABBB4561E72413EB40702C3 /* ComputeUVMappingProcess.cpp */; }; - 7F7924481AB43E20005A8E5D /* ConvertToLHProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 92D8734FFF9742B39A371B70 /* ConvertToLHProcess.cpp */; }; - 7F7924491AB43E20005A8E5D /* DXFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 466D6B9A7CCD402D9AA87071 /* DXFLoader.cpp */; }; - 7F79244A1AB43E20005A8E5D /* DeboneProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6E20FCC571F144DDBD831CCB /* DeboneProcess.cpp */; }; - 7F79244B1AB43E20005A8E5D /* DefaultIOStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F9FEF4D69EFC4605A4F752E5 /* DefaultIOStream.cpp */; }; - 7F79244C1AB43E20005A8E5D /* DefaultIOSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1D502654EF864101A2DA9476 /* DefaultIOSystem.cpp */; }; - 7F79244D1AB43E20005A8E5D /* DefaultLogger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A9E9EB834E09420197C3FB8C /* DefaultLogger.cpp */; }; - 7F79244E1AB43E20005A8E5D /* Exporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FF4E90FB1A3446F095ECC8BD /* Exporter.cpp */; }; - 7F79244F1AB43E20005A8E5D /* FBXAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EAD34F1AA6664B6B935C9421 /* FBXAnimation.cpp */; }; - 7F7924501AB43E20005A8E5D /* FBXBinaryTokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1108AC28566B4D2B9F27C691 /* FBXBinaryTokenizer.cpp */; }; - 7F7924511AB43E20005A8E5D /* FBXConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7A56A688A3845768410F500 /* FBXConverter.cpp */; }; - 7F7924521AB43E20005A8E5D /* FBXDeformer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9855496CEA774F4FA7FBB862 /* FBXDeformer.cpp */; }; - 7F7924531AB43E20005A8E5D /* FBXDocument.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F22D5BA425444A028DA42BEA /* FBXDocument.cpp */; }; - 7F7924541AB43E20005A8E5D /* FBXDocumentUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BB38E7E7661842448F008372 /* FBXDocumentUtil.cpp */; }; - 7F7924551AB43E20005A8E5D /* FBXImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B4C688FA08F44716855CDD3C /* FBXImporter.cpp */; }; - 7F7924561AB43E20005A8E5D /* FBXMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EE6163EB035149A6B8139DB8 /* FBXMaterial.cpp */; }; - 7F7924571AB43E20005A8E5D /* FBXMeshGeometry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42E110B9E6924AF9B55AE65A /* FBXMeshGeometry.cpp */; }; - 7F7924581AB43E20005A8E5D /* FBXModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A61BDC559CE4186B03C0396 /* FBXModel.cpp */; }; - 7F7924591AB43E20005A8E5D /* FBXNodeAttribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33B70115CA54405F895BA471 /* FBXNodeAttribute.cpp */; }; - 7F79245A1AB43E20005A8E5D /* FBXParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5F373DF3B03B4B848B78EAD2 /* FBXParser.cpp */; }; - 7F79245B1AB43E20005A8E5D /* FBXProperties.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9D203F78B24C4D7E8E2084A3 /* FBXProperties.cpp */; }; - 7F79245C1AB43E20005A8E5D /* FBXTokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CF07D05DC86F4C98BC42FDCF /* FBXTokenizer.cpp */; }; - 7F79245D1AB43E20005A8E5D /* FBXUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E6332CD992D447CA910DA456 /* FBXUtil.cpp */; }; - 7F79245E1AB43E20005A8E5D /* FindDegenerates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BABB7734139C452A9DDEE797 /* FindDegenerates.cpp */; }; - 7F79245F1AB43E20005A8E5D /* FindInstancesProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C9A101D1311C4E77AAEDD94C /* FindInstancesProcess.cpp */; }; - 7F7924601AB43E20005A8E5D /* FindInvalidDataProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B4221AA0AD2418FAA45EB64 /* FindInvalidDataProcess.cpp */; }; - 7F7924611AB43E20005A8E5D /* FixNormalsStep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C54518F708BA4A328D5D7325 /* FixNormalsStep.cpp */; }; - 7F7924621AB43E20005A8E5D /* GenFaceNormalsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 982AE676D2364350B1FBD095 /* GenFaceNormalsProcess.cpp */; }; - 7F7924631AB43E20005A8E5D /* GenVertexNormalsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A0AED12A1A6D4635A8CFB65A /* GenVertexNormalsProcess.cpp */; }; - 7F7924641AB43E20005A8E5D /* HMPLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43ABFF591F374920A5E18A24 /* HMPLoader.cpp */; }; - 7F7924651AB43E20005A8E5D /* IFCBoolean.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 285D1FDA48EC4DD8933B603E /* IFCBoolean.cpp */; }; - 7F7924661AB43E20005A8E5D /* IFCCurve.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E7FD92FFCF441B0A60FC8B4 /* IFCCurve.cpp */; }; - 7F7924671AB43E20005A8E5D /* IFCGeometry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3267EBBA6EEB435F83FF25E4 /* IFCGeometry.cpp */; }; - 7F7924681AB43E20005A8E5D /* IFCLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0E9BB0220704C5D93CE7CE9 /* IFCLoader.cpp */; }; - 7F7924691AB43E20005A8E5D /* IFCMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0014AE5E87A74AAA9EF0EC4B /* IFCMaterial.cpp */; }; - 7F79246A1AB43E20005A8E5D /* IFCOpenings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74679D2078FD46ED9AC73355 /* IFCOpenings.cpp */; }; - 7F79246B1AB43E20005A8E5D /* IFCProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46E9F455A3284DB399986293 /* IFCProfile.cpp */; }; - 7F79246C1AB43E20005A8E5D /* IFCReaderGen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F5D1E6368384D429BA29D5A /* IFCReaderGen.cpp */; }; - 7F79246D1AB43E20005A8E5D /* IFCUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 59E3D32E3FC7438DB148537F /* IFCUtil.cpp */; }; - 7F79246E1AB43E20005A8E5D /* IRRLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97DFA90F9D0C4B999C150B10 /* IRRLoader.cpp */; }; - 7F79246F1AB43E20005A8E5D /* IRRMeshLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD7FFD53046F4AEB898C0832 /* IRRMeshLoader.cpp */; }; - 7F7924701AB43E20005A8E5D /* IRRShared.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CC54A231FF6B4B0CABCFD167 /* IRRShared.cpp */; }; - 7F7924711AB43E20005A8E5D /* Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9472EFB6831740DD91471337 /* Importer.cpp */; }; - 7F7924721AB43E20005A8E5D /* ImporterRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D029CE902F8045B0B3AFFDDB /* ImporterRegistry.cpp */; }; - 7F7924731AB43E20005A8E5D /* ImproveCacheLocality.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70D5FDFA995E45E6A3E8FD37 /* ImproveCacheLocality.cpp */; }; - 7F7924741AB43E20005A8E5D /* JoinVerticesProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B36DA471B9E142FC9425EC45 /* JoinVerticesProcess.cpp */; }; - 7F7924751AB43E20005A8E5D /* LWOAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 680C392FFE0B4CC5ABC7CA64 /* LWOAnimation.cpp */; }; - 7F7924761AB43E20005A8E5D /* LWOBLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D629F6BF53864979B7619067 /* LWOBLoader.cpp */; }; - 7F7924771AB43E20005A8E5D /* LWOLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5A4E05386C094B809A315A07 /* LWOLoader.cpp */; }; - 7F7924781AB43E20005A8E5D /* LWOMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ED21FC57A384CE6B4F53C0C /* LWOMaterial.cpp */; }; - 7F7924791AB43E20005A8E5D /* LWSLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFF41974881F466A9561BE4B /* LWSLoader.cpp */; }; - 7F79247A1AB43E20005A8E5D /* LimitBoneWeightsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E065DB38B0284196A9283CA3 /* LimitBoneWeightsProcess.cpp */; }; - 7F79247B1AB43E20005A8E5D /* MD2Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49B655CCE1314D4E8A94B371 /* MD2Loader.cpp */; }; - 7F79247C1AB43E20005A8E5D /* MD3Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 563FBACCFD774BDEA4AEAC10 /* MD3Loader.cpp */; }; - 7F79247D1AB43E20005A8E5D /* MD5Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A277DBC1EFB944F995659A20 /* MD5Loader.cpp */; }; - 7F79247E1AB43E20005A8E5D /* MD5Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0BC5FD00572F4C58B267A0EC /* MD5Parser.cpp */; }; - 7F79247F1AB43E20005A8E5D /* MDCLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 35E4944C052A4C91BF31DE5F /* MDCLoader.cpp */; }; - 7F7924801AB43E20005A8E5D /* MDLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA92FFC8B06D4569AD9C4CB1 /* MDLLoader.cpp */; }; - 7F7924811AB43E20005A8E5D /* MDLMaterialLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CEC69808E1844C23B95D3475 /* MDLMaterialLoader.cpp */; }; - 7F7924821AB43E20005A8E5D /* MS3DLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7A990C6FF244DC397B7BA7C /* MS3DLoader.cpp */; }; - 7F7924831AB43E20005A8E5D /* MakeVerboseFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21B797DAB0E0427C9339AE0F /* MakeVerboseFormat.cpp */; }; - 7F7924841AB43E20005A8E5D /* MaterialSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FF72CB6E99E40E19AE0E64C /* MaterialSystem.cpp */; }; - 7F7924851AB43E20005A8E5D /* NDOLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B4F1B5789CA540C78FB9219D /* NDOLoader.cpp */; }; - 7F7924861AB43E20005A8E5D /* NFFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0D6E8E292F594A2DAFF53564 /* NFFLoader.cpp */; }; - 7F7924871AB43E20005A8E5D /* OFFLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EFD557FE2C3A46D78F070655 /* OFFLoader.cpp */; }; - 7F7924881AB43E20005A8E5D /* ObjExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE811A81663A492A84E13937 /* ObjExporter.cpp */; }; - 7F7924891AB43E20005A8E5D /* ObjFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 862131D4574B4CABA5EC957B /* ObjFileImporter.cpp */; }; - 7F79248A1AB43E20005A8E5D /* ObjFileMtlImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4108529663904025B21E526B /* ObjFileMtlImporter.cpp */; }; - 7F79248B1AB43E20005A8E5D /* ObjFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ACF73EEAB2424213BF7158D5 /* ObjFileParser.cpp */; }; - 7F79248C1AB43E20005A8E5D /* OgreBinarySerializer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 56ADEC4899C047F2839AD791 /* OgreBinarySerializer.cpp */; }; - 7F79248D1AB43E20005A8E5D /* OgreImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 923283A9791E4B4E86D623FC /* OgreImporter.cpp */; }; - 7F79248E1AB43E20005A8E5D /* OgreMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F75457C6D026451B9267B65E /* OgreMaterial.cpp */; }; - 7F79248F1AB43E20005A8E5D /* OgreStructs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79A49EFE23E34E1CBA2E4377 /* OgreStructs.cpp */; }; - 7F7924901AB43E20005A8E5D /* OgreXmlSerializer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = EF9F805A4BA4428CA98C9DE5 /* OgreXmlSerializer.cpp */; }; - 7F7924911AB43E20005A8E5D /* OptimizeGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AAB9AE5328F843F5A8A3E85C /* OptimizeGraph.cpp */; }; - 7F7924921AB43E20005A8E5D /* OptimizeMeshes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACC87E846AE4E4A86E1AEF4 /* OptimizeMeshes.cpp */; }; - 7F7924931AB43E20005A8E5D /* PlyExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E51043448F1744FFA78526D5 /* PlyExporter.cpp */; }; - 7F7924941AB43E20005A8E5D /* PlyLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 409C98EE093C499B8A574CA9 /* PlyLoader.cpp */; }; - 7F7924951AB43E20005A8E5D /* PlyParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2C4D504725E540109530E254 /* PlyParser.cpp */; }; - 7F7924961AB43E20005A8E5D /* PostStepRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E663847651834244834CB9F5 /* PostStepRegistry.cpp */; }; - 7F7924971AB43E20005A8E5D /* PretransformVertices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 023C115651B54570AA2040DB /* PretransformVertices.cpp */; }; - 7F7924981AB43E20005A8E5D /* ProcessHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 890E32C714444692AA016AE5 /* ProcessHelper.cpp */; }; - 7F7924991AB43E20005A8E5D /* Q3BSPFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A88D56FBEA084A3EA9A0ECB3 /* Q3BSPFileImporter.cpp */; }; - 7F79249A1AB43E20005A8E5D /* Q3BSPFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A60A00727F04E049CF3AE33 /* Q3BSPFileParser.cpp */; }; - 7F79249B1AB43E20005A8E5D /* Q3BSPZipArchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43C75175738C4119871E8BB0 /* Q3BSPZipArchive.cpp */; }; - 7F79249C1AB43E20005A8E5D /* Q3DLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C5178B3983F147F3B9BD8217 /* Q3DLoader.cpp */; }; - 7F79249D1AB43E20005A8E5D /* RawLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1D4A669762194B9D9A26DD20 /* RawLoader.cpp */; }; - 7F79249E1AB43E20005A8E5D /* RemoveComments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6A86069DEEDC42B88634F78D /* RemoveComments.cpp */; }; - 7F79249F1AB43E20005A8E5D /* RemoveRedundantMaterials.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADACEBC4973F4FC0A6FEC68A /* RemoveRedundantMaterials.cpp */; }; - 7F7924A01AB43E20005A8E5D /* RemoveVCProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB4ABA17AF264257BDA4D921 /* RemoveVCProcess.cpp */; }; - 7F7924A11AB43E20005A8E5D /* SGSpatialSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52836A0629E24447B924750A /* SGSpatialSort.cpp */; }; - 7F7924A21AB43E20005A8E5D /* SMDLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FD9BEC6B8A264AB092F98E20 /* SMDLoader.cpp */; }; - 7F7924A31AB43E20005A8E5D /* STEPFileEncoding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E11A39E91576445599DF2AC4 /* STEPFileEncoding.cpp */; }; - 7F7924A41AB43E20005A8E5D /* STEPFileReader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CDE3ECA98173418A9F997992 /* STEPFileReader.cpp */; }; - 7F7924A51AB43E20005A8E5D /* STLExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 89D2D359BD854D8AA60CB720 /* STLExporter.cpp */; }; - 7F7924A61AB43E20005A8E5D /* STLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4D2F1605B9484B08BB33402D /* STLLoader.cpp */; }; - 7F7924A71AB43E20005A8E5D /* SceneCombiner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 73A3D87FF2C04C3BA3684F54 /* SceneCombiner.cpp */; }; - 7F7924A81AB43E20005A8E5D /* ScenePreprocessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1775DE08FC8647EB896A0FB3 /* ScenePreprocessor.cpp */; }; - 7F7924A91AB43E20005A8E5D /* SkeletonMeshBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9B2827B3E64147E08A5AD334 /* SkeletonMeshBuilder.cpp */; }; - 7F7924AA1AB43E20005A8E5D /* SortByPTypeProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD9A81E0E27E44718609615B /* SortByPTypeProcess.cpp */; }; - 7F7924AB1AB43E20005A8E5D /* SpatialSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8EEC6646FC044D1E9658A590 /* SpatialSort.cpp */; }; - 7F7924AC1AB43E20005A8E5D /* SplitByBoneCountProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 99A4349D505F4CC593F48CF6 /* SplitByBoneCountProcess.cpp */; }; - 7F7924AD1AB43E20005A8E5D /* SplitLargeMeshes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A43641DC9C1B4B578BC40476 /* SplitLargeMeshes.cpp */; }; - 7F7924AE1AB43E20005A8E5D /* StandardShapes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C18C5023460E4D17B8C922D7 /* StandardShapes.cpp */; }; - 7F7924AF1AB43E20005A8E5D /* Subdivision.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBDEB63CFEB4F2EAA95358D /* Subdivision.cpp */; }; - 7F7924B01AB43E20005A8E5D /* TargetAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6F65B6129F774AEDB8DC845A /* TargetAnimation.cpp */; }; - 7F7924B11AB43E20005A8E5D /* TerragenLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4866DA5A7BFD49F79B61CBF8 /* TerragenLoader.cpp */; }; - 7F7924B21AB43E20005A8E5D /* TextureTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF76D04D95E649BCBC15E64F /* TextureTransform.cpp */; }; - 7F7924B31AB43E20005A8E5D /* TriangulateProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A0AC303D18A48A69AB3BC03 /* TriangulateProcess.cpp */; }; - 7F7924B41AB43E20005A8E5D /* UnrealLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3B8FD96D46314ACD8F157AC3 /* UnrealLoader.cpp */; }; - 7F7924B51AB43E20005A8E5D /* ValidateDataStructure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0EF4F7A237F648C2809A8F31 /* ValidateDataStructure.cpp */; }; - 7F7924B61AB43E20005A8E5D /* VertexTriangleAdjacency.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0AAF26EBF0A64ABDB840BA64 /* VertexTriangleAdjacency.cpp */; }; - 7F7924B71AB43E20005A8E5D /* XFileExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 435DC362E63D4CCBA68656D3 /* XFileExporter.cpp */; }; - 7F7924B81AB43E20005A8E5D /* XFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06DB494DCE4D47FDA00E8B35 /* XFileImporter.cpp */; }; - 7F7924B91AB43E20005A8E5D /* XFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 74C02A113B804568A7E39CBC /* XFileParser.cpp */; }; - 7F7924BA1AB43E20005A8E5D /* XGLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8E395349546A4FDF843E6963 /* XGLLoader.cpp */; }; - 7F7924BB1AB43E20005A8E5D /* ConvertUTF.c in Sources */ = {isa = PBXBuildFile; fileRef = 9A0960F123634603B15EEA38 /* ConvertUTF.c */; }; - 7F7924BC1AB43E20005A8E5D /* clipper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 59F8A11A7AED45CC94CEDF28 /* clipper.cpp */; }; - 7F7924BD1AB43E20005A8E5D /* irrXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 64C6BACDA5DD4139AA26EE81 /* irrXML.cpp */; }; - 7F7924BE1AB43E20005A8E5D /* shapes.cc in Sources */ = {isa = PBXBuildFile; fileRef = AE00939F150F413780C8AAD7 /* shapes.cc */; }; - 7F7924BF1AB43E20005A8E5D /* advancing_front.cc in Sources */ = {isa = PBXBuildFile; fileRef = B72D0BA3EF66439F8D582ED3 /* advancing_front.cc */; }; - 7F7924C01AB43E20005A8E5D /* cdt.cc in Sources */ = {isa = PBXBuildFile; fileRef = 849EC6315E4A4E5FA06521EA /* cdt.cc */; }; - 7F7924C11AB43E20005A8E5D /* sweep.cc in Sources */ = {isa = PBXBuildFile; fileRef = 49E993CD86A346869AF473BC /* sweep.cc */; }; - 7F7924C21AB43E20005A8E5D /* sweep_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5E10483FBE6D4F4594B460E0 /* sweep_context.cc */; }; - 7F7924C31AB43E20005A8E5D /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = AF75E6049338489BB256D295 /* ioapi.c */; }; - 7F7924C41AB43E20005A8E5D /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = 973D4231A4AA4925B019FEEE /* unzip.c */; }; - 7F7A93A81B65D0110094C4DA /* DDLNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F7A93A51B65D0110094C4DA /* DDLNode.cpp */; }; - 7F7A93A91B65D0110094C4DA /* OpenDDLParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F7A93A61B65D0110094C4DA /* OpenDDLParser.cpp */; }; - 7F7A93AA1B65D0110094C4DA /* Value.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F7A93A71B65D0110094C4DA /* Value.cpp */; }; - 7FBE9FEA1B65AC1200D2115E /* OpenGEXExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FBE9FE51B65AC1200D2115E /* OpenGEXExporter.cpp */; }; - 7FBE9FEB1B65AC1200D2115E /* OpenGEXImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FBE9FE71B65AC1200D2115E /* OpenGEXImporter.cpp */; }; - 7FBEA0121B65B11800D2115E /* Version.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7FBEA0111B65B11800D2115E /* Version.cpp */; }; - AFB7F8521C882F1A00D7B6E9 /* OpenDDLCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFB7F8501C882F1A00D7B6E9 /* OpenDDLCommon.cpp */; }; - AFB7F8531C882F1A00D7B6E9 /* OpenDDLExport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFB7F8511C882F1A00D7B6E9 /* OpenDDLExport.cpp */; }; - AFB7F85D1C882F8200D7B6E9 /* glTFExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFB7F8591C882F8200D7B6E9 /* glTFExporter.cpp */; }; - AFB7F85E1C882F8200D7B6E9 /* glTFImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFB7F85B1C882F8200D7B6E9 /* glTFImporter.cpp */; }; - AFB7F8631C88302500D7B6E9 /* SIBImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFB7F8611C88302500D7B6E9 /* SIBImporter.cpp */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 0014AE5E87A74AAA9EF0EC4B /* IFCMaterial.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IFCMaterial.cpp; path = code/IFCMaterial.cpp; sourceTree = SOURCE_ROOT; }; - 005DFE3B6FFC4BEBB7055330 /* ObjFileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ObjFileData.h; path = code/ObjFileData.h; sourceTree = SOURCE_ROOT; }; - 00EB692107B84590B0560BFB /* MD4FileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MD4FileData.h; path = code/MD4FileData.h; sourceTree = SOURCE_ROOT; }; - 023C115651B54570AA2040DB /* PretransformVertices.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = PretransformVertices.cpp; path = code/PretransformVertices.cpp; sourceTree = SOURCE_ROOT; }; - 02587469A85540EE875B04B5 /* heapsort.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = heapsort.h; path = contrib/irrXML/heapsort.h; sourceTree = SOURCE_ROOT; }; - 02E9476D129940BF84DE6682 /* 3DSLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = 3DSLoader.cpp; path = code/3DSLoader.cpp; sourceTree = SOURCE_ROOT; }; - 0535CB113239433DA7CD7FDE /* color4.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = color4.h; path = include/assimp/color4.h; sourceTree = SOURCE_ROOT; }; - 05EA73C462244F1791039BFB /* material.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = material.h; path = include/assimp/material.h; sourceTree = SOURCE_ROOT; }; - 06DB494DCE4D47FDA00E8B35 /* XFileImporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = XFileImporter.cpp; path = code/XFileImporter.cpp; sourceTree = SOURCE_ROOT; }; - 073189BEE7A5466B9EE817D4 /* matrix3x3.inl */ = {isa = PBXFileReference; explicitFileType = sourcecode; fileEncoding = 4; name = matrix3x3.inl; path = include/assimp/matrix3x3.inl; sourceTree = SOURCE_ROOT; }; - 079B3C75D1014265959C427D /* color4.inl */ = {isa = PBXFileReference; explicitFileType = sourcecode; fileEncoding = 4; name = color4.inl; path = include/assimp/color4.inl; sourceTree = SOURCE_ROOT; }; - 08E8379F20984AD59515AD95 /* MD3FileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MD3FileData.h; path = code/MD3FileData.h; sourceTree = SOURCE_ROOT; }; - 0A941971CBF04E8D900E9799 /* JoinVerticesProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = JoinVerticesProcess.h; path = code/JoinVerticesProcess.h; sourceTree = SOURCE_ROOT; }; - 0AA53AD6095A4D1088431EED /* MakeVerboseFormat.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MakeVerboseFormat.h; path = code/MakeVerboseFormat.h; sourceTree = SOURCE_ROOT; }; - 0AAF26EBF0A64ABDB840BA64 /* VertexTriangleAdjacency.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = VertexTriangleAdjacency.cpp; path = code/VertexTriangleAdjacency.cpp; sourceTree = SOURCE_ROOT; }; - 0B519CCAB4B241E59C567077 /* 3DSExporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = 3DSExporter.h; path = code/3DSExporter.h; sourceTree = SOURCE_ROOT; }; - 0BC5FD00572F4C58B267A0EC /* MD5Parser.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MD5Parser.cpp; path = code/MD5Parser.cpp; sourceTree = SOURCE_ROOT; }; - 0C1B00249A554394A4F9CF2A /* ParsingUtils.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ParsingUtils.h; path = code/ParsingUtils.h; sourceTree = SOURCE_ROOT; }; - 0CCD090F58EB40ACBBDBBDEE /* AssbinLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = AssbinLoader.h; path = code/AssbinLoader.h; sourceTree = SOURCE_ROOT; }; - 0D6E8E292F594A2DAFF53564 /* NFFLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = NFFLoader.cpp; path = code/NFFLoader.cpp; sourceTree = SOURCE_ROOT; }; - 0EF256EC06E345EB930772EC /* FBXDocument.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FBXDocument.h; path = code/FBXDocument.h; sourceTree = SOURCE_ROOT; }; - 0EF4F7A237F648C2809A8F31 /* ValidateDataStructure.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ValidateDataStructure.cpp; path = code/ValidateDataStructure.cpp; sourceTree = SOURCE_ROOT; }; - 0FBF026F27F340AD9FABAF02 /* GenFaceNormalsProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = GenFaceNormalsProcess.h; path = code/GenFaceNormalsProcess.h; sourceTree = SOURCE_ROOT; }; - 101172E4EF2E43D988B6B571 /* PretransformVertices.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = PretransformVertices.h; path = code/PretransformVertices.h; sourceTree = SOURCE_ROOT; }; - 1011FC45108745A7BBA98904 /* IRRLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = IRRLoader.h; path = code/IRRLoader.h; sourceTree = SOURCE_ROOT; }; - 10238FBD7A9D401A82D667CB /* Bitmap.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = Bitmap.cpp; path = code/Bitmap.cpp; sourceTree = SOURCE_ROOT; }; - 10E9B0497D844A10BC759A09 /* matrix3x3.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = matrix3x3.h; path = include/assimp/matrix3x3.h; sourceTree = SOURCE_ROOT; }; - 1108AC28566B4D2B9F27C691 /* FBXBinaryTokenizer.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXBinaryTokenizer.cpp; path = code/FBXBinaryTokenizer.cpp; sourceTree = SOURCE_ROOT; }; - 12C5DD7A285042EDB1897FAE /* BlenderTessellator.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = BlenderTessellator.cpp; path = code/BlenderTessellator.cpp; sourceTree = SOURCE_ROOT; }; - 12E167EBA81B4CD3A241D7AF /* irrXML.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = irrXML.h; path = contrib/irrXML/irrXML.h; sourceTree = SOURCE_ROOT; }; - 139DFC029C4C44B09952C645 /* material.inl */ = {isa = PBXFileReference; explicitFileType = sourcecode; fileEncoding = 4; name = material.inl; path = include/assimp/material.inl; sourceTree = SOURCE_ROOT; }; - 13BFADA520C04B15AE256CC2 /* IFCUtil.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = IFCUtil.h; path = code/IFCUtil.h; sourceTree = SOURCE_ROOT; }; - 1520A11AA6E54812939B1FBB /* FileLogStream.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FileLogStream.h; path = code/FileLogStream.h; sourceTree = SOURCE_ROOT; }; - 15221A74FC9C4B2AAA7306E3 /* 3DSConverter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = 3DSConverter.cpp; path = code/3DSConverter.cpp; sourceTree = SOURCE_ROOT; }; - 1533BE4C09F1430C8BF4D248 /* Vertex.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Vertex.h; path = code/Vertex.h; sourceTree = SOURCE_ROOT; }; - 157C3CC81232428FA535E05F /* BlenderLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BlenderLoader.h; path = code/BlenderLoader.h; sourceTree = SOURCE_ROOT; }; - 16437E08A946431EB2EFA3E0 /* SortByPTypeProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = SortByPTypeProcess.h; path = code/SortByPTypeProcess.h; sourceTree = SOURCE_ROOT; }; - 1775DE08FC8647EB896A0FB3 /* ScenePreprocessor.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ScenePreprocessor.cpp; path = code/ScenePreprocessor.cpp; sourceTree = SOURCE_ROOT; }; - 180177D50FDA4C10AD629DC2 /* ObjFileMtlImporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ObjFileMtlImporter.h; path = code/ObjFileMtlImporter.h; sourceTree = SOURCE_ROOT; }; - 1A0AC303D18A48A69AB3BC03 /* TriangulateProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = TriangulateProcess.cpp; path = code/TriangulateProcess.cpp; sourceTree = SOURCE_ROOT; }; - 1A4706D216414D4F8AA72EC9 /* ColladaLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ColladaLoader.cpp; path = code/ColladaLoader.cpp; sourceTree = SOURCE_ROOT; }; - 1A61BDC559CE4186B03C0396 /* FBXModel.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXModel.cpp; path = code/FBXModel.cpp; sourceTree = SOURCE_ROOT; }; - 1AF1EE8EFE594A40ACE03D19 /* fast_atof.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = fast_atof.h; path = code/fast_atof.h; sourceTree = SOURCE_ROOT; }; - 1BC6B0FE92DD4F38803BC17B /* CSMLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = CSMLoader.h; path = code/CSMLoader.h; sourceTree = SOURCE_ROOT; }; - 1C0527629078403F81CFD117 /* ColladaExporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ColladaExporter.cpp; path = code/ColladaExporter.cpp; sourceTree = SOURCE_ROOT; }; - 1CBCEE37D89145F19F23F036 /* MD3Loader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MD3Loader.h; path = code/MD3Loader.h; sourceTree = SOURCE_ROOT; }; - 1D4A669762194B9D9A26DD20 /* RawLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = RawLoader.cpp; path = code/RawLoader.cpp; sourceTree = SOURCE_ROOT; }; - 1D502654EF864101A2DA9476 /* DefaultIOSystem.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = DefaultIOSystem.cpp; path = code/DefaultIOSystem.cpp; sourceTree = SOURCE_ROOT; }; - 1DC56C794E434BA28E5CCC36 /* format.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = format.hpp; path = code/BoostWorkaround/boost/format.hpp; sourceTree = SOURCE_ROOT; }; - 1ED21FC57A384CE6B4F53C0C /* LWOMaterial.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = LWOMaterial.cpp; path = code/LWOMaterial.cpp; sourceTree = SOURCE_ROOT; }; - 1FC965B1F11B45F98051C565 /* ObjFileImporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ObjFileImporter.h; path = code/ObjFileImporter.h; sourceTree = SOURCE_ROOT; }; - 21B797DAB0E0427C9339AE0F /* MakeVerboseFormat.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MakeVerboseFormat.cpp; path = code/MakeVerboseFormat.cpp; sourceTree = SOURCE_ROOT; }; - 21E21BE7CB364AC3AB81E54C /* MD2FileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MD2FileData.h; path = code/MD2FileData.h; sourceTree = SOURCE_ROOT; }; - 23097CBD64E343738B8F22EE /* BlobIOSystem.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BlobIOSystem.h; path = code/BlobIOSystem.h; sourceTree = SOURCE_ROOT; }; - 262DFE65C6D34442AA79D15A /* qnan.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = qnan.h; path = code/qnan.h; sourceTree = SOURCE_ROOT; }; - 267A74499024423A86150697 /* cimport.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = cimport.h; path = include/assimp/cimport.h; sourceTree = SOURCE_ROOT; }; - 267D593135514108B7DEF072 /* sweep_context.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = sweep_context.h; path = contrib/poly2tri/poly2tri/sweep/sweep_context.h; sourceTree = SOURCE_ROOT; }; - 26BF681530B04B73961997CB /* FBXCompileConfig.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FBXCompileConfig.h; path = code/FBXCompileConfig.h; sourceTree = SOURCE_ROOT; }; - 27605E75944D41B0B98260A3 /* ASEParser.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ASEParser.h; path = code/ASEParser.h; sourceTree = SOURCE_ROOT; }; - 278FB5C8BD814F2DAE04A1C7 /* pstdint.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = pstdint.h; path = include/assimp/Compiler/pstdint.h; sourceTree = SOURCE_ROOT; }; - 279D2A482FE9402A8F7EC441 /* quaternion.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = quaternion.h; path = include/assimp/quaternion.h; sourceTree = SOURCE_ROOT; }; - 27F2019E621B4CDA94DD5270 /* UnrealLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = UnrealLoader.h; path = code/UnrealLoader.h; sourceTree = SOURCE_ROOT; }; - 285D1FDA48EC4DD8933B603E /* IFCBoolean.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IFCBoolean.cpp; path = code/IFCBoolean.cpp; sourceTree = SOURCE_ROOT; }; - 28A938B21261484998F68F4A /* FindInstancesProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FindInstancesProcess.h; path = code/FindInstancesProcess.h; sourceTree = SOURCE_ROOT; }; - 296407DE471C4F298742FB59 /* StandardShapes.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = StandardShapes.h; path = code/StandardShapes.h; sourceTree = SOURCE_ROOT; }; - 2ABBB4561E72413EB40702C3 /* ComputeUVMappingProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ComputeUVMappingProcess.cpp; path = code/ComputeUVMappingProcess.cpp; sourceTree = SOURCE_ROOT; }; - 2AC344FBB0C34D49800F4B8A /* GenVertexNormalsProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = GenVertexNormalsProcess.h; path = code/GenVertexNormalsProcess.h; sourceTree = SOURCE_ROOT; }; - 2ACC87E846AE4E4A86E1AEF4 /* OptimizeMeshes.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = OptimizeMeshes.cpp; path = code/OptimizeMeshes.cpp; sourceTree = SOURCE_ROOT; }; - 2BE34AF1CE0C4767ACE21597 /* IFCLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = IFCLoader.h; path = code/IFCLoader.h; sourceTree = SOURCE_ROOT; }; - 2C4D504725E540109530E254 /* PlyParser.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = PlyParser.cpp; path = code/PlyParser.cpp; sourceTree = SOURCE_ROOT; }; - 2DC891C61D2CFA22001E0B0E /* D3MFImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = D3MFImporter.cpp; path = code/D3MFImporter.cpp; sourceTree = ""; }; - 2DC891C71D2CFA22001E0B0E /* D3MFImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = D3MFImporter.h; path = code/D3MFImporter.h; sourceTree = ""; }; - 2DC891C81D2CFA22001E0B0E /* D3MFOpcPackage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = D3MFOpcPackage.cpp; path = code/D3MFOpcPackage.cpp; sourceTree = ""; }; - 2DC891C91D2CFA22001E0B0E /* D3MFOpcPackage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = D3MFOpcPackage.h; path = code/D3MFOpcPackage.h; sourceTree = ""; }; - 2DC891CD1D2CFA75001E0B0E /* ByteSwapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ByteSwapper.h; path = code/ByteSwapper.h; sourceTree = ""; }; - 2DC891CE1D2CFA75001E0B0E /* C4DImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = C4DImporter.cpp; path = code/C4DImporter.cpp; sourceTree = ""; }; - 2DC891CF1D2CFA75001E0B0E /* C4DImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = C4DImporter.h; path = code/C4DImporter.h; sourceTree = ""; }; - 2DCF6F156A3A4B4C807E5368 /* SmoothingGroups.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = SmoothingGroups.h; path = code/SmoothingGroups.h; sourceTree = SOURCE_ROOT; }; - 2E7FD92FFCF441B0A60FC8B4 /* IFCCurve.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IFCCurve.cpp; path = code/IFCCurve.cpp; sourceTree = SOURCE_ROOT; }; - 2F34A6A3C4104625A52BF7C2 /* cexport.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = cexport.h; path = include/assimp/cexport.h; sourceTree = SOURCE_ROOT; }; - 3106D75C13874F5AB3EBBFE7 /* BlenderModifier.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = BlenderModifier.cpp; path = code/BlenderModifier.cpp; sourceTree = SOURCE_ROOT; }; - 32170F499DAC4E4595AF6D6B /* BaseImporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BaseImporter.h; path = code/BaseImporter.h; sourceTree = SOURCE_ROOT; }; - 3267EBBA6EEB435F83FF25E4 /* IFCGeometry.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IFCGeometry.cpp; path = code/IFCGeometry.cpp; sourceTree = SOURCE_ROOT; }; - 32CC68350B7640ACA7C83DDA /* DefaultIOStream.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = DefaultIOStream.h; path = code/DefaultIOStream.h; sourceTree = SOURCE_ROOT; }; - 333F4676A92043739F5A9D32 /* ObjFileParser.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ObjFileParser.h; path = code/ObjFileParser.h; sourceTree = SOURCE_ROOT; }; - 339E56B5FD264481BBF21835 /* CInterfaceIOWrapper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = CInterfaceIOWrapper.h; path = code/CInterfaceIOWrapper.h; sourceTree = SOURCE_ROOT; }; - 33B70115CA54405F895BA471 /* FBXNodeAttribute.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXNodeAttribute.cpp; path = code/FBXNodeAttribute.cpp; sourceTree = SOURCE_ROOT; }; - 3551D90CCED1454A8B912066 /* XFileParser.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = XFileParser.h; path = code/XFileParser.h; sourceTree = SOURCE_ROOT; }; - 35A9B50143214C63A956FA27 /* ConvertToLHProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ConvertToLHProcess.h; path = code/ConvertToLHProcess.h; sourceTree = SOURCE_ROOT; }; - 35E4944C052A4C91BF31DE5F /* MDCLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MDCLoader.cpp; path = code/MDCLoader.cpp; sourceTree = SOURCE_ROOT; }; - 37A3E0E2BB484DD8B9FCCA5E /* NDOLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = NDOLoader.h; path = code/NDOLoader.h; sourceTree = SOURCE_ROOT; }; - 3ACFF3FC39C74C4A966C0FEA /* GenericProperty.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = GenericProperty.h; path = code/GenericProperty.h; sourceTree = SOURCE_ROOT; }; - 3B407EAF162843CBA46BC9D4 /* scene.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = scene.h; path = include/assimp/scene.h; sourceTree = SOURCE_ROOT; }; - 3B8FD96D46314ACD8F157AC3 /* UnrealLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = UnrealLoader.cpp; path = code/UnrealLoader.cpp; sourceTree = SOURCE_ROOT; }; - 3E84DEFC1E0646AD82F79998 /* shared_ptr.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = shared_ptr.hpp; path = code/BoostWorkaround/boost/shared_ptr.hpp; sourceTree = SOURCE_ROOT; }; - 3F5D1E6368384D429BA29D5A /* IFCReaderGen.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IFCReaderGen.cpp; path = code/IFCReaderGen.cpp; sourceTree = SOURCE_ROOT; }; - 409C98EE093C499B8A574CA9 /* PlyLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = PlyLoader.cpp; path = code/PlyLoader.cpp; sourceTree = SOURCE_ROOT; }; - 4108529663904025B21E526B /* ObjFileMtlImporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ObjFileMtlImporter.cpp; path = code/ObjFileMtlImporter.cpp; sourceTree = SOURCE_ROOT; }; - 41C2F6D564924BF4ACE75CAC /* postprocess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = postprocess.h; path = include/assimp/postprocess.h; sourceTree = SOURCE_ROOT; }; - 420D77ED33554D54AA4D50EF /* ColladaParser.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ColladaParser.cpp; path = code/ColladaParser.cpp; sourceTree = SOURCE_ROOT; }; - 42E110B9E6924AF9B55AE65A /* FBXMeshGeometry.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXMeshGeometry.cpp; path = code/FBXMeshGeometry.cpp; sourceTree = SOURCE_ROOT; }; - 42E68041B1C442E3B49FC304 /* B3DImporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = B3DImporter.h; path = code/B3DImporter.h; sourceTree = SOURCE_ROOT; }; - 435DC362E63D4CCBA68656D3 /* XFileExporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = XFileExporter.cpp; path = code/XFileExporter.cpp; sourceTree = SOURCE_ROOT; }; - 43899EB0B0704A9DB8F0C54F /* BlenderDNA.inl */ = {isa = PBXFileReference; explicitFileType = sourcecode; fileEncoding = 4; name = BlenderDNA.inl; path = code/BlenderDNA.inl; sourceTree = SOURCE_ROOT; }; - 43ABFF591F374920A5E18A24 /* HMPLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = HMPLoader.cpp; path = code/HMPLoader.cpp; sourceTree = SOURCE_ROOT; }; - 43C75175738C4119871E8BB0 /* Q3BSPZipArchive.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = Q3BSPZipArchive.cpp; path = code/Q3BSPZipArchive.cpp; sourceTree = SOURCE_ROOT; }; - 43FC808D2F4745ACB06A9D33 /* MD5Parser.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MD5Parser.h; path = code/MD5Parser.h; sourceTree = SOURCE_ROOT; }; - 445F70426FCC42F088405E86 /* COBLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = COBLoader.h; path = code/COBLoader.h; sourceTree = SOURCE_ROOT; }; - 4493838DDEE841BF96A0F008 /* matrix4x4.inl */ = {isa = PBXFileReference; explicitFileType = sourcecode; fileEncoding = 4; name = matrix4x4.inl; path = include/assimp/matrix4x4.inl; sourceTree = SOURCE_ROOT; }; - 4568875B66584E12AA1538C7 /* BlenderBMesh.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BlenderBMesh.h; path = code/BlenderBMesh.h; sourceTree = SOURCE_ROOT; }; - 45BC2EB74251493CBBFAEB5D /* SkeletonMeshBuilder.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = SkeletonMeshBuilder.h; path = code/SkeletonMeshBuilder.h; sourceTree = SOURCE_ROOT; }; - 45E342A1499E4F03ADD49028 /* BVHLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BVHLoader.h; path = code/BVHLoader.h; sourceTree = SOURCE_ROOT; }; - 45F6A2B351AB4B749E55B299 /* PlyParser.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = PlyParser.h; path = code/PlyParser.h; sourceTree = SOURCE_ROOT; }; - 466D6B9A7CCD402D9AA87071 /* DXFLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = DXFLoader.cpp; path = code/DXFLoader.cpp; sourceTree = SOURCE_ROOT; }; - 46E9F455A3284DB399986293 /* IFCProfile.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IFCProfile.cpp; path = code/IFCProfile.cpp; sourceTree = SOURCE_ROOT; }; - 4770D6DCA1854B4F9B85546A /* DeboneProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = DeboneProcess.h; path = code/DeboneProcess.h; sourceTree = SOURCE_ROOT; }; - 47FF3063906E4786ABF0939B /* STEPFile.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = STEPFile.h; path = code/STEPFile.h; sourceTree = SOURCE_ROOT; }; - 4866DA5A7BFD49F79B61CBF8 /* TerragenLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = TerragenLoader.cpp; path = code/TerragenLoader.cpp; sourceTree = SOURCE_ROOT; }; - 4936396409984881858E7B15 /* irrTypes.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = irrTypes.h; path = contrib/irrXML/irrTypes.h; sourceTree = SOURCE_ROOT; }; - 49AFF879142C4BA4865843DC /* Bitmap.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Bitmap.h; path = code/Bitmap.h; sourceTree = SOURCE_ROOT; }; - 49B655CCE1314D4E8A94B371 /* MD2Loader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MD2Loader.cpp; path = code/MD2Loader.cpp; sourceTree = SOURCE_ROOT; }; - 49E993CD86A346869AF473BC /* sweep.cc */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = sweep.cc; path = contrib/poly2tri/poly2tri/sweep/sweep.cc; sourceTree = SOURCE_ROOT; }; - 49FE5C30FC854A3EBD0E9C19 /* irrArray.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = irrArray.h; path = contrib/irrXML/irrArray.h; sourceTree = SOURCE_ROOT; }; - 4A60A00727F04E049CF3AE33 /* Q3BSPFileParser.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = Q3BSPFileParser.cpp; path = code/Q3BSPFileParser.cpp; sourceTree = SOURCE_ROOT; }; - 4B571231CE2B464BBF1E853F /* FindDegenerates.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FindDegenerates.h; path = code/FindDegenerates.h; sourceTree = SOURCE_ROOT; }; - 4BBDEB63CFEB4F2EAA95358D /* Subdivision.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = Subdivision.cpp; path = code/Subdivision.cpp; sourceTree = SOURCE_ROOT; }; - 4CBC1122A79D4F6C94E36CE3 /* StdOStreamLogStream.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = StdOStreamLogStream.h; path = code/StdOStreamLogStream.h; sourceTree = SOURCE_ROOT; }; - 4D2F1605B9484B08BB33402D /* STLLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = STLLoader.cpp; path = code/STLLoader.cpp; sourceTree = SOURCE_ROOT; }; - 4D82A29A8BBF44E69E026F84 /* importerdesc.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = importerdesc.h; path = include/assimp/importerdesc.h; sourceTree = SOURCE_ROOT; }; - 4DABF3CB245F4246B0184513 /* ACLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ACLoader.h; path = code/ACLoader.h; sourceTree = SOURCE_ROOT; }; - 4FE1E4726B144AD1B922A1A0 /* ScenePreprocessor.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ScenePreprocessor.h; path = code/ScenePreprocessor.h; sourceTree = SOURCE_ROOT; }; - 501B18C2B590455D8A3C3E78 /* XGLLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = XGLLoader.h; path = code/XGLLoader.h; sourceTree = SOURCE_ROOT; }; - 50935A81362041BEADF18609 /* utils.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = utils.h; path = contrib/poly2tri/poly2tri/common/utils.h; sourceTree = SOURCE_ROOT; }; - 52836A0629E24447B924750A /* SGSpatialSort.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = SGSpatialSort.cpp; path = code/SGSpatialSort.cpp; sourceTree = SOURCE_ROOT; }; - 531FBC4210644C61954EA4C4 /* MD2Loader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MD2Loader.h; path = code/MD2Loader.h; sourceTree = SOURCE_ROOT; }; - 53537D08E9B44A25B43B697B /* XFileImporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = XFileImporter.h; path = code/XFileImporter.h; sourceTree = SOURCE_ROOT; }; - 5631CE86F56F458EA0E2415F /* HMPLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = HMPLoader.h; path = code/HMPLoader.h; sourceTree = SOURCE_ROOT; }; - 563FBACCFD774BDEA4AEAC10 /* MD3Loader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MD3Loader.cpp; path = code/MD3Loader.cpp; sourceTree = SOURCE_ROOT; }; - 56ADEC4899C047F2839AD791 /* OgreBinarySerializer.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = OgreBinarySerializer.cpp; path = code/OgreBinarySerializer.cpp; sourceTree = SOURCE_ROOT; }; - 56CE07D64D114C4BAB6D9F08 /* Logger.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = Logger.hpp; path = include/assimp/Logger.hpp; sourceTree = SOURCE_ROOT; }; - 56DA1CDC223747F4AFBAF953 /* types.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = types.h; path = include/assimp/types.h; sourceTree = SOURCE_ROOT; }; - 59A1859480754E90B958CA85 /* BlenderTessellator.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BlenderTessellator.h; path = code/BlenderTessellator.h; sourceTree = SOURCE_ROOT; }; - 59E3D32E3FC7438DB148537F /* IFCUtil.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IFCUtil.cpp; path = code/IFCUtil.cpp; sourceTree = SOURCE_ROOT; }; - 59F8A11A7AED45CC94CEDF28 /* clipper.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = clipper.cpp; path = contrib/clipper/clipper.cpp; sourceTree = SOURCE_ROOT; }; - 5A4E05386C094B809A315A07 /* LWOLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = LWOLoader.cpp; path = code/LWOLoader.cpp; sourceTree = SOURCE_ROOT; }; - 5C15EEB253204E8A8E0D0E38 /* Q3BSPFileParser.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Q3BSPFileParser.h; path = code/Q3BSPFileParser.h; sourceTree = SOURCE_ROOT; }; - 5C1EA03E3AE24AA5A778B7F1 /* Profiler.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Profiler.h; path = code/Profiler.h; sourceTree = SOURCE_ROOT; }; - 5D4E64EABD9548A59E9637AF /* irrString.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = irrString.h; path = contrib/irrXML/irrString.h; sourceTree = SOURCE_ROOT; }; - 5E10483FBE6D4F4594B460E0 /* sweep_context.cc */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = sweep_context.cc; path = contrib/poly2tri/poly2tri/sweep/sweep_context.cc; sourceTree = SOURCE_ROOT; }; - 5F373DF3B03B4B848B78EAD2 /* FBXParser.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXParser.cpp; path = code/FBXParser.cpp; sourceTree = SOURCE_ROOT; }; - 5F84BDD0D5D345A2BF1E08E1 /* metadata.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = metadata.h; path = include/assimp/metadata.h; sourceTree = SOURCE_ROOT; }; - 5FBE72DCC6AC485ABCF89B8C /* ImproveCacheLocality.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ImproveCacheLocality.h; path = code/ImproveCacheLocality.h; sourceTree = SOURCE_ROOT; }; - 603AFA882AFF49AEAC2C8FA2 /* BlenderBMesh.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = BlenderBMesh.cpp; path = code/BlenderBMesh.cpp; sourceTree = SOURCE_ROOT; }; - 6162B57DE81A4E538430056E /* IFCReaderGen.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = IFCReaderGen.h; path = code/IFCReaderGen.h; sourceTree = SOURCE_ROOT; }; - 621E96E95F60421EB6B4525C /* MDCLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MDCLoader.h; path = code/MDCLoader.h; sourceTree = SOURCE_ROOT; }; - 62E8551653634972ABBABCAD /* sweep.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = sweep.h; path = contrib/poly2tri/poly2tri/sweep/sweep.h; sourceTree = SOURCE_ROOT; }; - 6347FA5D391D4320B9457D3F /* MS3DLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MS3DLoader.h; path = code/MS3DLoader.h; sourceTree = SOURCE_ROOT; }; - 6389F68312384CFD847B1D13 /* AssbinExporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = AssbinExporter.cpp; path = code/AssbinExporter.cpp; sourceTree = SOURCE_ROOT; }; - 638B3F6AC17A435C9B86C86C /* ColladaExporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ColladaExporter.h; path = code/ColladaExporter.h; sourceTree = SOURCE_ROOT; }; - 6454A961FAF44B3E9086D2F8 /* Q3BSPZipArchive.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Q3BSPZipArchive.h; path = code/Q3BSPZipArchive.h; sourceTree = SOURCE_ROOT; }; - 64C6BACDA5DD4139AA26EE81 /* irrXML.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = irrXML.cpp; path = contrib/irrXML/irrXML.cpp; sourceTree = SOURCE_ROOT; }; - 657B9A15EE7A4B7BA519A969 /* LogStream.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = LogStream.hpp; path = include/assimp/LogStream.hpp; sourceTree = SOURCE_ROOT; }; - 670FE6DD7EDF421488F2F97F /* IRRMeshLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = IRRMeshLoader.h; path = code/IRRMeshLoader.h; sourceTree = SOURCE_ROOT; }; - 680C392FFE0B4CC5ABC7CA64 /* LWOAnimation.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = LWOAnimation.cpp; path = code/LWOAnimation.cpp; sourceTree = SOURCE_ROOT; }; - 680FBD79376A41B690C405B8 /* LineSplitter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = LineSplitter.h; path = code/LineSplitter.h; sourceTree = SOURCE_ROOT; }; - 68703F99581F49CB9E2B9F37 /* LWSLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = LWSLoader.h; path = code/LWSLoader.h; sourceTree = SOURCE_ROOT; }; - 6981B16018CF46CAA54C0BAA /* ColladaLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ColladaLoader.h; path = code/ColladaLoader.h; sourceTree = SOURCE_ROOT; }; - 69AFF47737244CE3BD1653CC /* ProgressHandler.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = ProgressHandler.hpp; path = include/assimp/ProgressHandler.hpp; sourceTree = SOURCE_ROOT; }; - 6A86069DEEDC42B88634F78D /* RemoveComments.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = RemoveComments.cpp; path = code/RemoveComments.cpp; sourceTree = SOURCE_ROOT; }; - 6AC645CEB6F74AE5A62DF68B /* IFF.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = IFF.h; path = code/IFF.h; sourceTree = SOURCE_ROOT; }; - 6BAB32C8E06E43689FC5E7EA /* MD5Loader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MD5Loader.h; path = code/MD5Loader.h; sourceTree = SOURCE_ROOT; }; - 6CC21F1D0E4140FE923E4EE6 /* AssbinExporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = AssbinExporter.h; path = code/AssbinExporter.h; sourceTree = SOURCE_ROOT; }; - 6D72952403D04713A6451654 /* vector3.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = vector3.h; path = include/assimp/vector3.h; sourceTree = SOURCE_ROOT; }; - 6E20FCC571F144DDBD831CCB /* DeboneProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = DeboneProcess.cpp; path = code/DeboneProcess.cpp; sourceTree = SOURCE_ROOT; }; - 6E82409E9D274D278971F3B0 /* Q3BSPFileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Q3BSPFileData.h; path = code/Q3BSPFileData.h; sourceTree = SOURCE_ROOT; }; - 6F49958B5CCF423681133515 /* OgreParsingUtils.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = OgreParsingUtils.h; path = code/OgreParsingUtils.h; sourceTree = SOURCE_ROOT; }; - 6F65B6129F774AEDB8DC845A /* TargetAnimation.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = TargetAnimation.cpp; path = code/TargetAnimation.cpp; sourceTree = SOURCE_ROOT; }; - 6F88E78E61FC4A01BC30BE85 /* ConvertUTF.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ConvertUTF.h; path = contrib/ConvertUTF/ConvertUTF.h; sourceTree = SOURCE_ROOT; }; - 705D30EE141A48F292783F0E /* Assimp.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = Assimp.cpp; path = code/Assimp.cpp; sourceTree = SOURCE_ROOT; }; - 70D5FDFA995E45E6A3E8FD37 /* ImproveCacheLocality.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ImproveCacheLocality.cpp; path = code/ImproveCacheLocality.cpp; sourceTree = SOURCE_ROOT; }; - 71EAFDE1910B4A54AAAF2101 /* HMPFileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = HMPFileData.h; path = code/HMPFileData.h; sourceTree = SOURCE_ROOT; }; - 71F65BF6936E4E97A5933EF9 /* OgreImporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = OgreImporter.h; path = code/OgreImporter.h; sourceTree = SOURCE_ROOT; }; - 725DAD1CE04C4F64BDAB7037 /* ValidateDataStructure.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ValidateDataStructure.h; path = code/ValidateDataStructure.h; sourceTree = SOURCE_ROOT; }; - 72832410F47C44E3BAE709C2 /* BlenderDNA.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BlenderDNA.h; path = code/BlenderDNA.h; sourceTree = SOURCE_ROOT; }; - 72F2DF0B93CF4D3ABAD7513D /* LWOLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = LWOLoader.h; path = code/LWOLoader.h; sourceTree = SOURCE_ROOT; }; - 72F637AC7D9E4FBFBB9201CE /* ioapi.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ioapi.h; path = contrib/unzip/ioapi.h; sourceTree = SOURCE_ROOT; }; - 731205CAB88247C095E33412 /* Exporter.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = Exporter.hpp; path = include/assimp/Exporter.hpp; sourceTree = SOURCE_ROOT; }; - 73A3D87FF2C04C3BA3684F54 /* SceneCombiner.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = SceneCombiner.cpp; path = code/SceneCombiner.cpp; sourceTree = SOURCE_ROOT; }; - 74679D2078FD46ED9AC73355 /* IFCOpenings.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IFCOpenings.cpp; path = code/IFCOpenings.cpp; sourceTree = SOURCE_ROOT; }; - 74C02A113B804568A7E39CBC /* XFileParser.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = XFileParser.cpp; path = code/XFileParser.cpp; sourceTree = SOURCE_ROOT; }; - 7644CE6B26D740258577EE9D /* scoped_ptr.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = scoped_ptr.hpp; path = code/BoostWorkaround/boost/scoped_ptr.hpp; sourceTree = SOURCE_ROOT; }; - 76773A53296549FFA43956A1 /* Q3DLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Q3DLoader.h; path = code/Q3DLoader.h; sourceTree = SOURCE_ROOT; }; - 76D801D898C4443D8240EDB7 /* BlenderSceneGen.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BlenderSceneGen.h; path = code/BlenderSceneGen.h; sourceTree = SOURCE_ROOT; }; - 77908990BEF04D0881E8AE80 /* CSMLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = CSMLoader.cpp; path = code/CSMLoader.cpp; sourceTree = SOURCE_ROOT; }; - 79A49EFE23E34E1CBA2E4377 /* OgreStructs.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = OgreStructs.cpp; path = code/OgreStructs.cpp; sourceTree = SOURCE_ROOT; }; - 7BDF90B124F74A39A5EB3B02 /* DXFLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = DXFLoader.h; path = code/DXFLoader.h; sourceTree = SOURCE_ROOT; }; - 7C10178C0B7241DD874A0AF3 /* ColladaHelper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ColladaHelper.h; path = code/ColladaHelper.h; sourceTree = SOURCE_ROOT; }; - 7C477FA4D89548F1BCEDC5A0 /* ASELoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ASELoader.cpp; path = code/ASELoader.cpp; sourceTree = SOURCE_ROOT; }; - 7C63156710964DEDAC0929BD /* HalfLifeFileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = HalfLifeFileData.h; path = code/HalfLifeFileData.h; sourceTree = SOURCE_ROOT; }; - 7CAF8A3096E04CB983B53CC1 /* BlenderIntermediate.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BlenderIntermediate.h; path = code/BlenderIntermediate.h; sourceTree = SOURCE_ROOT; }; - 7DC4B0B5E57F4F4892CC823E /* MemoryIOWrapper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MemoryIOWrapper.h; path = code/MemoryIOWrapper.h; sourceTree = SOURCE_ROOT; }; - 7E8BA0D338C9433587BC6C35 /* StreamWriter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = StreamWriter.h; path = code/StreamWriter.h; sourceTree = SOURCE_ROOT; }; - 7F29EF981AB26C4900E9D380 /* libz.1.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.1.dylib; path = /usr/lib/libz.1.dylib; sourceTree = ""; }; - 7F392D921AB2C7BB00D952EB /* libc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libc++.dylib"; path = "/usr/lib/libc++.dylib"; sourceTree = ""; }; - 7F7922801AB43AC3005A8E5D /* libassimp.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libassimp.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 7F7A93A51B65D0110094C4DA /* DDLNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DDLNode.cpp; path = contrib/openddlparser/code/DDLNode.cpp; sourceTree = ""; }; - 7F7A93A61B65D0110094C4DA /* OpenDDLParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OpenDDLParser.cpp; path = contrib/openddlparser/code/OpenDDLParser.cpp; sourceTree = ""; }; - 7F7A93A71B65D0110094C4DA /* Value.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Value.cpp; path = contrib/openddlparser/code/Value.cpp; sourceTree = ""; }; - 7FBE9FE51B65AC1200D2115E /* OpenGEXExporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OpenGEXExporter.cpp; path = code/OpenGEXExporter.cpp; sourceTree = ""; }; - 7FBE9FE61B65AC1200D2115E /* OpenGEXExporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenGEXExporter.h; path = code/OpenGEXExporter.h; sourceTree = ""; }; - 7FBE9FE71B65AC1200D2115E /* OpenGEXImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OpenGEXImporter.cpp; path = code/OpenGEXImporter.cpp; sourceTree = ""; }; - 7FBE9FE81B65AC1200D2115E /* OpenGEXImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenGEXImporter.h; path = code/OpenGEXImporter.h; sourceTree = ""; }; - 7FBE9FE91B65AC1200D2115E /* OpenGEXStructs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenGEXStructs.h; path = code/OpenGEXStructs.h; sourceTree = ""; }; - 7FBEA0071B65AF9200D2115E /* DDLNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DDLNode.h; path = contrib/openddlparser/include/openddlparser/DDLNode.h; sourceTree = ""; }; - 7FBEA0081B65AF9200D2115E /* OpenDDLCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenDDLCommon.h; path = contrib/openddlparser/include/openddlparser/OpenDDLCommon.h; sourceTree = ""; }; - 7FBEA00A1B65AF9200D2115E /* OpenDDLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenDDLParser.h; path = contrib/openddlparser/include/openddlparser/OpenDDLParser.h; sourceTree = ""; }; - 7FBEA00B1B65AF9200D2115E /* OpenDDLParserUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OpenDDLParserUtils.h; path = contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h; sourceTree = ""; }; - 7FBEA00D1B65AF9200D2115E /* Value.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Value.h; path = contrib/openddlparser/include/openddlparser/Value.h; sourceTree = ""; }; - 7FBEA0111B65B11800D2115E /* Version.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Version.cpp; path = code/Version.cpp; sourceTree = ""; }; - 7FF72CB6E99E40E19AE0E64C /* MaterialSystem.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MaterialSystem.cpp; path = code/MaterialSystem.cpp; sourceTree = SOURCE_ROOT; }; - 815702BED5644DD5B242F347 /* TerragenLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = TerragenLoader.h; path = code/TerragenLoader.h; sourceTree = SOURCE_ROOT; }; - 8299401C3E4A43A18E887DC1 /* SGSpatialSort.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = SGSpatialSort.h; path = code/SGSpatialSort.h; sourceTree = SOURCE_ROOT; }; - 8343910BBD464297932B3CE0 /* FixNormalsStep.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FixNormalsStep.h; path = code/FixNormalsStep.h; sourceTree = SOURCE_ROOT; }; - 8476FEE874C1404B9B4B9617 /* SceneCombiner.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = SceneCombiner.h; path = code/SceneCombiner.h; sourceTree = SOURCE_ROOT; }; - 849EC6315E4A4E5FA06521EA /* cdt.cc */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = cdt.cc; path = contrib/poly2tri/poly2tri/sweep/cdt.cc; sourceTree = SOURCE_ROOT; }; - 862131D4574B4CABA5EC957B /* ObjFileImporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ObjFileImporter.cpp; path = code/ObjFileImporter.cpp; sourceTree = SOURCE_ROOT; }; - 86E296E459F94050ACBA3C63 /* IOSystem.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = IOSystem.hpp; path = include/assimp/IOSystem.hpp; sourceTree = SOURCE_ROOT; }; - 88ADA502481B403191BD35F0 /* STLExporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = STLExporter.h; path = code/STLExporter.h; sourceTree = SOURCE_ROOT; }; - 890E32C714444692AA016AE5 /* ProcessHelper.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ProcessHelper.cpp; path = code/ProcessHelper.cpp; sourceTree = SOURCE_ROOT; }; - 89473420F7E448A7BE71FCBA /* FBXUtil.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FBXUtil.h; path = code/FBXUtil.h; sourceTree = SOURCE_ROOT; }; - 89D2D359BD854D8AA60CB720 /* STLExporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = STLExporter.cpp; path = code/STLExporter.cpp; sourceTree = SOURCE_ROOT; }; - 8C9AEFFFF3B948148D32D76F /* shared_array.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = shared_array.hpp; path = code/BoostWorkaround/boost/shared_array.hpp; sourceTree = SOURCE_ROOT; }; - 8D53CC35AAED4CE8B9710E04 /* vector3.inl */ = {isa = PBXFileReference; explicitFileType = sourcecode; fileEncoding = 4; name = vector3.inl; path = include/assimp/vector3.inl; sourceTree = SOURCE_ROOT; }; - 8D977E197CA4477AB9F3278C /* NullLogger.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = NullLogger.hpp; path = include/assimp/NullLogger.hpp; sourceTree = SOURCE_ROOT; }; - 8E2108F568374F65ACE217D1 /* light.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = light.h; path = include/assimp/light.h; sourceTree = SOURCE_ROOT; }; - 8E395349546A4FDF843E6963 /* XGLLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = XGLLoader.cpp; path = code/XGLLoader.cpp; sourceTree = SOURCE_ROOT; }; - 8EEC6646FC044D1E9658A590 /* SpatialSort.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = SpatialSort.cpp; path = code/SpatialSort.cpp; sourceTree = SOURCE_ROOT; }; - 8F4261792A60481DA04E6E1A /* XFileHelper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = XFileHelper.h; path = code/XFileHelper.h; sourceTree = SOURCE_ROOT; }; - 8FE8B4781BB3406EB3452154 /* ObjTools.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ObjTools.h; path = code/ObjTools.h; sourceTree = SOURCE_ROOT; }; - 904A696E49D540C2A880792B /* cdt.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = cdt.h; path = contrib/poly2tri/poly2tri/sweep/cdt.h; sourceTree = SOURCE_ROOT; }; - 906F71D342544BF381E1318E /* BlenderLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = BlenderLoader.cpp; path = code/BlenderLoader.cpp; sourceTree = SOURCE_ROOT; }; - 90949C7A51E84D3595D71A6B /* config.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = config.h; path = include/assimp/config.h; sourceTree = SOURCE_ROOT; }; - 90DD6CA40A5E41458E11FF3E /* CalcTangentsProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = CalcTangentsProcess.cpp; path = code/CalcTangentsProcess.cpp; sourceTree = SOURCE_ROOT; }; - 916456789C75419DB1436FAD /* OgreBinarySerializer.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = OgreBinarySerializer.h; path = code/OgreBinarySerializer.h; sourceTree = SOURCE_ROOT; }; - 91D49B3C51684882A01EA492 /* PlyLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = PlyLoader.h; path = code/PlyLoader.h; sourceTree = SOURCE_ROOT; }; - 91EF6411C40946758A06144F /* ObjExporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ObjExporter.h; path = code/ObjExporter.h; sourceTree = SOURCE_ROOT; }; - 91FF8B1DCC0644008AE34A04 /* FindInvalidDataProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FindInvalidDataProcess.h; path = code/FindInvalidDataProcess.h; sourceTree = SOURCE_ROOT; }; - 923283A9791E4B4E86D623FC /* OgreImporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = OgreImporter.cpp; path = code/OgreImporter.cpp; sourceTree = SOURCE_ROOT; }; - 926E8B7924144B349A88023D /* OptimizeGraph.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = OptimizeGraph.h; path = code/OptimizeGraph.h; sourceTree = SOURCE_ROOT; }; - 9293C5A353F9497A850E05D5 /* unzip.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = unzip.h; path = contrib/unzip/unzip.h; sourceTree = SOURCE_ROOT; }; - 929F59CCA32549EC884A5033 /* ASEParser.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ASEParser.cpp; path = code/ASEParser.cpp; sourceTree = SOURCE_ROOT; }; - 92D8734FFF9742B39A371B70 /* ConvertToLHProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ConvertToLHProcess.cpp; path = code/ConvertToLHProcess.cpp; sourceTree = SOURCE_ROOT; }; - 9472EFB6831740DD91471337 /* Importer.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = Importer.cpp; path = code/Importer.cpp; sourceTree = SOURCE_ROOT; }; - 95641498F25A4F6FABBC03A4 /* MDCFileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MDCFileData.h; path = code/MDCFileData.h; sourceTree = SOURCE_ROOT; }; - 957FBC18FED2484F83308E36 /* SpatialSort.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = SpatialSort.h; path = code/SpatialSort.h; sourceTree = SOURCE_ROOT; }; - 967D69AC1A344D4E988F0B2C /* common_factor_rt.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = common_factor_rt.hpp; path = code/BoostWorkaround/boost/math/common_factor_rt.hpp; sourceTree = SOURCE_ROOT; }; - 96A02CBA1AE642BD9519719D /* make_shared.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = make_shared.hpp; path = code/BoostWorkaround/boost/make_shared.hpp; sourceTree = SOURCE_ROOT; }; - 973D4231A4AA4925B019FEEE /* unzip.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.c; fileEncoding = 4; name = unzip.c; path = contrib/unzip/unzip.c; sourceTree = SOURCE_ROOT; }; - 9761D873B9604504B9AD7CD5 /* defs.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = defs.h; path = include/assimp/defs.h; sourceTree = SOURCE_ROOT; }; - 97914BDA4AA34081855BF16C /* ScenePrivate.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ScenePrivate.h; path = code/ScenePrivate.h; sourceTree = SOURCE_ROOT; }; - 97DFA90F9D0C4B999C150B10 /* IRRLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IRRLoader.cpp; path = code/IRRLoader.cpp; sourceTree = SOURCE_ROOT; }; - 97F52051AF4F478FA77AABBC /* quaternion.inl */ = {isa = PBXFileReference; explicitFileType = sourcecode; fileEncoding = 4; name = quaternion.inl; path = include/assimp/quaternion.inl; sourceTree = SOURCE_ROOT; }; - 982AE676D2364350B1FBD095 /* GenFaceNormalsProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = GenFaceNormalsProcess.cpp; path = code/GenFaceNormalsProcess.cpp; sourceTree = SOURCE_ROOT; }; - 9855496CEA774F4FA7FBB862 /* FBXDeformer.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXDeformer.cpp; path = code/FBXDeformer.cpp; sourceTree = SOURCE_ROOT; }; - 99A4349D505F4CC593F48CF6 /* SplitByBoneCountProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = SplitByBoneCountProcess.cpp; path = code/SplitByBoneCountProcess.cpp; sourceTree = SOURCE_ROOT; }; - 9A0960F123634603B15EEA38 /* ConvertUTF.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.c; fileEncoding = 4; name = ConvertUTF.c; path = contrib/ConvertUTF/ConvertUTF.c; sourceTree = SOURCE_ROOT; }; - 9A61AF384D4D45778698DD7D /* ASELoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ASELoader.h; path = code/ASELoader.h; sourceTree = SOURCE_ROOT; }; - 9B2827B3E64147E08A5AD334 /* SkeletonMeshBuilder.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = SkeletonMeshBuilder.cpp; path = code/SkeletonMeshBuilder.cpp; sourceTree = SOURCE_ROOT; }; - 9B4221AA0AD2418FAA45EB64 /* FindInvalidDataProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FindInvalidDataProcess.cpp; path = code/FindInvalidDataProcess.cpp; sourceTree = SOURCE_ROOT; }; - 9C5E3F9248B64C7EBF20EC27 /* Hash.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Hash.h; path = code/Hash.h; sourceTree = SOURCE_ROOT; }; - 9D203F78B24C4D7E8E2084A3 /* FBXProperties.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXProperties.cpp; path = code/FBXProperties.cpp; sourceTree = SOURCE_ROOT; }; - 9E0572B45F1F4605BD5C919D /* COBScene.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = COBScene.h; path = code/COBScene.h; sourceTree = SOURCE_ROOT; }; - A06CBE89CFAB48E786F7A5C0 /* 3DSLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = 3DSLoader.h; path = code/3DSLoader.h; sourceTree = SOURCE_ROOT; }; - A0AED12A1A6D4635A8CFB65A /* GenVertexNormalsProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = GenVertexNormalsProcess.cpp; path = code/GenVertexNormalsProcess.cpp; sourceTree = SOURCE_ROOT; }; - A14347E954E8413CAF1455EA /* LWOAnimation.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = LWOAnimation.h; path = code/LWOAnimation.h; sourceTree = SOURCE_ROOT; }; - A1A9535EDF9A4FF2B8DABD7D /* AssimpCExport.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = AssimpCExport.cpp; path = code/AssimpCExport.cpp; sourceTree = SOURCE_ROOT; }; - A257229A058041389981CFC1 /* XFileExporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = XFileExporter.h; path = code/XFileExporter.h; sourceTree = SOURCE_ROOT; }; - A277DBC1EFB944F995659A20 /* MD5Loader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MD5Loader.cpp; path = code/MD5Loader.cpp; sourceTree = SOURCE_ROOT; }; - A3D3024C3A59423487A125C8 /* STEPFileReader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = STEPFileReader.h; path = code/STEPFileReader.h; sourceTree = SOURCE_ROOT; }; - A43641DC9C1B4B578BC40476 /* SplitLargeMeshes.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = SplitLargeMeshes.cpp; path = code/SplitLargeMeshes.cpp; sourceTree = SOURCE_ROOT; }; - A436C47FBF904FECB4A58462 /* ProcessHelper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ProcessHelper.h; path = code/ProcessHelper.h; sourceTree = SOURCE_ROOT; }; - A4CBF9157F01460ABEDEBF28 /* crypt.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = crypt.h; path = contrib/unzip/crypt.h; sourceTree = SOURCE_ROOT; }; - A58410FEAA884A2D8D73ACCE /* BaseImporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = BaseImporter.cpp; path = code/BaseImporter.cpp; sourceTree = SOURCE_ROOT; }; - A72115ED828F4069A427B460 /* Subdivision.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Subdivision.h; path = code/Subdivision.h; sourceTree = SOURCE_ROOT; }; - A7733823362B4A389102D177 /* TargetAnimation.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = TargetAnimation.h; path = code/TargetAnimation.h; sourceTree = SOURCE_ROOT; }; - A7A56A688A3845768410F500 /* FBXConverter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXConverter.cpp; path = code/FBXConverter.cpp; sourceTree = SOURCE_ROOT; }; - A7A86F81858F4D928A568E17 /* FBXConverter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FBXConverter.h; path = code/FBXConverter.h; sourceTree = SOURCE_ROOT; }; - A7A990C6FF244DC397B7BA7C /* MS3DLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MS3DLoader.cpp; path = code/MS3DLoader.cpp; sourceTree = SOURCE_ROOT; }; - A7CEBC6894424B888326CAB2 /* tuple.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = tuple.hpp; path = code/BoostWorkaround/boost/tuple/tuple.hpp; sourceTree = SOURCE_ROOT; }; - A88D56FBEA084A3EA9A0ECB3 /* Q3BSPFileImporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = Q3BSPFileImporter.cpp; path = code/Q3BSPFileImporter.cpp; sourceTree = SOURCE_ROOT; }; - A9E9EB834E09420197C3FB8C /* DefaultLogger.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = DefaultLogger.cpp; path = code/DefaultLogger.cpp; sourceTree = SOURCE_ROOT; }; - AA4946AEDB9F4F22873C4C4F /* FBXImporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FBXImporter.h; path = code/FBXImporter.h; sourceTree = SOURCE_ROOT; }; - AA92FFC8B06D4569AD9C4CB1 /* MDLLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MDLLoader.cpp; path = code/MDLLoader.cpp; sourceTree = SOURCE_ROOT; }; - AAB9AE5328F843F5A8A3E85C /* OptimizeGraph.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = OptimizeGraph.cpp; path = code/OptimizeGraph.cpp; sourceTree = SOURCE_ROOT; }; - AAD3EA9B0BB84A788FCCA83E /* foreach.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = foreach.hpp; path = code/BoostWorkaround/boost/foreach.hpp; sourceTree = SOURCE_ROOT; }; - ABDA70358E34432A8A4637F4 /* RemoveVCProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = RemoveVCProcess.h; path = code/RemoveVCProcess.h; sourceTree = SOURCE_ROOT; }; - AC699876B6364EC1878CBA44 /* OgreXmlSerializer.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = OgreXmlSerializer.h; path = code/OgreXmlSerializer.h; sourceTree = SOURCE_ROOT; }; - ACF73EEAB2424213BF7158D5 /* ObjFileParser.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ObjFileParser.cpp; path = code/ObjFileParser.cpp; sourceTree = SOURCE_ROOT; }; - AD969BA482564C7FAA372F7C /* RemoveRedundantMaterials.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = RemoveRedundantMaterials.h; path = code/RemoveRedundantMaterials.h; sourceTree = SOURCE_ROOT; }; - ADACEBC4973F4FC0A6FEC68A /* RemoveRedundantMaterials.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = RemoveRedundantMaterials.cpp; path = code/RemoveRedundantMaterials.cpp; sourceTree = SOURCE_ROOT; }; - AE00939F150F413780C8AAD7 /* shapes.cc */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = shapes.cc; path = contrib/poly2tri/poly2tri/common/shapes.cc; sourceTree = SOURCE_ROOT; }; - AE1C2E2C9C424B3684AD9D4A /* texture.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = texture.h; path = include/assimp/texture.h; sourceTree = SOURCE_ROOT; }; - AF75E6049338489BB256D295 /* ioapi.c */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.c; fileEncoding = 4; name = ioapi.c; path = contrib/unzip/ioapi.c; sourceTree = SOURCE_ROOT; }; - AFA8B6DE5B3A4E52A85041C9 /* LWOFileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = LWOFileData.h; path = code/LWOFileData.h; sourceTree = SOURCE_ROOT; }; - AFB7F8501C882F1A00D7B6E9 /* OpenDDLCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OpenDDLCommon.cpp; path = contrib/openddlparser/code/OpenDDLCommon.cpp; sourceTree = ""; }; - AFB7F8511C882F1A00D7B6E9 /* OpenDDLExport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OpenDDLExport.cpp; path = contrib/openddlparser/code/OpenDDLExport.cpp; sourceTree = ""; }; - AFB7F8551C882F8200D7B6E9 /* glTFAsset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = glTFAsset.h; path = code/glTFAsset.h; sourceTree = ""; }; - AFB7F8561C882F8200D7B6E9 /* glTFAsset.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = glTFAsset.inl; path = code/glTFAsset.inl; sourceTree = ""; }; - AFB7F8571C882F8200D7B6E9 /* glTFAssetWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = glTFAssetWriter.h; path = code/glTFAssetWriter.h; sourceTree = ""; }; - AFB7F8581C882F8200D7B6E9 /* glTFAssetWriter.inl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = glTFAssetWriter.inl; path = code/glTFAssetWriter.inl; sourceTree = ""; }; - AFB7F8591C882F8200D7B6E9 /* glTFExporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = glTFExporter.cpp; path = code/glTFExporter.cpp; sourceTree = ""; }; - AFB7F85A1C882F8200D7B6E9 /* glTFExporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = glTFExporter.h; path = code/glTFExporter.h; sourceTree = ""; }; - AFB7F85B1C882F8200D7B6E9 /* glTFImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = glTFImporter.cpp; path = code/glTFImporter.cpp; sourceTree = ""; }; - AFB7F85C1C882F8200D7B6E9 /* glTFImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = glTFImporter.h; path = code/glTFImporter.h; sourceTree = ""; }; - AFB7F8611C88302500D7B6E9 /* SIBImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SIBImporter.cpp; path = code/SIBImporter.cpp; sourceTree = ""; }; - AFB7F8621C88302500D7B6E9 /* SIBImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SIBImporter.h; path = code/SIBImporter.h; sourceTree = ""; }; - AFF41974881F466A9561BE4B /* LWSLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = LWSLoader.cpp; path = code/LWSLoader.cpp; sourceTree = SOURCE_ROOT; }; - B04FE3598E344EC09B59CA2F /* IRRShared.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = IRRShared.h; path = code/IRRShared.h; sourceTree = SOURCE_ROOT; }; - B05DC38593F04180B322360B /* camera.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = camera.h; path = include/assimp/camera.h; sourceTree = SOURCE_ROOT; }; - B211101B342C414A9E43B7BC /* SplitByBoneCountProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = SplitByBoneCountProcess.h; path = code/SplitByBoneCountProcess.h; sourceTree = SOURCE_ROOT; }; - B36DA471B9E142FC9425EC45 /* JoinVerticesProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = JoinVerticesProcess.cpp; path = code/JoinVerticesProcess.cpp; sourceTree = SOURCE_ROOT; }; - B3E8A1BEF8E74F04AE06871B /* AssxmlExporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = AssxmlExporter.cpp; path = code/AssxmlExporter.cpp; sourceTree = SOURCE_ROOT; }; - B4086213AE40445F817FA840 /* RemoveComments.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = RemoveComments.h; path = code/RemoveComments.h; sourceTree = SOURCE_ROOT; }; - B40FE1BF9D8E411493BBDE0C /* ComputeUVMappingProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ComputeUVMappingProcess.h; path = code/ComputeUVMappingProcess.h; sourceTree = SOURCE_ROOT; }; - B441D87EE6ED4EBFB0586B66 /* anim.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = anim.h; path = include/assimp/anim.h; sourceTree = SOURCE_ROOT; }; - B4C688FA08F44716855CDD3C /* FBXImporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXImporter.cpp; path = code/FBXImporter.cpp; sourceTree = SOURCE_ROOT; }; - B4F1B5789CA540C78FB9219D /* NDOLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = NDOLoader.cpp; path = code/NDOLoader.cpp; sourceTree = SOURCE_ROOT; }; - B522B83A39CA461CBCABE25A /* BlenderScene.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BlenderScene.h; path = code/BlenderScene.h; sourceTree = SOURCE_ROOT; }; - B54FBAAF061B40DBA3F48F83 /* IOStream.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = IOStream.hpp; path = include/assimp/IOStream.hpp; sourceTree = SOURCE_ROOT; }; - B6074B1E864740F787A97EA3 /* vector2.inl */ = {isa = PBXFileReference; explicitFileType = sourcecode; fileEncoding = 4; name = vector2.inl; path = include/assimp/vector2.inl; sourceTree = SOURCE_ROOT; }; - B65258E349704523BC43904D /* BlenderDNA.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = BlenderDNA.cpp; path = code/BlenderDNA.cpp; sourceTree = SOURCE_ROOT; }; - B6982D8069A145E5B9F97684 /* DXFHelper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = DXFHelper.h; path = code/DXFHelper.h; sourceTree = SOURCE_ROOT; }; - B7192C50B16142398B7CD221 /* DefaultProgressHandler.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = DefaultProgressHandler.h; path = code/DefaultProgressHandler.h; sourceTree = SOURCE_ROOT; }; - B72D0BA3EF66439F8D582ED3 /* advancing_front.cc */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = advancing_front.cc; path = contrib/poly2tri/poly2tri/sweep/advancing_front.cc; sourceTree = SOURCE_ROOT; }; - B9DFF24FD63A4D9FAE213EED /* Importer.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = Importer.hpp; path = include/assimp/Importer.hpp; sourceTree = SOURCE_ROOT; }; - BA832069DF214327AE067503 /* matrix4x4.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = matrix4x4.h; path = include/assimp/matrix4x4.h; sourceTree = SOURCE_ROOT; }; - BABB7734139C452A9DDEE797 /* FindDegenerates.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FindDegenerates.cpp; path = code/FindDegenerates.cpp; sourceTree = SOURCE_ROOT; }; - BB38E7E7661842448F008372 /* FBXDocumentUtil.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXDocumentUtil.cpp; path = code/FBXDocumentUtil.cpp; sourceTree = SOURCE_ROOT; }; - BBEE1CF81183473C8492FC03 /* CalcTangentsProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = CalcTangentsProcess.h; path = code/CalcTangentsProcess.h; sourceTree = SOURCE_ROOT; }; - BD9A81E0E27E44718609615B /* SortByPTypeProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = SortByPTypeProcess.cpp; path = code/SortByPTypeProcess.cpp; sourceTree = SOURCE_ROOT; }; - BDD30C77BB68497EA3B7F2F7 /* StringComparison.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = StringComparison.h; path = code/StringComparison.h; sourceTree = SOURCE_ROOT; }; - BF94F50C216B45388CDEC1EF /* OFFLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = OFFLoader.h; path = code/OFFLoader.h; sourceTree = SOURCE_ROOT; }; - C17C5037C995420C8D259C0C /* FBXImportSettings.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FBXImportSettings.h; path = code/FBXImportSettings.h; sourceTree = SOURCE_ROOT; }; - C18C5023460E4D17B8C922D7 /* StandardShapes.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = StandardShapes.cpp; path = code/StandardShapes.cpp; sourceTree = SOURCE_ROOT; }; - C2C9EAC9B5B74AC397B070E8 /* scoped_array.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = scoped_array.hpp; path = code/BoostWorkaround/boost/scoped_array.hpp; sourceTree = SOURCE_ROOT; }; - C490BBF1881240EEA4A96315 /* clipper.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = clipper.hpp; path = contrib/clipper/clipper.hpp; sourceTree = SOURCE_ROOT; }; - C5178B3983F147F3B9BD8217 /* Q3DLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = Q3DLoader.cpp; path = code/Q3DLoader.cpp; sourceTree = SOURCE_ROOT; }; - C54518F708BA4A328D5D7325 /* FixNormalsStep.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FixNormalsStep.cpp; path = code/FixNormalsStep.cpp; sourceTree = SOURCE_ROOT; }; - C582480917FF4EB09C164D70 /* SMDLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = SMDLoader.h; path = code/SMDLoader.h; sourceTree = SOURCE_ROOT; }; - C5C3ED2BE50D4684994BD533 /* TextureTransform.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = TextureTransform.h; path = code/TextureTransform.h; sourceTree = SOURCE_ROOT; }; - C6D3C3E2BA2F49F2B17E7580 /* STLLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = STLLoader.h; path = code/STLLoader.h; sourceTree = SOURCE_ROOT; }; - C7B37CA474DF4CE7A5B0658E /* ai_assert.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ai_assert.h; path = include/assimp/ai_assert.h; sourceTree = SOURCE_ROOT; }; - C80B9A3AF4204AE08AA50BAE /* BVHLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = BVHLoader.cpp; path = code/BVHLoader.cpp; sourceTree = SOURCE_ROOT; }; - C84DA0E6CE13493D833BA1C1 /* COBLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = COBLoader.cpp; path = code/COBLoader.cpp; sourceTree = SOURCE_ROOT; }; - C9A101D1311C4E77AAEDD94C /* FindInstancesProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FindInstancesProcess.cpp; path = code/FindInstancesProcess.cpp; sourceTree = SOURCE_ROOT; }; - CB042D863BD447FFB117AE34 /* 3DSHelper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = 3DSHelper.h; path = code/3DSHelper.h; sourceTree = SOURCE_ROOT; }; - CC54A231FF6B4B0CABCFD167 /* IRRShared.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IRRShared.cpp; path = code/IRRShared.cpp; sourceTree = SOURCE_ROOT; }; - CC5D5CA1789448E9869B9669 /* PlyExporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = PlyExporter.h; path = code/PlyExporter.h; sourceTree = SOURCE_ROOT; }; - CDE3ECA98173418A9F997992 /* STEPFileReader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = STEPFileReader.cpp; path = code/STEPFileReader.cpp; sourceTree = SOURCE_ROOT; }; - CEC69808E1844C23B95D3475 /* MDLMaterialLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = MDLMaterialLoader.cpp; path = code/MDLMaterialLoader.cpp; sourceTree = SOURCE_ROOT; }; - CF07D05DC86F4C98BC42FDCF /* FBXTokenizer.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXTokenizer.cpp; path = code/FBXTokenizer.cpp; sourceTree = SOURCE_ROOT; }; - D029CE902F8045B0B3AFFDDB /* ImporterRegistry.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ImporterRegistry.cpp; path = code/ImporterRegistry.cpp; sourceTree = SOURCE_ROOT; }; - D0E9BB0220704C5D93CE7CE9 /* IFCLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IFCLoader.cpp; path = code/IFCLoader.cpp; sourceTree = SOURCE_ROOT; }; - D1073FF20359469D921C9316 /* irrXMLWrapper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = irrXMLWrapper.h; path = code/irrXMLWrapper.h; sourceTree = SOURCE_ROOT; }; - D2869C6AD4814588A45E8F81 /* NFFLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = NFFLoader.h; path = code/NFFLoader.h; sourceTree = SOURCE_ROOT; }; - D2EEB62ECBF749AA89146C66 /* SplitLargeMeshes.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = SplitLargeMeshes.h; path = code/SplitLargeMeshes.h; sourceTree = SOURCE_ROOT; }; - D40F70AC841D4B788B5C696B /* CXMLReaderImpl.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = CXMLReaderImpl.h; path = contrib/irrXML/CXMLReaderImpl.h; sourceTree = SOURCE_ROOT; }; - D56A4C70F65D4E07BD792D2C /* STEPFileEncoding.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = STEPFileEncoding.h; path = code/STEPFileEncoding.h; sourceTree = SOURCE_ROOT; }; - D5F4108F03D7457EB641836B /* MDLFileData.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MDLFileData.h; path = code/MDLFileData.h; sourceTree = SOURCE_ROOT; }; - D629F6BF53864979B7619067 /* LWOBLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = LWOBLoader.cpp; path = code/LWOBLoader.cpp; sourceTree = SOURCE_ROOT; }; - D82B5BA87B184532BE74D24F /* LogAux.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = LogAux.h; path = code/LogAux.h; sourceTree = SOURCE_ROOT; }; - D958B0B445E64F4BA9145D82 /* DefaultLogger.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = DefaultLogger.hpp; path = include/assimp/DefaultLogger.hpp; sourceTree = SOURCE_ROOT; }; - D9AB66BD27E246A18091626F /* DefaultIOSystem.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = DefaultIOSystem.h; path = code/DefaultIOSystem.h; sourceTree = SOURCE_ROOT; }; - D9FEEF58B24548F782A5D53C /* AssbinLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = AssbinLoader.cpp; path = code/AssbinLoader.cpp; sourceTree = SOURCE_ROOT; }; - DAE82F651F9E4D91A6A6C753 /* advancing_front.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = advancing_front.h; path = contrib/poly2tri/poly2tri/sweep/advancing_front.h; sourceTree = SOURCE_ROOT; }; - DC0210D3F25F470C86F914B3 /* ColladaParser.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = ColladaParser.h; path = code/ColladaParser.h; sourceTree = SOURCE_ROOT; }; - DC67FF8B4313494F8C03D840 /* XMLTools.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = XMLTools.h; path = code/XMLTools.h; sourceTree = SOURCE_ROOT; }; - DD3D18BC2E58447D9879CB00 /* OptimizeMeshes.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = OptimizeMeshes.h; path = code/OptimizeMeshes.h; sourceTree = SOURCE_ROOT; }; - DD4E4641B0FE4369BF3775C3 /* MDCNormalTable.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MDCNormalTable.h; path = code/MDCNormalTable.h; sourceTree = SOURCE_ROOT; }; - DD7FFD53046F4AEB898C0832 /* IRRMeshLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = IRRMeshLoader.cpp; path = code/IRRMeshLoader.cpp; sourceTree = SOURCE_ROOT; }; - DDDE82BDF4F94E0EA35649A4 /* LimitBoneWeightsProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = LimitBoneWeightsProcess.h; path = code/LimitBoneWeightsProcess.h; sourceTree = SOURCE_ROOT; }; - DE0D259917354C80BE1CC791 /* BlenderScene.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = BlenderScene.cpp; path = code/BlenderScene.cpp; sourceTree = SOURCE_ROOT; }; - DE811A81663A492A84E13937 /* ObjExporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ObjExporter.cpp; path = code/ObjExporter.cpp; sourceTree = SOURCE_ROOT; }; - DF76D04D95E649BCBC15E64F /* TextureTransform.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = TextureTransform.cpp; path = code/TextureTransform.cpp; sourceTree = SOURCE_ROOT; }; - DFF8AF202CAA40E69D1A2BD0 /* static_assert.hpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; fileEncoding = 4; name = static_assert.hpp; path = code/BoostWorkaround/boost/static_assert.hpp; sourceTree = SOURCE_ROOT; }; - E01801CB159D47928B3D96B5 /* TinyFormatter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = TinyFormatter.h; path = code/TinyFormatter.h; sourceTree = SOURCE_ROOT; }; - E065DB38B0284196A9283CA3 /* LimitBoneWeightsProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = LimitBoneWeightsProcess.cpp; path = code/LimitBoneWeightsProcess.cpp; sourceTree = SOURCE_ROOT; }; - E11A39E91576445599DF2AC4 /* STEPFileEncoding.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = STEPFileEncoding.cpp; path = code/STEPFileEncoding.cpp; sourceTree = SOURCE_ROOT; }; - E1313C36045444619026E9FB /* cfileio.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = cfileio.h; path = include/assimp/cfileio.h; sourceTree = SOURCE_ROOT; }; - E24E950227C848D3A759F5C2 /* MDLLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MDLLoader.h; path = code/MDLLoader.h; sourceTree = SOURCE_ROOT; }; - E51043448F1744FFA78526D5 /* PlyExporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = PlyExporter.cpp; path = code/PlyExporter.cpp; sourceTree = SOURCE_ROOT; }; - E6332CD992D447CA910DA456 /* FBXUtil.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXUtil.cpp; path = code/FBXUtil.cpp; sourceTree = SOURCE_ROOT; }; - E663847651834244834CB9F5 /* PostStepRegistry.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = PostStepRegistry.cpp; path = code/PostStepRegistry.cpp; sourceTree = SOURCE_ROOT; }; - E7E85BF696E74CFAAEBF895C /* FBXTokenizer.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FBXTokenizer.h; path = code/FBXTokenizer.h; sourceTree = SOURCE_ROOT; }; - E81BAB0ED0854DDFA62CB956 /* pushpack1.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = pushpack1.h; path = include/assimp/Compiler/pushpack1.h; sourceTree = SOURCE_ROOT; }; - E9ED3048A21E483F9C2721F4 /* mesh.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = mesh.h; path = include/assimp/mesh.h; sourceTree = SOURCE_ROOT; }; - EAD338BE19AE4C2E897B38B6 /* RawLoader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = RawLoader.h; path = code/RawLoader.h; sourceTree = SOURCE_ROOT; }; - EAD34F1AA6664B6B935C9421 /* FBXAnimation.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXAnimation.cpp; path = code/FBXAnimation.cpp; sourceTree = SOURCE_ROOT; }; - ECCBBF2D75A44335AB93C84A /* 3DSExporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = 3DSExporter.cpp; path = code/3DSExporter.cpp; sourceTree = SOURCE_ROOT; }; - ED20428B31DF46C6A9D65322 /* StreamReader.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = StreamReader.h; path = code/StreamReader.h; sourceTree = SOURCE_ROOT; }; - EE545B58FA1246C792C6AD01 /* shapes.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = shapes.h; path = contrib/poly2tri/poly2tri/common/shapes.h; sourceTree = SOURCE_ROOT; }; - EE6163EB035149A6B8139DB8 /* FBXMaterial.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXMaterial.cpp; path = code/FBXMaterial.cpp; sourceTree = SOURCE_ROOT; }; - EF9F805A4BA4428CA98C9DE5 /* OgreXmlSerializer.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = OgreXmlSerializer.cpp; path = code/OgreXmlSerializer.cpp; sourceTree = SOURCE_ROOT; }; - EFD557FE2C3A46D78F070655 /* OFFLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = OFFLoader.cpp; path = code/OFFLoader.cpp; sourceTree = SOURCE_ROOT; }; - F1076BAC69DB4935A93045A8 /* ACLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = ACLoader.cpp; path = code/ACLoader.cpp; sourceTree = SOURCE_ROOT; }; - F1A7BD0B5CAE48699FCAEBD1 /* MDLDefaultColorMap.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MDLDefaultColorMap.h; path = code/MDLDefaultColorMap.h; sourceTree = SOURCE_ROOT; }; - F22D5BA425444A028DA42BEA /* FBXDocument.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = FBXDocument.cpp; path = code/FBXDocument.cpp; sourceTree = SOURCE_ROOT; }; - F44E3625C31843B0AFA1A744 /* AssxmlExporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = AssxmlExporter.h; path = code/AssxmlExporter.h; sourceTree = SOURCE_ROOT; }; - F468200042534D7CA2C9D891 /* BaseProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BaseProcess.h; path = code/BaseProcess.h; sourceTree = SOURCE_ROOT; }; - F4AE5F74C20B400EA688B5ED /* VertexTriangleAdjacency.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = VertexTriangleAdjacency.h; path = code/VertexTriangleAdjacency.h; sourceTree = SOURCE_ROOT; }; - F4BA09C943DD49E184316D97 /* Win32DebugLogStream.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Win32DebugLogStream.h; path = code/Win32DebugLogStream.h; sourceTree = SOURCE_ROOT; }; - F5720C42345840CB9FEA5A40 /* BlenderModifier.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = BlenderModifier.h; path = code/BlenderModifier.h; sourceTree = SOURCE_ROOT; }; - F75457C6D026451B9267B65E /* OgreMaterial.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = OgreMaterial.cpp; path = code/OgreMaterial.cpp; sourceTree = SOURCE_ROOT; }; - F81AE18E4AA94F9597FCB040 /* Importer.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Importer.h; path = code/Importer.h; sourceTree = SOURCE_ROOT; }; - F898EEA0D9E64425A790587D /* Q3BSPFileImporter.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = Q3BSPFileImporter.h; path = code/Q3BSPFileImporter.h; sourceTree = SOURCE_ROOT; }; - F8AC3A243B9C47D6B31348BA /* FBXParser.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FBXParser.h; path = code/FBXParser.h; sourceTree = SOURCE_ROOT; }; - F8B1133805564E18B32FFA83 /* OgreStructs.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = OgreStructs.h; path = code/OgreStructs.h; sourceTree = SOURCE_ROOT; }; - F9FEF4D69EFC4605A4F752E5 /* DefaultIOStream.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = DefaultIOStream.cpp; path = code/DefaultIOStream.cpp; sourceTree = SOURCE_ROOT; }; - FAB6BC13FCFE40F5801D0972 /* BaseProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = BaseProcess.cpp; path = code/BaseProcess.cpp; sourceTree = SOURCE_ROOT; }; - FAC67CC462484F92A2CBD7D3 /* poppack1.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = poppack1.h; path = include/assimp/Compiler/poppack1.h; sourceTree = SOURCE_ROOT; }; - FB1E84BE85A34F98A44BBB2B /* vector2.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = vector2.h; path = include/assimp/vector2.h; sourceTree = SOURCE_ROOT; }; - FB2510D46F504365A03EE8A8 /* TriangulateProcess.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = TriangulateProcess.h; path = code/TriangulateProcess.h; sourceTree = SOURCE_ROOT; }; - FB4ABA17AF264257BDA4D921 /* RemoveVCProcess.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = RemoveVCProcess.cpp; path = code/RemoveVCProcess.cpp; sourceTree = SOURCE_ROOT; }; - FB55283BC24C4A1CA86C4900 /* PolyTools.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = PolyTools.h; path = code/PolyTools.h; sourceTree = SOURCE_ROOT; }; - FBC2BA7F2269489694BC890D /* FBXProperties.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = FBXProperties.h; path = code/FBXProperties.h; sourceTree = SOURCE_ROOT; }; - FC0801BA1F95494498A089AF /* version.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = version.h; path = include/assimp/version.h; sourceTree = SOURCE_ROOT; }; - FCCB4BB481FB461688FE2F29 /* B3DImporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = B3DImporter.cpp; path = code/B3DImporter.cpp; sourceTree = SOURCE_ROOT; }; - FD84CFD1BD3E4AF4BA622BB8 /* MD2NormalTable.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MD2NormalTable.h; path = code/MD2NormalTable.h; sourceTree = SOURCE_ROOT; }; - FD9BEC6B8A264AB092F98E20 /* SMDLoader.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = SMDLoader.cpp; path = code/SMDLoader.cpp; sourceTree = SOURCE_ROOT; }; - FEEA39CDD7934999B89E2B4D /* MaterialSystem.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; name = MaterialSystem.h; path = code/MaterialSystem.h; sourceTree = SOURCE_ROOT; }; - FF4E90FB1A3446F095ECC8BD /* Exporter.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = Exporter.cpp; path = code/Exporter.cpp; sourceTree = SOURCE_ROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7F79227D1AB43AC3005A8E5D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 0117589D2B25420F831BA4CE /* MS3D */ = { - isa = PBXGroup; - children = ( - A7A990C6FF244DC397B7BA7C /* MS3DLoader.cpp */, - 6347FA5D391D4320B9457D3F /* MS3DLoader.h */, - ); - name = MS3D; - sourceTree = ""; - }; - 0593669570C8417B8FE0C89E /* Obj */ = { - isa = PBXGroup; - children = ( - DE811A81663A492A84E13937 /* ObjExporter.cpp */, - 91EF6411C40946758A06144F /* ObjExporter.h */, - 005DFE3B6FFC4BEBB7055330 /* ObjFileData.h */, - 862131D4574B4CABA5EC957B /* ObjFileImporter.cpp */, - 1FC965B1F11B45F98051C565 /* ObjFileImporter.h */, - 4108529663904025B21E526B /* ObjFileMtlImporter.cpp */, - 180177D50FDA4C10AD629DC2 /* ObjFileMtlImporter.h */, - ACF73EEAB2424213BF7158D5 /* ObjFileParser.cpp */, - 333F4676A92043739F5A9D32 /* ObjFileParser.h */, - 8FE8B4781BB3406EB3452154 /* ObjTools.h */, - ); - name = Obj; - sourceTree = ""; - }; - 09D1759329AB410E92DC273A /* Collada */ = { - isa = PBXGroup; - children = ( - 1C0527629078403F81CFD117 /* ColladaExporter.cpp */, - 638B3F6AC17A435C9B86C86C /* ColladaExporter.h */, - 7C10178C0B7241DD874A0AF3 /* ColladaHelper.h */, - 1A4706D216414D4F8AA72EC9 /* ColladaLoader.cpp */, - 6981B16018CF46CAA54C0BAA /* ColladaLoader.h */, - 420D77ED33554D54AA4D50EF /* ColladaParser.cpp */, - DC0210D3F25F470C86F914B3 /* ColladaParser.h */, - ); - name = Collada; - sourceTree = ""; - }; - 0C22F81E750C429183194A1D /* Assxml */ = { - isa = PBXGroup; - children = ( - B3E8A1BEF8E74F04AE06871B /* AssxmlExporter.cpp */, - F44E3625C31843B0AFA1A744 /* AssxmlExporter.h */, - ); - name = Assxml; - sourceTree = ""; - }; - 1126F68352DC4FD49AC55DD7 /* ConvertUTF */ = { - isa = PBXGroup; - children = ( - 9A0960F123634603B15EEA38 /* ConvertUTF.c */, - 6F88E78E61FC4A01BC30BE85 /* ConvertUTF.h */, - ); - name = ConvertUTF; - sourceTree = ""; - }; - 16ED8F46E8ED44BAB8D7BA1B /* MaterialSystem */ = { - isa = PBXGroup; - children = ( - 7FF72CB6E99E40E19AE0E64C /* MaterialSystem.cpp */, - FEEA39CDD7934999B89E2B4D /* MaterialSystem.h */, - ); - name = MaterialSystem; - sourceTree = ""; - }; - 1AC84A1DBE804A71B13E06C2 /* Clipper */ = { - isa = PBXGroup; - children = ( - 59F8A11A7AED45CC94CEDF28 /* clipper.cpp */, - C490BBF1881240EEA4A96315 /* clipper.hpp */, - ); - name = Clipper; - sourceTree = ""; - }; - 1BF60AA5F4B147508EB44D8C /* Exporter */ = { - isa = PBXGroup; - children = ( - A1A9535EDF9A4FF2B8DABD7D /* AssimpCExport.cpp */, - 23097CBD64E343738B8F22EE /* BlobIOSystem.h */, - FF4E90FB1A3446F095ECC8BD /* Exporter.cpp */, - ); - name = Exporter; - sourceTree = ""; - }; - 2B78DE034A954FAD96DA8432 /* IFC */ = { - isa = PBXGroup; - children = ( - 285D1FDA48EC4DD8933B603E /* IFCBoolean.cpp */, - 2E7FD92FFCF441B0A60FC8B4 /* IFCCurve.cpp */, - 3267EBBA6EEB435F83FF25E4 /* IFCGeometry.cpp */, - D0E9BB0220704C5D93CE7CE9 /* IFCLoader.cpp */, - 2BE34AF1CE0C4767ACE21597 /* IFCLoader.h */, - 0014AE5E87A74AAA9EF0EC4B /* IFCMaterial.cpp */, - 74679D2078FD46ED9AC73355 /* IFCOpenings.cpp */, - 46E9F455A3284DB399986293 /* IFCProfile.cpp */, - 3F5D1E6368384D429BA29D5A /* IFCReaderGen.cpp */, - 6162B57DE81A4E538430056E /* IFCReaderGen.h */, - 59E3D32E3FC7438DB148537F /* IFCUtil.cpp */, - 13BFADA520C04B15AE256CC2 /* IFCUtil.h */, - 47FF3063906E4786ABF0939B /* STEPFile.h */, - E11A39E91576445599DF2AC4 /* STEPFileEncoding.cpp */, - D56A4C70F65D4E07BD792D2C /* STEPFileEncoding.h */, - CDE3ECA98173418A9F997992 /* STEPFileReader.cpp */, - A3D3024C3A59423487A125C8 /* STEPFileReader.h */, - ); - name = IFC; - sourceTree = ""; - }; - 2CA4999D40FC406B97E1FFD3 /* Compiler */ = { - isa = PBXGroup; - children = ( - FAC67CC462484F92A2CBD7D3 /* poppack1.h */, - 278FB5C8BD814F2DAE04A1C7 /* pstdint.h */, - E81BAB0ED0854DDFA62CB956 /* pushpack1.h */, - ); - name = Compiler; - sourceTree = ""; - }; - 2DC7AE369B84444B9649035D /* assimp */ = { - isa = PBXGroup; - children = ( - 2DC891CC1D2CFA44001E0B0E /* C4D */, - 2DC891C51D2CFA01001E0B0E /* 3MF */, - DB181885BFCC44F594A1FA01 /* Source Files */, - 628C9A9A9FA640B9AA1DAC09 /* Common */, - 874C614E5BEB41419F0EEE1C /* Logging */, - 1BF60AA5F4B147508EB44D8C /* Exporter */, - D3013C8FC8034BC6859BC020 /* PostProcessing */, - 9AC9FD0CD777436C9C7291FF /* 3DS */, - 98D9A21F310D47DD8F390780 /* AC */, - CB3420FADCED418CACDBB584 /* ASE */, - A7F45F8E82C445EBA7D67C36 /* Assbin */, - 0C22F81E750C429183194A1D /* Assxml */, - A1E04517F0D440CDB46985A7 /* B3D */, - 91C8DA33C37E491BBAD264C5 /* BVH */, - 09D1759329AB410E92DC273A /* Collada */, - 5F3147F7FF1044D49A824DBC /* DXF */, - DD5B35196B184EFB820D1FBB /* CSM */, - AFB7F8541C882F6E00D7B6E9 /* glTF */, - 723B9CB1C871444FBB302576 /* HMP */, - 6CB3C1AECE8A4745861D913D /* Irr */, - 873AA0EB80814B0A9461BB7E /* LWO */, - 32F48CB0DF784B6BA63A5025 /* LWS */, - F9261D592F00437EAFC663B5 /* MD2 */, - 7D3FF9CAC50E41F0B59B9758 /* MD3 */, - 97326C49E0E34D43AE80F0FF /* MD5 */, - CB981D90CEF4472191978170 /* MDC */, - EF7D37EB84AF45FC8BF47E7F /* MDL */, - 16ED8F46E8ED44BAB8D7BA1B /* MaterialSystem */, - CF7D1A0DBB134AC4BCFE3C3F /* NFF */, - 8438F0F891674542AF8F2302 /* OFFFormat */, - 0593669570C8417B8FE0C89E /* Obj */, - 6D12DDA749D645C68DBED62E /* Ogre */, - 7FBE9FE41B65ABEF00D2115E /* OpenGEX */, - 462ED039D874460E97B08346 /* Ply */, - F0273EDFDBD34EDAA6678613 /* Q3D */, - C3D412701D614559B698CED1 /* Q3BSP */, - 9A8E68D1ECFC49B9BB435F1C /* Raw */, - AFB7F8601C88301600D7B6E9 /* SIB */, - 8C2B1B7516DD4C4798F5048F /* SMD */, - 2E29D94CA6DA405EB4AF90E0 /* STL */, - 3A5EB041B5CD4F98802B2540 /* Terragen */, - 8565C30231D64E81BB2B4ECD /* Unreal */, - 96A36CD42ADB4BBBB54004E1 /* XFile */, - 6E21649785DD4DB08D9A505D /* Extra */, - 0117589D2B25420F831BA4CE /* MS3D */, - DAFF6641A88441AFBE8B99B1 /* COB */, - 71D6A260C79746D3B50849D2 /* BLENDER */, - 71199EE27B264D74B9D0A1C2 /* NDO */, - 2B78DE034A954FAD96DA8432 /* IFC */, - 2FC31A6272B94FB681FB8087 /* XGL */, - 7F21D60E8DCD4C65923BD76C /* FBX */, - 6B385D1E46704FB7BABB2D90 /* IrrXML */, - 1126F68352DC4FD49AC55DD7 /* ConvertUTF */, - 8B032622745B45FDB154A53C /* unzip */, - F61A479614764D11AC3311A8 /* Poly2Tri */, - 1AC84A1DBE804A71B13E06C2 /* Clipper */, - 3B11CB13DD484F938D3E3792 /* Boost */, - FCFE51BCE7384933A972EDEE /* Header Files */, - 2CA4999D40FC406B97E1FFD3 /* Compiler */, - ); - name = assimp; - sourceTree = ""; - }; - 2DC891C51D2CFA01001E0B0E /* 3MF */ = { - isa = PBXGroup; - children = ( - 2DC891C61D2CFA22001E0B0E /* D3MFImporter.cpp */, - 2DC891C71D2CFA22001E0B0E /* D3MFImporter.h */, - 2DC891C81D2CFA22001E0B0E /* D3MFOpcPackage.cpp */, - 2DC891C91D2CFA22001E0B0E /* D3MFOpcPackage.h */, - ); - name = 3MF; - sourceTree = ""; - }; - 2DC891CC1D2CFA44001E0B0E /* C4D */ = { - isa = PBXGroup; - children = ( - 2DC891CE1D2CFA75001E0B0E /* C4DImporter.cpp */, - 2DC891CF1D2CFA75001E0B0E /* C4DImporter.h */, - ); - name = C4D; - sourceTree = ""; - }; - 2E29D94CA6DA405EB4AF90E0 /* STL */ = { - isa = PBXGroup; - children = ( - 89D2D359BD854D8AA60CB720 /* STLExporter.cpp */, - 88ADA502481B403191BD35F0 /* STLExporter.h */, - 4D2F1605B9484B08BB33402D /* STLLoader.cpp */, - C6D3C3E2BA2F49F2B17E7580 /* STLLoader.h */, - ); - name = STL; - sourceTree = ""; - }; - 2FC31A6272B94FB681FB8087 /* XGL */ = { - isa = PBXGroup; - children = ( - 8E395349546A4FDF843E6963 /* XGLLoader.cpp */, - 501B18C2B590455D8A3C3E78 /* XGLLoader.h */, - ); - name = XGL; - sourceTree = ""; - }; - 32F48CB0DF784B6BA63A5025 /* LWS */ = { - isa = PBXGroup; - children = ( - AFF41974881F466A9561BE4B /* LWSLoader.cpp */, - 68703F99581F49CB9E2B9F37 /* LWSLoader.h */, - ); - name = LWS; - sourceTree = ""; - }; - 3A5EB041B5CD4F98802B2540 /* Terragen */ = { - isa = PBXGroup; - children = ( - 4866DA5A7BFD49F79B61CBF8 /* TerragenLoader.cpp */, - 815702BED5644DD5B242F347 /* TerragenLoader.h */, - ); - name = Terragen; - sourceTree = ""; - }; - 3B11CB13DD484F938D3E3792 /* Boost */ = { - isa = PBXGroup; - children = ( - AAD3EA9B0BB84A788FCCA83E /* foreach.hpp */, - 1DC56C794E434BA28E5CCC36 /* format.hpp */, - 96A02CBA1AE642BD9519719D /* make_shared.hpp */, - 967D69AC1A344D4E988F0B2C /* common_factor_rt.hpp */, - C2C9EAC9B5B74AC397B070E8 /* scoped_array.hpp */, - 7644CE6B26D740258577EE9D /* scoped_ptr.hpp */, - 8C9AEFFFF3B948148D32D76F /* shared_array.hpp */, - 3E84DEFC1E0646AD82F79998 /* shared_ptr.hpp */, - DFF8AF202CAA40E69D1A2BD0 /* static_assert.hpp */, - A7CEBC6894424B888326CAB2 /* tuple.hpp */, - ); - name = Boost; - sourceTree = ""; - }; - 462ED039D874460E97B08346 /* Ply */ = { - isa = PBXGroup; - children = ( - E51043448F1744FFA78526D5 /* PlyExporter.cpp */, - CC5D5CA1789448E9869B9669 /* PlyExporter.h */, - 409C98EE093C499B8A574CA9 /* PlyLoader.cpp */, - 91D49B3C51684882A01EA492 /* PlyLoader.h */, - 2C4D504725E540109530E254 /* PlyParser.cpp */, - 45F6A2B351AB4B749E55B299 /* PlyParser.h */, - ); - name = Ply; - sourceTree = ""; - }; - 5F3147F7FF1044D49A824DBC /* DXF */ = { - isa = PBXGroup; - children = ( - B6982D8069A145E5B9F97684 /* DXFHelper.h */, - 466D6B9A7CCD402D9AA87071 /* DXFLoader.cpp */, - 7BDF90B124F74A39A5EB3B02 /* DXFLoader.h */, - ); - name = DXF; - sourceTree = ""; - }; - 628C9A9A9FA640B9AA1DAC09 /* Common */ = { - isa = PBXGroup; - children = ( - 2DC891CD1D2CFA75001E0B0E /* ByteSwapper.h */, - A58410FEAA884A2D8D73ACCE /* BaseImporter.cpp */, - 32170F499DAC4E4595AF6D6B /* BaseImporter.h */, - FAB6BC13FCFE40F5801D0972 /* BaseProcess.cpp */, - F468200042534D7CA2C9D891 /* BaseProcess.h */, - 10238FBD7A9D401A82D667CB /* Bitmap.cpp */, - 49AFF879142C4BA4865843DC /* Bitmap.h */, - 339E56B5FD264481BBF21835 /* CInterfaceIOWrapper.h */, - F9FEF4D69EFC4605A4F752E5 /* DefaultIOStream.cpp */, - 32CC68350B7640ACA7C83DDA /* DefaultIOStream.h */, - 1D502654EF864101A2DA9476 /* DefaultIOSystem.cpp */, - D9AB66BD27E246A18091626F /* DefaultIOSystem.h */, - B7192C50B16142398B7CD221 /* DefaultProgressHandler.h */, - 3ACFF3FC39C74C4A966C0FEA /* GenericProperty.h */, - 9C5E3F9248B64C7EBF20EC27 /* Hash.h */, - 6AC645CEB6F74AE5A62DF68B /* IFF.h */, - 9472EFB6831740DD91471337 /* Importer.cpp */, - F81AE18E4AA94F9597FCB040 /* Importer.h */, - D029CE902F8045B0B3AFFDDB /* ImporterRegistry.cpp */, - 680FBD79376A41B690C405B8 /* LineSplitter.h */, - D82B5BA87B184532BE74D24F /* LogAux.h */, - 7DC4B0B5E57F4F4892CC823E /* MemoryIOWrapper.h */, - 0C1B00249A554394A4F9CF2A /* ParsingUtils.h */, - E663847651834244834CB9F5 /* PostStepRegistry.cpp */, - 5C1EA03E3AE24AA5A778B7F1 /* Profiler.h */, - 6A86069DEEDC42B88634F78D /* RemoveComments.cpp */, - B4086213AE40445F817FA840 /* RemoveComments.h */, - 52836A0629E24447B924750A /* SGSpatialSort.cpp */, - 8299401C3E4A43A18E887DC1 /* SGSpatialSort.h */, - 73A3D87FF2C04C3BA3684F54 /* SceneCombiner.cpp */, - 8476FEE874C1404B9B4B9617 /* SceneCombiner.h */, - 1775DE08FC8647EB896A0FB3 /* ScenePreprocessor.cpp */, - 4FE1E4726B144AD1B922A1A0 /* ScenePreprocessor.h */, - 97914BDA4AA34081855BF16C /* ScenePrivate.h */, - 9B2827B3E64147E08A5AD334 /* SkeletonMeshBuilder.cpp */, - 45BC2EB74251493CBBFAEB5D /* SkeletonMeshBuilder.h */, - 2DCF6F156A3A4B4C807E5368 /* SmoothingGroups.h */, - 8EEC6646FC044D1E9658A590 /* SpatialSort.cpp */, - 957FBC18FED2484F83308E36 /* SpatialSort.h */, - 99A4349D505F4CC593F48CF6 /* SplitByBoneCountProcess.cpp */, - B211101B342C414A9E43B7BC /* SplitByBoneCountProcess.h */, - C18C5023460E4D17B8C922D7 /* StandardShapes.cpp */, - 296407DE471C4F298742FB59 /* StandardShapes.h */, - ED20428B31DF46C6A9D65322 /* StreamReader.h */, - 7E8BA0D338C9433587BC6C35 /* StreamWriter.h */, - BDD30C77BB68497EA3B7F2F7 /* StringComparison.h */, - 4BBDEB63CFEB4F2EAA95358D /* Subdivision.cpp */, - A72115ED828F4069A427B460 /* Subdivision.h */, - 6F65B6129F774AEDB8DC845A /* TargetAnimation.cpp */, - A7733823362B4A389102D177 /* TargetAnimation.h */, - E01801CB159D47928B3D96B5 /* TinyFormatter.h */, - 1533BE4C09F1430C8BF4D248 /* Vertex.h */, - 0AAF26EBF0A64ABDB840BA64 /* VertexTriangleAdjacency.cpp */, - F4AE5F74C20B400EA688B5ED /* VertexTriangleAdjacency.h */, - DC67FF8B4313494F8C03D840 /* XMLTools.h */, - 1AF1EE8EFE594A40ACE03D19 /* fast_atof.h */, - 262DFE65C6D34442AA79D15A /* qnan.h */, - ); - name = Common; - sourceTree = ""; - }; - 6B385D1E46704FB7BABB2D90 /* IrrXML */ = { - isa = PBXGroup; - children = ( - D1073FF20359469D921C9316 /* irrXMLWrapper.h */, - D40F70AC841D4B788B5C696B /* CXMLReaderImpl.h */, - 02587469A85540EE875B04B5 /* heapsort.h */, - 49FE5C30FC854A3EBD0E9C19 /* irrArray.h */, - 5D4E64EABD9548A59E9637AF /* irrString.h */, - 4936396409984881858E7B15 /* irrTypes.h */, - 64C6BACDA5DD4139AA26EE81 /* irrXML.cpp */, - 12E167EBA81B4CD3A241D7AF /* irrXML.h */, - ); - name = IrrXML; - sourceTree = ""; - }; - 6CB3C1AECE8A4745861D913D /* Irr */ = { - isa = PBXGroup; - children = ( - 97DFA90F9D0C4B999C150B10 /* IRRLoader.cpp */, - 1011FC45108745A7BBA98904 /* IRRLoader.h */, - DD7FFD53046F4AEB898C0832 /* IRRMeshLoader.cpp */, - 670FE6DD7EDF421488F2F97F /* IRRMeshLoader.h */, - CC54A231FF6B4B0CABCFD167 /* IRRShared.cpp */, - B04FE3598E344EC09B59CA2F /* IRRShared.h */, - ); - name = Irr; - sourceTree = ""; - }; - 6D12DDA749D645C68DBED62E /* Ogre */ = { - isa = PBXGroup; - children = ( - 56ADEC4899C047F2839AD791 /* OgreBinarySerializer.cpp */, - 916456789C75419DB1436FAD /* OgreBinarySerializer.h */, - 923283A9791E4B4E86D623FC /* OgreImporter.cpp */, - 71F65BF6936E4E97A5933EF9 /* OgreImporter.h */, - F75457C6D026451B9267B65E /* OgreMaterial.cpp */, - 6F49958B5CCF423681133515 /* OgreParsingUtils.h */, - 79A49EFE23E34E1CBA2E4377 /* OgreStructs.cpp */, - F8B1133805564E18B32FFA83 /* OgreStructs.h */, - EF9F805A4BA4428CA98C9DE5 /* OgreXmlSerializer.cpp */, - AC699876B6364EC1878CBA44 /* OgreXmlSerializer.h */, - ); - name = Ogre; - sourceTree = ""; - }; - 6E21649785DD4DB08D9A505D /* Extra */ = { - isa = PBXGroup; - children = ( - 00EB692107B84590B0560BFB /* MD4FileData.h */, - ); - name = Extra; - sourceTree = ""; - }; - 71199EE27B264D74B9D0A1C2 /* NDO */ = { - isa = PBXGroup; - children = ( - B4F1B5789CA540C78FB9219D /* NDOLoader.cpp */, - 37A3E0E2BB484DD8B9FCCA5E /* NDOLoader.h */, - ); - name = NDO; - sourceTree = ""; - }; - 71D6A260C79746D3B50849D2 /* BLENDER */ = { - isa = PBXGroup; - children = ( - 603AFA882AFF49AEAC2C8FA2 /* BlenderBMesh.cpp */, - 4568875B66584E12AA1538C7 /* BlenderBMesh.h */, - B65258E349704523BC43904D /* BlenderDNA.cpp */, - 72832410F47C44E3BAE709C2 /* BlenderDNA.h */, - 43899EB0B0704A9DB8F0C54F /* BlenderDNA.inl */, - 7CAF8A3096E04CB983B53CC1 /* BlenderIntermediate.h */, - 906F71D342544BF381E1318E /* BlenderLoader.cpp */, - 157C3CC81232428FA535E05F /* BlenderLoader.h */, - 3106D75C13874F5AB3EBBFE7 /* BlenderModifier.cpp */, - F5720C42345840CB9FEA5A40 /* BlenderModifier.h */, - DE0D259917354C80BE1CC791 /* BlenderScene.cpp */, - B522B83A39CA461CBCABE25A /* BlenderScene.h */, - 76D801D898C4443D8240EDB7 /* BlenderSceneGen.h */, - 12C5DD7A285042EDB1897FAE /* BlenderTessellator.cpp */, - 59A1859480754E90B958CA85 /* BlenderTessellator.h */, - ); - name = BLENDER; - sourceTree = ""; - }; - 723B9CB1C871444FBB302576 /* HMP */ = { - isa = PBXGroup; - children = ( - 71EAFDE1910B4A54AAAF2101 /* HMPFileData.h */, - 43ABFF591F374920A5E18A24 /* HMPLoader.cpp */, - 5631CE86F56F458EA0E2415F /* HMPLoader.h */, - 7C63156710964DEDAC0929BD /* HalfLifeFileData.h */, - ); - name = HMP; - sourceTree = ""; - }; - 7D3FF9CAC50E41F0B59B9758 /* MD3 */ = { - isa = PBXGroup; - children = ( - 08E8379F20984AD59515AD95 /* MD3FileData.h */, - 563FBACCFD774BDEA4AEAC10 /* MD3Loader.cpp */, - 1CBCEE37D89145F19F23F036 /* MD3Loader.h */, - ); - name = MD3; - sourceTree = ""; - }; - 7F21D60E8DCD4C65923BD76C /* FBX */ = { - isa = PBXGroup; - children = ( - EAD34F1AA6664B6B935C9421 /* FBXAnimation.cpp */, - 1108AC28566B4D2B9F27C691 /* FBXBinaryTokenizer.cpp */, - 26BF681530B04B73961997CB /* FBXCompileConfig.h */, - A7A56A688A3845768410F500 /* FBXConverter.cpp */, - A7A86F81858F4D928A568E17 /* FBXConverter.h */, - 9855496CEA774F4FA7FBB862 /* FBXDeformer.cpp */, - F22D5BA425444A028DA42BEA /* FBXDocument.cpp */, - 0EF256EC06E345EB930772EC /* FBXDocument.h */, - BB38E7E7661842448F008372 /* FBXDocumentUtil.cpp */, - C17C5037C995420C8D259C0C /* FBXImportSettings.h */, - B4C688FA08F44716855CDD3C /* FBXImporter.cpp */, - AA4946AEDB9F4F22873C4C4F /* FBXImporter.h */, - EE6163EB035149A6B8139DB8 /* FBXMaterial.cpp */, - 42E110B9E6924AF9B55AE65A /* FBXMeshGeometry.cpp */, - 1A61BDC559CE4186B03C0396 /* FBXModel.cpp */, - 33B70115CA54405F895BA471 /* FBXNodeAttribute.cpp */, - 5F373DF3B03B4B848B78EAD2 /* FBXParser.cpp */, - F8AC3A243B9C47D6B31348BA /* FBXParser.h */, - 9D203F78B24C4D7E8E2084A3 /* FBXProperties.cpp */, - FBC2BA7F2269489694BC890D /* FBXProperties.h */, - CF07D05DC86F4C98BC42FDCF /* FBXTokenizer.cpp */, - E7E85BF696E74CFAAEBF895C /* FBXTokenizer.h */, - E6332CD992D447CA910DA456 /* FBXUtil.cpp */, - 89473420F7E448A7BE71FCBA /* FBXUtil.h */, - ); - name = FBX; - sourceTree = ""; - }; - 7F392D931AB2C7C200D952EB /* Frameworks */ = { - isa = PBXGroup; - children = ( - 7F29EF981AB26C4900E9D380 /* libz.1.dylib */, - 7F392D921AB2C7BB00D952EB /* libc++.dylib */, - ); - name = Frameworks; - sourceTree = ""; - }; - 7FBE9FE41B65ABEF00D2115E /* OpenGEX */ = { - isa = PBXGroup; - children = ( - 7FBE9FE51B65AC1200D2115E /* OpenGEXExporter.cpp */, - 7FBE9FE61B65AC1200D2115E /* OpenGEXExporter.h */, - 7FBE9FE71B65AC1200D2115E /* OpenGEXImporter.cpp */, - 7FBE9FE81B65AC1200D2115E /* OpenGEXImporter.h */, - 7FBE9FE91B65AC1200D2115E /* OpenGEXStructs.h */, - 7FBEA0051B65AF8900D2115E /* openddlparser */, - ); - name = OpenGEX; - sourceTree = ""; - }; - 7FBEA0051B65AF8900D2115E /* openddlparser */ = { - isa = PBXGroup; - children = ( - AFB7F8501C882F1A00D7B6E9 /* OpenDDLCommon.cpp */, - AFB7F8511C882F1A00D7B6E9 /* OpenDDLExport.cpp */, - 7FBEA0081B65AF9200D2115E /* OpenDDLCommon.h */, - 7FBEA00B1B65AF9200D2115E /* OpenDDLParserUtils.h */, - 7FBEA0071B65AF9200D2115E /* DDLNode.h */, - 7F7A93A51B65D0110094C4DA /* DDLNode.cpp */, - 7FBEA00A1B65AF9200D2115E /* OpenDDLParser.h */, - 7F7A93A61B65D0110094C4DA /* OpenDDLParser.cpp */, - 7FBEA00D1B65AF9200D2115E /* Value.h */, - 7F7A93A71B65D0110094C4DA /* Value.cpp */, - ); - name = openddlparser; - sourceTree = ""; - }; - 8438F0F891674542AF8F2302 /* OFFFormat */ = { - isa = PBXGroup; - children = ( - EFD557FE2C3A46D78F070655 /* OFFLoader.cpp */, - BF94F50C216B45388CDEC1EF /* OFFLoader.h */, - ); - name = OFFFormat; - sourceTree = ""; - }; - 8565C30231D64E81BB2B4ECD /* Unreal */ = { - isa = PBXGroup; - children = ( - 3B8FD96D46314ACD8F157AC3 /* UnrealLoader.cpp */, - 27F2019E621B4CDA94DD5270 /* UnrealLoader.h */, - ); - name = Unreal; - sourceTree = ""; - }; - 873AA0EB80814B0A9461BB7E /* LWO */ = { - isa = PBXGroup; - children = ( - 680C392FFE0B4CC5ABC7CA64 /* LWOAnimation.cpp */, - A14347E954E8413CAF1455EA /* LWOAnimation.h */, - D629F6BF53864979B7619067 /* LWOBLoader.cpp */, - AFA8B6DE5B3A4E52A85041C9 /* LWOFileData.h */, - 5A4E05386C094B809A315A07 /* LWOLoader.cpp */, - 72F2DF0B93CF4D3ABAD7513D /* LWOLoader.h */, - 1ED21FC57A384CE6B4F53C0C /* LWOMaterial.cpp */, - ); - name = LWO; - sourceTree = ""; - }; - 874C614E5BEB41419F0EEE1C /* Logging */ = { - isa = PBXGroup; - children = ( - A9E9EB834E09420197C3FB8C /* DefaultLogger.cpp */, - 1520A11AA6E54812939B1FBB /* FileLogStream.h */, - 4CBC1122A79D4F6C94E36CE3 /* StdOStreamLogStream.h */, - F4BA09C943DD49E184316D97 /* Win32DebugLogStream.h */, - D958B0B445E64F4BA9145D82 /* DefaultLogger.hpp */, - 657B9A15EE7A4B7BA519A969 /* LogStream.hpp */, - 56CE07D64D114C4BAB6D9F08 /* Logger.hpp */, - 8D977E197CA4477AB9F3278C /* NullLogger.hpp */, - ); - name = Logging; - sourceTree = ""; - }; - 8B032622745B45FDB154A53C /* unzip */ = { - isa = PBXGroup; - children = ( - A4CBF9157F01460ABEDEBF28 /* crypt.h */, - AF75E6049338489BB256D295 /* ioapi.c */, - 72F637AC7D9E4FBFBB9201CE /* ioapi.h */, - 973D4231A4AA4925B019FEEE /* unzip.c */, - 9293C5A353F9497A850E05D5 /* unzip.h */, - ); - name = unzip; - sourceTree = ""; - }; - 8C2B1B7516DD4C4798F5048F /* SMD */ = { - isa = PBXGroup; - children = ( - FD9BEC6B8A264AB092F98E20 /* SMDLoader.cpp */, - C582480917FF4EB09C164D70 /* SMDLoader.h */, - ); - name = SMD; - sourceTree = ""; - }; - 91C8DA33C37E491BBAD264C5 /* BVH */ = { - isa = PBXGroup; - children = ( - C80B9A3AF4204AE08AA50BAE /* BVHLoader.cpp */, - 45E342A1499E4F03ADD49028 /* BVHLoader.h */, - ); - name = BVH; - sourceTree = ""; - }; - 96A36CD42ADB4BBBB54004E1 /* XFile */ = { - isa = PBXGroup; - children = ( - 435DC362E63D4CCBA68656D3 /* XFileExporter.cpp */, - A257229A058041389981CFC1 /* XFileExporter.h */, - 8F4261792A60481DA04E6E1A /* XFileHelper.h */, - 06DB494DCE4D47FDA00E8B35 /* XFileImporter.cpp */, - 53537D08E9B44A25B43B697B /* XFileImporter.h */, - 74C02A113B804568A7E39CBC /* XFileParser.cpp */, - 3551D90CCED1454A8B912066 /* XFileParser.h */, - ); - name = XFile; - sourceTree = ""; - }; - 97326C49E0E34D43AE80F0FF /* MD5 */ = { - isa = PBXGroup; - children = ( - A277DBC1EFB944F995659A20 /* MD5Loader.cpp */, - 6BAB32C8E06E43689FC5E7EA /* MD5Loader.h */, - 0BC5FD00572F4C58B267A0EC /* MD5Parser.cpp */, - 43FC808D2F4745ACB06A9D33 /* MD5Parser.h */, - ); - name = MD5; - sourceTree = ""; - }; - 98D9A21F310D47DD8F390780 /* AC */ = { - isa = PBXGroup; - children = ( - F1076BAC69DB4935A93045A8 /* ACLoader.cpp */, - 4DABF3CB245F4246B0184513 /* ACLoader.h */, - ); - name = AC; - sourceTree = ""; - }; - 9A8E68D1ECFC49B9BB435F1C /* Raw */ = { - isa = PBXGroup; - children = ( - 1D4A669762194B9D9A26DD20 /* RawLoader.cpp */, - EAD338BE19AE4C2E897B38B6 /* RawLoader.h */, - ); - name = Raw; - sourceTree = ""; - }; - 9AC9FD0CD777436C9C7291FF /* 3DS */ = { - isa = PBXGroup; - children = ( - 15221A74FC9C4B2AAA7306E3 /* 3DSConverter.cpp */, - ECCBBF2D75A44335AB93C84A /* 3DSExporter.cpp */, - 0B519CCAB4B241E59C567077 /* 3DSExporter.h */, - CB042D863BD447FFB117AE34 /* 3DSHelper.h */, - 02E9476D129940BF84DE6682 /* 3DSLoader.cpp */, - A06CBE89CFAB48E786F7A5C0 /* 3DSLoader.h */, - ); - name = 3DS; - sourceTree = ""; - }; - A1E04517F0D440CDB46985A7 /* B3D */ = { - isa = PBXGroup; - children = ( - FCCB4BB481FB461688FE2F29 /* B3DImporter.cpp */, - 42E68041B1C442E3B49FC304 /* B3DImporter.h */, - ); - name = B3D; - sourceTree = ""; - }; - A7F45F8E82C445EBA7D67C36 /* Assbin */ = { - isa = PBXGroup; - children = ( - 6389F68312384CFD847B1D13 /* AssbinExporter.cpp */, - 6CC21F1D0E4140FE923E4EE6 /* AssbinExporter.h */, - D9FEEF58B24548F782A5D53C /* AssbinLoader.cpp */, - 0CCD090F58EB40ACBBDBBDEE /* AssbinLoader.h */, - ); - name = Assbin; - sourceTree = ""; - }; - AF05BC16567A496BB5DCB2F0 /* Products */ = { - isa = PBXGroup; - children = ( - 7F7922801AB43AC3005A8E5D /* libassimp.a */, - ); - name = Products; - sourceTree = ""; - }; - AFB7F8541C882F6E00D7B6E9 /* glTF */ = { - isa = PBXGroup; - children = ( - AFB7F8551C882F8200D7B6E9 /* glTFAsset.h */, - AFB7F8561C882F8200D7B6E9 /* glTFAsset.inl */, - AFB7F8571C882F8200D7B6E9 /* glTFAssetWriter.h */, - AFB7F8581C882F8200D7B6E9 /* glTFAssetWriter.inl */, - AFB7F8591C882F8200D7B6E9 /* glTFExporter.cpp */, - AFB7F85A1C882F8200D7B6E9 /* glTFExporter.h */, - AFB7F85B1C882F8200D7B6E9 /* glTFImporter.cpp */, - AFB7F85C1C882F8200D7B6E9 /* glTFImporter.h */, - ); - name = glTF; - sourceTree = ""; - }; - AFB7F8601C88301600D7B6E9 /* SIB */ = { - isa = PBXGroup; - children = ( - AFB7F8611C88302500D7B6E9 /* SIBImporter.cpp */, - AFB7F8621C88302500D7B6E9 /* SIBImporter.h */, - ); - name = SIB; - sourceTree = ""; - }; - BCC52F1D5AF74E54A2D69524 = { - isa = PBXGroup; - children = ( - 2DC7AE369B84444B9649035D /* assimp */, - 7F392D931AB2C7C200D952EB /* Frameworks */, - AF05BC16567A496BB5DCB2F0 /* Products */, - ); - sourceTree = ""; - }; - C3D412701D614559B698CED1 /* Q3BSP */ = { - isa = PBXGroup; - children = ( - 6E82409E9D274D278971F3B0 /* Q3BSPFileData.h */, - A88D56FBEA084A3EA9A0ECB3 /* Q3BSPFileImporter.cpp */, - F898EEA0D9E64425A790587D /* Q3BSPFileImporter.h */, - 4A60A00727F04E049CF3AE33 /* Q3BSPFileParser.cpp */, - 5C15EEB253204E8A8E0D0E38 /* Q3BSPFileParser.h */, - 43C75175738C4119871E8BB0 /* Q3BSPZipArchive.cpp */, - 6454A961FAF44B3E9086D2F8 /* Q3BSPZipArchive.h */, - ); - name = Q3BSP; - sourceTree = ""; - }; - CB3420FADCED418CACDBB584 /* ASE */ = { - isa = PBXGroup; - children = ( - 7C477FA4D89548F1BCEDC5A0 /* ASELoader.cpp */, - 9A61AF384D4D45778698DD7D /* ASELoader.h */, - 929F59CCA32549EC884A5033 /* ASEParser.cpp */, - 27605E75944D41B0B98260A3 /* ASEParser.h */, - ); - name = ASE; - sourceTree = ""; - }; - CB981D90CEF4472191978170 /* MDC */ = { - isa = PBXGroup; - children = ( - 95641498F25A4F6FABBC03A4 /* MDCFileData.h */, - 35E4944C052A4C91BF31DE5F /* MDCLoader.cpp */, - 621E96E95F60421EB6B4525C /* MDCLoader.h */, - DD4E4641B0FE4369BF3775C3 /* MDCNormalTable.h */, - ); - name = MDC; - sourceTree = ""; - }; - CF7D1A0DBB134AC4BCFE3C3F /* NFF */ = { - isa = PBXGroup; - children = ( - 0D6E8E292F594A2DAFF53564 /* NFFLoader.cpp */, - D2869C6AD4814588A45E8F81 /* NFFLoader.h */, - ); - name = NFF; - sourceTree = ""; - }; - D3013C8FC8034BC6859BC020 /* PostProcessing */ = { - isa = PBXGroup; - children = ( - 90DD6CA40A5E41458E11FF3E /* CalcTangentsProcess.cpp */, - BBEE1CF81183473C8492FC03 /* CalcTangentsProcess.h */, - 2ABBB4561E72413EB40702C3 /* ComputeUVMappingProcess.cpp */, - B40FE1BF9D8E411493BBDE0C /* ComputeUVMappingProcess.h */, - 92D8734FFF9742B39A371B70 /* ConvertToLHProcess.cpp */, - 35A9B50143214C63A956FA27 /* ConvertToLHProcess.h */, - 6E20FCC571F144DDBD831CCB /* DeboneProcess.cpp */, - 4770D6DCA1854B4F9B85546A /* DeboneProcess.h */, - BABB7734139C452A9DDEE797 /* FindDegenerates.cpp */, - 4B571231CE2B464BBF1E853F /* FindDegenerates.h */, - C9A101D1311C4E77AAEDD94C /* FindInstancesProcess.cpp */, - 28A938B21261484998F68F4A /* FindInstancesProcess.h */, - 9B4221AA0AD2418FAA45EB64 /* FindInvalidDataProcess.cpp */, - 91FF8B1DCC0644008AE34A04 /* FindInvalidDataProcess.h */, - C54518F708BA4A328D5D7325 /* FixNormalsStep.cpp */, - 8343910BBD464297932B3CE0 /* FixNormalsStep.h */, - 982AE676D2364350B1FBD095 /* GenFaceNormalsProcess.cpp */, - 0FBF026F27F340AD9FABAF02 /* GenFaceNormalsProcess.h */, - A0AED12A1A6D4635A8CFB65A /* GenVertexNormalsProcess.cpp */, - 2AC344FBB0C34D49800F4B8A /* GenVertexNormalsProcess.h */, - 70D5FDFA995E45E6A3E8FD37 /* ImproveCacheLocality.cpp */, - 5FBE72DCC6AC485ABCF89B8C /* ImproveCacheLocality.h */, - B36DA471B9E142FC9425EC45 /* JoinVerticesProcess.cpp */, - 0A941971CBF04E8D900E9799 /* JoinVerticesProcess.h */, - E065DB38B0284196A9283CA3 /* LimitBoneWeightsProcess.cpp */, - DDDE82BDF4F94E0EA35649A4 /* LimitBoneWeightsProcess.h */, - 21B797DAB0E0427C9339AE0F /* MakeVerboseFormat.cpp */, - 0AA53AD6095A4D1088431EED /* MakeVerboseFormat.h */, - AAB9AE5328F843F5A8A3E85C /* OptimizeGraph.cpp */, - 926E8B7924144B349A88023D /* OptimizeGraph.h */, - 2ACC87E846AE4E4A86E1AEF4 /* OptimizeMeshes.cpp */, - DD3D18BC2E58447D9879CB00 /* OptimizeMeshes.h */, - FB55283BC24C4A1CA86C4900 /* PolyTools.h */, - 023C115651B54570AA2040DB /* PretransformVertices.cpp */, - 101172E4EF2E43D988B6B571 /* PretransformVertices.h */, - 890E32C714444692AA016AE5 /* ProcessHelper.cpp */, - A436C47FBF904FECB4A58462 /* ProcessHelper.h */, - ADACEBC4973F4FC0A6FEC68A /* RemoveRedundantMaterials.cpp */, - AD969BA482564C7FAA372F7C /* RemoveRedundantMaterials.h */, - FB4ABA17AF264257BDA4D921 /* RemoveVCProcess.cpp */, - ABDA70358E34432A8A4637F4 /* RemoveVCProcess.h */, - BD9A81E0E27E44718609615B /* SortByPTypeProcess.cpp */, - 16437E08A946431EB2EFA3E0 /* SortByPTypeProcess.h */, - A43641DC9C1B4B578BC40476 /* SplitLargeMeshes.cpp */, - D2EEB62ECBF749AA89146C66 /* SplitLargeMeshes.h */, - DF76D04D95E649BCBC15E64F /* TextureTransform.cpp */, - C5C3ED2BE50D4684994BD533 /* TextureTransform.h */, - 1A0AC303D18A48A69AB3BC03 /* TriangulateProcess.cpp */, - FB2510D46F504365A03EE8A8 /* TriangulateProcess.h */, - 0EF4F7A237F648C2809A8F31 /* ValidateDataStructure.cpp */, - 725DAD1CE04C4F64BDAB7037 /* ValidateDataStructure.h */, - ); - name = PostProcessing; - sourceTree = ""; - }; - DAFF6641A88441AFBE8B99B1 /* COB */ = { - isa = PBXGroup; - children = ( - C84DA0E6CE13493D833BA1C1 /* COBLoader.cpp */, - 445F70426FCC42F088405E86 /* COBLoader.h */, - 9E0572B45F1F4605BD5C919D /* COBScene.h */, - ); - name = COB; - sourceTree = ""; - }; - DB181885BFCC44F594A1FA01 /* Source Files */ = { - isa = PBXGroup; - children = ( - 705D30EE141A48F292783F0E /* Assimp.cpp */, - 7FBEA0111B65B11800D2115E /* Version.cpp */, - ); - name = "Source Files"; - sourceTree = ""; - }; - DD5B35196B184EFB820D1FBB /* CSM */ = { - isa = PBXGroup; - children = ( - 77908990BEF04D0881E8AE80 /* CSMLoader.cpp */, - 1BC6B0FE92DD4F38803BC17B /* CSMLoader.h */, - ); - name = CSM; - sourceTree = ""; - }; - EF7D37EB84AF45FC8BF47E7F /* MDL */ = { - isa = PBXGroup; - children = ( - F1A7BD0B5CAE48699FCAEBD1 /* MDLDefaultColorMap.h */, - D5F4108F03D7457EB641836B /* MDLFileData.h */, - AA92FFC8B06D4569AD9C4CB1 /* MDLLoader.cpp */, - E24E950227C848D3A759F5C2 /* MDLLoader.h */, - CEC69808E1844C23B95D3475 /* MDLMaterialLoader.cpp */, - ); - name = MDL; - sourceTree = ""; - }; - F0273EDFDBD34EDAA6678613 /* Q3D */ = { - isa = PBXGroup; - children = ( - C5178B3983F147F3B9BD8217 /* Q3DLoader.cpp */, - 76773A53296549FFA43956A1 /* Q3DLoader.h */, - ); - name = Q3D; - sourceTree = ""; - }; - F61A479614764D11AC3311A8 /* Poly2Tri */ = { - isa = PBXGroup; - children = ( - AE00939F150F413780C8AAD7 /* shapes.cc */, - EE545B58FA1246C792C6AD01 /* shapes.h */, - 50935A81362041BEADF18609 /* utils.h */, - B72D0BA3EF66439F8D582ED3 /* advancing_front.cc */, - DAE82F651F9E4D91A6A6C753 /* advancing_front.h */, - 849EC6315E4A4E5FA06521EA /* cdt.cc */, - 904A696E49D540C2A880792B /* cdt.h */, - 49E993CD86A346869AF473BC /* sweep.cc */, - 62E8551653634972ABBABCAD /* sweep.h */, - 5E10483FBE6D4F4594B460E0 /* sweep_context.cc */, - 267D593135514108B7DEF072 /* sweep_context.h */, - ); - name = Poly2Tri; - sourceTree = ""; - }; - F9261D592F00437EAFC663B5 /* MD2 */ = { - isa = PBXGroup; - children = ( - 21E21BE7CB364AC3AB81E54C /* MD2FileData.h */, - 49B655CCE1314D4E8A94B371 /* MD2Loader.cpp */, - 531FBC4210644C61954EA4C4 /* MD2Loader.h */, - FD84CFD1BD3E4AF4BA622BB8 /* MD2NormalTable.h */, - ); - name = MD2; - sourceTree = ""; - }; - FCFE51BCE7384933A972EDEE /* Header Files */ = { - isa = PBXGroup; - children = ( - 731205CAB88247C095E33412 /* Exporter.hpp */, - B54FBAAF061B40DBA3F48F83 /* IOStream.hpp */, - 86E296E459F94050ACBA3C63 /* IOSystem.hpp */, - B9DFF24FD63A4D9FAE213EED /* Importer.hpp */, - 69AFF47737244CE3BD1653CC /* ProgressHandler.hpp */, - C7B37CA474DF4CE7A5B0658E /* ai_assert.h */, - B441D87EE6ED4EBFB0586B66 /* anim.h */, - B05DC38593F04180B322360B /* camera.h */, - 2F34A6A3C4104625A52BF7C2 /* cexport.h */, - E1313C36045444619026E9FB /* cfileio.h */, - 267A74499024423A86150697 /* cimport.h */, - 0535CB113239433DA7CD7FDE /* color4.h */, - 079B3C75D1014265959C427D /* color4.inl */, - 90949C7A51E84D3595D71A6B /* config.h */, - 9761D873B9604504B9AD7CD5 /* defs.h */, - 4D82A29A8BBF44E69E026F84 /* importerdesc.h */, - 8E2108F568374F65ACE217D1 /* light.h */, - 05EA73C462244F1791039BFB /* material.h */, - 139DFC029C4C44B09952C645 /* material.inl */, - 10E9B0497D844A10BC759A09 /* matrix3x3.h */, - 073189BEE7A5466B9EE817D4 /* matrix3x3.inl */, - BA832069DF214327AE067503 /* matrix4x4.h */, - 4493838DDEE841BF96A0F008 /* matrix4x4.inl */, - E9ED3048A21E483F9C2721F4 /* mesh.h */, - 5F84BDD0D5D345A2BF1E08E1 /* metadata.h */, - 41C2F6D564924BF4ACE75CAC /* postprocess.h */, - 279D2A482FE9402A8F7EC441 /* quaternion.h */, - 97F52051AF4F478FA77AABBC /* quaternion.inl */, - 3B407EAF162843CBA46BC9D4 /* scene.h */, - AE1C2E2C9C424B3684AD9D4A /* texture.h */, - 56DA1CDC223747F4AFBAF953 /* types.h */, - FB1E84BE85A34F98A44BBB2B /* vector2.h */, - B6074B1E864740F787A97EA3 /* vector2.inl */, - 6D72952403D04713A6451654 /* vector3.h */, - 8D53CC35AAED4CE8B9710E04 /* vector3.inl */, - FC0801BA1F95494498A089AF /* version.h */, - ); - name = "Header Files"; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 7F79227F1AB43AC3005A8E5D /* assimp */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7F7922911AB43AC3005A8E5D /* Build configuration list for PBXNativeTarget "assimp" */; - buildPhases = ( - 7F79229B1AB43AF4005A8E5D /* Run Script to build "revision.h" */, - 7F79227C1AB43AC3005A8E5D /* Sources */, - 7F79227D1AB43AC3005A8E5D /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = assimp; - productName = assimp; - productReference = 7F7922801AB43AC3005A8E5D /* libassimp.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 9DE203BC835F4C81BCDF25CF /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 0700; - TargetAttributes = { - 7F79227F1AB43AC3005A8E5D = { - CreatedOnToolsVersion = 6.3; - }; - }; - }; - buildConfigurationList = 0C36C32B633D49CB92166176 /* Build configuration list for PBXProject "Assimp" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = BCC52F1D5AF74E54A2D69524; - projectDirPath = ../..; - projectRoot = ""; - targets = ( - 7F79227F1AB43AC3005A8E5D /* assimp */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXShellScriptBuildPhase section */ - 7F79229B1AB43AF4005A8E5D /* Run Script to build "revision.h" */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script to build \"revision.h\""; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "mkdir -p \"${DERIVED_FILE_DIR}\"\ncat \"${SRCROOT}/revision.h.in\" | sed \"s/@GIT_COMMIT_HASH@/`git rev-parse --short HEAD`/g\" | sed \"s/@GIT_BRANCH@/`git rev-parse --abbrev-ref HEAD`/g\" > \"${DERIVED_FILE_DIR}/revision.h\""; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 7F79227C1AB43AC3005A8E5D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7F79242A1AB43E20005A8E5D /* 3DSConverter.cpp in Sources */, - 7F79242B1AB43E20005A8E5D /* 3DSExporter.cpp in Sources */, - 7F79242C1AB43E20005A8E5D /* 3DSLoader.cpp in Sources */, - 7F79242D1AB43E20005A8E5D /* ACLoader.cpp in Sources */, - 7F79242E1AB43E20005A8E5D /* ASELoader.cpp in Sources */, - 7F79242F1AB43E20005A8E5D /* ASEParser.cpp in Sources */, - 7F7924301AB43E20005A8E5D /* AssbinExporter.cpp in Sources */, - 7F7924311AB43E20005A8E5D /* AssbinLoader.cpp in Sources */, - 7F7924321AB43E20005A8E5D /* Assimp.cpp in Sources */, - 7F7924331AB43E20005A8E5D /* AssimpCExport.cpp in Sources */, - 7F7924351AB43E20005A8E5D /* AssxmlExporter.cpp in Sources */, - 7F7924361AB43E20005A8E5D /* B3DImporter.cpp in Sources */, - 7F7924371AB43E20005A8E5D /* BVHLoader.cpp in Sources */, - 7F7924381AB43E20005A8E5D /* BaseImporter.cpp in Sources */, - 7F7924391AB43E20005A8E5D /* BaseProcess.cpp in Sources */, - 7F79243A1AB43E20005A8E5D /* Bitmap.cpp in Sources */, - 7F79243B1AB43E20005A8E5D /* BlenderBMesh.cpp in Sources */, - 7F79243C1AB43E20005A8E5D /* BlenderDNA.cpp in Sources */, - 7F79243D1AB43E20005A8E5D /* BlenderLoader.cpp in Sources */, - AFB7F85D1C882F8200D7B6E9 /* glTFExporter.cpp in Sources */, - 7F79243E1AB43E20005A8E5D /* BlenderModifier.cpp in Sources */, - 7F79243F1AB43E20005A8E5D /* BlenderScene.cpp in Sources */, - 7F7924401AB43E20005A8E5D /* BlenderTessellator.cpp in Sources */, - 7F7924411AB43E20005A8E5D /* COBLoader.cpp in Sources */, - 7F7924421AB43E20005A8E5D /* CSMLoader.cpp in Sources */, - 7F7924431AB43E20005A8E5D /* CalcTangentsProcess.cpp in Sources */, - 7F7924441AB43E20005A8E5D /* ColladaExporter.cpp in Sources */, - 7F7924451AB43E20005A8E5D /* ColladaLoader.cpp in Sources */, - 7F7924461AB43E20005A8E5D /* ColladaParser.cpp in Sources */, - 7F7924471AB43E20005A8E5D /* ComputeUVMappingProcess.cpp in Sources */, - 7F7924481AB43E20005A8E5D /* ConvertToLHProcess.cpp in Sources */, - 7F7924491AB43E20005A8E5D /* DXFLoader.cpp in Sources */, - 7F79244A1AB43E20005A8E5D /* DeboneProcess.cpp in Sources */, - 7F79244B1AB43E20005A8E5D /* DefaultIOStream.cpp in Sources */, - 7F79244C1AB43E20005A8E5D /* DefaultIOSystem.cpp in Sources */, - 7F7A93A81B65D0110094C4DA /* DDLNode.cpp in Sources */, - 7F79244D1AB43E20005A8E5D /* DefaultLogger.cpp in Sources */, - 2DC891D01D2CFA75001E0B0E /* C4DImporter.cpp in Sources */, - 7F79244E1AB43E20005A8E5D /* Exporter.cpp in Sources */, - 7F79244F1AB43E20005A8E5D /* FBXAnimation.cpp in Sources */, - 7F7924501AB43E20005A8E5D /* FBXBinaryTokenizer.cpp in Sources */, - 7F7924511AB43E20005A8E5D /* FBXConverter.cpp in Sources */, - 7F7924521AB43E20005A8E5D /* FBXDeformer.cpp in Sources */, - 7F7924531AB43E20005A8E5D /* FBXDocument.cpp in Sources */, - 7F7924541AB43E20005A8E5D /* FBXDocumentUtil.cpp in Sources */, - 7F7924551AB43E20005A8E5D /* FBXImporter.cpp in Sources */, - 7F7924561AB43E20005A8E5D /* FBXMaterial.cpp in Sources */, - 7F7924571AB43E20005A8E5D /* FBXMeshGeometry.cpp in Sources */, - 7F7924581AB43E20005A8E5D /* FBXModel.cpp in Sources */, - 7F7924591AB43E20005A8E5D /* FBXNodeAttribute.cpp in Sources */, - 7F79245A1AB43E20005A8E5D /* FBXParser.cpp in Sources */, - 7F79245B1AB43E20005A8E5D /* FBXProperties.cpp in Sources */, - 7F79245C1AB43E20005A8E5D /* FBXTokenizer.cpp in Sources */, - 7F79245D1AB43E20005A8E5D /* FBXUtil.cpp in Sources */, - 7F7A93A91B65D0110094C4DA /* OpenDDLParser.cpp in Sources */, - 7F79245E1AB43E20005A8E5D /* FindDegenerates.cpp in Sources */, - AFB7F8531C882F1A00D7B6E9 /* OpenDDLExport.cpp in Sources */, - 7F79245F1AB43E20005A8E5D /* FindInstancesProcess.cpp in Sources */, - 7F7924601AB43E20005A8E5D /* FindInvalidDataProcess.cpp in Sources */, - 7F7924611AB43E20005A8E5D /* FixNormalsStep.cpp in Sources */, - 2DC891CA1D2CFA22001E0B0E /* D3MFImporter.cpp in Sources */, - 7F7924621AB43E20005A8E5D /* GenFaceNormalsProcess.cpp in Sources */, - 7F7924631AB43E20005A8E5D /* GenVertexNormalsProcess.cpp in Sources */, - 7F7924641AB43E20005A8E5D /* HMPLoader.cpp in Sources */, - 7F7924651AB43E20005A8E5D /* IFCBoolean.cpp in Sources */, - 2DC891CB1D2CFA22001E0B0E /* D3MFOpcPackage.cpp in Sources */, - 7F7924661AB43E20005A8E5D /* IFCCurve.cpp in Sources */, - AFB7F85E1C882F8200D7B6E9 /* glTFImporter.cpp in Sources */, - 7F7924671AB43E20005A8E5D /* IFCGeometry.cpp in Sources */, - 7F7924681AB43E20005A8E5D /* IFCLoader.cpp in Sources */, - 7F7924691AB43E20005A8E5D /* IFCMaterial.cpp in Sources */, - 7F79246A1AB43E20005A8E5D /* IFCOpenings.cpp in Sources */, - 7F79246B1AB43E20005A8E5D /* IFCProfile.cpp in Sources */, - 7FBEA0121B65B11800D2115E /* Version.cpp in Sources */, - 7F79246C1AB43E20005A8E5D /* IFCReaderGen.cpp in Sources */, - 7F79246D1AB43E20005A8E5D /* IFCUtil.cpp in Sources */, - 7F79246E1AB43E20005A8E5D /* IRRLoader.cpp in Sources */, - 7F79246F1AB43E20005A8E5D /* IRRMeshLoader.cpp in Sources */, - 7F7924701AB43E20005A8E5D /* IRRShared.cpp in Sources */, - 7F7924711AB43E20005A8E5D /* Importer.cpp in Sources */, - 7F7924721AB43E20005A8E5D /* ImporterRegistry.cpp in Sources */, - 7F7924731AB43E20005A8E5D /* ImproveCacheLocality.cpp in Sources */, - 7F7924741AB43E20005A8E5D /* JoinVerticesProcess.cpp in Sources */, - 7F7924751AB43E20005A8E5D /* LWOAnimation.cpp in Sources */, - 7F7924761AB43E20005A8E5D /* LWOBLoader.cpp in Sources */, - 7F7924771AB43E20005A8E5D /* LWOLoader.cpp in Sources */, - 7F7924781AB43E20005A8E5D /* LWOMaterial.cpp in Sources */, - 7F7924791AB43E20005A8E5D /* LWSLoader.cpp in Sources */, - AFB7F8521C882F1A00D7B6E9 /* OpenDDLCommon.cpp in Sources */, - 7F79247A1AB43E20005A8E5D /* LimitBoneWeightsProcess.cpp in Sources */, - 7F79247B1AB43E20005A8E5D /* MD2Loader.cpp in Sources */, - 7F79247C1AB43E20005A8E5D /* MD3Loader.cpp in Sources */, - 7F79247D1AB43E20005A8E5D /* MD5Loader.cpp in Sources */, - 7F79247E1AB43E20005A8E5D /* MD5Parser.cpp in Sources */, - 7F79247F1AB43E20005A8E5D /* MDCLoader.cpp in Sources */, - 7F7924801AB43E20005A8E5D /* MDLLoader.cpp in Sources */, - 7F7924811AB43E20005A8E5D /* MDLMaterialLoader.cpp in Sources */, - 7F7924821AB43E20005A8E5D /* MS3DLoader.cpp in Sources */, - 7FBE9FEB1B65AC1200D2115E /* OpenGEXImporter.cpp in Sources */, - 7F7924831AB43E20005A8E5D /* MakeVerboseFormat.cpp in Sources */, - 7F7924841AB43E20005A8E5D /* MaterialSystem.cpp in Sources */, - 7F7924851AB43E20005A8E5D /* NDOLoader.cpp in Sources */, - 7F7924861AB43E20005A8E5D /* NFFLoader.cpp in Sources */, - 7F7924871AB43E20005A8E5D /* OFFLoader.cpp in Sources */, - 7F7924881AB43E20005A8E5D /* ObjExporter.cpp in Sources */, - 7F7924891AB43E20005A8E5D /* ObjFileImporter.cpp in Sources */, - 7F79248A1AB43E20005A8E5D /* ObjFileMtlImporter.cpp in Sources */, - 7F79248B1AB43E20005A8E5D /* ObjFileParser.cpp in Sources */, - 7F79248C1AB43E20005A8E5D /* OgreBinarySerializer.cpp in Sources */, - 7F79248D1AB43E20005A8E5D /* OgreImporter.cpp in Sources */, - 7F79248E1AB43E20005A8E5D /* OgreMaterial.cpp in Sources */, - 7F79248F1AB43E20005A8E5D /* OgreStructs.cpp in Sources */, - 7F7924901AB43E20005A8E5D /* OgreXmlSerializer.cpp in Sources */, - 7F7924911AB43E20005A8E5D /* OptimizeGraph.cpp in Sources */, - 7F7924921AB43E20005A8E5D /* OptimizeMeshes.cpp in Sources */, - 7F7924931AB43E20005A8E5D /* PlyExporter.cpp in Sources */, - 7F7924941AB43E20005A8E5D /* PlyLoader.cpp in Sources */, - 7F7924951AB43E20005A8E5D /* PlyParser.cpp in Sources */, - 7F7924961AB43E20005A8E5D /* PostStepRegistry.cpp in Sources */, - 7F7924971AB43E20005A8E5D /* PretransformVertices.cpp in Sources */, - 7F7924981AB43E20005A8E5D /* ProcessHelper.cpp in Sources */, - 7F7A93AA1B65D0110094C4DA /* Value.cpp in Sources */, - 7F7924991AB43E20005A8E5D /* Q3BSPFileImporter.cpp in Sources */, - 7F79249A1AB43E20005A8E5D /* Q3BSPFileParser.cpp in Sources */, - 7F79249B1AB43E20005A8E5D /* Q3BSPZipArchive.cpp in Sources */, - 7F79249C1AB43E20005A8E5D /* Q3DLoader.cpp in Sources */, - 7F79249D1AB43E20005A8E5D /* RawLoader.cpp in Sources */, - 7F79249E1AB43E20005A8E5D /* RemoveComments.cpp in Sources */, - 7F79249F1AB43E20005A8E5D /* RemoveRedundantMaterials.cpp in Sources */, - 7F7924A01AB43E20005A8E5D /* RemoveVCProcess.cpp in Sources */, - 7F7924A11AB43E20005A8E5D /* SGSpatialSort.cpp in Sources */, - 7F7924A21AB43E20005A8E5D /* SMDLoader.cpp in Sources */, - 7F7924A31AB43E20005A8E5D /* STEPFileEncoding.cpp in Sources */, - 7F7924A41AB43E20005A8E5D /* STEPFileReader.cpp in Sources */, - 7F7924A51AB43E20005A8E5D /* STLExporter.cpp in Sources */, - 7FBE9FEA1B65AC1200D2115E /* OpenGEXExporter.cpp in Sources */, - 7F7924A61AB43E20005A8E5D /* STLLoader.cpp in Sources */, - 7F7924A71AB43E20005A8E5D /* SceneCombiner.cpp in Sources */, - 7F7924A81AB43E20005A8E5D /* ScenePreprocessor.cpp in Sources */, - 7F7924A91AB43E20005A8E5D /* SkeletonMeshBuilder.cpp in Sources */, - 7F7924AA1AB43E20005A8E5D /* SortByPTypeProcess.cpp in Sources */, - 7F7924AB1AB43E20005A8E5D /* SpatialSort.cpp in Sources */, - 7F7924AC1AB43E20005A8E5D /* SplitByBoneCountProcess.cpp in Sources */, - 7F7924AD1AB43E20005A8E5D /* SplitLargeMeshes.cpp in Sources */, - AFB7F8631C88302500D7B6E9 /* SIBImporter.cpp in Sources */, - 7F7924AE1AB43E20005A8E5D /* StandardShapes.cpp in Sources */, - 7F7924AF1AB43E20005A8E5D /* Subdivision.cpp in Sources */, - 7F7924B01AB43E20005A8E5D /* TargetAnimation.cpp in Sources */, - 7F7924B11AB43E20005A8E5D /* TerragenLoader.cpp in Sources */, - 7F7924B21AB43E20005A8E5D /* TextureTransform.cpp in Sources */, - 7F7924B31AB43E20005A8E5D /* TriangulateProcess.cpp in Sources */, - 7F7924B41AB43E20005A8E5D /* UnrealLoader.cpp in Sources */, - 7F7924B51AB43E20005A8E5D /* ValidateDataStructure.cpp in Sources */, - 7F7924B61AB43E20005A8E5D /* VertexTriangleAdjacency.cpp in Sources */, - 7F7924B71AB43E20005A8E5D /* XFileExporter.cpp in Sources */, - 7F7924B81AB43E20005A8E5D /* XFileImporter.cpp in Sources */, - 7F7924B91AB43E20005A8E5D /* XFileParser.cpp in Sources */, - 7F7924BA1AB43E20005A8E5D /* XGLLoader.cpp in Sources */, - 7F7924BB1AB43E20005A8E5D /* ConvertUTF.c in Sources */, - 7F7924BC1AB43E20005A8E5D /* clipper.cpp in Sources */, - 7F7924BD1AB43E20005A8E5D /* irrXML.cpp in Sources */, - 7F7924BE1AB43E20005A8E5D /* shapes.cc in Sources */, - 7F7924BF1AB43E20005A8E5D /* advancing_front.cc in Sources */, - 7F7924C01AB43E20005A8E5D /* cdt.cc in Sources */, - 7F7924C11AB43E20005A8E5D /* sweep.cc in Sources */, - 7F7924C21AB43E20005A8E5D /* sweep_context.cc in Sources */, - 7F7924C31AB43E20005A8E5D /* ioapi.c in Sources */, - 7F7924C41AB43E20005A8E5D /* unzip.c in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 137567A2412C45B8A269E344 /* RelWithDebInfo */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_PREPROCESSOR_DEFINITIONS = NDEBUG; - MACH_O_TYPE = staticlib; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx"; - }; - name = RelWithDebInfo; - }; - 7F7922921AB43AC3005A8E5D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = NO; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = NO; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DYLIB_COMPATIBILITY_VERSION = 3.0.0; - DYLIB_CURRENT_VERSION = 3.1.1; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_GENERATE_DEBUGGING_SYMBOLS = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - assimp_EXPORTS, - ASSIMP_BUILD_BOOST_WORKAROUND, - ASSIMP_BUILD_NO_OWN_ZLIB, - ASSIMP_BUILD_NO_C4D_IMPORTER, - ASSIMP_BUILD_DLL_EXPORT, - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = NO; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - HEADER_SEARCH_PATHS = "$(SRCROOT)"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - USER_HEADER_SEARCH_PATHS = "code code/BoostWorkaround contrib/openddlparser/include contrib/rapidjson/include include $(inherited)"; - }; - name = Debug; - }; - 7F7922931AB43AC3005A8E5D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = NO; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = NO; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DYLIB_COMPATIBILITY_VERSION = 3.0.0; - DYLIB_CURRENT_VERSION = 3.1.1; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_GENERATE_DEBUGGING_SYMBOLS = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = fast; - GCC_PREPROCESSOR_DEFINITIONS = ( - assimp_EXPORTS, - ASSIMP_BUILD_BOOST_WORKAROUND, - ASSIMP_BUILD_NO_OWN_ZLIB, - ASSIMP_BUILD_NO_C4D_IMPORTER, - ASSIMP_BUILD_DLL_EXPORT, - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = NO; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - HEADER_SEARCH_PATHS = "$(SRCROOT)"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - USER_HEADER_SEARCH_PATHS = "code code/BoostWorkaround contrib/openddlparser/include contrib/rapidjson/include include $(inherited)"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 7F7922941AB43AC3005A8E5D /* MinSizeRel */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = NO; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = NO; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DYLIB_COMPATIBILITY_VERSION = 3.0.0; - DYLIB_CURRENT_VERSION = 3.1.1; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_GENERATE_DEBUGGING_SYMBOLS = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - assimp_EXPORTS, - ASSIMP_BUILD_BOOST_WORKAROUND, - ASSIMP_BUILD_NO_OWN_ZLIB, - ASSIMP_BUILD_NO_C4D_IMPORTER, - ASSIMP_BUILD_DLL_EXPORT, - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = NO; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - HEADER_SEARCH_PATHS = "$(SRCROOT)"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - USER_HEADER_SEARCH_PATHS = "code code/BoostWorkaround contrib/openddlparser/include contrib/rapidjson/include include $(inherited)"; - VALIDATE_PRODUCT = YES; - }; - name = MinSizeRel; - }; - 7F7922951AB43AC3005A8E5D /* RelWithDebInfo */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = YES; - ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = NO; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = NO; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DYLIB_COMPATIBILITY_VERSION = 3.0.0; - DYLIB_CURRENT_VERSION = 3.1.1; - ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_GENERATE_DEBUGGING_SYMBOLS = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - assimp_EXPORTS, - ASSIMP_BUILD_BOOST_WORKAROUND, - ASSIMP_BUILD_NO_OWN_ZLIB, - ASSIMP_BUILD_NO_C4D_IMPORTER, - ASSIMP_BUILD_DLL_EXPORT, - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = NO; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - HEADER_SEARCH_PATHS = "$(SRCROOT)"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - USER_HEADER_SEARCH_PATHS = "code code/BoostWorkaround contrib/openddlparser/include contrib/rapidjson/include include $(inherited)"; - VALIDATE_PRODUCT = YES; - }; - name = RelWithDebInfo; - }; - 9604718722A94CBB9F87A9D8 /* MinSizeRel */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_PREPROCESSOR_DEFINITIONS = NDEBUG; - MACH_O_TYPE = staticlib; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx"; - }; - name = MinSizeRel; - }; - C58F2FA1D18E452FBFD3B286 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ENABLE_TESTABILITY = YES; - GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; - MACH_O_TYPE = staticlib; - ONLY_ACTIVE_ARCH = YES; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx"; - }; - name = Debug; - }; - DB0088F8DB7C490CBA3CCB90 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_PREPROCESSOR_DEFINITIONS = NDEBUG; - MACH_O_TYPE = staticlib; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 0C36C32B633D49CB92166176 /* Build configuration list for PBXProject "Assimp" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C58F2FA1D18E452FBFD3B286 /* Debug */, - DB0088F8DB7C490CBA3CCB90 /* Release */, - 9604718722A94CBB9F87A9D8 /* MinSizeRel */, - 137567A2412C45B8A269E344 /* RelWithDebInfo */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - 7F7922911AB43AC3005A8E5D /* Build configuration list for PBXNativeTarget "assimp" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7F7922921AB43AC3005A8E5D /* Debug */, - 7F7922931AB43AC3005A8E5D /* Release */, - 7F7922941AB43AC3005A8E5D /* MinSizeRel */, - 7F7922951AB43AC3005A8E5D /* RelWithDebInfo */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; -/* End XCConfigurationList section */ - }; - rootObject = 9DE203BC835F4C81BCDF25CF /* Project object */; -} diff --git a/workspaces/xcode6/Assimp.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/workspaces/xcode6/Assimp.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 0abcc1fa5..000000000 --- a/workspaces/xcode6/Assimp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/workspaces/xcode6/Assimp.xcodeproj/xcshareddata/xcschemes/assimp.xcscheme b/workspaces/xcode6/Assimp.xcodeproj/xcshareddata/xcschemes/assimp.xcscheme deleted file mode 100644 index 99aae1cbb..000000000 --- a/workspaces/xcode6/Assimp.xcodeproj/xcshareddata/xcschemes/assimp.xcscheme +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -